OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "device/usb/usb_service_impl.h" | 5 #include "device/usb/usb_service_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <list> | 8 #include <list> |
9 #include <set> | 9 #include <set> |
10 | 10 |
11 #include "base/barrier_closure.h" | 11 #include "base/barrier_closure.h" |
12 #include "base/bind.h" | 12 #include "base/bind.h" |
13 #include "base/location.h" | 13 #include "base/location.h" |
14 #include "base/memory/weak_ptr.h" | 14 #include "base/memory/weak_ptr.h" |
15 #include "base/single_thread_task_runner.h" | 15 #include "base/single_thread_task_runner.h" |
16 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
17 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
18 #include "base/strings/utf_string_conversions.h" | 18 #include "base/strings/utf_string_conversions.h" |
19 #include "base/thread_task_runner_handle.h" | 19 #include "base/thread_task_runner_handle.h" |
20 #include "components/device_event_log/device_event_log.h" | 20 #include "components/device_event_log/device_event_log.h" |
21 #include "device/usb/usb_device_handle.h" | 21 #include "device/usb/usb_device_handle.h" |
22 #include "device/usb/usb_error.h" | 22 #include "device/usb/usb_error.h" |
23 #include "device/usb/webusb_descriptors.h" | |
23 #include "third_party/libusb/src/libusb/libusb.h" | 24 #include "third_party/libusb/src/libusb/libusb.h" |
24 | 25 |
25 #if defined(OS_WIN) | 26 #if defined(OS_WIN) |
26 #include <setupapi.h> | 27 #include <setupapi.h> |
27 #include <usbiodef.h> | 28 #include <usbiodef.h> |
28 | 29 |
29 #include "base/strings/string_util.h" | 30 #include "base/strings/string_util.h" |
30 #endif // OS_WIN | 31 #endif // OS_WIN |
31 | 32 |
32 #if defined(USE_UDEV) | 33 #if defined(USE_UDEV) |
33 #include "device/udev_linux/scoped_udev.h" | 34 #include "device/udev_linux/scoped_udev.h" |
34 #endif // USE_UDEV | 35 #endif // USE_UDEV |
35 | 36 |
37 using net::IOBufferWithSize; | |
38 | |
36 namespace device { | 39 namespace device { |
37 | 40 |
38 namespace { | 41 namespace { |
39 | 42 |
43 // Standard USB requests and descriptor types: | |
44 const uint8_t kGetDescriptorRequest = 0x06; | |
45 const uint8_t kStringDescriptorType = 0x03; | |
46 const uint8_t kBosDescriptorType = 0x0F; | |
47 | |
48 // WebUSB requests: | |
49 const uint8_t kGetAllowedOriginsRequest = 0x01; | |
50 const uint8_t kGetLandingPageRequest = 0x02; | |
51 const uint8_t kUrlDescriptorType = 0x03; | |
52 | |
53 const int kControlTransferTimeout = 60000; /* 1 minute */ | |
Ken Rockot(use gerrit already)
2015/08/04 01:15:01
nit: a cursory grep through the repo suggests you
Reilly Grant (use Gerrit)
2015/08/04 20:48:56
Done.
| |
54 | |
40 #if defined(OS_WIN) | 55 #if defined(OS_WIN) |
41 | 56 |
42 // Wrapper around a HDEVINFO that automatically destroys it. | 57 // Wrapper around a HDEVINFO that automatically destroys it. |
43 class ScopedDeviceInfoList { | 58 class ScopedDeviceInfoList { |
44 public: | 59 public: |
45 explicit ScopedDeviceInfoList(HDEVINFO handle) : handle_(handle) {} | 60 explicit ScopedDeviceInfoList(HDEVINFO handle) : handle_(handle) {} |
46 | 61 |
47 ~ScopedDeviceInfoList() { | 62 ~ScopedDeviceInfoList() { |
48 if (valid()) { | 63 if (valid()) { |
49 SetupDiDestroyDeviceInfoList(handle_); | 64 SetupDiDestroyDeviceInfoList(handle_); |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
158 USB_LOG(ERROR) << "Failed to get device list: " | 173 USB_LOG(ERROR) << "Failed to get device list: " |
159 << ConvertPlatformUsbErrorToString(device_count); | 174 << ConvertPlatformUsbErrorToString(device_count); |
160 task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr, 0)); | 175 task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr, 0)); |
161 return; | 176 return; |
162 } | 177 } |
163 | 178 |
164 task_runner->PostTask(FROM_HERE, | 179 task_runner->PostTask(FROM_HERE, |
165 base::Bind(callback, platform_devices, device_count)); | 180 base::Bind(callback, platform_devices, device_count)); |
166 } | 181 } |
167 | 182 |
168 #if defined(USE_UDEV) | |
169 | |
170 void EnumerateUdevDevice(scoped_refptr<UsbDeviceImpl> device, | |
171 scoped_refptr<base::SequencedTaskRunner> task_runner, | |
172 const base::Closure& success_closure, | |
173 const base::Closure& failure_closure) { | |
174 ScopedUdevPtr udev(udev_new()); | |
175 ScopedUdevEnumeratePtr udev_enumerate(udev_enumerate_new(udev.get())); | |
176 | |
177 udev_enumerate_add_match_subsystem(udev_enumerate.get(), "usb"); | |
178 if (udev_enumerate_scan_devices(udev_enumerate.get()) != 0) { | |
179 task_runner->PostTask(FROM_HERE, failure_closure); | |
180 return; | |
181 } | |
182 | |
183 std::string bus_number = | |
184 base::IntToString(libusb_get_bus_number(device->platform_device())); | |
185 std::string device_address = | |
186 base::IntToString(libusb_get_device_address(device->platform_device())); | |
187 udev_list_entry* devices = | |
188 udev_enumerate_get_list_entry(udev_enumerate.get()); | |
189 for (udev_list_entry* i = devices; i != NULL; | |
190 i = udev_list_entry_get_next(i)) { | |
191 ScopedUdevDevicePtr udev_device( | |
192 udev_device_new_from_syspath(udev.get(), udev_list_entry_get_name(i))); | |
193 if (udev_device) { | |
194 const char* value = | |
195 udev_device_get_sysattr_value(udev_device.get(), "busnum"); | |
196 if (!value || bus_number != value) { | |
197 continue; | |
198 } | |
199 value = udev_device_get_sysattr_value(udev_device.get(), "devnum"); | |
200 if (!value || device_address != value) { | |
201 continue; | |
202 } | |
203 | |
204 value = udev_device_get_sysattr_value(udev_device.get(), "manufacturer"); | |
205 if (value) { | |
206 device->set_manufacturer_string(base::UTF8ToUTF16(value)); | |
207 } | |
208 value = udev_device_get_sysattr_value(udev_device.get(), "product"); | |
209 if (value) { | |
210 device->set_product_string(base::UTF8ToUTF16(value)); | |
211 } | |
212 value = udev_device_get_sysattr_value(udev_device.get(), "serial"); | |
213 if (value) { | |
214 device->set_serial_number(base::UTF8ToUTF16(value)); | |
215 } | |
216 | |
217 value = udev_device_get_devnode(udev_device.get()); | |
218 if (value) { | |
219 device->set_device_path(value); | |
220 task_runner->PostTask(FROM_HERE, success_closure); | |
221 return; | |
222 } | |
223 | |
224 break; | |
225 } | |
226 } | |
227 | |
228 task_runner->PostTask(FROM_HERE, failure_closure); | |
229 } | |
230 | |
231 #else | |
232 | |
233 void OnReadStringDescriptor( | 183 void OnReadStringDescriptor( |
234 const base::Callback<void(const base::string16&)>& callback, | 184 const base::Callback<void(const base::string16&)>& callback, |
235 UsbTransferStatus status, | 185 UsbTransferStatus status, |
236 scoped_refptr<net::IOBuffer> buffer, | 186 scoped_refptr<net::IOBuffer> buffer, |
237 size_t length) { | 187 size_t length) { |
238 if (status != USB_TRANSFER_COMPLETED || length < 2) { | 188 if (status != USB_TRANSFER_COMPLETED || length < 2) { |
239 callback.Run(base::string16()); | 189 callback.Run(base::string16()); |
240 } else { | 190 } else { |
241 // Take the lesser of the length of data returned by the device and the | 191 // Take the lesser of the length of data returned by the device and the |
242 // length reported in the descriptor. | 192 // length reported in the descriptor. |
243 size_t internal_length = reinterpret_cast<uint8*>(buffer->data())[0]; | 193 size_t internal_length = reinterpret_cast<uint8*>(buffer->data())[0]; |
244 length = std::min(length, internal_length); | 194 length = std::min(length, internal_length); |
245 // Cut off the first 2 bytes of the descriptor which are the length and | 195 // Cut off the first 2 bytes of the descriptor which are the length and |
246 // descriptor type (always STRING). | 196 // descriptor type (always STRING). |
247 callback.Run(base::string16( | 197 callback.Run(base::string16( |
248 reinterpret_cast<base::char16*>(buffer->data() + 2), length / 2 - 1)); | 198 reinterpret_cast<base::char16*>(buffer->data() + 2), length / 2 - 1)); |
249 } | 199 } |
250 } | 200 } |
251 | 201 |
252 void ReadStringDescriptor( | 202 void ReadStringDescriptor( |
253 scoped_refptr<UsbDeviceHandle> device_handle, | 203 scoped_refptr<UsbDeviceHandle> device_handle, |
254 uint8 index, | 204 uint8 index, |
255 uint16 language_id, | 205 uint16 language_id, |
256 const base::Callback<void(const base::string16&)>& callback) { | 206 const base::Callback<void(const base::string16&)>& callback) { |
257 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(256); | 207 scoped_refptr<IOBufferWithSize> buffer = new IOBufferWithSize(256); |
258 device_handle->ControlTransfer( | 208 device_handle->ControlTransfer( |
259 USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, UsbDeviceHandle::DEVICE, | 209 USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, UsbDeviceHandle::DEVICE, |
260 6 /* GET_DESCRIPTOR */, 3 /* STRING */ << 8 | index, language_id, buffer, | 210 kGetDescriptorRequest, kStringDescriptorType << 8 | index, language_id, |
261 256, 60, base::Bind(&OnReadStringDescriptor, callback)); | 211 buffer, buffer->size(), kControlTransferTimeout, |
212 base::Bind(&OnReadStringDescriptor, callback)); | |
213 } | |
214 | |
215 void OnReadWebUsbLandingPage(scoped_refptr<UsbDevice> device, | |
216 const base::Closure& callback, | |
217 UsbTransferStatus status, | |
218 scoped_refptr<net::IOBuffer> buffer, | |
219 size_t length) { | |
220 if (status != USB_TRANSFER_COMPLETED || length < 2) { | |
221 callback.Run(); | |
222 return; | |
223 } | |
224 | |
225 uint8_t string_length = buffer->data()[0]; | |
226 if (string_length < 2 || string_length > length || | |
227 buffer->data()[1] != kUrlDescriptorType) { | |
228 callback.Run(); | |
229 return; | |
230 } | |
231 | |
232 GURL url(std::string(&buffer->data()[2], string_length - 2)); | |
233 if (url.is_valid()) { | |
234 UsbDeviceImpl* device_impl = static_cast<UsbDeviceImpl*>(device.get()); | |
235 device_impl->set_webusb_landing_page(url); | |
236 } | |
237 callback.Run(); | |
238 } | |
239 | |
240 void ReadWebUsbLandingPage(scoped_refptr<UsbDeviceHandle> device_handle, | |
241 const base::Closure& callback, | |
242 uint8 vendor_code) { | |
243 scoped_refptr<IOBufferWithSize> buffer = new IOBufferWithSize(256); | |
244 device_handle->ControlTransfer( | |
245 USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR, UsbDeviceHandle::DEVICE, | |
246 vendor_code, 0, kGetLandingPageRequest, buffer, buffer->size(), | |
247 kControlTransferTimeout, | |
248 base::Bind(&OnReadWebUsbLandingPage, device_handle->GetDevice(), | |
249 callback)); | |
250 } | |
251 | |
252 void OnReadWebUsbAllowedOrigins(scoped_refptr<UsbDevice> device, | |
253 const base::Closure& callback, | |
254 UsbTransferStatus status, | |
255 scoped_refptr<net::IOBuffer> buffer, | |
256 size_t length) { | |
257 if (status != USB_TRANSFER_COMPLETED) { | |
258 USB_LOG(EVENT) << "Failed to read WebUSB allowed origins."; | |
259 callback.Run(); | |
260 return; | |
261 } | |
262 | |
263 scoped_ptr<WebUsbDescriptorSet> descriptors(new WebUsbDescriptorSet()); | |
264 if (descriptors->Parse( | |
265 std::vector<uint8>(buffer->data(), buffer->data() + length))) { | |
266 UsbDeviceImpl* device_impl = static_cast<UsbDeviceImpl*>(device.get()); | |
267 device_impl->set_webusb_allowed_origins(descriptors.Pass()); | |
268 } | |
269 callback.Run(); | |
270 } | |
271 | |
272 void OnReadWebUsbAllowedOriginsHeader( | |
273 scoped_refptr<UsbDeviceHandle> device_handle, | |
274 const base::Closure& callback, | |
275 uint8 vendor_code, | |
276 UsbTransferStatus status, | |
277 scoped_refptr<net::IOBuffer> buffer, | |
278 size_t length) { | |
279 if (status != USB_TRANSFER_COMPLETED || length != 4) { | |
280 USB_LOG(EVENT) << "Failed to read WebUSB allowed origins header."; | |
281 callback.Run(); | |
282 return; | |
283 } | |
284 | |
285 uint16 new_length = buffer->data()[2] | (buffer->data()[3] << 8); | |
286 scoped_refptr<IOBufferWithSize> new_buffer = new IOBufferWithSize(new_length); | |
287 device_handle->ControlTransfer( | |
288 USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR, UsbDeviceHandle::DEVICE, | |
289 vendor_code, 0, kGetAllowedOriginsRequest, new_buffer, new_buffer->size(), | |
290 kControlTransferTimeout, | |
291 base::Bind(&OnReadWebUsbAllowedOrigins, device_handle->GetDevice(), | |
292 callback)); | |
293 } | |
294 | |
295 void ReadWebUsbAllowedOrigins(scoped_refptr<UsbDeviceHandle> device_handle, | |
296 const base::Closure& callback, | |
297 uint8 vendor_code) { | |
298 scoped_refptr<IOBufferWithSize> buffer = new IOBufferWithSize(4); | |
299 device_handle->ControlTransfer( | |
300 USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR, UsbDeviceHandle::DEVICE, | |
301 vendor_code, 0, kGetAllowedOriginsRequest, buffer, buffer->size(), | |
302 kControlTransferTimeout, | |
303 base::Bind(&OnReadWebUsbAllowedOriginsHeader, device_handle, callback, | |
304 vendor_code)); | |
305 } | |
306 | |
307 void OnReadBosDescriptor(scoped_refptr<UsbDeviceHandle> device_handle, | |
308 const base::Closure& callback, | |
309 UsbTransferStatus status, | |
310 scoped_refptr<net::IOBuffer> buffer, | |
311 size_t length) { | |
312 if (status != USB_TRANSFER_COMPLETED) { | |
313 USB_LOG(EVENT) << "Failed to read BOS descriptor."; | |
314 callback.Run(); | |
315 return; | |
316 } | |
317 | |
318 WebUsbPlatformCapabilityDescriptor descriptor; | |
319 if (!descriptor.ParseFromBosDescriptor( | |
320 std::vector<uint8>(buffer->data(), buffer->data() + length))) { | |
321 callback.Run(); | |
322 return; | |
323 } | |
324 | |
325 base::Closure barrier = base::BarrierClosure(2, callback); | |
326 ReadWebUsbLandingPage(device_handle, barrier, descriptor.vendor_code); | |
327 ReadWebUsbAllowedOrigins(device_handle, barrier, descriptor.vendor_code); | |
328 } | |
329 | |
330 void OnReadBosDescriptorHeader(scoped_refptr<UsbDeviceHandle> device_handle, | |
331 const base::Closure& callback, | |
332 UsbTransferStatus status, | |
333 scoped_refptr<net::IOBuffer> buffer, | |
334 size_t length) { | |
335 if (status != USB_TRANSFER_COMPLETED || length != 5) { | |
336 USB_LOG(EVENT) << "Failed to read BOS descriptor header."; | |
337 callback.Run(); | |
338 return; | |
339 } | |
340 | |
341 uint16 new_length = buffer->data()[2] | (buffer->data()[3] << 8); | |
342 scoped_refptr<IOBufferWithSize> new_buffer = new IOBufferWithSize(new_length); | |
343 device_handle->ControlTransfer( | |
Ken Rockot(use gerrit already)
2015/08/04 01:15:01
nit: maaaaybe it's worth adding a utility method t
| |
344 USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, UsbDeviceHandle::DEVICE, | |
345 kGetDescriptorRequest, kBosDescriptorType << 8, 0, new_buffer, | |
346 new_buffer->size(), kControlTransferTimeout, | |
347 base::Bind(&OnReadBosDescriptor, device_handle, callback)); | |
348 } | |
349 | |
350 void ReadBosDescriptor(scoped_refptr<UsbDeviceHandle> device_handle, | |
351 const base::Closure& callback) { | |
352 scoped_refptr<IOBufferWithSize> buffer = new IOBufferWithSize(5); | |
353 device_handle->ControlTransfer( | |
354 USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, UsbDeviceHandle::DEVICE, | |
355 kGetDescriptorRequest, kBosDescriptorType << 8, 0, buffer, buffer->size(), | |
356 kControlTransferTimeout, | |
357 base::Bind(&OnReadBosDescriptorHeader, device_handle, callback)); | |
262 } | 358 } |
263 | 359 |
264 void CloseHandleAndRunContinuation(scoped_refptr<UsbDeviceHandle> device_handle, | 360 void CloseHandleAndRunContinuation(scoped_refptr<UsbDeviceHandle> device_handle, |
265 const base::Closure& continuation) { | 361 const base::Closure& continuation) { |
266 device_handle->Close(); | 362 device_handle->Close(); |
267 continuation.Run(); | 363 continuation.Run(); |
268 } | 364 } |
269 | 365 |
270 void SaveStringAndRunContinuation( | 366 void SaveStringAndRunContinuation( |
271 const base::Callback<void(const base::string16&)>& save_callback, | 367 const base::Callback<void(const base::string16&)>& save_callback, |
272 const base::Closure& continuation, | 368 const base::Closure& continuation, |
273 const base::string16& value) { | 369 const base::string16& value) { |
274 if (!value.empty()) { | 370 if (!value.empty()) { |
275 save_callback.Run(value); | 371 save_callback.Run(value); |
276 } | 372 } |
277 continuation.Run(); | 373 continuation.Run(); |
278 } | 374 } |
279 | 375 |
376 // This function runs |barrier| once for every string it tries to read. | |
280 void OnReadLanguageIds(scoped_refptr<UsbDeviceHandle> device_handle, | 377 void OnReadLanguageIds(scoped_refptr<UsbDeviceHandle> device_handle, |
281 uint8 manufacturer, | 378 uint8 manufacturer, |
282 uint8 product, | 379 uint8 product, |
283 uint8 serial_number, | 380 uint8 serial_number, |
284 const base::Closure& success_closure, | 381 const base::Closure& barrier, |
285 const base::string16& languages) { | 382 const base::string16& languages) { |
286 // Default to English unless the device provides a language and then just pick | 383 // Default to English unless the device provides a language and then just pick |
287 // the first one. | 384 // the first one. |
288 uint16 language_id = 0x0409; | 385 uint16 language_id = 0x0409; |
289 if (!languages.empty()) { | 386 if (!languages.empty()) { |
290 language_id = languages[0]; | 387 language_id = languages[0]; |
291 } | 388 } |
292 | 389 |
293 scoped_refptr<UsbDeviceImpl> device = | 390 scoped_refptr<UsbDeviceImpl> device = |
294 static_cast<UsbDeviceImpl*>(device_handle->GetDevice().get()); | 391 static_cast<UsbDeviceImpl*>(device_handle->GetDevice().get()); |
295 base::Closure continuation = | |
296 base::BarrierClosure(3, base::Bind(&CloseHandleAndRunContinuation, | |
297 device_handle, success_closure)); | |
298 | 392 |
299 if (manufacturer == 0) { | 393 if (manufacturer != 0) { |
300 continuation.Run(); | |
301 } else { | |
302 ReadStringDescriptor( | 394 ReadStringDescriptor( |
303 device_handle, manufacturer, language_id, | 395 device_handle, manufacturer, language_id, |
304 base::Bind(&SaveStringAndRunContinuation, | 396 base::Bind(&SaveStringAndRunContinuation, |
305 base::Bind(&UsbDeviceImpl::set_manufacturer_string, device), | 397 base::Bind(&UsbDeviceImpl::set_manufacturer_string, device), |
306 continuation)); | 398 barrier)); |
307 } | 399 } |
308 | 400 |
309 if (product == 0) { | 401 if (product != 0) { |
310 continuation.Run(); | |
311 } else { | |
312 ReadStringDescriptor( | 402 ReadStringDescriptor( |
313 device_handle, product, language_id, | 403 device_handle, product, language_id, |
314 base::Bind(&SaveStringAndRunContinuation, | 404 base::Bind(&SaveStringAndRunContinuation, |
315 base::Bind(&UsbDeviceImpl::set_product_string, device), | 405 base::Bind(&UsbDeviceImpl::set_product_string, device), |
316 continuation)); | 406 barrier)); |
317 } | 407 } |
318 | 408 |
319 if (serial_number == 0) { | 409 if (serial_number != 0) { |
320 continuation.Run(); | |
321 } else { | |
322 ReadStringDescriptor( | 410 ReadStringDescriptor( |
323 device_handle, serial_number, language_id, | 411 device_handle, serial_number, language_id, |
324 base::Bind(&SaveStringAndRunContinuation, | 412 base::Bind(&SaveStringAndRunContinuation, |
325 base::Bind(&UsbDeviceImpl::set_serial_number, device), | 413 base::Bind(&UsbDeviceImpl::set_serial_number, device), |
326 continuation)); | 414 barrier)); |
327 } | 415 } |
328 } | 416 } |
329 | 417 |
330 void ReadDeviceLanguage(uint8 manufacturer, | 418 void OnDeviceOpenedReadDescriptors( |
331 uint8 product, | 419 uint8 manufacturer, |
332 uint8 serial_number, | 420 uint8 product, |
333 const base::Closure& success_closure, | 421 uint8 serial_number, |
334 const base::Closure& failure_closure, | 422 bool read_bos_descriptors, |
335 scoped_refptr<UsbDeviceHandle> device_handle) { | 423 const base::Closure& success_closure, |
424 const base::Closure& failure_closure, | |
425 scoped_refptr<UsbDeviceHandle> device_handle) { | |
336 if (device_handle) { | 426 if (device_handle) { |
337 ReadStringDescriptor( | 427 size_t count = 0; |
338 device_handle, 0, 0, | 428 if (manufacturer != 0) |
339 base::Bind(&OnReadLanguageIds, device_handle, manufacturer, product, | 429 count++; |
340 serial_number, success_closure)); | 430 if (product != 0) |
431 count++; | |
432 if (serial_number != 0) | |
433 count++; | |
434 if (read_bos_descriptors) | |
435 count++; | |
436 | |
437 base::Closure barrier = | |
438 base::BarrierClosure(count, base::Bind(&CloseHandleAndRunContinuation, | |
439 device_handle, success_closure)); | |
440 | |
441 if (manufacturer != 0 || product != 0 || serial_number != 0) { | |
442 ReadStringDescriptor( | |
443 device_handle, 0, 0, | |
444 base::Bind(&OnReadLanguageIds, device_handle, manufacturer, product, | |
445 serial_number, barrier)); | |
446 } | |
447 | |
448 if (read_bos_descriptors) { | |
449 ReadBosDescriptor(device_handle, barrier); | |
450 } | |
341 } else { | 451 } else { |
342 failure_closure.Run(); | 452 failure_closure.Run(); |
343 } | 453 } |
344 } | 454 } |
345 | 455 |
456 #if defined(USE_UDEV) | |
457 | |
458 void EnumerateUdevDevice(scoped_refptr<UsbDeviceImpl> device, | |
459 bool read_bos_descriptors, | |
460 scoped_refptr<base::SequencedTaskRunner> task_runner, | |
461 const base::Closure& success_closure, | |
462 const base::Closure& failure_closure) { | |
463 ScopedUdevPtr udev(udev_new()); | |
464 ScopedUdevEnumeratePtr udev_enumerate(udev_enumerate_new(udev.get())); | |
465 | |
466 udev_enumerate_add_match_subsystem(udev_enumerate.get(), "usb"); | |
467 if (udev_enumerate_scan_devices(udev_enumerate.get()) != 0) { | |
468 task_runner->PostTask(FROM_HERE, failure_closure); | |
469 return; | |
470 } | |
471 | |
472 std::string bus_number = | |
473 base::IntToString(libusb_get_bus_number(device->platform_device())); | |
474 std::string device_address = | |
475 base::IntToString(libusb_get_device_address(device->platform_device())); | |
476 udev_list_entry* devices = | |
477 udev_enumerate_get_list_entry(udev_enumerate.get()); | |
478 for (udev_list_entry* i = devices; i != NULL; | |
479 i = udev_list_entry_get_next(i)) { | |
480 ScopedUdevDevicePtr udev_device( | |
481 udev_device_new_from_syspath(udev.get(), udev_list_entry_get_name(i))); | |
482 if (udev_device) { | |
483 const char* value = | |
484 udev_device_get_sysattr_value(udev_device.get(), "busnum"); | |
485 if (!value || bus_number != value) { | |
486 continue; | |
487 } | |
488 value = udev_device_get_sysattr_value(udev_device.get(), "devnum"); | |
489 if (!value || device_address != value) { | |
490 continue; | |
491 } | |
492 | |
493 value = udev_device_get_sysattr_value(udev_device.get(), "manufacturer"); | |
494 if (value) { | |
495 device->set_manufacturer_string(base::UTF8ToUTF16(value)); | |
496 } | |
497 value = udev_device_get_sysattr_value(udev_device.get(), "product"); | |
498 if (value) { | |
499 device->set_product_string(base::UTF8ToUTF16(value)); | |
500 } | |
501 value = udev_device_get_sysattr_value(udev_device.get(), "serial"); | |
502 if (value) { | |
503 device->set_serial_number(base::UTF8ToUTF16(value)); | |
504 } | |
505 | |
506 value = udev_device_get_devnode(udev_device.get()); | |
507 if (value) { | |
508 device->set_device_path(value); | |
509 | |
510 if (read_bos_descriptors) { | |
511 task_runner->PostTask( | |
512 FROM_HERE, | |
513 base::Bind(&UsbDevice::Open, device, | |
514 base::Bind(&OnDeviceOpenedReadDescriptors, 0, 0, 0, | |
515 true, success_closure, failure_closure))); | |
516 } else { | |
517 task_runner->PostTask(FROM_HERE, success_closure); | |
518 } | |
519 return; | |
520 } | |
521 | |
522 break; | |
523 } | |
524 } | |
525 | |
526 task_runner->PostTask(FROM_HERE, failure_closure); | |
527 } | |
528 | |
346 #endif // USE_UDEV | 529 #endif // USE_UDEV |
347 | 530 |
348 } // namespace | 531 } // namespace |
349 | 532 |
350 // static | 533 // static |
351 UsbService* UsbServiceImpl::Create( | 534 UsbService* UsbServiceImpl::Create( |
352 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) { | 535 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) { |
353 PlatformUsbContext context = NULL; | 536 PlatformUsbContext context = NULL; |
354 const int rv = libusb_init(&context); | 537 const int rv = libusb_init(&context); |
355 if (rv != LIBUSB_SUCCESS) { | 538 if (rv != LIBUSB_SUCCESS) { |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
566 libusb_device_descriptor descriptor; | 749 libusb_device_descriptor descriptor; |
567 int rv = libusb_get_device_descriptor(platform_device, &descriptor); | 750 int rv = libusb_get_device_descriptor(platform_device, &descriptor); |
568 if (rv == LIBUSB_SUCCESS) { | 751 if (rv == LIBUSB_SUCCESS) { |
569 scoped_refptr<UsbDeviceImpl> device( | 752 scoped_refptr<UsbDeviceImpl> device( |
570 new UsbDeviceImpl(context_, platform_device, descriptor.idVendor, | 753 new UsbDeviceImpl(context_, platform_device, descriptor.idVendor, |
571 descriptor.idProduct, blocking_task_runner_)); | 754 descriptor.idProduct, blocking_task_runner_)); |
572 | 755 |
573 base::Closure add_device = | 756 base::Closure add_device = |
574 base::Bind(&UsbServiceImpl::AddDevice, weak_factory_.GetWeakPtr(), | 757 base::Bind(&UsbServiceImpl::AddDevice, weak_factory_.GetWeakPtr(), |
575 refresh_complete, device); | 758 refresh_complete, device); |
759 bool read_bos_descriptors = descriptor.bcdUSB >= 0x0210; | |
Ken Rockot(use gerrit already)
2015/08/04 01:15:01
nit: add a named constant for 0x210?
Reilly Grant (use Gerrit)
2015/08/04 20:48:56
Done.
| |
576 | 760 |
577 #if defined(USE_UDEV) | 761 #if defined(USE_UDEV) |
578 blocking_task_runner_->PostTask( | 762 blocking_task_runner_->PostTask( |
579 FROM_HERE, base::Bind(&EnumerateUdevDevice, device, task_runner_, | 763 FROM_HERE, |
580 add_device, refresh_complete)); | 764 base::Bind(&EnumerateUdevDevice, device, read_bos_descriptors, |
765 task_runner_, add_device, refresh_complete)); | |
581 #else | 766 #else |
582 if (descriptor.iManufacturer == 0 && descriptor.iProduct == 0 && | 767 if (descriptor.iManufacturer == 0 && descriptor.iProduct == 0 && |
583 descriptor.iSerialNumber == 0) { | 768 descriptor.iSerialNumber == 0 && !read_bos_descriptors) { |
584 // Don't bother disturbing the device if it has no string descriptors to | 769 // Don't bother disturbing the device if it has no descriptors to offer. |
585 // offer. | |
586 add_device.Run(); | 770 add_device.Run(); |
587 } else { | 771 } else { |
588 device->Open(base::Bind(&ReadDeviceLanguage, descriptor.iManufacturer, | 772 device->Open(base::Bind(&OnDeviceOpenedReadDescriptors, |
589 descriptor.iProduct, descriptor.iSerialNumber, | 773 descriptor.iManufacturer, descriptor.iProduct, |
774 descriptor.iSerialNumber, read_bos_descriptors, | |
590 add_device, refresh_complete)); | 775 add_device, refresh_complete)); |
591 } | 776 } |
592 #endif | 777 #endif |
593 } else { | 778 } else { |
594 USB_LOG(EVENT) << "Failed to get device descriptor: " | 779 USB_LOG(EVENT) << "Failed to get device descriptor: " |
595 << ConvertPlatformUsbErrorToString(rv); | 780 << ConvertPlatformUsbErrorToString(rv); |
596 refresh_complete.Run(); | 781 refresh_complete.Run(); |
597 } | 782 } |
598 } | 783 } |
599 | 784 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
685 if (it != platform_devices_.end()) { | 870 if (it != platform_devices_.end()) { |
686 RemoveDevice(it->second); | 871 RemoveDevice(it->second); |
687 } else { | 872 } else { |
688 DCHECK(ContainsKey(devices_being_enumerated_, platform_device)); | 873 DCHECK(ContainsKey(devices_being_enumerated_, platform_device)); |
689 devices_being_enumerated_.erase(platform_device); | 874 devices_being_enumerated_.erase(platform_device); |
690 } | 875 } |
691 libusb_unref_device(platform_device); | 876 libusb_unref_device(platform_device); |
692 } | 877 } |
693 | 878 |
694 } // namespace device | 879 } // namespace device |
OLD | NEW |