Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / device / hid / hid_service_win.cc
blob42c9a3a86d6d99f1fc0b6767295d666a6939be17
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "device/hid/hid_service_win.h"
7 #include <cstdlib>
9 #include "base/stl_util.h"
10 #include "base/strings/sys_string_conversions.h"
11 #include "device/hid/hid_connection_win.h"
12 #include "device/hid/hid_device_info.h"
13 #include "net/base/io_buffer.h"
15 #if defined(OS_WIN)
17 #define INITGUID
19 #include <windows.h>
20 #include <hidclass.h>
22 extern "C" {
24 #include <hidsdi.h>
25 #include <hidpi.h>
29 #include <setupapi.h>
30 #include <winioctl.h>
31 #include "base/win/scoped_handle.h"
33 #endif // defined(OS_WIN)
35 // Setup API is required to enumerate HID devices.
36 #pragma comment(lib, "setupapi.lib")
37 #pragma comment(lib, "hid.lib")
39 namespace device {
40 namespace {
42 const char kHIDClass[] = "HIDClass";
44 } // namespace
46 HidServiceWin::HidServiceWin() {
47 Enumerate();
50 HidServiceWin::~HidServiceWin() {}
52 void HidServiceWin::Enumerate() {
53 BOOL res;
54 HDEVINFO device_info_set;
55 SP_DEVINFO_DATA devinfo_data;
56 SP_DEVICE_INTERFACE_DATA device_interface_data;
58 memset(&devinfo_data, 0, sizeof(SP_DEVINFO_DATA));
59 devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA);
60 device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
62 device_info_set = SetupDiGetClassDevs(
63 &GUID_DEVINTERFACE_HID,
64 NULL,
65 NULL,
66 DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
68 if (device_info_set == INVALID_HANDLE_VALUE)
69 return;
71 for (int device_index = 0;
72 SetupDiEnumDeviceInterfaces(device_info_set,
73 NULL,
74 &GUID_DEVINTERFACE_HID,
75 device_index,
76 &device_interface_data);
77 ++device_index) {
78 DWORD required_size = 0;
80 // Determime the required size of detail struct.
81 SetupDiGetDeviceInterfaceDetailA(device_info_set,
82 &device_interface_data,
83 NULL,
85 &required_size,
86 NULL);
88 scoped_ptr<SP_DEVICE_INTERFACE_DETAIL_DATA_A, base::FreeDeleter>
89 device_interface_detail_data(
90 static_cast<SP_DEVICE_INTERFACE_DETAIL_DATA_A*>(
91 malloc(required_size)));
92 device_interface_detail_data->cbSize =
93 sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
95 // Get the detailed data for this device.
96 res = SetupDiGetDeviceInterfaceDetailA(device_info_set,
97 &device_interface_data,
98 device_interface_detail_data.get(),
99 required_size,
100 NULL,
101 NULL);
102 if (!res)
103 continue;
105 // Enumerate device info. Looking for Setup Class "HIDClass".
106 for (DWORD i = 0;
107 SetupDiEnumDeviceInfo(device_info_set, i, &devinfo_data);
108 i++) {
109 char class_name[256] = {0};
110 res = SetupDiGetDeviceRegistryPropertyA(device_info_set,
111 &devinfo_data,
112 SPDRP_CLASS,
113 NULL,
114 (PBYTE) class_name,
115 sizeof(class_name) - 1,
116 NULL);
117 if (!res)
118 break;
119 if (memcmp(class_name, kHIDClass, sizeof(kHIDClass)) == 0) {
120 char driver_name[256] = {0};
121 // Get bounded driver.
122 res = SetupDiGetDeviceRegistryPropertyA(device_info_set,
123 &devinfo_data,
124 SPDRP_DRIVER,
125 NULL,
126 (PBYTE) driver_name,
127 sizeof(driver_name) - 1,
128 NULL);
129 if (res) {
130 // Found the driver.
131 break;
136 if (!res)
137 continue;
139 PlatformAddDevice(device_interface_detail_data->DevicePath);
143 void HidServiceWin::PlatformAddDevice(const std::string& device_path) {
144 HidDeviceInfo device_info;
145 device_info.device_id = device_path;
147 // Try to open the device.
148 base::win::ScopedHandle device_handle(
149 CreateFileA(device_path.c_str(),
151 FILE_SHARE_READ,
152 NULL,
153 OPEN_EXISTING,
154 FILE_FLAG_OVERLAPPED,
155 0));
156 if (!device_handle.IsValid())
157 return;
159 // Get VID/PID pair.
160 HIDD_ATTRIBUTES attrib = {0};
161 attrib.Size = sizeof(HIDD_ATTRIBUTES);
162 if (!HidD_GetAttributes(device_handle.Get(), &attrib))
163 return;
165 device_info.vendor_id = attrib.VendorID;
166 device_info.product_id = attrib.ProductID;
168 for (ULONG i = 32;
169 HidD_SetNumInputBuffers(device_handle.Get(), i);
170 i <<= 1);
172 // Get usage and usage page (optional).
173 PHIDP_PREPARSED_DATA preparsed_data;
174 if (HidD_GetPreparsedData(device_handle.Get(), &preparsed_data) &&
175 preparsed_data) {
176 HIDP_CAPS capabilities;
177 if (HidP_GetCaps(preparsed_data, &capabilities) == HIDP_STATUS_SUCCESS) {
178 device_info.input_report_size = capabilities.InputReportByteLength;
179 device_info.output_report_size = capabilities.OutputReportByteLength;
180 device_info.feature_report_size = capabilities.FeatureReportByteLength;
181 device_info.usages.push_back(HidUsageAndPage(
182 capabilities.Usage,
183 static_cast<HidUsageAndPage::Page>(capabilities.UsagePage)));
185 // Detect if the device supports report ids.
186 if (capabilities.NumberInputValueCaps > 0) {
187 scoped_ptr<HIDP_VALUE_CAPS[]> value_caps(
188 new HIDP_VALUE_CAPS[capabilities.NumberInputValueCaps]);
189 USHORT value_caps_length = capabilities.NumberInputValueCaps;
190 if (HidP_GetValueCaps(HidP_Input, &value_caps[0], &value_caps_length,
191 preparsed_data) == HIDP_STATUS_SUCCESS) {
192 device_info.has_report_id = (value_caps[0].ReportID != 0);
195 if (!device_info.has_report_id && capabilities.NumberInputButtonCaps > 0)
197 scoped_ptr<HIDP_BUTTON_CAPS[]> button_caps(
198 new HIDP_BUTTON_CAPS[capabilities.NumberInputButtonCaps]);
199 USHORT button_caps_length = capabilities.NumberInputButtonCaps;
200 if (HidP_GetButtonCaps(HidP_Input,
201 &button_caps[0],
202 &button_caps_length,
203 preparsed_data) == HIDP_STATUS_SUCCESS) {
204 device_info.has_report_id = (button_caps[0].ReportID != 0);
208 HidD_FreePreparsedData(preparsed_data);
211 AddDevice(device_info);
214 void HidServiceWin::PlatformRemoveDevice(const std::string& device_path) {
215 RemoveDevice(device_path);
218 void HidServiceWin::GetDevices(std::vector<HidDeviceInfo>* devices) {
219 Enumerate();
220 HidService::GetDevices(devices);
223 scoped_refptr<HidConnection> HidServiceWin::Connect(
224 const HidDeviceId& device_id) {
225 HidDeviceInfo device_info;
226 if (!GetDeviceInfo(device_id, &device_info))
227 return NULL;
228 scoped_refptr<HidConnectionWin> connection(new HidConnectionWin(device_info));
229 if (!connection->available()) {
230 LOG_GETLASTERROR(ERROR) << "Failed to open device.";
231 return NULL;
233 return connection;
236 } // namespace device