// 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 WiimoteScanner::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(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) { ERROR_LOG(WIIMOTE, "found a device..."); // BT names are a maximum of 248 bytes apparently char name[255] = {}; if (hci_read_remote_name(device_sock, &scan_infos[i].bdaddr, sizeof(name), name, 1000) < 0) { ERROR_LOG(WIIMOTE, "name request failed"); continue; } ERROR_LOG(WIIMOTE, "device name %s", name); if (IsValidBluetoothName(name)) { bool new_wiimote = true; // Determine if this Wiimote has already been found. for (int j = 0; j < MAX_BBMOTES && new_wiimote; ++j) { // compare this address with the stored addresses in our global array // static_cast is OK here, since we're only ever going to have this subclass in g_wiimotes // on Linux (and likewise, only WiimoteWindows on Windows, etc) auto connected_wiimote = static_cast<WiimoteLinux*>(g_wiimotes[j]); if (connected_wiimote && bacmp(&scan_infos[i].bdaddr, &connected_wiimote->Address()) == 0) new_wiimote = false; } if (new_wiimote) { // Found a new device char bdaddr_str[18] = {}; ba2str(&scan_infos[i].bdaddr, bdaddr_str); 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); } } } } }
// Connect to a Wiimote with a known device path. bool WiimoteWindows::ConnectInternal() { if (IsConnected()) return false; #ifdef SHARE_WRITE_WIIMOTES std::lock_guard<std::mutex> lk(g_connected_wiimotes_lock); if (g_connected_wiimotes.count(m_devicepath) != 0) return false; auto const open_flags = FILE_SHARE_READ | FILE_SHARE_WRITE; #else // Having no FILE_SHARE_WRITE disallows us from connecting to the same Wiimote twice. // (And disallows using Wiimotes in use by other programs) // This is what "WiiYourself" does. // Apparently this doesn't work for everyone. It might be their fault. auto const open_flags = FILE_SHARE_READ; #endif 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 = 0; 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"); } */ #ifdef SHARE_WRITE_WIIMOTES g_connected_wiimotes.insert(m_devicepath); #endif return true; }
void ProcessWiimotes(bool new_scan, T& callback) { BLUETOOTH_DEVICE_SEARCH_PARAMS srch; srch.dwSize = sizeof(srch); srch.fReturnAuthenticated = true; srch.fReturnRemembered = true; // Does not filter properly somehow, so we need to do an additional check on // fConnected BT Devices srch.fReturnConnected = true; srch.fReturnUnknown = true; srch.fIssueInquiry = new_scan; // multiple of 1.28 seconds srch.cTimeoutMultiplier = 2; BLUETOOTH_FIND_RADIO_PARAMS radioParam; radioParam.dwSize = sizeof(radioParam); HANDLE hRadio; // TODO: save radio(s) in the WiimoteScanner constructor? // Enumerate BT radios HBLUETOOTH_RADIO_FIND hFindRadio = pBluetoothFindFirstRadio(&radioParam, &hRadio); while (hFindRadio) { BLUETOOTH_RADIO_INFO radioInfo; radioInfo.dwSize = sizeof(radioInfo); auto const rinfo_result = pBluetoothGetRadioInfo(hRadio, &radioInfo); if (ERROR_SUCCESS == rinfo_result) { srch.hRadio = hRadio; BLUETOOTH_DEVICE_INFO btdi; btdi.dwSize = sizeof(btdi); // Enumerate BT devices HBLUETOOTH_DEVICE_FIND hFindDevice = pBluetoothFindFirstDevice(&srch, &btdi); while (hFindDevice) { // btdi.szName is sometimes missing it's content - it's a bt feature.. DEBUG_LOG(WIIMOTE, "Authenticated %i connected %i remembered %i ", btdi.fAuthenticated, btdi.fConnected, btdi.fRemembered); if (IsValidBluetoothName(UTF16ToUTF8(btdi.szName))) { callback(hRadio, radioInfo, btdi); } if (false == pBluetoothFindNextDevice(hFindDevice, &btdi)) { pBluetoothFindDeviceClose(hFindDevice); hFindDevice = nullptr; } } } if (false == pBluetoothFindNextRadio(hFindRadio, &hRadio)) { pBluetoothFindRadioClose(hFindRadio); hFindRadio = nullptr; } } }
void WiimoteScanner::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; // Scan for Bluetooth devices int const found_devices = hci_inquiry(device_id, wait_len, max_infos, nullptr, &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) { ERROR_LOG(WIIMOTE, "found a device..."); // BT names are a maximum of 248 bytes apparently char name[255] = {}; if (hci_read_remote_name(device_sock, &scan_infos[i].bdaddr, sizeof(name), name, 1000) < 0) { ERROR_LOG(WIIMOTE, "name request failed"); continue; } ERROR_LOG(WIIMOTE, "device name %s", name); if (IsValidBluetoothName(name)) { bool new_wiimote = true; // TODO: do this // Determine if this Wiimote has already been found. // for (int j = 0; j < MAX_WIIMOTES && new_wiimote; ++j) //{ // if (wm[j] && bacmp(&scan_infos[i].bdaddr,&wm[j]->bdaddr) == 0) // new_wiimote = false; //} if (new_wiimote) { // Found a new device char bdaddr_str[18] = {}; ba2str(&scan_infos[i].bdaddr, bdaddr_str); 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); } } } } }