hid_service_win.cc revision 03b57e008b61dfcb1fbad3aea950ae0e001748b0
1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "device/hid/hid_service_win.h" 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <cstdlib> 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/files/file.h" 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/stl_util.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/sys_string_conversions.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "device/hid/hid_connection_win.h" 13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "device/hid/hid_device_info.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/base/io_buffer.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_WIN) 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define INITGUID 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <setupapi.h> 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <winioctl.h> 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/win/scoped_handle.h" 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif // defined(OS_WIN) 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Setup API is required to enumerate HID devices. 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#pragma comment(lib, "setupapi.lib") 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#pragma comment(lib, "hid.lib") 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace device { 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kHIDClass[] = "HIDClass"; 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)HidServiceWin::HidServiceWin() { 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Enumerate(); 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)HidServiceWin::~HidServiceWin() {} 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void HidServiceWin::Enumerate() { 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BOOL res; 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HDEVINFO device_info_set; 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SP_DEVINFO_DATA devinfo_data; 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SP_DEVICE_INTERFACE_DATA device_interface_data; 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) memset(&devinfo_data, 0, sizeof(SP_DEVINFO_DATA)); 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA); 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_info_set = SetupDiGetClassDevs( 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &GUID_DEVINTERFACE_HID, 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::set<std::string> connected_devices; 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (device_info_set != INVALID_HANDLE_VALUE) { 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (int device_index = 0; 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SetupDiEnumDeviceInterfaces(device_info_set, 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &GUID_DEVINTERFACE_HID, 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) device_index, 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &device_interface_data); 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ++device_index) { 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DWORD required_size = 0; 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Determime the required size of detail struct. 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SetupDiGetDeviceInterfaceDetailA(device_info_set, 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &device_interface_data, 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NULL, 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 0, 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &required_size, 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NULL); 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<SP_DEVICE_INTERFACE_DETAIL_DATA_A, base::FreeDeleter> 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) device_interface_detail_data( 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) static_cast<SP_DEVICE_INTERFACE_DETAIL_DATA_A*>( 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) malloc(required_size))); 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) device_interface_detail_data->cbSize = 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Get the detailed data for this device. 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) res = SetupDiGetDeviceInterfaceDetailA(device_info_set, 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &device_interface_data, 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) device_interface_detail_data.get(), 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) required_size, 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NULL, 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NULL); 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!res) 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) continue; 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Enumerate device info. Looking for Setup Class "HIDClass". 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (DWORD i = 0; 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SetupDiEnumDeviceInfo(device_info_set, i, &devinfo_data); 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) i++) { 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) char class_name[256] = {0}; 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) res = SetupDiGetDeviceRegistryPropertyA(device_info_set, 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &devinfo_data, 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SPDRP_CLASS, 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) (PBYTE) class_name, 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sizeof(class_name) - 1, 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL); 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!res) 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (memcmp(class_name, kHIDClass, sizeof(kHIDClass)) == 0) { 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) char driver_name[256] = {0}; 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Get bounded driver. 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) res = SetupDiGetDeviceRegistryPropertyA(device_info_set, 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &devinfo_data, 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SPDRP_DRIVER, 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NULL, 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) (PBYTE) driver_name, 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sizeof(driver_name) - 1, 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NULL); 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (res) { 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Found the driver. 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!res) 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) continue; 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PlatformAddDevice(device_interface_detail_data->DevicePath); 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) connected_devices.insert(device_interface_detail_data->DevicePath); 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Find disconnected devices. 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const DeviceMap& devices = GetDevicesNoEnumerate(); 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::vector<std::string> disconnected_devices; 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (DeviceMap::const_iterator it = devices.begin(); 1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) it != devices.end(); 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ++it) { 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!ContainsKey(connected_devices, it->first)) { 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) disconnected_devices.push_back(it->first); 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Remove disconnected devices. 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (size_t i = 0; i < disconnected_devices.size(); ++i) { 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PlatformRemoveDevice(disconnected_devices[i]); 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 15203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void HidServiceWin::CollectInfoFromButtonCaps( 15303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) PHIDP_PREPARSED_DATA preparsed_data, 15403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) HIDP_REPORT_TYPE report_type, 15503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) USHORT button_caps_length, 15603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) HidCollectionInfo* collection_info) { 15703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (button_caps_length > 0) { 15803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_ptr<HIDP_BUTTON_CAPS[]> button_caps( 15903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) new HIDP_BUTTON_CAPS[button_caps_length]); 16003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (HidP_GetButtonCaps(report_type, 16103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) &button_caps[0], 16203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) &button_caps_length, 16303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) preparsed_data) == HIDP_STATUS_SUCCESS) { 16403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) for (size_t i = 0; i < button_caps_length; i++) { 16503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int report_id = button_caps[i].ReportID; 16603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (report_id != 0) { 16703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) collection_info->report_ids.insert(report_id); 16803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 16903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 17003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 17103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 17203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 17303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 17403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void HidServiceWin::CollectInfoFromValueCaps( 17503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) PHIDP_PREPARSED_DATA preparsed_data, 17603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) HIDP_REPORT_TYPE report_type, 17703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) USHORT value_caps_length, 17803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) HidCollectionInfo* collection_info) { 17903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (value_caps_length > 0) { 18003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_ptr<HIDP_VALUE_CAPS[]> value_caps( 18103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) new HIDP_VALUE_CAPS[value_caps_length]); 18203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (HidP_GetValueCaps( 18303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) report_type, &value_caps[0], &value_caps_length, preparsed_data) == 18403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) HIDP_STATUS_SUCCESS) { 18503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) for (size_t i = 0; i < value_caps_length; i++) { 18603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int report_id = value_caps[i].ReportID; 18703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (report_id != 0) { 18803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) collection_info->report_ids.insert(report_id); 18903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 19003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 19103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 19203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 19303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 19403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void HidServiceWin::PlatformAddDevice(const std::string& device_path) { 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HidDeviceInfo device_info; 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_info.device_id = device_path; 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Try to open the device. 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::win::ScopedHandle device_handle( 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateFileA(device_path.c_str(), 202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GENERIC_WRITE | GENERIC_READ, 203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FILE_SHARE_READ | FILE_SHARE_WRITE, 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OPEN_EXISTING, 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FILE_FLAG_OVERLAPPED, 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 0)); 208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!device_handle.IsValid() && 210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetLastError() == base::File::FILE_ERROR_ACCESS_DENIED) { 211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::win::ScopedHandle device_handle( 212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateFileA(device_path.c_str(), 213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GENERIC_READ, 214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FILE_SHARE_READ, 215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NULL, 216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) OPEN_EXISTING, 217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FILE_FLAG_OVERLAPPED, 218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 0)); 219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!device_handle.IsValid()) 221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Get VID/PID pair. 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HIDD_ATTRIBUTES attrib = {0}; 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) attrib.Size = sizeof(HIDD_ATTRIBUTES); 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!HidD_GetAttributes(device_handle.Get(), &attrib)) 2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_info.vendor_id = attrib.VendorID; 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_info.product_id = attrib.ProductID; 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (ULONG i = 32; 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HidD_SetNumInputBuffers(device_handle.Get(), i); 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) i <<= 1); 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Get usage and usage page (optional). 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PHIDP_PREPARSED_DATA preparsed_data; 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (HidD_GetPreparsedData(device_handle.Get(), &preparsed_data) && 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) preparsed_data) { 241116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch HIDP_CAPS capabilities = {0}; 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (HidP_GetCaps(preparsed_data, &capabilities) == HIDP_STATUS_SUCCESS) { 243116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch device_info.max_input_report_size = capabilities.InputReportByteLength; 244116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch device_info.max_output_report_size = capabilities.OutputReportByteLength; 245116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch device_info.max_feature_report_size = 246116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch capabilities.FeatureReportByteLength; 247116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch HidCollectionInfo collection_info; 248116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch collection_info.usage = HidUsageAndPage( 249116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch capabilities.Usage, 250116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch static_cast<HidUsageAndPage::Page>(capabilities.UsagePage)); 25103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) CollectInfoFromButtonCaps(preparsed_data, 25203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) HidP_Input, 25303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) capabilities.NumberInputButtonCaps, 25403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) &collection_info); 25503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) CollectInfoFromButtonCaps(preparsed_data, 25603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) HidP_Output, 25703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) capabilities.NumberOutputButtonCaps, 25803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) &collection_info); 25903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) CollectInfoFromButtonCaps(preparsed_data, 26003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) HidP_Feature, 26103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) capabilities.NumberFeatureButtonCaps, 26203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) &collection_info); 26303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) CollectInfoFromValueCaps(preparsed_data, 26403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) HidP_Input, 26503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) capabilities.NumberInputValueCaps, 26603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) &collection_info); 26703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) CollectInfoFromValueCaps(preparsed_data, 26803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) HidP_Output, 26903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) capabilities.NumberOutputValueCaps, 27003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) &collection_info); 27103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) CollectInfoFromValueCaps(preparsed_data, 27203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) HidP_Feature, 27303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) capabilities.NumberFeatureValueCaps, 27403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) &collection_info); 27503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!collection_info.report_ids.empty()) { 27603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) device_info.has_report_id = true; 277116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 278116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch device_info.collections.push_back(collection_info); 279c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 28003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Whether or not the device includes report IDs in its reports the size 28103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // of the report ID is included in the value provided by Windows. This 28203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // appears contrary to the MSDN documentation. 28303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (device_info.max_input_report_size > 0) { 2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) device_info.max_input_report_size--; 2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 28603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (device_info.max_output_report_size > 0) { 2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) device_info.max_output_report_size--; 2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 28903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (device_info.max_feature_report_size > 0) { 2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) device_info.max_feature_report_size--; 2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 292010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) HidD_FreePreparsedData(preparsed_data); 2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) AddDevice(device_info); 2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void HidServiceWin::PlatformRemoveDevice(const std::string& device_path) { 299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RemoveDevice(device_path); 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void HidServiceWin::GetDevices(std::vector<HidDeviceInfo>* devices) { 3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Enumerate(); 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HidService::GetDevices(devices); 3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)scoped_refptr<HidConnection> HidServiceWin::Connect( 308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const HidDeviceId& device_id) { 309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) HidDeviceInfo device_info; 310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!GetDeviceInfo(device_id, &device_info)) 311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return NULL; 312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<HidConnectionWin> connection(new HidConnectionWin(device_info)); 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!connection->available()) { 314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PLOG(ERROR) << "Failed to open device."; 3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return NULL; 3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return connection; 3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace device 321