1 Commits
0.9.0 ... 0.9.1

Author SHA1 Message Date
ITotalJustice
365ae2d0cb fix freeze if the usb menu is closed whilst a usb cable is not connected, 0.9.0 -> 0.9.1 2025-05-03 21:15:21 +01:00
4 changed files with 50 additions and 5 deletions

View File

@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.13)
set(sphaira_VERSION 0.9.0)
set(sphaira_VERSION 0.9.1)
project(sphaira
VERSION ${sphaira_VERSION}

View File

@@ -19,6 +19,7 @@ struct Usb final : Base {
Result_BadCount = MAKERESULT(USBModule, 2),
Result_BadTransferSize = MAKERESULT(USBModule, 3),
Result_BadTotalSize = MAKERESULT(USBModule, 4),
Result_Cancelled = MAKERESULT(USBModule, 11),
};
Usb(u64 transfer_timeout);
@@ -28,7 +29,7 @@ struct Usb final : Base {
Result Finished();
Result Init();
Result IsUsbConnected(u64 timeout) const;
Result IsUsbConnected(u64 timeout);
Result WaitForConnection(u64 timeout, std::vector<std::string>& out_names);
void SetFileNameForTranfser(const std::string& name);

View File

@@ -22,6 +22,9 @@ void thread_func(void* user) {
}
const auto rc = app->m_usb_source->IsUsbConnected(CONNECTION_TIMEOUT);
if (rc == app->m_usb_source->Result_Cancelled) {
break;
}
// set connected status
mutexLock(&app->m_mutex);

View File

@@ -224,8 +224,49 @@ Result Usb::Init() {
R_SUCCEED();
}
Result Usb::IsUsbConnected(u64 timeout) const {
return usbDsWaitReady(timeout);
// the blow code is taken from libnx, with the addition of a uevent to cancel.
Result Usb::IsUsbConnected(u64 timeout) {
Result rc;
UsbState state = UsbState_Detached;
rc = usbDsGetState(&state);
if (R_FAILED(rc)) return rc;
if (state == UsbState_Configured) return 0;
bool has_timeout = timeout != UINT64_MAX;
u64 deadline = 0;
const std::array waiters{
waiterForEvent(usbDsGetStateChangeEvent()),
waiterForUEvent(GetCancelEvent()),
};
if (has_timeout)
deadline = armGetSystemTick() + armNsToTicks(timeout);
do {
if (has_timeout) {
s64 remaining = deadline - armGetSystemTick();
timeout = remaining > 0 ? armTicksToNs(remaining) : 0;
}
s32 idx;
rc = waitObjects(&idx, waiters.data(), waiters.size(), timeout);
eventClear(usbDsGetStateChangeEvent());
// check if we got one of the cancel events.
if (R_SUCCEEDED(rc) && idx != 0) {
rc = Result_Cancelled; // cancelled.
break;
}
rc = usbDsGetState(&state);
} while (R_SUCCEEDED(rc) && state != UsbState_Configured && timeout > 0);
if (R_SUCCEEDED(rc) && state != UsbState_Configured && timeout == 0)
return KERNELRESULT(TimedOut);
return rc;
}
Result Usb::WaitForConnection(u64 timeout, std::vector<std::string>& out_names) {
@@ -276,7 +317,7 @@ Result Usb::WaitTransferCompletion(UsbSessionEndpoint ep, u64 timeout) {
// check if we got one of the cancel events.
if (R_SUCCEEDED(rc) && idx != 0) {
log_write("got usb cancel event\n");
rc = 0xEC01; // cancelled.
rc = Result_Cancelled; // cancelled.
}
if (R_FAILED(rc)) {