diff --git a/nx/include/switch/services/hiddbg.h b/nx/include/switch/services/hiddbg.h index e6f46b2c..df4aaf3d 100644 --- a/nx/include/switch/services/hiddbg.h +++ b/nx/include/switch/services/hiddbg.h @@ -127,10 +127,20 @@ Result hiddbgUpdateControllerColor(u32 colorBody, u32 colorButtons, u64 UniquePa /// Writes the input RGB colors followed by inval to the spi-flash for the specified controller (offset 0x6050 size 0xD). See hidsys.h for UniquePadId. Only available with [5.0.0+]. Result hiddbgUpdateDesignInfo(u32 colorBody, u32 colorButtons, u32 colorLeftGrip, u32 colorRightGrip, u8 inval, u64 UniquePadId); +/// Get the OperationEvent for the specified controller. See hidsys.h for UniquePadId. +/// The Event must be closed by the user once finished with it. +/// Only available with [6.0.0+]. +Result hiddbgAcquireOperationEventHandle(Event* out_event, bool autoclear, u64 UniquePadId); + /// Reads spi-flash for the specified controller. See hidsys.h for UniquePadId. -/// This doesn't seem to be usable? +/// This also uses \ref hiddbgAcquireOperationEventHandle to wait for the operation to finish, then \ref hiddbgGetOperationResult is used. +/// Only available with [6.0.0+]. Result hiddbgReadSerialFlash(u32 offset, void* buffer, size_t size, u64 UniquePadId); +/// Get the Result for the Operation and handles cleanup, for the specified controller. See hidsys.h for UniquePadId. +/// Only available with [6.0.0+]. +Result hiddbgGetOperationResult(u64 UniquePadId); + /// Gets the internal DeviceType for the specified controller. See hidsys.h for UniquePadId. /// Only available with [6.0.0+]. /// Pre-9.0.0 the output is an u32, with [9.0.0+] it's an u8. diff --git a/nx/source/services/hiddbg.c b/nx/source/services/hiddbg.c index e86acad5..f4372cae 100644 --- a/nx/source/services/hiddbg.c +++ b/nx/source/services/hiddbg.c @@ -102,6 +102,21 @@ Result hiddbgUpdateDesignInfo(u32 colorBody, u32 colorButtons, u32 colorLeftGrip return serviceDispatchIn(&g_hiddbgSrv, 224, in); } +Result hiddbgAcquireOperationEventHandle(Event* out_event, bool autoclear, u64 UniquePadId) { + if (hosversionBefore(6,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Handle tmp_handle = INVALID_HANDLE; + Result rc = 0; + + rc = serviceDispatchIn(&g_hiddbgSrv, 228, UniquePadId, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &tmp_handle, + ); + if (R_SUCCEEDED(rc)) eventLoadRemote(out_event, tmp_handle, autoclear); + return rc; +} + static Result _hiddbgReadSerialFlash(TransferMemory *tmem, u32 offset, u64 size, u64 UniquePadId) { const struct { u32 offset; @@ -115,8 +130,10 @@ static Result _hiddbgReadSerialFlash(TransferMemory *tmem, u32 offset, u64 size, ); } +// sdk-nso doesn't use hiddbgAcquireOperationEventHandle/hiddbgGetOperationResult in the ReadSerialFlash impl, those are used seperately by the user. Result hiddbgReadSerialFlash(u32 offset, void* buffer, size_t size, u64 UniquePadId) { Result rc=0; + Event tmpevent={0}; TransferMemory tmem; size_t sizealign = (size+0x1000) & ~0xfff; @@ -126,12 +143,22 @@ Result hiddbgReadSerialFlash(u32 offset, void* buffer, size_t size, u64 UniquePa rc = tmemCreate(&tmem, sizealign, Perm_Rw); if (R_FAILED(rc)) return rc; - rc = _hiddbgReadSerialFlash(&tmem, offset, size, UniquePadId); + rc = hiddbgAcquireOperationEventHandle(&tmpevent, true, UniquePadId); // *Must* be used before _hiddbgReadSerialFlash. + if (R_SUCCEEDED(rc)) rc = _hiddbgReadSerialFlash(&tmem, offset, size, UniquePadId); + if (R_SUCCEEDED(rc)) rc = eventWait(&tmpevent, U64_MAX); + if (R_SUCCEEDED(rc)) rc = hiddbgGetOperationResult(UniquePadId); if (R_SUCCEEDED(rc)) memcpy(buffer, tmem.src_addr, size); - tmemClose(&g_hiddbgHdlsTmem); + eventClose(&tmpevent); + tmemClose(&tmem); return rc; } +Result hiddbgGetOperationResult(u64 UniquePadId) { + if (hosversionBefore(6,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _hiddbgCmdInU64NoOut(UniquePadId, 231); +} + Result hiddbgGetUniquePadDeviceTypeSetInternal(u64 UniquePadId, u32 *out) { if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);