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

Side by Side Diff: chrome/browser/usb/usb_service.cc

Issue 10382204: Use a detached platform thread to handle USB events. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Minor formatting. Created 8 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « chrome/browser/usb/usb_service.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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "chrome/browser/usb/usb_service.h" 5 #include "chrome/browser/usb/usb_service.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/logging.h"
9 #include "base/stl_util.h" 10 #include "base/stl_util.h"
10 #include "chrome/browser/usb/usb_device.h" 11 #include "chrome/browser/usb/usb_device.h"
11 #include "third_party/libusb/libusb.h" 12 #include "third_party/libusb/libusb.h"
12 13
13 UsbService::UsbService() : running_(true), thread_("UsbThread") { 14 // The UsbEventHandler works around a design flaw in the libusb interface. There
15 // is currently no way to signal to libusb that any caller into one of the event
16 // handler calls should return without handling any events.
17 class UsbEventHandler : public base::PlatformThread::Delegate {
18 public:
19 explicit UsbEventHandler(PlatformUsbContext context)
20 : running_(true), context_(context) {
21 base::PlatformThread::CreateNonJoinable(0, this);
22 }
23
24 virtual ~UsbEventHandler() {}
25
26 virtual void ThreadMain() {
27 base::PlatformThread::SetName("UsbEventHandler");
28
29 DLOG(INFO) << "UsbEventHandler started.";
30 while (running_) {
31 libusb_handle_events(context_);
32 }
33 DLOG(INFO) << "UsbEventHandler shutting down.";
34 libusb_exit(context_);
35
36 delete this;
37 }
38
39 void Stop() {
40 running_ = false;
41 }
42
43 private:
44 bool running_;
45 PlatformUsbContext context_;
46
47 DISALLOW_EVIL_CONSTRUCTORS(UsbEventHandler);
48 };
49
50 UsbService::UsbService() {
14 libusb_init(&context_); 51 libusb_init(&context_);
15 thread_.Start(); 52 event_handler_ = new UsbEventHandler(context_);
16 PostHandleEventTask();
17 } 53 }
18 54
19 UsbService::~UsbService() {} 55 UsbService::~UsbService() {}
20 56
21 // TODO(gdk): There is currently no clean way to indicate to the event handler
22 // thread that it must break out of the handling loop before the event timeout,
23 // therefore we currently are at the whim of the event handler timeout before
24 // the message handling thread can be joined.
25 void UsbService::Cleanup() { 57 void UsbService::Cleanup() {
26 running_ = false; 58 event_handler_->Stop();
27 59 event_handler_ = NULL;
28 if (!devices_.empty()) {
29 libusb_close(devices_.begin()->second->handle());
30 } else {
31 LOG(WARNING) << "UsbService cannot force the USB event-handler thread to "
32 << "exit because there are no open devices with which to "
33 << "manipulate it. It maybe take up to 60 (!) seconds for the "
34 << "thread to join from this point.";
35 }
36
37 thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
38 &UsbService::PlatformShutdown, base::Unretained(this)));
39 } 60 }
40 61
41 UsbDevice* UsbService::FindDevice(const uint16 vendor_id, 62 UsbDevice* UsbService::FindDevice(const uint16 vendor_id,
42 const uint16 product_id) { 63 const uint16 product_id) {
64 DCHECK(event_handler_) << "FindDevice called after event handler stopped.";
65
43 const std::pair<uint16, uint16> key = std::make_pair(vendor_id, product_id); 66 const std::pair<uint16, uint16> key = std::make_pair(vendor_id, product_id);
44 if (ContainsKey(devices_, key)) { 67 if (ContainsKey(devices_, key)) {
45 return devices_[key]; 68 return devices_[key];
46 } 69 }
47 70
48 libusb_device_handle* const handle = libusb_open_device_with_vid_pid( 71 libusb_device_handle* const handle = libusb_open_device_with_vid_pid(
49 context_, vendor_id, product_id); 72 context_, vendor_id, product_id);
50 if (!handle) { 73 if (!handle) {
51 return NULL; 74 return NULL;
52 } 75 }
53 76
54 UsbDevice* const device = new UsbDevice(this, handle); 77 UsbDevice* const device = new UsbDevice(this, handle);
55 devices_[key] = device; 78 devices_[key] = device;
56 79
57 return device; 80 return device;
58 } 81 }
59 82
60 void UsbService::CloseDevice(scoped_refptr<UsbDevice> device) { 83 void UsbService::CloseDevice(scoped_refptr<UsbDevice> device) {
61 DCHECK(running_) << "Cannot close device after service has stopped running."; 84 DCHECK(event_handler_) << "CloseDevice called after event handler stopped.";
62 85
63 for (DeviceMap::iterator i = devices_.begin(); i != devices_.end(); ++i) { 86 for (DeviceMap::iterator i = devices_.begin(); i != devices_.end(); ++i) {
64 if (i->second.get() == device.get()) { 87 if (i->second.get() == device.get()) {
65 devices_.erase(i); 88 devices_.erase(i);
66 libusb_close(device->handle()); 89 libusb_close(device->handle());
67 return; 90 return;
68 } 91 }
69 } 92 }
70 } 93 }
71
72 void UsbService::PostHandleEventTask() {
73 thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
74 &UsbService::HandleEvent, base::Unretained(this)));
75 }
76
77 void UsbService::HandleEvent() {
78 libusb_handle_events(context_);
79 if (running_) {
80 PostHandleEventTask();
81 }
82 }
83
84 void UsbService::PlatformShutdown() {
85 libusb_exit(context_);
86 }
OLDNEW
« no previous file with comments | « chrome/browser/usb/usb_service.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698