hid_service_win.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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 <windows.h> 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <hidclass.h> 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)extern "C" { 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <hidsdi.h> 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <hidpi.h> 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <setupapi.h> 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <winioctl.h> 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/win/scoped_handle.h" 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif // defined(OS_WIN) 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Setup API is required to enumerate HID devices. 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#pragma comment(lib, "setupapi.lib") 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#pragma comment(lib, "hid.lib") 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace device { 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kHIDClass[] = "HIDClass"; 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)HidServiceWin::HidServiceWin() { 48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Enumerate(); 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)HidServiceWin::~HidServiceWin() {} 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void HidServiceWin::Enumerate() { 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BOOL res; 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HDEVINFO device_info_set; 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SP_DEVINFO_DATA devinfo_data; 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SP_DEVICE_INTERFACE_DATA device_interface_data; 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) memset(&devinfo_data, 0, sizeof(SP_DEVINFO_DATA)); 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA); 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_info_set = SetupDiGetClassDevs( 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &GUID_DEVINTERFACE_HID, 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (device_info_set == INVALID_HANDLE_VALUE) 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (int device_index = 0; 73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SetupDiEnumDeviceInterfaces(device_info_set, 74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NULL, 75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &GUID_DEVINTERFACE_HID, 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_index, 77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &device_interface_data); 78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ++device_index) { 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DWORD required_size = 0; 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Determime the required size of detail struct. 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetupDiGetDeviceInterfaceDetailA(device_info_set, 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &device_interface_data, 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 0, 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &required_size, 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL); 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<SP_DEVICE_INTERFACE_DETAIL_DATA_A, base::FreeDeleter> 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_interface_detail_data( 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static_cast<SP_DEVICE_INTERFACE_DETAIL_DATA_A*>( 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) malloc(required_size))); 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_interface_detail_data->cbSize = 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Get the detailed data for this device. 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) res = SetupDiGetDeviceInterfaceDetailA(device_info_set, 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &device_interface_data, 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_interface_detail_data.get(), 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) required_size, 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL); 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!res) 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Enumerate device info. Looking for Setup Class "HIDClass". 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (DWORD i = 0; 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetupDiEnumDeviceInfo(device_info_set, i, &devinfo_data); 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) i++) { 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) char class_name[256] = {0}; 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) res = SetupDiGetDeviceRegistryPropertyA(device_info_set, 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &devinfo_data, 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SPDRP_CLASS, 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (PBYTE) class_name, 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sizeof(class_name) - 1, 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL); 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!res) 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (memcmp(class_name, kHIDClass, sizeof(kHIDClass)) == 0) { 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) char driver_name[256] = {0}; 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Get bounded driver. 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) res = SetupDiGetDeviceRegistryPropertyA(device_info_set, 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &devinfo_data, 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SPDRP_DRIVER, 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (PBYTE) driver_name, 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sizeof(driver_name) - 1, 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL); 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (res) { 131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Found the driver. 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!res) 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PlatformAddDevice(device_interface_detail_data->DevicePath); 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void HidServiceWin::PlatformAddDevice(const std::string& device_path) { 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HidDeviceInfo device_info; 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_info.device_id = device_path; 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Try to open the device. 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::win::ScopedHandle device_handle( 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateFileA(device_path.c_str(), 151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GENERIC_WRITE | GENERIC_READ, 152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FILE_SHARE_READ | FILE_SHARE_WRITE, 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OPEN_EXISTING, 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FILE_FLAG_OVERLAPPED, 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 0)); 157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!device_handle.IsValid() && 159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetLastError() == base::File::FILE_ERROR_ACCESS_DENIED) { 160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::win::ScopedHandle device_handle( 161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateFileA(device_path.c_str(), 162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GENERIC_READ, 163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FILE_SHARE_READ, 164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NULL, 165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) OPEN_EXISTING, 166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FILE_FLAG_OVERLAPPED, 167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 0)); 168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!device_handle.IsValid()) 170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Get VID/PID pair. 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HIDD_ATTRIBUTES attrib = {0}; 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) attrib.Size = sizeof(HIDD_ATTRIBUTES); 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!HidD_GetAttributes(device_handle.Get(), &attrib)) 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_info.vendor_id = attrib.VendorID; 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_info.product_id = attrib.ProductID; 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (ULONG i = 32; 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HidD_SetNumInputBuffers(device_handle.Get(), i); 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) i <<= 1); 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Get usage and usage page (optional). 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PHIDP_PREPARSED_DATA preparsed_data; 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (HidD_GetPreparsedData(device_handle.Get(), &preparsed_data) && 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) preparsed_data) { 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HIDP_CAPS capabilities; 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (HidP_GetCaps(preparsed_data, &capabilities) == HIDP_STATUS_SUCCESS) { 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_info.input_report_size = capabilities.InputReportByteLength; 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_info.output_report_size = capabilities.OutputReportByteLength; 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_info.feature_report_size = capabilities.FeatureReportByteLength; 1955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu device_info.usages.push_back(HidUsageAndPage( 1965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu capabilities.Usage, 1975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu static_cast<HidUsageAndPage::Page>(capabilities.UsagePage))); 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Detect if the device supports report ids. 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (capabilities.NumberInputValueCaps > 0) { 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<HIDP_VALUE_CAPS[]> value_caps( 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new HIDP_VALUE_CAPS[capabilities.NumberInputValueCaps]); 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) USHORT value_caps_length = capabilities.NumberInputValueCaps; 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (HidP_GetValueCaps(HidP_Input, &value_caps[0], &value_caps_length, 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) preparsed_data) == HIDP_STATUS_SUCCESS) { 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_info.has_report_id = (value_caps[0].ReportID != 0); 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 209c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!device_info.has_report_id && capabilities.NumberInputButtonCaps > 0) 210c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch { 211c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch scoped_ptr<HIDP_BUTTON_CAPS[]> button_caps( 212c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch new HIDP_BUTTON_CAPS[capabilities.NumberInputButtonCaps]); 213c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch USHORT button_caps_length = capabilities.NumberInputButtonCaps; 214c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (HidP_GetButtonCaps(HidP_Input, 215c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch &button_caps[0], 216c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch &button_caps_length, 217c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch preparsed_data) == HIDP_STATUS_SUCCESS) { 218c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch device_info.has_report_id = (button_caps[0].ReportID != 0); 219c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 220c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 222010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) HidD_FreePreparsedData(preparsed_data); 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) AddDevice(device_info); 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void HidServiceWin::PlatformRemoveDevice(const std::string& device_path) { 229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RemoveDevice(device_path); 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void HidServiceWin::GetDevices(std::vector<HidDeviceInfo>* devices) { 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Enumerate(); 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HidService::GetDevices(devices); 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)scoped_refptr<HidConnection> HidServiceWin::Connect( 238a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const HidDeviceId& device_id) { 239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) HidDeviceInfo device_info; 240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!GetDeviceInfo(device_id, &device_info)) 241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return NULL; 242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<HidConnectionWin> connection(new HidConnectionWin(device_info)); 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!connection->available()) { 244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PLOG(ERROR) << "Failed to open device."; 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return NULL; 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return connection; 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace device 251