Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(917)

Side by Side Diff: device/hid/hid_service_win.cc

Issue 143883005: HID backend (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@hid-impl-base
Patch Set: Really fix tests for lack of testing hardware; adapt to ancient libudev in the cros distro Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 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.
4
5 #include "device/hid/hid_service_win.h"
6
7 #include <cstdlib>
8 #include <string>
9
10 #include "base/callback_helpers.h"
11 #include "base/lazy_instance.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/stl_util.h"
14 #include "base/strings/sys_string_conversions.h"
15 #include "device/hid/hid_connection.h"
16 #include "device/hid/hid_connection_win.h"
17 #include "device/hid/hid_service.h"
18 #include "net/base/io_buffer.h"
19
20 #if defined(OS_WIN)
21
22 #define INITGUID
23
24 #include <windows.h>
25 #include <hidclass.h>
26
27 extern "C" {
28
29 #include <hidsdi.h>
30 #include <hidpi.h>
31
32 }
33
34 #include <setupapi.h>
35 #include <winioctl.h>
36 #include "base/win/scoped_handle.h"
37
38 #endif // defined(OS_WIN)
39
40 // Setup API is required to enumerate HID devices.
41 #pragma comment(lib, "setupapi.lib")
42 #pragma comment(lib, "hid.lib")
43
44 namespace device {
45 namespace {
46
47 const char kHIDClass[] = "HIDClass";
48
49 } // namespace
50
51 HidServiceWin::HidServiceWin() {
52 initialized_ = Enumerate();
53 }
54 HidServiceWin::~HidServiceWin() {}
55
56 bool HidServiceWin::Enumerate() {
57 BOOL res;
58 HDEVINFO device_info_set;
59 SP_DEVINFO_DATA devinfo_data;
60 SP_DEVICE_INTERFACE_DATA device_interface_data;
61
62 memset(&devinfo_data, 0, sizeof(SP_DEVINFO_DATA));
63 devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA);
64 device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
65
66 device_info_set = SetupDiGetClassDevs(
67 &GUID_DEVINTERFACE_HID,
68 NULL,
69 NULL,
70 DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
71
72 if (device_info_set == INVALID_HANDLE_VALUE)
73 return false;
74
75 for (int device_index = 0;
76 SetupDiEnumDeviceInterfaces(device_info_set,
77 NULL,
78 &GUID_DEVINTERFACE_HID,
79 device_index,
80 &device_interface_data);
81 device_index++) {
82 DWORD required_size = 0;
83
84 // Determime the required size of detail struct.
85 SetupDiGetDeviceInterfaceDetailA(device_info_set,
86 &device_interface_data,
87 NULL,
88 0,
89 &required_size,
90 NULL);
91
92 scoped_ptr_malloc<SP_DEVICE_INTERFACE_DETAIL_DATA_A>
93 device_interface_detail_data(
94 reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA_A*>(
95 malloc(required_size)));
96 device_interface_detail_data->cbSize =
97 sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
98
99 // Get the detailed data for this device.
100 res = SetupDiGetDeviceInterfaceDetailA(device_info_set,
101 &device_interface_data,
102 device_interface_detail_data.get(),
103 required_size,
104 NULL,
105 NULL);
106 if (!res)
107 continue;
108
109 // Enumerate device info. Looking for Setup Class "HIDClass".
110 for (DWORD i = 0;
111 SetupDiEnumDeviceInfo(device_info_set, i, &devinfo_data);
112 i++) {
113 char class_name[256] = {0};
114 res = SetupDiGetDeviceRegistryPropertyA(device_info_set,
115 &devinfo_data,
116 SPDRP_CLASS,
117 NULL,
118 (PBYTE) class_name,
119 sizeof(class_name) - 1,
120 NULL);
121 if (!res)
122 break;
123 if (memcmp(class_name, kHIDClass, sizeof(kHIDClass)) == 0) {
124 char driver_name[256] = {0};
125 // Get bounded driver.
126 res = SetupDiGetDeviceRegistryPropertyA(device_info_set,
127 &devinfo_data,
128 SPDRP_DRIVER,
129 NULL,
130 (PBYTE) driver_name,
131 sizeof(driver_name) - 1,
132 NULL);
133 if (res) {
134 // Found the drive.
135 break;
136 }
137 }
138 }
139
140 if (!res)
141 continue;
142
143 PlatformAddDevice(device_interface_detail_data->DevicePath);
144 }
145
146 return true;
147 }
148
149 void HidServiceWin::PlatformAddDevice(std::string device_path) {
150 HidDeviceInfo device_info;
151 device_info.device_id = device_path;
152
153 // Try to open the device.
154 base::win::ScopedHandle device_handle(
155 CreateFileA(device_path.c_str(),
156 0,
157 FILE_SHARE_READ | FILE_SHARE_WRITE,
158 NULL,
159 OPEN_EXISTING,
160 FILE_FLAG_OVERLAPPED,
161 0));
162 if (!device_handle.IsValid())
163 return;
164
165 // Get VID/PID pair.
166 HIDD_ATTRIBUTES attrib = {0};
167 attrib.Size = sizeof(HIDD_ATTRIBUTES);
168 if (!HidD_GetAttributes(device_handle.Get(), &attrib))
169 return;
170
171 device_info.vendor_id = attrib.VendorID;
172 device_info.product_id = attrib.ProductID;
173
174 for (ULONG i = 32;
175 HidD_SetNumInputBuffers(device_handle.Get(), i);
176 i <<= 1);
177
178 // Get usage and usage page (optional).
179 PHIDP_PREPARSED_DATA preparsed_data;
180 if (HidD_GetPreparsedData(device_handle.Get(), &preparsed_data) &&
181 preparsed_data) {
182 HIDP_CAPS capabilities;
183 if (HidP_GetCaps(preparsed_data, &capabilities) == HIDP_STATUS_SUCCESS) {
184 device_info.usage = capabilities.Usage;
185 device_info.usage_page = capabilities.UsagePage;
186 device_info.input_report_size = capabilities.InputReportByteLength;
187 device_info.output_report_size = capabilities.OutputReportByteLength;
188 device_info.feature_report_size = capabilities.FeatureReportByteLength;
189 }
190 // Detect if the device supports report ids.
191 if (capabilities.NumberInputValueCaps > 0) {
192 scoped_ptr<HIDP_VALUE_CAPS[]> value_caps(
193 new HIDP_VALUE_CAPS[capabilities.NumberInputValueCaps]);
194 USHORT value_caps_length = capabilities.NumberInputValueCaps;
195 if (HidP_GetValueCaps(HidP_Input, &value_caps[0], &value_caps_length,
196 preparsed_data) == HIDP_STATUS_SUCCESS) {
197 device_info.has_report_id = (value_caps[0].ReportID != 0);
198 }
199 }
200 HidD_FreePreparsedData(preparsed_data);
201 }
202
203 // Get the serial number
204 wchar_t str_property[512] = { 0 };
205 if (HidD_GetSerialNumberString(device_handle.Get(),
206 str_property,
207 sizeof(str_property))) {
208 device_info.serial_number = base::SysWideToUTF8(str_property);
209 }
210
211 if (HidD_GetProductString(device_handle.Get(),
212 str_property,
213 sizeof(str_property))) {
214 device_info.product_name = base::SysWideToUTF8(str_property);
215 }
216
217 HidService::AddDevice(device_info);
218 }
219
220 void HidServiceWin::PlatformRemoveDevice(std::string device_path) {
221 HidService::RemoveDevice(device_path);
222 }
223
224 void HidServiceWin::GetDevices(std::vector<HidDeviceInfo>* devices) {
225 Enumerate();
226 HidService::GetDevices(devices);
227 }
228
229 scoped_refptr<HidConnection> HidServiceWin::Connect(std::string device_id) {
230 if (!ContainsKey(devices_, device_id)) return NULL;
231 scoped_refptr<HidConnectionWin> connection(
232 new HidConnectionWin(devices_[device_id]));
233 if (!connection->available()) {
234 LOG_GETLASTERROR(ERROR) << "Failed to open device.";
235 return NULL;
236 }
237 return connection;
238 }
239
240 } // namespace device
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698