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

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

Issue 2557073004: Call libusb_init on the FILE thread. (Closed)
Patch Set: Created 4 years 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
« device/usb/usb_service_impl.h ('K') | « 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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
OLDNEW
« device/usb/usb_service_impl.h ('K') | « device/usb/usb_service_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698