| 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 <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <list> | 9 #include <list> |
| 10 #include <memory> | 10 #include <memory> |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 } | 73 } |
| 74 | 74 |
| 75 USB_LOG(DEBUG) << "Driver for " << device_path << " is " << buffer << "."; | 75 USB_LOG(DEBUG) << "Driver for " << device_path << " is " << buffer << "."; |
| 76 if (base::StartsWith(buffer, "WinUSB", base::CompareCase::INSENSITIVE_ASCII)) | 76 if (base::StartsWith(buffer, "WinUSB", base::CompareCase::INSENSITIVE_ASCII)) |
| 77 return true; | 77 return true; |
| 78 return false; | 78 return false; |
| 79 } | 79 } |
| 80 | 80 |
| 81 #endif // OS_WIN | 81 #endif // OS_WIN |
| 82 | 82 |
| 83 void InitializeUsbContextOnBlockingThread( |
| 84 scoped_refptr<base::SequencedTaskRunner> task_runner, |
| 85 const base::Callback<void(scoped_refptr<UsbContext>)>& callback) { |
| 86 scoped_refptr<UsbContext> context; |
| 87 PlatformUsbContext platform_context = nullptr; |
| 88 int rv = libusb_init(&platform_context); |
| 89 if (rv == LIBUSB_SUCCESS && platform_context) { |
| 90 context = new UsbContext(platform_context); |
| 91 } else { |
| 92 USB_LOG(DEBUG) << "Failed to initialize libusb: " |
| 93 << ConvertPlatformUsbErrorToString(rv); |
| 94 } |
| 95 |
| 96 task_runner->PostTask(FROM_HERE, |
| 97 base::Bind(callback, base::Passed(&context))); |
| 98 } |
| 99 |
| 83 void GetDeviceListOnBlockingThread( | 100 void GetDeviceListOnBlockingThread( |
| 84 const std::string& new_device_path, | 101 const std::string& new_device_path, |
| 85 scoped_refptr<UsbContext> usb_context, | 102 scoped_refptr<UsbContext> usb_context, |
| 86 scoped_refptr<base::SequencedTaskRunner> task_runner, | 103 scoped_refptr<base::SequencedTaskRunner> task_runner, |
| 87 base::Callback<void(libusb_device**, size_t)> callback) { | 104 const base::Callback<void(libusb_device**, size_t)>& callback) { |
| 88 #if defined(OS_WIN) | 105 #if defined(OS_WIN) |
| 89 if (!new_device_path.empty()) { | 106 if (!new_device_path.empty()) { |
| 90 if (!IsWinUsbInterface(new_device_path)) { | 107 if (!IsWinUsbInterface(new_device_path)) { |
| 91 // Wait to call libusb_get_device_list until libusb will be able to find | 108 // Wait to call libusb_get_device_list until libusb will be able to find |
| 92 // a WinUSB interface for the device. | 109 // a WinUSB interface for the device. |
| 93 task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr, 0)); | 110 task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr, 0)); |
| 94 return; | 111 return; |
| 95 } | 112 } |
| 96 } | 113 } |
| 97 #endif // defined(OS_WIN) | 114 #endif // defined(OS_WIN) |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 | 214 |
| 198 } // namespace | 215 } // namespace |
| 199 | 216 |
| 200 UsbServiceImpl::UsbServiceImpl( | 217 UsbServiceImpl::UsbServiceImpl( |
| 201 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) | 218 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) |
| 202 : UsbService(base::ThreadTaskRunnerHandle::Get(), blocking_task_runner), | 219 : UsbService(base::ThreadTaskRunnerHandle::Get(), blocking_task_runner), |
| 203 #if defined(OS_WIN) | 220 #if defined(OS_WIN) |
| 204 device_observer_(this), | 221 device_observer_(this), |
| 205 #endif | 222 #endif |
| 206 weak_factory_(this) { | 223 weak_factory_(this) { |
| 207 PlatformUsbContext platform_context = nullptr; | 224 blocking_task_runner->PostTask( |
| 208 int rv = libusb_init(&platform_context); | 225 FROM_HERE, base::Bind(&InitializeUsbContextOnBlockingThread, |
| 209 if (rv != LIBUSB_SUCCESS || !platform_context) { | 226 base::ThreadTaskRunnerHandle::Get(), |
| 210 USB_LOG(DEBUG) << "Failed to initialize libusb: " | 227 base::Bind(&UsbServiceImpl::OnUsbContext, |
| 211 << ConvertPlatformUsbErrorToString(rv); | 228 weak_factory_.GetWeakPtr()))); |
| 212 return; | |
| 213 } | |
| 214 context_ = new UsbContext(platform_context); | |
| 215 | |
| 216 rv = libusb_hotplug_register_callback( | |
| 217 context_->context(), | |
| 218 static_cast<libusb_hotplug_event>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | | |
| 219 LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT), | |
| 220 static_cast<libusb_hotplug_flag>(0), LIBUSB_HOTPLUG_MATCH_ANY, | |
| 221 LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, | |
| 222 &UsbServiceImpl::HotplugCallback, this, &hotplug_handle_); | |
| 223 if (rv == LIBUSB_SUCCESS) { | |
| 224 hotplug_enabled_ = true; | |
| 225 } | |
| 226 | |
| 227 RefreshDevices(); | |
| 228 #if defined(OS_WIN) | |
| 229 DeviceMonitorWin* device_monitor = DeviceMonitorWin::GetForAllInterfaces(); | |
| 230 if (device_monitor) { | |
| 231 device_observer_.Add(device_monitor); | |
| 232 } | |
| 233 #endif // OS_WIN | |
| 234 } | 229 } |
| 235 | 230 |
| 236 UsbServiceImpl::~UsbServiceImpl() { | 231 UsbServiceImpl::~UsbServiceImpl() { |
| 237 if (hotplug_enabled_) | 232 if (hotplug_enabled_) |
| 238 libusb_hotplug_deregister_callback(context_->context(), hotplug_handle_); | 233 libusb_hotplug_deregister_callback(context_->context(), hotplug_handle_); |
| 239 for (auto* platform_device : ignored_devices_) | 234 for (auto* platform_device : ignored_devices_) |
| 240 libusb_unref_device(platform_device); | 235 libusb_unref_device(platform_device); |
| 241 } | 236 } |
| 242 | 237 |
| 243 void UsbServiceImpl::GetDevices(const GetDevicesCallback& callback) { | 238 void UsbServiceImpl::GetDevices(const GetDevicesCallback& callback) { |
| 244 DCHECK(CalledOnValidThread()); | 239 DCHECK(CalledOnValidThread()); |
| 245 | 240 |
| 246 if (!context_) { | 241 if (usb_unavailable_) { |
| 247 task_runner()->PostTask( | 242 task_runner()->PostTask( |
| 248 FROM_HERE, | 243 FROM_HERE, |
| 249 base::Bind(callback, std::vector<scoped_refptr<UsbDevice>>())); | 244 base::Bind(callback, std::vector<scoped_refptr<UsbDevice>>())); |
| 250 return; | 245 return; |
| 251 } | 246 } |
| 252 | 247 |
| 253 if (hotplug_enabled_ && !enumeration_in_progress_) { | 248 if (hotplug_enabled_ && !enumeration_in_progress_) { |
| 254 // The device list is updated live when hotplug events are supported. | 249 // The device list is updated live when hotplug events are supported. |
| 255 UsbService::GetDevices(callback); | 250 UsbService::GetDevices(callback); |
| 256 } else { | 251 } else { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 277 void UsbServiceImpl::OnDeviceRemoved(const GUID& class_guid, | 272 void UsbServiceImpl::OnDeviceRemoved(const GUID& class_guid, |
| 278 const std::string& device_path) { | 273 const std::string& device_path) { |
| 279 // The root USB device node is removed last. | 274 // The root USB device node is removed last. |
| 280 if (class_guid == GUID_DEVINTERFACE_USB_DEVICE) { | 275 if (class_guid == GUID_DEVINTERFACE_USB_DEVICE) { |
| 281 RefreshDevices(); | 276 RefreshDevices(); |
| 282 } | 277 } |
| 283 } | 278 } |
| 284 | 279 |
| 285 #endif // OS_WIN | 280 #endif // OS_WIN |
| 286 | 281 |
| 287 void UsbServiceImpl::RefreshDevices() { | 282 void UsbServiceImpl::OnUsbContext(scoped_refptr<UsbContext> context) { |
| 288 DCHECK(CalledOnValidThread()); | 283 if (!context) { |
| 289 DCHECK(context_); | 284 usb_unavailable_ = true; |
| 290 | |
| 291 if (enumeration_in_progress_) { | |
| 292 return; | 285 return; |
| 293 } | 286 } |
| 294 | 287 |
| 288 context_ = std::move(context); |
| 289 |
| 290 int rv = libusb_hotplug_register_callback( |
| 291 context_->context(), |
| 292 static_cast<libusb_hotplug_event>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | |
| 293 LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT), |
| 294 static_cast<libusb_hotplug_flag>(0), LIBUSB_HOTPLUG_MATCH_ANY, |
| 295 LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, |
| 296 &UsbServiceImpl::HotplugCallback, this, &hotplug_handle_); |
| 297 if (rv == LIBUSB_SUCCESS) |
| 298 hotplug_enabled_ = true; |
| 299 |
| 300 // This will call any enumeration callbacks queued while initializing. |
| 301 RefreshDevices(); |
| 302 |
| 303 #if defined(OS_WIN) |
| 304 DeviceMonitorWin* device_monitor = DeviceMonitorWin::GetForAllInterfaces(); |
| 305 if (device_monitor) |
| 306 device_observer_.Add(device_monitor); |
| 307 #endif // OS_WIN |
| 308 } |
| 309 |
| 310 void UsbServiceImpl::RefreshDevices() { |
| 311 DCHECK(CalledOnValidThread()); |
| 312 |
| 313 if (!context_ || enumeration_in_progress_) |
| 314 return; |
| 315 |
| 295 enumeration_in_progress_ = true; | 316 enumeration_in_progress_ = true; |
| 296 DCHECK(devices_being_enumerated_.empty()); | 317 DCHECK(devices_being_enumerated_.empty()); |
| 297 | 318 |
| 298 std::string device_path; | 319 std::string device_path; |
| 299 if (!pending_path_enumerations_.empty()) { | 320 if (!pending_path_enumerations_.empty()) { |
| 300 device_path = pending_path_enumerations_.front(); | 321 device_path = pending_path_enumerations_.front(); |
| 301 pending_path_enumerations_.pop(); | 322 pending_path_enumerations_.pop(); |
| 302 } | 323 } |
| 303 | 324 |
| 304 blocking_task_runner()->PostTask( | 325 blocking_task_runner()->PostTask( |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 480 // static | 501 // static |
| 481 int LIBUSB_CALL UsbServiceImpl::HotplugCallback(libusb_context* context, | 502 int LIBUSB_CALL UsbServiceImpl::HotplugCallback(libusb_context* context, |
| 482 PlatformUsbDevice device, | 503 PlatformUsbDevice device, |
| 483 libusb_hotplug_event event, | 504 libusb_hotplug_event event, |
| 484 void* user_data) { | 505 void* user_data) { |
| 485 // It is safe to access the UsbServiceImpl* here because libusb takes a lock | 506 // It is safe to access the UsbServiceImpl* here because libusb takes a lock |
| 486 // around registering, deregistering and calling hotplug callback functions | 507 // around registering, deregistering and calling hotplug callback functions |
| 487 // and so guarantees that this function will not be called by the event | 508 // and so guarantees that this function will not be called by the event |
| 488 // processing thread after it has been deregistered. | 509 // processing thread after it has been deregistered. |
| 489 UsbServiceImpl* self = reinterpret_cast<UsbServiceImpl*>(user_data); | 510 UsbServiceImpl* self = reinterpret_cast<UsbServiceImpl*>(user_data); |
| 511 DCHECK(!self->task_runner()->BelongsToCurrentThread()); |
| 490 switch (event) { | 512 switch (event) { |
| 491 case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: | 513 case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: |
| 492 libusb_ref_device(device); // Released in OnPlatformDeviceAdded. | 514 libusb_ref_device(device); // Released in OnPlatformDeviceAdded. |
| 493 if (self->task_runner()->BelongsToCurrentThread()) { | 515 self->task_runner()->PostTask( |
| 494 self->OnPlatformDeviceAdded(device); | 516 FROM_HERE, base::Bind(&UsbServiceImpl::OnPlatformDeviceAdded, |
| 495 } else { | 517 base::Unretained(self), device)); |
| 496 self->task_runner()->PostTask( | |
| 497 FROM_HERE, base::Bind(&UsbServiceImpl::OnPlatformDeviceAdded, | |
| 498 base::Unretained(self), device)); | |
| 499 } | |
| 500 break; | 518 break; |
| 501 case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: | 519 case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: |
| 502 libusb_ref_device(device); // Released in OnPlatformDeviceRemoved. | 520 libusb_ref_device(device); // Released in OnPlatformDeviceRemoved. |
| 503 if (self->task_runner()->BelongsToCurrentThread()) { | 521 self->task_runner()->PostTask( |
| 504 self->OnPlatformDeviceRemoved(device); | 522 FROM_HERE, base::Bind(&UsbServiceImpl::OnPlatformDeviceRemoved, |
| 505 } else { | 523 base::Unretained(self), device)); |
| 506 self->task_runner()->PostTask( | |
| 507 FROM_HERE, base::Bind(&UsbServiceImpl::OnPlatformDeviceRemoved, | |
| 508 base::Unretained(self), device)); | |
| 509 } | |
| 510 break; | 524 break; |
| 511 default: | 525 default: |
| 512 NOTREACHED(); | 526 NOTREACHED(); |
| 513 } | 527 } |
| 514 | 528 |
| 515 return 0; | 529 return 0; |
| 516 } | 530 } |
| 517 | 531 |
| 518 void UsbServiceImpl::OnPlatformDeviceAdded(PlatformUsbDevice platform_device) { | 532 void UsbServiceImpl::OnPlatformDeviceAdded(PlatformUsbDevice platform_device) { |
| 519 DCHECK(CalledOnValidThread()); | 533 DCHECK(CalledOnValidThread()); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 535 } | 549 } |
| 536 | 550 |
| 537 void UsbServiceImpl::EnumerationFailed(PlatformUsbDevice platform_device, | 551 void UsbServiceImpl::EnumerationFailed(PlatformUsbDevice platform_device, |
| 538 const base::Closure& refresh_complete) { | 552 const base::Closure& refresh_complete) { |
| 539 libusb_ref_device(platform_device); | 553 libusb_ref_device(platform_device); |
| 540 ignored_devices_.insert(platform_device); | 554 ignored_devices_.insert(platform_device); |
| 541 refresh_complete.Run(); | 555 refresh_complete.Run(); |
| 542 } | 556 } |
| 543 | 557 |
| 544 } // namespace device | 558 } // namespace device |
| OLD | NEW |