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

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

Issue 1903933002: Store devices that only need to be enumerated once (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fixed device leak at usb_service_impl.cc Created 4 years, 8 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_service_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 <stdint.h> 7 #include <stdint.h>
8 8
9 #include <list> 9 #include <list>
10 #include <memory> 10 #include <memory>
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 #endif // OS_WIN 314 #endif // OS_WIN
315 } 315 }
316 316
317 UsbServiceImpl::~UsbServiceImpl() { 317 UsbServiceImpl::~UsbServiceImpl() {
318 if (hotplug_enabled_) { 318 if (hotplug_enabled_) {
319 libusb_hotplug_deregister_callback(context_->context(), hotplug_handle_); 319 libusb_hotplug_deregister_callback(context_->context(), hotplug_handle_);
320 } 320 }
321 for (const auto& map_entry : devices_) { 321 for (const auto& map_entry : devices_) {
322 map_entry.second->OnDisconnect(); 322 map_entry.second->OnDisconnect();
323 } 323 }
324 for (const auto& platform_device : ignored_devices_)
325 libusb_unref_device(platform_device);
324 } 326 }
325 327
326 scoped_refptr<UsbDevice> UsbServiceImpl::GetDevice(const std::string& guid) { 328 scoped_refptr<UsbDevice> UsbServiceImpl::GetDevice(const std::string& guid) {
327 DCHECK(CalledOnValidThread()); 329 DCHECK(CalledOnValidThread());
328 DeviceMap::iterator it = devices_.find(guid); 330 DeviceMap::iterator it = devices_.find(guid);
329 if (it != devices_.end()) { 331 if (it != devices_.end()) {
330 return it->second; 332 return it->second;
331 } 333 }
332 return NULL; 334 return NULL;
333 } 335 }
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 if (!platform_devices) { 412 if (!platform_devices) {
411 RefreshDevicesComplete(); 413 RefreshDevicesComplete();
412 return; 414 return;
413 } 415 }
414 416
415 base::Closure refresh_complete = 417 base::Closure refresh_complete =
416 base::BarrierClosure(static_cast<int>(device_count), 418 base::BarrierClosure(static_cast<int>(device_count),
417 base::Bind(&UsbServiceImpl::RefreshDevicesComplete, 419 base::Bind(&UsbServiceImpl::RefreshDevicesComplete,
418 weak_factory_.GetWeakPtr())); 420 weak_factory_.GetWeakPtr()));
419 std::list<PlatformUsbDevice> new_devices; 421 std::list<PlatformUsbDevice> new_devices;
422 std::set<PlatformUsbDevice> existing_ignored_devices;
420 423
421 // Look for new and existing devices. 424 // Look for new and existing devices.
422 for (size_t i = 0; i < device_count; ++i) { 425 for (size_t i = 0; i < device_count; ++i) {
423 PlatformUsbDevice platform_device = platform_devices[i]; 426 PlatformUsbDevice platform_device = platform_devices[i];
427 // Ignore some devices.
428 if (ContainsValue(ignored_devices_, platform_device)) {
429 existing_ignored_devices.insert(platform_device);
430 refresh_complete.Run();
431 continue;
432 }
433
424 auto it = platform_devices_.find(platform_device); 434 auto it = platform_devices_.find(platform_device);
425 435
426 if (it == platform_devices_.end()) { 436 if (it == platform_devices_.end()) {
427 libusb_ref_device(platform_device);
428 new_devices.push_back(platform_device); 437 new_devices.push_back(platform_device);
429 } else { 438 } else {
430 it->second->set_visited(true); 439 it->second->set_visited(true);
431 refresh_complete.Run(); 440 refresh_complete.Run();
432 } 441 }
433 } 442 }
434 443
435 // Remove devices not seen in this enumeration. 444 // Remove devices not seen in this enumeration.
436 for (PlatformDeviceMap::iterator it = platform_devices_.begin(); 445 for (PlatformDeviceMap::iterator it = platform_devices_.begin();
437 it != platform_devices_.end(); 446 it != platform_devices_.end();
438 /* incremented internally */) { 447 /* incremented internally */) {
439 PlatformDeviceMap::iterator current = it++; 448 PlatformDeviceMap::iterator current = it++;
440 const scoped_refptr<UsbDeviceImpl>& device = current->second; 449 const scoped_refptr<UsbDeviceImpl>& device = current->second;
441 if (device->was_visited()) { 450 if (device->was_visited()) {
442 device->set_visited(false); 451 device->set_visited(false);
443 } else { 452 } else {
444 RemoveDevice(device); 453 RemoveDevice(device);
445 } 454 }
446 } 455 }
447 456
457 // Remove devices not seen in this enumeration from |ignored_devices_|.
458 for (auto it = ignored_devices_.begin(); it != ignored_devices_.end();
459 /* incremented internally */) {
460 auto current = it++;
461 if (!ContainsValue(existing_ignored_devices, *current)) {
462 libusb_unref_device(*current);
463 ignored_devices_.erase(current);
464 }
465 }
466
448 for (PlatformUsbDevice platform_device : new_devices) { 467 for (PlatformUsbDevice platform_device : new_devices) {
449 EnumerateDevice(platform_device, refresh_complete); 468 EnumerateDevice(platform_device, refresh_complete);
450 } 469 }
451 470
452 libusb_free_device_list(platform_devices, true); 471 libusb_free_device_list(platform_devices, true);
453 } 472 }
454 473
455 void UsbServiceImpl::RefreshDevicesComplete() { 474 void UsbServiceImpl::RefreshDevicesComplete() {
456 DCHECK(CalledOnValidThread()); 475 DCHECK(CalledOnValidThread());
457 DCHECK(enumeration_in_progress_); 476 DCHECK(enumeration_in_progress_);
(...skipping 23 matching lines...) Expand all
481 void UsbServiceImpl::EnumerateDevice(PlatformUsbDevice platform_device, 500 void UsbServiceImpl::EnumerateDevice(PlatformUsbDevice platform_device,
482 const base::Closure& refresh_complete) { 501 const base::Closure& refresh_complete) {
483 DCHECK(context_); 502 DCHECK(context_);
484 devices_being_enumerated_.insert(platform_device); 503 devices_being_enumerated_.insert(platform_device);
485 504
486 libusb_device_descriptor descriptor; 505 libusb_device_descriptor descriptor;
487 int rv = libusb_get_device_descriptor(platform_device, &descriptor); 506 int rv = libusb_get_device_descriptor(platform_device, &descriptor);
488 if (rv == LIBUSB_SUCCESS) { 507 if (rv == LIBUSB_SUCCESS) {
489 if (descriptor.bDeviceClass == LIBUSB_CLASS_HUB) { 508 if (descriptor.bDeviceClass == LIBUSB_CLASS_HUB) {
490 // Don't try to enumerate hubs. We never want to connect to a hub. 509 // Don't try to enumerate hubs. We never want to connect to a hub.
510 libusb_ref_device(platform_device);
511 ignored_devices_.insert(platform_device);
491 refresh_complete.Run(); 512 refresh_complete.Run();
492 return; 513 return;
493 } 514 }
494 515
495 scoped_refptr<UsbDeviceImpl> device(new UsbDeviceImpl( 516 scoped_refptr<UsbDeviceImpl> device(new UsbDeviceImpl(
496 context_, platform_device, descriptor, blocking_task_runner_)); 517 context_, platform_device, descriptor, blocking_task_runner_));
497 base::Closure add_device = 518 base::Closure add_device =
498 base::Bind(&UsbServiceImpl::AddDevice, weak_factory_.GetWeakPtr(), 519 base::Bind(&UsbServiceImpl::AddDevice, weak_factory_.GetWeakPtr(),
499 refresh_complete, device); 520 refresh_complete, device);
521 base::Closure enumeration_failed = base::Bind(
522 &UsbServiceImpl::EnumerationFailed, weak_factory_.GetWeakPtr(),
523 platform_device, refresh_complete);
500 bool read_bos_descriptors = descriptor.bcdUSB >= kUsbVersion2_1; 524 bool read_bos_descriptors = descriptor.bcdUSB >= kUsbVersion2_1;
501 525
502 #if defined(USE_UDEV) 526 #if defined(USE_UDEV)
503 blocking_task_runner_->PostTask( 527 blocking_task_runner_->PostTask(
504 FROM_HERE, 528 FROM_HERE,
505 base::Bind(&EnumerateUdevDevice, device, read_bos_descriptors, 529 base::Bind(&EnumerateUdevDevice, device, read_bos_descriptors,
506 task_runner_, add_device, refresh_complete)); 530 task_runner_, add_device, enumeration_failed));
507 #else 531 #else
508 if (descriptor.iManufacturer == 0 && descriptor.iProduct == 0 && 532 if (descriptor.iManufacturer == 0 && descriptor.iProduct == 0 &&
509 descriptor.iSerialNumber == 0 && !read_bos_descriptors) { 533 descriptor.iSerialNumber == 0 && !read_bos_descriptors) {
510 // Don't bother disturbing the device if it has no descriptors to offer. 534 // Don't bother disturbing the device if it has no descriptors to offer.
511 add_device.Run(); 535 add_device.Run();
512 } else { 536 } else {
513 device->Open(base::Bind(&OnDeviceOpenedReadDescriptors, 537 device->Open(base::Bind(&OnDeviceOpenedReadDescriptors,
514 descriptor.iManufacturer, descriptor.iProduct, 538 descriptor.iManufacturer, descriptor.iProduct,
515 descriptor.iSerialNumber, read_bos_descriptors, 539 descriptor.iSerialNumber, read_bos_descriptors,
516 add_device, refresh_complete)); 540 add_device, enumeration_failed));
517 } 541 }
518 #endif 542 #endif
519 } else { 543 } else {
520 USB_LOG(EVENT) << "Failed to get device descriptor: " 544 USB_LOG(EVENT) << "Failed to get device descriptor: "
521 << ConvertPlatformUsbErrorToString(rv); 545 << ConvertPlatformUsbErrorToString(rv);
522 refresh_complete.Run(); 546 refresh_complete.Run();
523 } 547 }
524 } 548 }
525 549
526 void UsbServiceImpl::AddDevice(const base::Closure& refresh_complete, 550 void UsbServiceImpl::AddDevice(const base::Closure& refresh_complete,
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 DCHECK(CalledOnValidThread()); 633 DCHECK(CalledOnValidThread());
610 PlatformDeviceMap::iterator it = platform_devices_.find(platform_device); 634 PlatformDeviceMap::iterator it = platform_devices_.find(platform_device);
611 if (it != platform_devices_.end()) { 635 if (it != platform_devices_.end()) {
612 RemoveDevice(it->second); 636 RemoveDevice(it->second);
613 } else { 637 } else {
614 devices_being_enumerated_.erase(platform_device); 638 devices_being_enumerated_.erase(platform_device);
615 } 639 }
616 libusb_unref_device(platform_device); 640 libusb_unref_device(platform_device);
617 } 641 }
618 642
643 void UsbServiceImpl::EnumerationFailed(PlatformUsbDevice platform_device,
644 const base::Closure& refresh_complete) {
645 libusb_ref_device(platform_device);
646 ignored_devices_.insert(platform_device);
647 refresh_complete.Run();
648 }
649
619 } // namespace device 650 } // namespace device
OLDNEW
« no previous file with comments | « device/usb/usb_service_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698