// Find and connect Wiimotes. // Does not replace already found Wiimotes even if they are disconnected. // wm is an array of max_wiimotes Wiimotes // Returns the total number of found and connected Wiimotes. void WiimoteScanner::FindWiimotes(std::vector<Wiimote*> & found_wiimotes, Wiimote* & found_board) { if (!s_loaded_ok) return; ProcessWiimotes(true, [](HANDLE hRadio, const BLUETOOTH_RADIO_INFO& rinfo, BLUETOOTH_DEVICE_INFO_STRUCT& btdi) { ForgetWiimote(btdi); AttachWiimote(hRadio, rinfo, btdi); }); // Get the device id GUID device_id; pHidD_GetHidGuid(&device_id); // Get all hid devices connected HDEVINFO const device_info = SetupDiGetClassDevs(&device_id, nullptr, nullptr, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT)); SP_DEVICE_INTERFACE_DATA device_data; device_data.cbSize = sizeof(device_data); PSP_DEVICE_INTERFACE_DETAIL_DATA detail_data = nullptr; for (int index = 0; SetupDiEnumDeviceInterfaces(device_info, nullptr, &device_id, index, &device_data); ++index) { // Get the size of the data block required DWORD len; SetupDiGetDeviceInterfaceDetail(device_info, &device_data, nullptr, 0, &len, nullptr); detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(len); detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); // Query the data for this device if (SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, nullptr, nullptr)) { std::basic_string<TCHAR> device_path(detail_data->DevicePath); Wiimote* wm = new WiimoteWindows(device_path); bool real_wiimote = false, is_bb = false; CheckDeviceType(device_path, real_wiimote, is_bb); if (is_bb) { found_board = wm; } else if (real_wiimote) { found_wiimotes.push_back(wm); } else { delete wm; } } free(detail_data); } SetupDiDestroyDeviceInfoList(device_info); // Don't mind me, just a random sleep to fix stuff on Windows //if (!wiimotes.empty()) // SLEEP(2000); }
// Find and connect Wiimotes. // Does not replace already found Wiimotes even if they are disconnected. // wm is an array of max_wiimotes Wiimotes // Returns the total number of found and connected Wiimotes. void WiimoteScannerWindows::FindWiimotes(std::vector<Wiimote*>& found_wiimotes, Wiimote*& found_board) { if (!s_loaded_ok) return; ProcessWiimotes(true, [](HANDLE hRadio, const BLUETOOTH_RADIO_INFO& rinfo, BLUETOOTH_DEVICE_INFO_STRUCT& btdi) { ForgetWiimote(btdi); AttachWiimote(hRadio, rinfo, btdi); }); // Get the device id GUID device_id; pHidD_GetHidGuid(&device_id); // Get all hid devices connected HDEVINFO const device_info = SetupDiGetClassDevs(&device_id, nullptr, nullptr, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT)); SP_DEVICE_INTERFACE_DATA device_data = {}; device_data.cbSize = sizeof(device_data); PSP_DEVICE_INTERFACE_DETAIL_DATA detail_data = nullptr; for (int index = 0; SetupDiEnumDeviceInterfaces(device_info, nullptr, &device_id, index, &device_data); ++index) { // Get the size of the data block required DWORD len; SetupDiGetDeviceInterfaceDetail(device_info, &device_data, nullptr, 0, &len, nullptr); detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(len); detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); SP_DEVINFO_DATA device_info_data = {}; device_info_data.cbSize = sizeof(SP_DEVINFO_DATA); // Query the data for this device if (SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, nullptr, &device_info_data)) { std::basic_string<TCHAR> device_path(detail_data->DevicePath); bool IsUsingToshibaStack = CheckForToshibaStack(device_info_data.DevInst); WinWriteMethod write_method = GetInitialWriteMethod(IsUsingToshibaStack); if (!IsNewWiimote(UTF16ToUTF8(device_path)) || !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); } SetupDiDestroyDeviceInfoList(device_info); }
// PC に接続ずみの「USB 接続赤外線リモコンキット」のデバイスパスを取得 DWORD GetDevicePath(OUT char *pszDevicePath, IN DWORD cchBuf) { // USB IR REMOCON 固有の ID 文字列 char *szIdStr1 = "vid_22ea&pid_001e"; char *szIdStr2 = "mi_03"; int i; char *pszProp; HDEVINFO DeviceInfoTable = NULL; SP_DEVICE_INTERFACE_DATA DeviceIfData; PSP_DEVICE_INTERFACE_DETAIL_DATA pDeviceIfDetailData; SP_DEVINFO_DATA DevInfoData; DWORD InterfaceIndex, dwSize, dwError = ERROR_SUCCESS; HGLOBAL hMem = NULL; BOOL bFound; GUID InterfaceClassGuid; HMODULE hHidDLL; DEF_HidD_GetHidGuid pHidD_GetHidGuid; size_t len; //GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30}; // HIDClass の GUID を取得 hHidDLL = LoadLibrary("hid.dll"); pHidD_GetHidGuid = (DEF_HidD_GetHidGuid)GetProcAddress(hHidDLL, "HidD_GetHidGuid"); pHidD_GetHidGuid(&InterfaceClassGuid); FreeLibrary(hHidDLL); // HIDClass に属するデバイス群の含まれるデバイス情報セットを取得 DeviceInfoTable = SetupDiGetClassDevs(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if(!DeviceInfoTable) { dwError = GetLastError(); goto DONE; } // デバイス情報セットを走査し IR REMOCON デバイスを探す for (InterfaceIndex = 0; InterfaceIndex < 10000000; InterfaceIndex++) { DeviceIfData.cbSize = sizeof(DeviceIfData); if(SetupDiEnumDeviceInterfaces(DeviceInfoTable, NULL, &InterfaceClassGuid, InterfaceIndex, &DeviceIfData)) { dwError = GetLastError(); if (dwError == ERROR_NO_MORE_ITEMS) { goto DONE; } } else { dwError = GetLastError(); goto DONE; } // 現在見ているデバイスの VID, PID の含まれるハードウェア ID 文字列を取得 DevInfoData.cbSize = sizeof(DevInfoData); SetupDiEnumDeviceInfo(DeviceInfoTable, InterfaceIndex, &DevInfoData); SetupDiGetDeviceRegistryProperty(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, NULL, NULL, 0, &dwSize); hMem = GlobalAlloc(0, dwSize); if (!hMem) { dwError = GetLastError(); goto DONE; } SetupDiGetDeviceRegistryProperty(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, NULL, (PBYTE)hMem, dwSize, NULL); pszProp = strdup((char*)hMem); GlobalFree(hMem); hMem = NULL; // 取得したハードウェア ID 文字列に USB IR REMOCON 固有の VID, PID が含まれるか len = strlen(pszProp); for (i = 0; i < (int)len; i++) { pszProp[i] = tolower(pszProp[i]); } bFound = FALSE; if (strstr(pszProp, szIdStr1) != NULL && strstr(pszProp, szIdStr2) != NULL) { bFound = TRUE; } free(pszProp); // USB IR REMOCON 発見 if (bFound) { // USB IR REMOCON のデバイスパスを得る SetupDiGetDeviceInterfaceDetail(DeviceInfoTable, &DeviceIfData, NULL, 0, &dwSize, NULL); hMem = GlobalAlloc(0, dwSize); if (!hMem) { dwError = GetLastError(); goto DONE; } pDeviceIfDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)hMem; pDeviceIfDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); if (SetupDiGetDeviceInterfaceDetail(DeviceInfoTable, &DeviceIfData, pDeviceIfDetailData, dwSize, NULL, NULL)) { if (cchBuf > dwSize - sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA)) { // 成功 strcpy(pszDevicePath, pDeviceIfDetailData->DevicePath); dwError = ERROR_SUCCESS; } else { dwError = ERROR_NOT_ENOUGH_MEMORY; goto DONE; } goto DONE; } else { dwError = GetLastError(); goto DONE; } } } DONE: if (hMem) { GlobalFree(hMem); } if (DeviceInfoTable) { SetupDiDestroyDeviceInfoList(DeviceInfoTable); } return dwError; }