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

Side by Side Diff: device/usb/usb_service_impl.cc

Issue 1253163005: Try to read BOS and WebUSB descriptors from USB devices. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 4 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
« no previous file with comments | « device/usb/usb_device_impl.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « device/usb/usb_device_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698