fix freeze if the usb menu is closed whilst a usb cable is not connected, 0.9.0 -> 0.9.1
This commit is contained in:
@@ -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}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
Reference in New Issue
Block a user