| 97 | } |
| 98 | |
| 99 | void UsbInterfaceChangeThreadFunc(void* arg) |
| 100 | { |
| 101 | do |
| 102 | { |
| 103 | if (R_SUCCEEDED(eventWait(usbHsGetInterfaceStateChangeEvent(), UINT64_MAX))) |
| 104 | { |
| 105 | s32 total_entries; |
| 106 | WriteToLog("Interface state was changed"); |
| 107 | |
| 108 | SwitchUtils::ScopedLock usbLock(usbMutex); |
| 109 | SwitchUtils::ScopedLock controllersLock(controllers::GetScopedLock()); |
| 110 | |
| 111 | eventClear(usbHsGetInterfaceStateChangeEvent()); |
| 112 | memset(interfaces, 0, sizeof(interfaces)); |
| 113 | if (R_SUCCEEDED(usbHsQueryAcquiredInterfaces(interfaces, sizeof(interfaces), &total_entries))) |
| 114 | { |
| 115 | for (auto it = controllers::Get().begin(); it != controllers::Get().end(); ++it) |
| 116 | { |
| 117 | bool found_flag = false; |
| 118 | |
| 119 | for (auto&& ptr : (*it)->GetController()->GetDevice()->GetInterfaces()) |
| 120 | { |
| 121 | // We check if a device was removed by comparing the controller's interfaces and the currently acquired interfaces |
| 122 | // If we didn't find a single matching interface ID, we consider a controller removed |
| 123 | for (int i = 0; i != total_entries; ++i) |
| 124 | { |
| 125 | if (interfaces[i].inf.ID == static_cast<SwitchUSBInterface*>(ptr.get())->GetID()) |
| 126 | { |
| 127 | found_flag = true; |
| 128 | break; |
| 129 | } |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | if (!found_flag) |
| 134 | { |
| 135 | WriteToLog("Erasing controller"); |
| 136 | controllers::Get().erase(it--); |
| 137 | WriteToLog("Controller erased!"); |
| 138 | } |
| 139 | } |
| 140 | } |
| 141 | } |
| 142 | } while (is_usb_interface_change_thread_running); |
| 143 | } |
| 144 | |
| 145 | s32 QueryInterfaces(u8 iclass, u8 isubclass, u8 iprotocol) |
| 146 | { |
nothing calls this directly
no test coverage detected