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

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