void WiimoteScannerHidapi::FindWiimotes(std::vector<Wiimote*>& wiimotes, Wiimote*& board) { hid_device_info* list = hid_enumerate(0x0, 0x0); for (hid_device_info* device = list; device; device = device->next) { const std::string name = device->product_string ? UTF16ToUTF8(device->product_string) : ""; const bool is_wiimote = IsValidDeviceName(name) || (device->vendor_id == 0x057e && (device->product_id == 0x0306 || device->product_id == 0x0330)); if (!is_wiimote || !IsNewWiimote(device->path) || !IsDeviceUsable(device->path)) continue; auto* wiimote = new WiimoteHidapi(device->path); const bool is_balance_board = IsBalanceBoardName(name) || wiimote->IsBalanceBoard(); if (is_balance_board) board = wiimote; else wiimotes.push_back(wiimote); NOTICE_LOG(WIIMOTE, "Found %s at %s: %ls %ls (%04hx:%04hx)", is_balance_board ? "balance board" : "Wiimote", device->path, device->manufacturer_string, device->product_string, device->vendor_id, device->product_id); } hid_free_enumeration(list); }
// Connect to a Wiimote with a known device path. bool WiimoteWindows::ConnectInternal() { if (IsConnected()) return true; if (!IsNewWiimote(UTF16ToUTF8(m_devicepath))) return false; auto const open_flags = FILE_SHARE_READ | FILE_SHARE_WRITE; m_dev_handle = CreateFile(m_devicepath.c_str(), GENERIC_READ | GENERIC_WRITE, open_flags, nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr); if (m_dev_handle == INVALID_HANDLE_VALUE) { m_dev_handle = nullptr; return false; } #if 0 TCHAR name[128] = {}; pHidD_GetProductString(dev_handle, name, 128); //ERROR_LOG(WIIMOTE, "Product string: %s", TStrToUTF8(name).c_str()); if (!IsValidBluetoothName(TStrToUTF8(name))) { CloseHandle(dev_handle); dev_handle = 0; return false; } #endif #if 0 HIDD_ATTRIBUTES attr; attr.Size = sizeof(attr); if (!pHidD_GetAttributes(dev_handle, &attr)) { CloseHandle(dev_handle); dev_handle = 0; return false; } #endif // TODO: thread isn't started here now, do this elsewhere // This isn't as drastic as it sounds, since the process in which the threads // reside is normal priority. Needed for keeping audio reports at a decent rate /* if (!SetThreadPriority(m_wiimote_thread.native_handle(), THREAD_PRIORITY_TIME_CRITICAL)) { ERROR_LOG(WIIMOTE, "Failed to set Wiimote thread priority"); } */ return true; }
void WiimoteScannerLinux::FindWiimotes(std::vector<Wiimote*>& found_wiimotes, Wiimote*& found_board) { // supposedly 1.28 seconds int const wait_len = 1; int const max_infos = 255; inquiry_info scan_infos[max_infos] = {}; auto* scan_infos_ptr = scan_infos; found_board = nullptr; // Use Limited Dedicated Inquiry Access Code (LIAC) to query, since third-party Wiimotes // cannot be discovered without it. const u8 lap[3] = {0x00, 0x8b, 0x9e}; // Scan for Bluetooth devices int const found_devices = hci_inquiry(m_device_id, wait_len, max_infos, lap, &scan_infos_ptr, IREQ_CACHE_FLUSH); if (found_devices < 0) { ERROR_LOG(WIIMOTE, "Error searching for Bluetooth devices."); return; } DEBUG_LOG(WIIMOTE, "Found %i Bluetooth device(s).", found_devices); // Display discovered devices for (int i = 0; i < found_devices; ++i) { NOTICE_LOG(WIIMOTE, "found a device..."); // BT names are a maximum of 248 bytes apparently char name[255] = {}; if (hci_read_remote_name(m_device_sock, &scan_infos[i].bdaddr, sizeof(name), name, 1000) < 0) { ERROR_LOG(WIIMOTE, "name request failed"); continue; } NOTICE_LOG(WIIMOTE, "device name %s", name); if (!IsValidDeviceName(name)) continue; char bdaddr_str[18] = {}; ba2str(&scan_infos[i].bdaddr, bdaddr_str); if (!IsNewWiimote(bdaddr_str)) continue; // Found a new device Wiimote* wm = new WiimoteLinux(scan_infos[i].bdaddr); if (IsBalanceBoardName(name)) { found_board = wm; NOTICE_LOG(WIIMOTE, "Found balance board (%s).", bdaddr_str); } else { found_wiimotes.push_back(wm); NOTICE_LOG(WIIMOTE, "Found Wiimote (%s).", bdaddr_str); } } }
// 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); }