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_device_impl.h" | 5 #include "device/usb/usb_device_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/location.h" | 10 #include "base/location.h" |
| 11 #include "base/sequenced_task_runner.h" |
11 #include "base/single_thread_task_runner.h" | 12 #include "base/single_thread_task_runner.h" |
12 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
13 #include "base/strings/string_number_conversions.h" | |
14 #include "base/strings/utf_string_conversions.h" | |
15 #include "base/thread_task_runner_handle.h" | 14 #include "base/thread_task_runner_handle.h" |
16 #include "components/device_event_log/device_event_log.h" | 15 #include "components/device_event_log/device_event_log.h" |
17 #include "device/usb/usb_context.h" | 16 #include "device/usb/usb_context.h" |
18 #include "device/usb/usb_descriptors.h" | 17 #include "device/usb/usb_descriptors.h" |
19 #include "device/usb/usb_device_handle_impl.h" | 18 #include "device/usb/usb_device_handle_impl.h" |
20 #include "device/usb/usb_error.h" | 19 #include "device/usb/usb_error.h" |
21 #include "third_party/libusb/src/libusb/libusb.h" | 20 #include "third_party/libusb/src/libusb/libusb.h" |
22 | 21 |
23 #if defined(OS_CHROMEOS) | 22 #if defined(OS_CHROMEOS) |
24 #include "chromeos/dbus/dbus_thread_manager.h" | 23 #include "chromeos/dbus/dbus_thread_manager.h" |
25 #include "chromeos/dbus/permission_broker_client.h" | 24 #include "chromeos/dbus/permission_broker_client.h" |
26 #endif // defined(OS_CHROMEOS) | 25 #endif // defined(OS_CHROMEOS) |
27 | 26 |
28 #if defined(USE_UDEV) | |
29 #include "device/udev_linux/scoped_udev.h" | |
30 #endif // defined(USE_UDEV) | |
31 | |
32 namespace device { | 27 namespace device { |
33 | 28 |
34 namespace { | 29 namespace { |
35 | 30 |
36 #if defined(OS_CHROMEOS) | |
37 | |
38 void PostResultOnTaskRunner( | |
39 scoped_refptr<base::SingleThreadTaskRunner> task_runner, | |
40 const base::Callback<void(bool success)>& callback, | |
41 bool success) { | |
42 task_runner->PostTask(FROM_HERE, base::Bind(callback, success)); | |
43 } | |
44 | |
45 #endif // defined(OS_CHROMEOS) | |
46 | |
47 UsbEndpointDirection GetDirection( | 31 UsbEndpointDirection GetDirection( |
48 const libusb_endpoint_descriptor* descriptor) { | 32 const libusb_endpoint_descriptor* descriptor) { |
49 switch (descriptor->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) { | 33 switch (descriptor->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) { |
50 case LIBUSB_ENDPOINT_IN: | 34 case LIBUSB_ENDPOINT_IN: |
51 return USB_DIRECTION_INBOUND; | 35 return USB_DIRECTION_INBOUND; |
52 case LIBUSB_ENDPOINT_OUT: | 36 case LIBUSB_ENDPOINT_OUT: |
53 return USB_DIRECTION_OUTBOUND; | 37 return USB_DIRECTION_OUTBOUND; |
54 default: | 38 default: |
55 NOTREACHED(); | 39 NOTREACHED(); |
56 return USB_DIRECTION_INBOUND; | 40 return USB_DIRECTION_INBOUND; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 default: | 85 default: |
102 NOTREACHED(); | 86 NOTREACHED(); |
103 return USB_USAGE_DATA; | 87 return USB_USAGE_DATA; |
104 } | 88 } |
105 } | 89 } |
106 | 90 |
107 } // namespace | 91 } // namespace |
108 | 92 |
109 UsbDeviceImpl::UsbDeviceImpl( | 93 UsbDeviceImpl::UsbDeviceImpl( |
110 scoped_refptr<UsbContext> context, | 94 scoped_refptr<UsbContext> context, |
111 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, | |
112 PlatformUsbDevice platform_device, | 95 PlatformUsbDevice platform_device, |
113 uint16 vendor_id, | 96 uint16 vendor_id, |
114 uint16 product_id, | 97 uint16 product_id, |
115 uint32 unique_id) | 98 uint32 unique_id, |
116 : UsbDevice(vendor_id, product_id, unique_id), | 99 const base::string16& manufacturer_string, |
| 100 const base::string16& product_string, |
| 101 const base::string16& serial_number, |
| 102 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) |
| 103 : UsbDevice(vendor_id, |
| 104 product_id, |
| 105 unique_id, |
| 106 manufacturer_string, |
| 107 product_string, |
| 108 serial_number), |
117 platform_device_(platform_device), | 109 platform_device_(platform_device), |
118 context_(context), | 110 context_(context), |
119 ui_task_runner_(ui_task_runner) { | 111 task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 112 blocking_task_runner_(blocking_task_runner) { |
120 CHECK(platform_device) << "platform_device cannot be NULL"; | 113 CHECK(platform_device) << "platform_device cannot be NULL"; |
121 libusb_ref_device(platform_device); | 114 libusb_ref_device(platform_device); |
122 RefreshConfiguration(); | 115 RefreshConfiguration(); |
123 #if defined(USE_UDEV) | |
124 ScopedUdevPtr udev(udev_new()); | |
125 ScopedUdevEnumeratePtr enumerate(udev_enumerate_new(udev.get())); | |
126 | |
127 udev_enumerate_add_match_subsystem(enumerate.get(), "usb"); | |
128 if (udev_enumerate_scan_devices(enumerate.get()) != 0) { | |
129 return; | |
130 } | |
131 std::string bus_number = | |
132 base::IntToString(libusb_get_bus_number(platform_device)); | |
133 std::string device_address = | |
134 base::IntToString(libusb_get_device_address(platform_device)); | |
135 udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate.get()); | |
136 for (udev_list_entry* i = devices; i != NULL; | |
137 i = udev_list_entry_get_next(i)) { | |
138 ScopedUdevDevicePtr device( | |
139 udev_device_new_from_syspath(udev.get(), udev_list_entry_get_name(i))); | |
140 if (device) { | |
141 const char* value = udev_device_get_sysattr_value(device.get(), "busnum"); | |
142 if (!value || bus_number != value) { | |
143 continue; | |
144 } | |
145 value = udev_device_get_sysattr_value(device.get(), "devnum"); | |
146 if (!value || device_address != value) { | |
147 continue; | |
148 } | |
149 | |
150 #if defined(OS_CHROMEOS) | |
151 value = udev_device_get_devnode(device.get()); | |
152 if (value) { | |
153 devnode_ = value; | |
154 } | |
155 #endif | |
156 value = udev_device_get_sysattr_value(device.get(), "manufacturer"); | |
157 if (value) { | |
158 manufacturer_ = base::UTF8ToUTF16(value); | |
159 } | |
160 value = udev_device_get_sysattr_value(device.get(), "product"); | |
161 if (value) { | |
162 product_ = base::UTF8ToUTF16(value); | |
163 } | |
164 value = udev_device_get_sysattr_value(device.get(), "serial"); | |
165 if (value) { | |
166 serial_number_ = base::UTF8ToUTF16(value); | |
167 } | |
168 break; | |
169 } | |
170 } | |
171 #else | |
172 strings_cached_ = false; | |
173 #endif | |
174 } | 116 } |
175 | 117 |
176 UsbDeviceImpl::~UsbDeviceImpl() { | 118 UsbDeviceImpl::~UsbDeviceImpl() { |
177 // The destructor must be safe to call from any thread. | 119 // The destructor must be safe to call from any thread. |
178 libusb_unref_device(platform_device_); | 120 libusb_unref_device(platform_device_); |
179 } | 121 } |
180 | 122 |
181 #if defined(OS_CHROMEOS) | 123 #if defined(OS_CHROMEOS) |
182 | 124 |
183 void UsbDeviceImpl::CheckUsbAccess(const ResultCallback& callback) { | 125 void UsbDeviceImpl::CheckUsbAccess(const ResultCallback& callback) { |
184 DCHECK(thread_checker_.CalledOnValidThread()); | 126 DCHECK(thread_checker_.CalledOnValidThread()); |
185 | |
186 chromeos::PermissionBrokerClient* client = | 127 chromeos::PermissionBrokerClient* client = |
187 chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient(); | 128 chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient(); |
188 DCHECK(client) << "Could not get permission broker client."; | 129 DCHECK(client) << "Could not get permission broker client."; |
189 | 130 client->CheckPathAccess(devnode_, callback); |
190 ui_task_runner_->PostTask( | |
191 FROM_HERE, | |
192 base::Bind(&chromeos::PermissionBrokerClient::CheckPathAccess, | |
193 base::Unretained(client), devnode_, | |
194 base::Bind(&PostResultOnTaskRunner, | |
195 base::ThreadTaskRunnerHandle::Get(), callback))); | |
196 } | 131 } |
197 | 132 |
198 void UsbDeviceImpl::RequestUsbAccess(int interface_id, | 133 void UsbDeviceImpl::RequestUsbAccess(int interface_id, |
199 const ResultCallback& callback) { | 134 const ResultCallback& callback) { |
200 DCHECK(thread_checker_.CalledOnValidThread()); | 135 DCHECK(thread_checker_.CalledOnValidThread()); |
201 | |
202 chromeos::PermissionBrokerClient* client = | 136 chromeos::PermissionBrokerClient* client = |
203 chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient(); | 137 chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient(); |
204 DCHECK(client) << "Could not get permission broker client."; | 138 DCHECK(client) << "Could not get permission broker client."; |
205 | 139 client->RequestPathAccess(devnode_, interface_id, callback); |
206 ui_task_runner_->PostTask( | |
207 FROM_HERE, | |
208 base::Bind(&chromeos::PermissionBrokerClient::RequestPathAccess, | |
209 base::Unretained(client), devnode_, interface_id, | |
210 base::Bind(&PostResultOnTaskRunner, | |
211 base::ThreadTaskRunnerHandle::Get(), callback))); | |
212 } | 140 } |
213 | 141 |
214 #endif | 142 #endif |
215 | 143 |
216 scoped_refptr<UsbDeviceHandle> UsbDeviceImpl::Open() { | 144 void UsbDeviceImpl::Open(const OpenCallback& callback) { |
217 DCHECK(thread_checker_.CalledOnValidThread()); | 145 DCHECK(thread_checker_.CalledOnValidThread()); |
218 PlatformUsbDeviceHandle handle; | 146 blocking_task_runner_->PostTask( |
219 const int rv = libusb_open(platform_device_, &handle); | 147 FROM_HERE, |
220 if (LIBUSB_SUCCESS == rv) { | 148 base::Bind(&UsbDeviceImpl::OpenOnBlockingThread, this, callback)); |
221 scoped_refptr<UsbDeviceHandleImpl> device_handle = | |
222 new UsbDeviceHandleImpl(context_, this, handle); | |
223 handles_.push_back(device_handle); | |
224 return device_handle; | |
225 } else { | |
226 USB_LOG(EVENT) << "Failed to open device: " | |
227 << ConvertPlatformUsbErrorToString(rv); | |
228 return NULL; | |
229 } | |
230 } | 149 } |
231 | 150 |
232 bool UsbDeviceImpl::Close(scoped_refptr<UsbDeviceHandle> handle) { | 151 bool UsbDeviceImpl::Close(scoped_refptr<UsbDeviceHandle> handle) { |
233 DCHECK(thread_checker_.CalledOnValidThread()); | 152 DCHECK(thread_checker_.CalledOnValidThread()); |
234 | 153 |
235 for (HandlesVector::iterator it = handles_.begin(); it != handles_.end(); | 154 for (HandlesVector::iterator it = handles_.begin(); it != handles_.end(); |
236 ++it) { | 155 ++it) { |
237 if (it->get() == handle.get()) { | 156 if (it->get() == handle.get()) { |
238 (*it)->InternalClose(); | 157 (*it)->InternalClose(); |
239 handles_.erase(it); | 158 handles_.erase(it); |
240 return true; | 159 return true; |
241 } | 160 } |
242 } | 161 } |
243 return false; | 162 return false; |
244 } | 163 } |
245 | 164 |
246 const UsbConfigDescriptor* UsbDeviceImpl::GetConfiguration() { | 165 const UsbConfigDescriptor* UsbDeviceImpl::GetConfiguration() { |
247 DCHECK(thread_checker_.CalledOnValidThread()); | 166 DCHECK(thread_checker_.CalledOnValidThread()); |
248 return configuration_.get(); | 167 return configuration_.get(); |
249 } | 168 } |
250 | 169 |
251 bool UsbDeviceImpl::GetManufacturer(base::string16* manufacturer) { | |
252 DCHECK(thread_checker_.CalledOnValidThread()); | |
253 | |
254 #if !defined(USE_UDEV) | |
255 if (!strings_cached_) { | |
256 CacheStrings(); | |
257 } | |
258 #endif | |
259 | |
260 *manufacturer = manufacturer_; | |
261 return !manufacturer_.empty(); | |
262 } | |
263 | |
264 bool UsbDeviceImpl::GetProduct(base::string16* product) { | |
265 DCHECK(thread_checker_.CalledOnValidThread()); | |
266 | |
267 #if !defined(USE_UDEV) | |
268 if (!strings_cached_) { | |
269 CacheStrings(); | |
270 } | |
271 #endif | |
272 | |
273 *product = product_; | |
274 return !product_.empty(); | |
275 } | |
276 | |
277 bool UsbDeviceImpl::GetSerialNumber(base::string16* serial_number) { | |
278 DCHECK(thread_checker_.CalledOnValidThread()); | |
279 | |
280 #if !defined(USE_UDEV) | |
281 if (!strings_cached_) { | |
282 CacheStrings(); | |
283 } | |
284 #endif | |
285 | |
286 *serial_number = serial_number_; | |
287 return !serial_number_.empty(); | |
288 } | |
289 | |
290 void UsbDeviceImpl::OnDisconnect() { | 170 void UsbDeviceImpl::OnDisconnect() { |
291 DCHECK(thread_checker_.CalledOnValidThread()); | 171 DCHECK(thread_checker_.CalledOnValidThread()); |
292 | 172 |
293 // Swap the list of handles into a local variable because closing all open | 173 // Swap the list of handles into a local variable because closing all open |
294 // handles may release the last reference to this object. | 174 // handles may release the last reference to this object. |
295 HandlesVector handles; | 175 HandlesVector handles; |
296 swap(handles, handles_); | 176 swap(handles, handles_); |
297 | 177 |
298 for (const scoped_refptr<UsbDeviceHandleImpl>& handle : handles_) { | 178 for (const scoped_refptr<UsbDeviceHandleImpl>& handle : handles_) { |
299 handle->InternalClose(); | 179 handle->InternalClose(); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 } | 238 } |
359 } | 239 } |
360 | 240 |
361 configuration_->extra_data = std::vector<uint8_t>( | 241 configuration_->extra_data = std::vector<uint8_t>( |
362 platform_config->extra, | 242 platform_config->extra, |
363 platform_config->extra + platform_config->extra_length); | 243 platform_config->extra + platform_config->extra_length); |
364 | 244 |
365 libusb_free_config_descriptor(platform_config); | 245 libusb_free_config_descriptor(platform_config); |
366 } | 246 } |
367 | 247 |
368 #if !defined(USE_UDEV) | 248 void UsbDeviceImpl::OpenOnBlockingThread(const OpenCallback& callback) { |
369 void UsbDeviceImpl::CacheStrings() { | 249 PlatformUsbDeviceHandle handle; |
| 250 const int rv = libusb_open(platform_device_, &handle); |
| 251 if (LIBUSB_SUCCESS == rv) { |
| 252 task_runner_->PostTask( |
| 253 FROM_HERE, base::Bind(&UsbDeviceImpl::Opened, this, handle, callback)); |
| 254 } else { |
| 255 USB_LOG(EVENT) << "Failed to open device: " |
| 256 << ConvertPlatformUsbErrorToString(rv); |
| 257 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); |
| 258 } |
| 259 } |
| 260 |
| 261 void UsbDeviceImpl::Opened(PlatformUsbDeviceHandle platform_handle, |
| 262 const OpenCallback& callback) { |
370 DCHECK(thread_checker_.CalledOnValidThread()); | 263 DCHECK(thread_checker_.CalledOnValidThread()); |
371 // This is a non-blocking call as libusb has the descriptor in memory. | 264 scoped_refptr<UsbDeviceHandleImpl> device_handle = new UsbDeviceHandleImpl( |
372 libusb_device_descriptor desc; | 265 context_, this, platform_handle, blocking_task_runner_); |
373 const int rv = libusb_get_device_descriptor(platform_device_, &desc); | 266 handles_.push_back(device_handle); |
374 if (rv == LIBUSB_SUCCESS) { | 267 callback.Run(device_handle); |
375 scoped_refptr<UsbDeviceHandle> device_handle = Open(); | |
376 if (device_handle.get()) { | |
377 if (desc.iManufacturer != 0) { | |
378 device_handle->GetStringDescriptor(desc.iManufacturer, &manufacturer_); | |
379 } | |
380 if (desc.iProduct != 0) { | |
381 device_handle->GetStringDescriptor(desc.iProduct, &product_); | |
382 } | |
383 if (desc.iSerialNumber != 0) { | |
384 device_handle->GetStringDescriptor(desc.iSerialNumber, &serial_number_); | |
385 } | |
386 device_handle->Close(); | |
387 } else { | |
388 USB_LOG(EVENT) << "Failed to open device to cache string descriptors."; | |
389 } | |
390 } else { | |
391 USB_LOG(EVENT) | |
392 << "Failed to read device descriptor to cache string descriptors: " | |
393 << ConvertPlatformUsbErrorToString(rv); | |
394 } | |
395 strings_cached_ = true; | |
396 } | 268 } |
397 #endif // !defined(USE_UDEV) | |
398 | 269 |
399 } // namespace device | 270 } // namespace device |
OLD | NEW |