OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "components/usb_service/usb_device_impl.h" | |
6 | |
7 #include <algorithm> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/location.h" | |
11 #include "base/single_thread_task_runner.h" | |
12 #include "base/stl_util.h" | |
13 #include "base/thread_task_runner_handle.h" | |
14 #include "components/usb_service/usb_context.h" | |
15 #include "components/usb_service/usb_device_handle_impl.h" | |
16 #include "components/usb_service/usb_error.h" | |
17 #include "components/usb_service/usb_interface_impl.h" | |
18 #include "third_party/libusb/src/libusb/libusb.h" | |
19 | |
20 #if defined(OS_CHROMEOS) | |
21 #include "base/sys_info.h" | |
22 #include "chromeos/dbus/dbus_thread_manager.h" | |
23 #include "chromeos/dbus/permission_broker_client.h" | |
24 #endif // defined(OS_CHROMEOS) | |
25 | |
26 namespace { | |
27 | |
28 #if defined(OS_CHROMEOS) | |
29 void OnRequestUsbAccessReplied( | |
30 scoped_refptr<base::SingleThreadTaskRunner> task_runner, | |
31 const base::Callback<void(bool success)>& callback, | |
32 bool success) { | |
33 task_runner->PostTask(FROM_HERE, base::Bind(callback, success)); | |
34 } | |
35 #endif // defined(OS_CHROMEOS) | |
36 | |
37 } // namespace | |
38 | |
39 namespace usb_service { | |
40 | |
41 UsbDeviceImpl::UsbDeviceImpl( | |
42 scoped_refptr<UsbContext> context, | |
43 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, | |
44 PlatformUsbDevice platform_device, | |
45 uint16 vendor_id, | |
46 uint16 product_id, | |
47 uint32 unique_id) | |
48 : UsbDevice(vendor_id, product_id, unique_id), | |
49 platform_device_(platform_device), | |
50 context_(context), | |
51 ui_task_runner_(ui_task_runner) { | |
52 CHECK(platform_device) << "platform_device cannot be NULL"; | |
53 libusb_ref_device(platform_device); | |
54 } | |
55 | |
56 UsbDeviceImpl::~UsbDeviceImpl() { | |
57 DCHECK(thread_checker_.CalledOnValidThread()); | |
58 for (HandlesVector::iterator it = handles_.begin(); it != handles_.end(); | |
59 ++it) { | |
60 (*it)->InternalClose(); | |
61 } | |
62 STLClearObject(&handles_); | |
63 libusb_unref_device(platform_device_); | |
64 } | |
65 | |
66 #if defined(OS_CHROMEOS) | |
67 | |
68 void UsbDeviceImpl::RequestUsbAccess( | |
69 int interface_id, | |
70 const base::Callback<void(bool success)>& callback) { | |
71 DCHECK(thread_checker_.CalledOnValidThread()); | |
72 | |
73 // ChromeOS builds on non-ChromeOS machines (dev) should not attempt to | |
74 // use permission broker. | |
75 if (base::SysInfo::IsRunningOnChromeOS()) { | |
76 chromeos::PermissionBrokerClient* client = | |
77 chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient(); | |
78 DCHECK(client) << "Could not get permission broker client."; | |
79 if (!client) { | |
80 callback.Run(false); | |
81 return; | |
82 } | |
83 | |
84 ui_task_runner_->PostTask( | |
85 FROM_HERE, | |
86 base::Bind(&chromeos::PermissionBrokerClient::RequestUsbAccess, | |
87 base::Unretained(client), | |
88 vendor_id(), | |
89 product_id(), | |
90 interface_id, | |
91 base::Bind(&OnRequestUsbAccessReplied, | |
92 base::ThreadTaskRunnerHandle::Get(), | |
93 callback))); | |
94 } | |
95 } | |
96 | |
97 #endif | |
98 | |
99 scoped_refptr<UsbDeviceHandle> UsbDeviceImpl::Open() { | |
100 DCHECK(thread_checker_.CalledOnValidThread()); | |
101 PlatformUsbDeviceHandle handle; | |
102 const int rv = libusb_open(platform_device_, &handle); | |
103 if (LIBUSB_SUCCESS == rv) { | |
104 scoped_refptr<UsbConfigDescriptor> interfaces = ListInterfaces(); | |
105 if (!interfaces.get()) | |
106 return NULL; | |
107 scoped_refptr<UsbDeviceHandleImpl> device_handle = | |
108 new UsbDeviceHandleImpl(context_, this, handle, interfaces); | |
109 handles_.push_back(device_handle); | |
110 return device_handle; | |
111 } else { | |
112 VLOG(1) << "Failed to open device: " << ConvertErrorToString(rv); | |
113 return NULL; | |
114 } | |
115 } | |
116 | |
117 bool UsbDeviceImpl::Close(scoped_refptr<UsbDeviceHandle> handle) { | |
118 DCHECK(thread_checker_.CalledOnValidThread()); | |
119 | |
120 for (HandlesVector::iterator it = handles_.begin(); it != handles_.end(); | |
121 ++it) { | |
122 if (it->get() == handle.get()) { | |
123 (*it)->InternalClose(); | |
124 handles_.erase(it); | |
125 return true; | |
126 } | |
127 } | |
128 return false; | |
129 } | |
130 | |
131 scoped_refptr<UsbConfigDescriptor> UsbDeviceImpl::ListInterfaces() { | |
132 DCHECK(thread_checker_.CalledOnValidThread()); | |
133 | |
134 PlatformUsbConfigDescriptor platform_config; | |
135 const int rv = | |
136 libusb_get_active_config_descriptor(platform_device_, &platform_config); | |
137 if (rv == LIBUSB_SUCCESS) { | |
138 return new UsbConfigDescriptorImpl(platform_config); | |
139 } else { | |
140 VLOG(1) << "Failed to get config descriptor: " << ConvertErrorToString(rv); | |
141 return NULL; | |
142 } | |
143 } | |
144 | |
145 void UsbDeviceImpl::OnDisconnect() { | |
146 DCHECK(thread_checker_.CalledOnValidThread()); | |
147 HandlesVector handles; | |
148 swap(handles, handles_); | |
149 for (HandlesVector::iterator it = handles.begin(); it != handles.end(); ++it) | |
150 (*it)->InternalClose(); | |
151 } | |
152 | |
153 } // namespace usb_service | |
OLD | NEW |