| 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.h" | 5 #include "device/usb/usb_service_impl.h" |
| 6 | 6 |
| 7 #include <map> | |
| 8 #include <set> | 7 #include <set> |
| 9 | 8 |
| 10 #include "base/bind.h" | 9 #include "base/bind.h" |
| 11 #include "base/lazy_instance.h" | 10 #include "base/location.h" |
| 12 #include "base/memory/weak_ptr.h" | 11 #include "base/memory/weak_ptr.h" |
| 13 #include "base/message_loop/message_loop.h" | |
| 14 #include "base/single_thread_task_runner.h" | 12 #include "base/single_thread_task_runner.h" |
| 15 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
| 16 #include "base/thread_task_runner_handle.h" | 14 #include "base/thread_task_runner_handle.h" |
| 17 #include "device/usb/usb_context.h" | |
| 18 #include "device/usb/usb_device_impl.h" | |
| 19 #include "device/usb/usb_error.h" | 15 #include "device/usb/usb_error.h" |
| 20 #include "third_party/libusb/src/libusb/libusb.h" | |
| 21 | 16 |
| 22 #if defined(OS_WIN) | 17 #if defined(OS_WIN) |
| 23 #include <usbiodef.h> | 18 #include <usbiodef.h> |
| 24 | 19 |
| 25 #include "base/scoped_observer.h" | 20 #include "base/scoped_observer.h" |
| 26 #include "device/core/device_monitor_win.h" | 21 #include "device/core/device_monitor_win.h" |
| 27 #endif // OS_WIN | 22 #endif // OS_WIN |
| 28 | 23 |
| 29 namespace device { | 24 namespace device { |
| 30 | 25 |
| 31 namespace { | |
| 32 | |
| 33 base::LazyInstance<scoped_ptr<UsbService> >::Leaky g_usb_service_instance = | |
| 34 LAZY_INSTANCE_INITIALIZER; | |
| 35 | |
| 36 } // namespace | |
| 37 | |
| 38 typedef struct libusb_device* PlatformUsbDevice; | |
| 39 typedef struct libusb_context* PlatformUsbContext; | |
| 40 | |
| 41 class UsbServiceImpl : public UsbService, | |
| 42 private base::MessageLoop::DestructionObserver { | |
| 43 public: | |
| 44 explicit UsbServiceImpl( | |
| 45 PlatformUsbContext context, | |
| 46 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner); | |
| 47 ~UsbServiceImpl() override; | |
| 48 | |
| 49 private: | |
| 50 // device::UsbService implementation | |
| 51 scoped_refptr<UsbDevice> GetDeviceById(uint32 unique_id) override; | |
| 52 void GetDevices(std::vector<scoped_refptr<UsbDevice>>* devices) override; | |
| 53 | |
| 54 // base::MessageLoop::DestructionObserver implementation. | |
| 55 void WillDestroyCurrentMessageLoop() override; | |
| 56 | |
| 57 // Enumerate USB devices from OS and update devices_ map. | |
| 58 void RefreshDevices(); | |
| 59 | |
| 60 // Adds a new UsbDevice to the devices_ map based on the given libusb device. | |
| 61 scoped_refptr<UsbDeviceImpl> AddDevice(PlatformUsbDevice platform_device); | |
| 62 | |
| 63 // Handle hotplug events from libusb. | |
| 64 static int LIBUSB_CALL HotplugCallback(libusb_context* context, | |
| 65 PlatformUsbDevice device, | |
| 66 libusb_hotplug_event event, | |
| 67 void* user_data); | |
| 68 // These functions release a reference to the provided platform device. | |
| 69 void OnDeviceAdded(PlatformUsbDevice platform_device); | |
| 70 void OnDeviceRemoved(PlatformUsbDevice platform_device); | |
| 71 | |
| 72 scoped_refptr<UsbContext> context_; | |
| 73 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | |
| 74 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; | |
| 75 | |
| 76 #if defined(OS_WIN) | |
| 77 class UIThreadHelper; | |
| 78 UIThreadHelper* ui_thread_helper_; | |
| 79 #endif // OS_WIN | |
| 80 | |
| 81 // TODO(reillyg): Figure out a better solution for device IDs. | |
| 82 uint32 next_unique_id_; | |
| 83 | |
| 84 // When available the device list will be updated when new devices are | |
| 85 // connected instead of only when a full enumeration is requested. | |
| 86 // TODO(reillyg): Support this on all platforms. crbug.com/411715 | |
| 87 bool hotplug_enabled_; | |
| 88 libusb_hotplug_callback_handle hotplug_handle_; | |
| 89 | |
| 90 // The map from unique IDs to UsbDevices. | |
| 91 typedef std::map<uint32, scoped_refptr<UsbDeviceImpl> > DeviceMap; | |
| 92 DeviceMap devices_; | |
| 93 | |
| 94 // The map from PlatformUsbDevices to UsbDevices. | |
| 95 typedef std::map<PlatformUsbDevice, scoped_refptr<UsbDeviceImpl> > | |
| 96 PlatformDeviceMap; | |
| 97 PlatformDeviceMap platform_devices_; | |
| 98 | |
| 99 base::WeakPtrFactory<UsbServiceImpl> weak_factory_; | |
| 100 | |
| 101 DISALLOW_COPY_AND_ASSIGN(UsbServiceImpl); | |
| 102 }; | |
| 103 | |
| 104 #if defined(OS_WIN) | 26 #if defined(OS_WIN) |
| 105 // This class lives on the application main thread so that it can listen for | 27 // This class lives on the application main thread so that it can listen for |
| 106 // device change notification window messages. It registers for notifications | 28 // device change notification window messages. It registers for notifications |
| 107 // regarding devices implementating the "UsbDevice" interface, which represents | 29 // regarding devices implementating the "UsbDevice" interface, which represents |
| 108 // most of the devices the UsbService will enumerate. | 30 // most of the devices the UsbService will enumerate. |
| 109 class UsbServiceImpl::UIThreadHelper : DeviceMonitorWin::Observer { | 31 class UsbServiceImpl::UIThreadHelper : DeviceMonitorWin::Observer { |
| 110 public: | 32 public: |
| 111 UIThreadHelper(base::WeakPtr<UsbServiceImpl> usb_service) | 33 UIThreadHelper(base::WeakPtr<UsbServiceImpl> usb_service) |
| 112 : task_runner_(base::ThreadTaskRunnerHandle::Get()), | 34 : task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 113 usb_service_(usb_service), | 35 usb_service_(usb_service), |
| (...skipping 19 matching lines...) Expand all Loading... |
| 133 task_runner_->PostTask( | 55 task_runner_->PostTask( |
| 134 FROM_HERE, base::Bind(&UsbServiceImpl::RefreshDevices, usb_service_)); | 56 FROM_HERE, base::Bind(&UsbServiceImpl::RefreshDevices, usb_service_)); |
| 135 } | 57 } |
| 136 | 58 |
| 137 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | 59 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| 138 base::WeakPtr<UsbServiceImpl> usb_service_; | 60 base::WeakPtr<UsbServiceImpl> usb_service_; |
| 139 ScopedObserver<DeviceMonitorWin, DeviceMonitorWin::Observer> device_observer_; | 61 ScopedObserver<DeviceMonitorWin, DeviceMonitorWin::Observer> device_observer_; |
| 140 }; | 62 }; |
| 141 #endif | 63 #endif |
| 142 | 64 |
| 65 // static |
| 66 UsbService* UsbServiceImpl::Create( |
| 67 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { |
| 68 PlatformUsbContext context = NULL; |
| 69 const int rv = libusb_init(&context); |
| 70 if (rv != LIBUSB_SUCCESS) { |
| 71 VLOG(1) << "Failed to initialize libusb: " |
| 72 << ConvertPlatformUsbErrorToString(rv); |
| 73 return nullptr; |
| 74 } |
| 75 if (!context) { |
| 76 return nullptr; |
| 77 } |
| 78 |
| 79 return new UsbServiceImpl(context, ui_task_runner); |
| 80 } |
| 81 |
| 143 scoped_refptr<UsbDevice> UsbServiceImpl::GetDeviceById(uint32 unique_id) { | 82 scoped_refptr<UsbDevice> UsbServiceImpl::GetDeviceById(uint32 unique_id) { |
| 144 DCHECK(CalledOnValidThread()); | 83 DCHECK(CalledOnValidThread()); |
| 145 RefreshDevices(); | 84 RefreshDevices(); |
| 146 DeviceMap::iterator it = devices_.find(unique_id); | 85 DeviceMap::iterator it = devices_.find(unique_id); |
| 147 if (it != devices_.end()) { | 86 if (it != devices_.end()) { |
| 148 return it->second; | 87 return it->second; |
| 149 } | 88 } |
| 150 return NULL; | 89 return NULL; |
| 151 } | 90 } |
| 152 | 91 |
| 153 void UsbServiceImpl::GetDevices( | 92 void UsbServiceImpl::GetDevices( |
| 154 std::vector<scoped_refptr<UsbDevice> >* devices) { | 93 std::vector<scoped_refptr<UsbDevice> >* devices) { |
| 155 DCHECK(CalledOnValidThread()); | 94 DCHECK(CalledOnValidThread()); |
| 156 STLClearObject(devices); | 95 STLClearObject(devices); |
| 157 | 96 |
| 158 if (!hotplug_enabled_) { | 97 if (!hotplug_enabled_) { |
| 159 RefreshDevices(); | 98 RefreshDevices(); |
| 160 } | 99 } |
| 161 | 100 |
| 162 for (const auto& map_entry : devices_) { | 101 for (const auto& map_entry : devices_) { |
| 163 devices->push_back(map_entry.second); | 102 devices->push_back(map_entry.second); |
| 164 } | 103 } |
| 165 } | 104 } |
| 166 | 105 |
| 167 void UsbServiceImpl::WillDestroyCurrentMessageLoop() { | |
| 168 DCHECK(CalledOnValidThread()); | |
| 169 g_usb_service_instance.Get().reset(NULL); | |
| 170 } | |
| 171 | |
| 172 UsbServiceImpl::UsbServiceImpl( | 106 UsbServiceImpl::UsbServiceImpl( |
| 173 PlatformUsbContext context, | 107 PlatformUsbContext context, |
| 174 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) | 108 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) |
| 175 : context_(new UsbContext(context)), | 109 : context_(new UsbContext(context)), |
| 176 ui_task_runner_(ui_task_runner), | 110 ui_task_runner_(ui_task_runner), |
| 177 next_unique_id_(0), | 111 next_unique_id_(0), |
| 178 hotplug_enabled_(false), | 112 hotplug_enabled_(false), |
| 179 weak_factory_(this) { | 113 weak_factory_(this) { |
| 180 base::MessageLoop::current()->AddDestructionObserver(this); | |
| 181 task_runner_ = base::ThreadTaskRunnerHandle::Get(); | 114 task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
| 182 int rv = libusb_hotplug_register_callback( | 115 int rv = libusb_hotplug_register_callback( |
| 183 context_->context(), | 116 context_->context(), |
| 184 static_cast<libusb_hotplug_event>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | | 117 static_cast<libusb_hotplug_event>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | |
| 185 LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT), | 118 LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT), |
| 186 LIBUSB_HOTPLUG_ENUMERATE, LIBUSB_HOTPLUG_MATCH_ANY, | 119 LIBUSB_HOTPLUG_ENUMERATE, LIBUSB_HOTPLUG_MATCH_ANY, |
| 187 LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, | 120 LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, |
| 188 &UsbServiceImpl::HotplugCallback, this, &hotplug_handle_); | 121 &UsbServiceImpl::HotplugCallback, this, &hotplug_handle_); |
| 189 if (rv == LIBUSB_SUCCESS) { | 122 if (rv == LIBUSB_SUCCESS) { |
| 190 hotplug_enabled_ = true; | 123 hotplug_enabled_ = true; |
| 191 } else { | 124 } else { |
| 192 #if defined(OS_WIN) | 125 #if defined(OS_WIN) |
| 193 ui_thread_helper_ = new UIThreadHelper(weak_factory_.GetWeakPtr()); | 126 ui_thread_helper_ = new UIThreadHelper(weak_factory_.GetWeakPtr()); |
| 194 ui_task_runner_->PostTask(FROM_HERE, | 127 ui_task_runner_->PostTask(FROM_HERE, |
| 195 base::Bind(&UIThreadHelper::Start, | 128 base::Bind(&UIThreadHelper::Start, |
| 196 base::Unretained(ui_thread_helper_))); | 129 base::Unretained(ui_thread_helper_))); |
| 197 #endif // OS_WIN | 130 #endif // OS_WIN |
| 198 } | 131 } |
| 199 } | 132 } |
| 200 | 133 |
| 201 UsbServiceImpl::~UsbServiceImpl() { | 134 UsbServiceImpl::~UsbServiceImpl() { |
| 202 base::MessageLoop::current()->RemoveDestructionObserver(this); | |
| 203 if (hotplug_enabled_) { | 135 if (hotplug_enabled_) { |
| 204 libusb_hotplug_deregister_callback(context_->context(), hotplug_handle_); | 136 libusb_hotplug_deregister_callback(context_->context(), hotplug_handle_); |
| 205 } | 137 } |
| 206 #if defined(OS_WIN) | 138 #if defined(OS_WIN) |
| 207 if (ui_thread_helper_) { | 139 if (ui_thread_helper_) { |
| 208 ui_task_runner_->DeleteSoon(FROM_HERE, ui_thread_helper_); | 140 ui_task_runner_->DeleteSoon(FROM_HERE, ui_thread_helper_); |
| 209 } | 141 } |
| 210 #endif // OS_WIN | 142 #endif // OS_WIN |
| 211 for (const auto& map_entry : devices_) { | 143 for (const auto& map_entry : devices_) { |
| 212 map_entry.second->OnDisconnect(); | 144 map_entry.second->OnDisconnect(); |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 348 | 280 |
| 349 NotifyDeviceRemoved(device); | 281 NotifyDeviceRemoved(device); |
| 350 device->OnDisconnect(); | 282 device->OnDisconnect(); |
| 351 } else { | 283 } else { |
| 352 NOTREACHED(); | 284 NOTREACHED(); |
| 353 } | 285 } |
| 354 | 286 |
| 355 libusb_unref_device(platform_device); | 287 libusb_unref_device(platform_device); |
| 356 } | 288 } |
| 357 | 289 |
| 358 void UsbService::Observer::OnDeviceAdded(scoped_refptr<UsbDevice> device) { | |
| 359 } | |
| 360 | |
| 361 void UsbService::Observer::OnDeviceRemoved(scoped_refptr<UsbDevice> device) { | |
| 362 } | |
| 363 | |
| 364 // static | |
| 365 UsbService* UsbService::GetInstance( | |
| 366 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { | |
| 367 UsbService* instance = g_usb_service_instance.Get().get(); | |
| 368 if (!instance) { | |
| 369 PlatformUsbContext context = NULL; | |
| 370 | |
| 371 const int rv = libusb_init(&context); | |
| 372 if (rv != LIBUSB_SUCCESS) { | |
| 373 VLOG(1) << "Failed to initialize libusb: " | |
| 374 << ConvertPlatformUsbErrorToString(rv); | |
| 375 return NULL; | |
| 376 } | |
| 377 if (!context) | |
| 378 return NULL; | |
| 379 | |
| 380 instance = new UsbServiceImpl(context, ui_task_runner); | |
| 381 g_usb_service_instance.Get().reset(instance); | |
| 382 } | |
| 383 return instance; | |
| 384 } | |
| 385 | |
| 386 // static | |
| 387 void UsbService::SetInstanceForTest(UsbService* instance) { | |
| 388 g_usb_service_instance.Get().reset(instance); | |
| 389 } | |
| 390 | |
| 391 UsbService::UsbService() { | |
| 392 } | |
| 393 | |
| 394 UsbService::~UsbService() { | |
| 395 } | |
| 396 | |
| 397 void UsbService::AddObserver(Observer* observer) { | |
| 398 DCHECK(CalledOnValidThread()); | |
| 399 observer_list_.AddObserver(observer); | |
| 400 } | |
| 401 | |
| 402 void UsbService::RemoveObserver(Observer* observer) { | |
| 403 DCHECK(CalledOnValidThread()); | |
| 404 observer_list_.RemoveObserver(observer); | |
| 405 } | |
| 406 | |
| 407 void UsbService::NotifyDeviceAdded(scoped_refptr<UsbDevice> device) { | |
| 408 DCHECK(CalledOnValidThread()); | |
| 409 FOR_EACH_OBSERVER(Observer, observer_list_, OnDeviceAdded(device)); | |
| 410 } | |
| 411 | |
| 412 void UsbService::NotifyDeviceRemoved(scoped_refptr<UsbDevice> device) { | |
| 413 DCHECK(CalledOnValidThread()); | |
| 414 FOR_EACH_OBSERVER(Observer, observer_list_, OnDeviceRemoved(device)); | |
| 415 } | |
| 416 | |
| 417 } // namespace device | 290 } // namespace device |
| OLD | NEW |