From 222f7e6fc38fddba9e1f96f631b27e47611d8efd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Thu, 4 Aug 2016 21:15:32 +0200 Subject: [PATCH] WiimoteReal: IOWin: Remove duplicate code The Balance board detection logic is already implemented in a simpler way in Wiimote::IsBalanceBoard() (since hidapi also needs it). Therefore, IOWin now only needs to check if a device is a Wiimote. --- Source/Core/Core/HW/WiimoteReal/IOWin.cpp | 255 +++++++--------------- Source/Core/Core/HW/WiimoteReal/IOWin.h | 4 - 2 files changed, 74 insertions(+), 185 deletions(-) diff --git a/Source/Core/Core/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/HW/WiimoteReal/IOWin.cpp index 74fd866d63..8a0558e1d1 100644 --- a/Source/Core/Core/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/HW/WiimoteReal/IOWin.cpp @@ -344,6 +344,61 @@ static WinWriteMethod GetInitialWriteMethod(bool IsUsingToshibaStack) WWM_WRITE_FILE_ACTUAL_REPORT_SIZE); } +static int WriteToHandle(HANDLE& dev_handle, WinWriteMethod& method, const u8* buf, size_t size) +{ + OVERLAPPED hid_overlap_write = OVERLAPPED(); + hid_overlap_write.hEvent = CreateEvent(nullptr, true, false, nullptr); + + DWORD written = 0; + IOWrite(dev_handle, hid_overlap_write, method, buf, size, &written); + + CloseHandle(hid_overlap_write.hEvent); + + return written; +} + +static int ReadFromHandle(HANDLE& dev_handle, u8* buf) +{ + OVERLAPPED hid_overlap_read = OVERLAPPED(); + hid_overlap_read.hEvent = CreateEvent(nullptr, true, false, nullptr); + const int read = IORead(dev_handle, hid_overlap_read, buf, 1); + CloseHandle(hid_overlap_read.hEvent); + return read; +} + +static bool IsWiimote(const std::basic_string& device_path, WinWriteMethod& method) +{ + HANDLE dev_handle = CreateFile(device_path.c_str(), GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, nullptr); + if (dev_handle == INVALID_HANDLE_VALUE) + return false; + + u8 buf[MAX_PAYLOAD]; + u8 const req_status_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_REQUEST_STATUS, 0}; + int invalid_report_count = 0; + int rc = WriteToHandle(dev_handle, method, req_status_report, sizeof(req_status_report)); + while (rc > 0) + { + rc = ReadFromHandle(dev_handle, buf); + if (rc <= 0) + break; + + switch (buf[1]) + { + case WM_STATUS_REPORT: + return true; + default: + WARN_LOG(WIIMOTE, "IsWiimote(): Received unexpected report %02x", buf[1]); + invalid_report_count++; + // If we receive over 15 invalid reports, then this is probably not a Wiimote. + if (invalid_report_count > 15) + return false; + } + } + return false; +} + // Find and connect Wiimotes. // Does not replace already found Wiimotes even if they are disconnected. // wm is an array of max_wiimotes Wiimotes @@ -389,27 +444,32 @@ void WiimoteScannerWindows::FindWiimotes(std::vector& found_wiimotes, &device_info_data)) { std::basic_string device_path(detail_data->DevicePath); - bool real_wiimote = false; - bool is_bb = false; bool IsUsingToshibaStack = CheckForToshibaStack(device_info_data.DevInst); WinWriteMethod write_method = GetInitialWriteMethod(IsUsingToshibaStack); - CheckDeviceType(device_path, write_method, real_wiimote, is_bb); - - if (real_wiimote) +#ifdef SHARE_WRITE_WIIMOTES { - Wiimote* wm = new WiimoteWindows(device_path, write_method); - - if (is_bb) + std::lock_guard lk(g_connected_wiimotes_lock); + // This device is a Wiimote that is already connected. Skip it. + if (g_connected_wiimotes.count(device_path) != 0) { - found_board = wm; - } - else - { - found_wiimotes.push_back(wm); + free(detail_data); + continue; } } +#endif + if (!IsWiimote(device_path, write_method)) + { + free(detail_data); + continue; + } + + auto* wiimote = new WiimoteWindows(device_path, write_method); + if (wiimote->IsBalanceBoard()) + found_board = wiimote; + else + found_wiimotes.push_back(wiimote); } free(detail_data); @@ -418,173 +478,6 @@ void WiimoteScannerWindows::FindWiimotes(std::vector& found_wiimotes, SetupDiDestroyDeviceInfoList(device_info); } -int CheckDeviceType_Write(HANDLE& dev_handle, WinWriteMethod& write_method, const u8* buf, - size_t size, int attempts) -{ - OVERLAPPED hid_overlap_write = OVERLAPPED(); - hid_overlap_write.hEvent = CreateEvent(nullptr, true, false, nullptr); - - DWORD written = 0; - - for (; attempts > 0; --attempts) - { - if (IOWrite(dev_handle, hid_overlap_write, write_method, buf, size, &written)) - break; - } - - CloseHandle(hid_overlap_write.hEvent); - - return written; -} - -int CheckDeviceType_Read(HANDLE& dev_handle, u8* buf, int attempts) -{ - OVERLAPPED hid_overlap_read = OVERLAPPED(); - hid_overlap_read.hEvent = CreateEvent(nullptr, true, false, nullptr); - int read = 0; - for (; attempts > 0; --attempts) - { - read = IORead(dev_handle, hid_overlap_read, buf, 1); - if (read > 0) - break; - } - - CloseHandle(hid_overlap_read.hEvent); - - return read; -} - -// A convoluted way of checking if a device is a Wii Balance Board and if it is a connectible -// Wiimote. -// Because nothing on Windows should be easy. -// (We can't seem to easily identify the Bluetooth device an HID device belongs to...) -void WiimoteScannerWindows::CheckDeviceType(std::basic_string& devicepath, - WinWriteMethod& write_method, bool& real_wiimote, - bool& is_bb) -{ - real_wiimote = false; - is_bb = false; - -#ifdef SHARE_WRITE_WIIMOTES - std::lock_guard lk(g_connected_wiimotes_lock); - if (g_connected_wiimotes.count(devicepath) != 0) - return; -#endif - - HANDLE dev_handle = CreateFile(devicepath.c_str(), GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, nullptr); - if (dev_handle == INVALID_HANDLE_VALUE) - return; - // enable to only check for official nintendo wiimotes/bb's - bool check_vidpid = false; - HIDD_ATTRIBUTES attrib; - attrib.Size = sizeof(attrib); - if (!check_vidpid || (pHidD_GetAttributes(dev_handle, &attrib) && (attrib.VendorID == 0x057e) && - (attrib.ProductID == 0x0306))) - { - // max_cycles insures we are never stuck here due to bad coding... - int max_cycles = 20; - u8 buf[MAX_PAYLOAD] = {0}; - - u8 const req_status_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_REQUEST_STATUS, 0}; - // The new way to initialize the extension is by writing 0x55 to 0x(4)A400F0, then writing 0x00 - // to 0x(4)A400FB - // 52 16 04 A4 00 F0 01 55 - // 52 16 04 A4 00 FB 01 00 - u8 const disable_enc_pt1_report[MAX_PAYLOAD] = { - WM_SET_REPORT | WM_BT_OUTPUT, WM_WRITE_DATA, 0x04, 0xa4, 0x00, 0xf0, 0x01, 0x55}; - u8 const disable_enc_pt2_report[MAX_PAYLOAD] = { - WM_SET_REPORT | WM_BT_OUTPUT, WM_WRITE_DATA, 0x04, 0xa4, 0x00, 0xfb, 0x01, 0x00}; - - CheckDeviceType_Write(dev_handle, write_method, disable_enc_pt1_report, - sizeof(disable_enc_pt1_report), 1); - CheckDeviceType_Write(dev_handle, write_method, disable_enc_pt2_report, - sizeof(disable_enc_pt2_report), 1); - - int rc = CheckDeviceType_Write(dev_handle, write_method, req_status_report, - sizeof(req_status_report), 1); - - while (rc > 0 && --max_cycles > 0) - { - if ((rc = CheckDeviceType_Read(dev_handle, buf, 1)) <= 0) - { - // DEBUG_LOG(WIIMOTE, "CheckDeviceType: Read failed..."); - break; - } - - switch (buf[1]) - { - case WM_STATUS_REPORT: - { - real_wiimote = true; - - // DEBUG_LOG(WIIMOTE, "CheckDeviceType: Got Status Report"); - wm_status_report* wsr = (wm_status_report*)&buf[2]; - if (wsr->extension) - { - // Wiimote with extension, we ask it what kind. - u8 read_ext[MAX_PAYLOAD] = {0}; - read_ext[0] = WM_SET_REPORT | WM_BT_OUTPUT; - read_ext[1] = WM_READ_DATA; - // Extension type register. - *(u32*)&read_ext[2] = Common::swap32(0x4a400fa); - // Size. - *(u16*)&read_ext[6] = Common::swap16(6); - rc = CheckDeviceType_Write(dev_handle, write_method, read_ext, 8, 1); - } - else - { - // Normal Wiimote, exit while and be happy. - rc = -1; - } - break; - } - case WM_ACK_DATA: - { - real_wiimote = true; - // wm_acknowledge * wm = (wm_acknowledge*)&buf[2]; - // DEBUG_LOG(WIIMOTE, "CheckDeviceType: Got Ack Error: %X ReportID: %X", wm->errorID, - // wm->reportID); - break; - } - case WM_READ_DATA_REPLY: - { - // DEBUG_LOG(WIIMOTE, "CheckDeviceType: Got Data Reply"); - wm_read_data_reply* wrdr = (wm_read_data_reply*)&buf[2]; - // Check if it has returned what we asked. - if (Common::swap16(wrdr->address) == 0x00fa) - { - real_wiimote = true; - // 0x020420A40000ULL means balance board. - u64 ext_type = (*(u64*)&wrdr->data[0]); - // DEBUG_LOG(WIIMOTE, - // "CheckDeviceType: GOT EXT TYPE %llX", - // ext_type); - is_bb = (ext_type == 0x020420A40000ULL); - } - else - { - ERROR_LOG(WIIMOTE, "CheckDeviceType: GOT UNREQUESTED ADDRESS %X", - Common::swap16(wrdr->address)); - } - // force end - rc = -1; - - break; - } - default: - { - // We let read try again incase there is another packet waiting. - // DEBUG_LOG(WIIMOTE, "CheckDeviceType: GOT UNKNOWN REPLY: %X", buf[1]); - break; - } - } - } - } - CloseHandle(dev_handle); -} - bool WiimoteScannerWindows::IsReady() const { if (!s_loaded_ok) @@ -615,7 +508,7 @@ bool WiimoteScannerWindows::IsReady() const bool WiimoteWindows::ConnectInternal() { if (IsConnected()) - return false; + return true; #ifdef SHARE_WRITE_WIIMOTES std::lock_guard lk(g_connected_wiimotes_lock); diff --git a/Source/Core/Core/HW/WiimoteReal/IOWin.h b/Source/Core/Core/HW/WiimoteReal/IOWin.h index b3561c7f0c..ceda5085ad 100644 --- a/Source/Core/Core/HW/WiimoteReal/IOWin.h +++ b/Source/Core/Core/HW/WiimoteReal/IOWin.h @@ -50,10 +50,6 @@ public: bool IsReady() const override; void FindWiimotes(std::vector&, Wiimote*&) override; void Update() override; - -private: - void CheckDeviceType(std::basic_string& devicepath, WinWriteMethod& write_method, - bool& real_wiimote, bool& is_bb); }; }