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_impl.h" | 5 #include "device/usb/usb_service_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <list> | 8 #include <list> |
9 #include <set> | 9 #include <set> |
10 | 10 |
11 #include "base/barrier_closure.h" | 11 #include "base/barrier_closure.h" |
12 #include "base/bind.h" | 12 #include "base/bind.h" |
13 #include "base/location.h" | 13 #include "base/location.h" |
14 #include "base/memory/weak_ptr.h" | 14 #include "base/memory/weak_ptr.h" |
15 #include "base/single_thread_task_runner.h" | 15 #include "base/single_thread_task_runner.h" |
16 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
17 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
18 #include "base/strings/utf_string_conversions.h" | 18 #include "base/strings/utf_string_conversions.h" |
19 #include "base/thread_task_runner_handle.h" | 19 #include "base/thread_task_runner_handle.h" |
20 #include "components/device_event_log/device_event_log.h" | 20 #include "components/device_event_log/device_event_log.h" |
21 #include "device/usb/usb_device_handle.h" | 21 #include "device/usb/usb_device_handle.h" |
22 #include "device/usb/usb_error.h" | 22 #include "device/usb/usb_error.h" |
| 23 #include "device/usb/webusb_descriptors.h" |
23 #include "third_party/libusb/src/libusb/libusb.h" | 24 #include "third_party/libusb/src/libusb/libusb.h" |
24 | 25 |
25 #if defined(OS_WIN) | 26 #if defined(OS_WIN) |
26 #include <setupapi.h> | 27 #include <setupapi.h> |
27 #include <usbiodef.h> | 28 #include <usbiodef.h> |
28 | 29 |
29 #include "base/strings/string_util.h" | 30 #include "base/strings/string_util.h" |
30 #endif // OS_WIN | 31 #endif // OS_WIN |
31 | 32 |
32 #if defined(USE_UDEV) | 33 #if defined(USE_UDEV) |
33 #include "device/udev_linux/scoped_udev.h" | 34 #include "device/udev_linux/scoped_udev.h" |
34 #endif // USE_UDEV | 35 #endif // USE_UDEV |
35 | 36 |
| 37 using net::IOBufferWithSize; |
| 38 |
36 namespace device { | 39 namespace device { |
37 | 40 |
38 namespace { | 41 namespace { |
39 | 42 |
| 43 // Standard USB requests and descriptor types: |
| 44 const uint16_t kUsbVersion2_1 = 0x0210; |
| 45 const uint8_t kGetDescriptorRequest = 0x06; |
| 46 const uint8_t kStringDescriptorType = 0x03; |
| 47 const uint8_t kBosDescriptorType = 0x0F; |
| 48 |
| 49 // WebUSB requests: |
| 50 const uint8_t kGetAllowedOriginsRequest = 0x01; |
| 51 const uint8_t kGetLandingPageRequest = 0x02; |
| 52 const uint8_t kUrlDescriptorType = 0x03; |
| 53 |
| 54 const int kControlTransferTimeout = 60000; // 1 minute |
| 55 |
40 #if defined(OS_WIN) | 56 #if defined(OS_WIN) |
41 | 57 |
42 // Wrapper around a HDEVINFO that automatically destroys it. | 58 // Wrapper around a HDEVINFO that automatically destroys it. |
43 class ScopedDeviceInfoList { | 59 class ScopedDeviceInfoList { |
44 public: | 60 public: |
45 explicit ScopedDeviceInfoList(HDEVINFO handle) : handle_(handle) {} | 61 explicit ScopedDeviceInfoList(HDEVINFO handle) : handle_(handle) {} |
46 | 62 |
47 ~ScopedDeviceInfoList() { | 63 ~ScopedDeviceInfoList() { |
48 if (valid()) { | 64 if (valid()) { |
49 SetupDiDestroyDeviceInfoList(handle_); | 65 SetupDiDestroyDeviceInfoList(handle_); |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 USB_LOG(ERROR) << "Failed to get device list: " | 174 USB_LOG(ERROR) << "Failed to get device list: " |
159 << ConvertPlatformUsbErrorToString(device_count); | 175 << ConvertPlatformUsbErrorToString(device_count); |
160 task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr, 0)); | 176 task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr, 0)); |
161 return; | 177 return; |
162 } | 178 } |
163 | 179 |
164 task_runner->PostTask(FROM_HERE, | 180 task_runner->PostTask(FROM_HERE, |
165 base::Bind(callback, platform_devices, device_count)); | 181 base::Bind(callback, platform_devices, device_count)); |
166 } | 182 } |
167 | 183 |
168 #if defined(USE_UDEV) | |
169 | |
170 void EnumerateUdevDevice(scoped_refptr<UsbDeviceImpl> device, | |
171 scoped_refptr<base::SequencedTaskRunner> task_runner, | |
172 const base::Closure& success_closure, | |
173 const base::Closure& failure_closure) { | |
174 ScopedUdevPtr udev(udev_new()); | |
175 ScopedUdevEnumeratePtr udev_enumerate(udev_enumerate_new(udev.get())); | |
176 | |
177 udev_enumerate_add_match_subsystem(udev_enumerate.get(), "usb"); | |
178 if (udev_enumerate_scan_devices(udev_enumerate.get()) != 0) { | |
179 task_runner->PostTask(FROM_HERE, failure_closure); | |
180 return; | |
181 } | |
182 | |
183 std::string bus_number = | |
184 base::IntToString(libusb_get_bus_number(device->platform_device())); | |
185 std::string device_address = | |
186 base::IntToString(libusb_get_device_address(device->platform_device())); | |
187 udev_list_entry* devices = | |
188 udev_enumerate_get_list_entry(udev_enumerate.get()); | |
189 for (udev_list_entry* i = devices; i != NULL; | |
190 i = udev_list_entry_get_next(i)) { | |
191 ScopedUdevDevicePtr udev_device( | |
192 udev_device_new_from_syspath(udev.get(), udev_list_entry_get_name(i))); | |
193 if (udev_device) { | |
194 const char* value = | |
195 udev_device_get_sysattr_value(udev_device.get(), "busnum"); | |
196 if (!value || bus_number != value) { | |
197 continue; | |
198 } | |
199 value = udev_device_get_sysattr_value(udev_device.get(), "devnum"); | |
200 if (!value || device_address != value) { | |
201 continue; | |
202 } | |
203 | |
204 value = udev_device_get_sysattr_value(udev_device.get(), "manufacturer"); | |
205 if (value) { | |
206 device->set_manufacturer_string(base::UTF8ToUTF16(value)); | |
207 } | |
208 value = udev_device_get_sysattr_value(udev_device.get(), "product"); | |
209 if (value) { | |
210 device->set_product_string(base::UTF8ToUTF16(value)); | |
211 } | |
212 value = udev_device_get_sysattr_value(udev_device.get(), "serial"); | |
213 if (value) { | |
214 device->set_serial_number(base::UTF8ToUTF16(value)); | |
215 } | |
216 | |
217 value = udev_device_get_devnode(udev_device.get()); | |
218 if (value) { | |
219 device->set_device_path(value); | |
220 task_runner->PostTask(FROM_HERE, success_closure); | |
221 return; | |
222 } | |
223 | |
224 break; | |
225 } | |
226 } | |
227 | |
228 task_runner->PostTask(FROM_HERE, failure_closure); | |
229 } | |
230 | |
231 #else | |
232 | |
233 void OnReadStringDescriptor( | 184 void OnReadStringDescriptor( |
234 const base::Callback<void(const base::string16&)>& callback, | 185 const base::Callback<void(const base::string16&)>& callback, |
235 UsbTransferStatus status, | 186 UsbTransferStatus status, |
236 scoped_refptr<net::IOBuffer> buffer, | 187 scoped_refptr<net::IOBuffer> buffer, |
237 size_t length) { | 188 size_t length) { |
238 if (status != USB_TRANSFER_COMPLETED || length < 2) { | 189 if (status != USB_TRANSFER_COMPLETED || length < 2) { |
239 callback.Run(base::string16()); | 190 callback.Run(base::string16()); |
240 } else { | 191 } else { |
241 // Take the lesser of the length of data returned by the device and the | 192 // Take the lesser of the length of data returned by the device and the |
242 // length reported in the descriptor. | 193 // length reported in the descriptor. |
243 size_t internal_length = reinterpret_cast<uint8*>(buffer->data())[0]; | 194 size_t internal_length = reinterpret_cast<uint8*>(buffer->data())[0]; |
244 length = std::min(length, internal_length); | 195 length = std::min(length, internal_length); |
245 // Cut off the first 2 bytes of the descriptor which are the length and | 196 // Cut off the first 2 bytes of the descriptor which are the length and |
246 // descriptor type (always STRING). | 197 // descriptor type (always STRING). |
247 callback.Run(base::string16( | 198 callback.Run(base::string16( |
248 reinterpret_cast<base::char16*>(buffer->data() + 2), length / 2 - 1)); | 199 reinterpret_cast<base::char16*>(buffer->data() + 2), length / 2 - 1)); |
249 } | 200 } |
250 } | 201 } |
251 | 202 |
252 void ReadStringDescriptor( | 203 void ReadStringDescriptor( |
253 scoped_refptr<UsbDeviceHandle> device_handle, | 204 scoped_refptr<UsbDeviceHandle> device_handle, |
254 uint8 index, | 205 uint8 index, |
255 uint16 language_id, | 206 uint16 language_id, |
256 const base::Callback<void(const base::string16&)>& callback) { | 207 const base::Callback<void(const base::string16&)>& callback) { |
257 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(256); | 208 scoped_refptr<IOBufferWithSize> buffer = new IOBufferWithSize(256); |
258 device_handle->ControlTransfer( | 209 device_handle->ControlTransfer( |
259 USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, UsbDeviceHandle::DEVICE, | 210 USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, UsbDeviceHandle::DEVICE, |
260 6 /* GET_DESCRIPTOR */, 3 /* STRING */ << 8 | index, language_id, buffer, | 211 kGetDescriptorRequest, kStringDescriptorType << 8 | index, language_id, |
261 256, 60, base::Bind(&OnReadStringDescriptor, callback)); | 212 buffer, buffer->size(), kControlTransferTimeout, |
| 213 base::Bind(&OnReadStringDescriptor, callback)); |
| 214 } |
| 215 |
| 216 void OnReadWebUsbLandingPage(scoped_refptr<UsbDevice> device, |
| 217 const base::Closure& callback, |
| 218 UsbTransferStatus status, |
| 219 scoped_refptr<net::IOBuffer> buffer, |
| 220 size_t length) { |
| 221 if (status != USB_TRANSFER_COMPLETED || length < 2) { |
| 222 callback.Run(); |
| 223 return; |
| 224 } |
| 225 |
| 226 uint8_t string_length = buffer->data()[0]; |
| 227 if (string_length < 2 || string_length > length || |
| 228 buffer->data()[1] != kUrlDescriptorType) { |
| 229 callback.Run(); |
| 230 return; |
| 231 } |
| 232 |
| 233 GURL url(std::string(&buffer->data()[2], string_length - 2)); |
| 234 if (url.is_valid()) { |
| 235 UsbDeviceImpl* device_impl = static_cast<UsbDeviceImpl*>(device.get()); |
| 236 device_impl->set_webusb_landing_page(url); |
| 237 } |
| 238 callback.Run(); |
| 239 } |
| 240 |
| 241 void ReadWebUsbLandingPage(scoped_refptr<UsbDeviceHandle> device_handle, |
| 242 const base::Closure& callback, |
| 243 uint8 vendor_code) { |
| 244 scoped_refptr<IOBufferWithSize> buffer = new IOBufferWithSize(256); |
| 245 device_handle->ControlTransfer( |
| 246 USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR, UsbDeviceHandle::DEVICE, |
| 247 vendor_code, 0, kGetLandingPageRequest, buffer, buffer->size(), |
| 248 kControlTransferTimeout, |
| 249 base::Bind(&OnReadWebUsbLandingPage, device_handle->GetDevice(), |
| 250 callback)); |
| 251 } |
| 252 |
| 253 void OnReadWebUsbAllowedOrigins(scoped_refptr<UsbDevice> device, |
| 254 const base::Closure& callback, |
| 255 UsbTransferStatus status, |
| 256 scoped_refptr<net::IOBuffer> buffer, |
| 257 size_t length) { |
| 258 if (status != USB_TRANSFER_COMPLETED) { |
| 259 USB_LOG(EVENT) << "Failed to read WebUSB allowed origins."; |
| 260 callback.Run(); |
| 261 return; |
| 262 } |
| 263 |
| 264 scoped_ptr<WebUsbDescriptorSet> descriptors(new WebUsbDescriptorSet()); |
| 265 if (descriptors->Parse( |
| 266 std::vector<uint8>(buffer->data(), buffer->data() + length))) { |
| 267 UsbDeviceImpl* device_impl = static_cast<UsbDeviceImpl*>(device.get()); |
| 268 device_impl->set_webusb_allowed_origins(descriptors.Pass()); |
| 269 } |
| 270 callback.Run(); |
| 271 } |
| 272 |
| 273 void OnReadWebUsbAllowedOriginsHeader( |
| 274 scoped_refptr<UsbDeviceHandle> device_handle, |
| 275 const base::Closure& callback, |
| 276 uint8 vendor_code, |
| 277 UsbTransferStatus status, |
| 278 scoped_refptr<net::IOBuffer> buffer, |
| 279 size_t length) { |
| 280 if (status != USB_TRANSFER_COMPLETED || length != 4) { |
| 281 USB_LOG(EVENT) << "Failed to read WebUSB allowed origins header."; |
| 282 callback.Run(); |
| 283 return; |
| 284 } |
| 285 |
| 286 uint16 new_length = buffer->data()[2] | (buffer->data()[3] << 8); |
| 287 scoped_refptr<IOBufferWithSize> new_buffer = new IOBufferWithSize(new_length); |
| 288 device_handle->ControlTransfer( |
| 289 USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR, UsbDeviceHandle::DEVICE, |
| 290 vendor_code, 0, kGetAllowedOriginsRequest, new_buffer, new_buffer->size(), |
| 291 kControlTransferTimeout, |
| 292 base::Bind(&OnReadWebUsbAllowedOrigins, device_handle->GetDevice(), |
| 293 callback)); |
| 294 } |
| 295 |
| 296 void ReadWebUsbAllowedOrigins(scoped_refptr<UsbDeviceHandle> device_handle, |
| 297 const base::Closure& callback, |
| 298 uint8 vendor_code) { |
| 299 scoped_refptr<IOBufferWithSize> buffer = new IOBufferWithSize(4); |
| 300 device_handle->ControlTransfer( |
| 301 USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR, UsbDeviceHandle::DEVICE, |
| 302 vendor_code, 0, kGetAllowedOriginsRequest, buffer, buffer->size(), |
| 303 kControlTransferTimeout, |
| 304 base::Bind(&OnReadWebUsbAllowedOriginsHeader, device_handle, callback, |
| 305 vendor_code)); |
| 306 } |
| 307 |
| 308 void OnReadBosDescriptor(scoped_refptr<UsbDeviceHandle> device_handle, |
| 309 const base::Closure& callback, |
| 310 UsbTransferStatus status, |
| 311 scoped_refptr<net::IOBuffer> buffer, |
| 312 size_t length) { |
| 313 if (status != USB_TRANSFER_COMPLETED) { |
| 314 USB_LOG(EVENT) << "Failed to read BOS descriptor."; |
| 315 callback.Run(); |
| 316 return; |
| 317 } |
| 318 |
| 319 WebUsbPlatformCapabilityDescriptor descriptor; |
| 320 if (!descriptor.ParseFromBosDescriptor( |
| 321 std::vector<uint8>(buffer->data(), buffer->data() + length))) { |
| 322 callback.Run(); |
| 323 return; |
| 324 } |
| 325 |
| 326 base::Closure barrier = base::BarrierClosure(2, callback); |
| 327 ReadWebUsbLandingPage(device_handle, barrier, descriptor.vendor_code); |
| 328 ReadWebUsbAllowedOrigins(device_handle, barrier, descriptor.vendor_code); |
| 329 } |
| 330 |
| 331 void OnReadBosDescriptorHeader(scoped_refptr<UsbDeviceHandle> device_handle, |
| 332 const base::Closure& callback, |
| 333 UsbTransferStatus status, |
| 334 scoped_refptr<net::IOBuffer> buffer, |
| 335 size_t length) { |
| 336 if (status != USB_TRANSFER_COMPLETED || length != 5) { |
| 337 USB_LOG(EVENT) << "Failed to read BOS descriptor header."; |
| 338 callback.Run(); |
| 339 return; |
| 340 } |
| 341 |
| 342 uint16 new_length = buffer->data()[2] | (buffer->data()[3] << 8); |
| 343 scoped_refptr<IOBufferWithSize> new_buffer = new IOBufferWithSize(new_length); |
| 344 device_handle->ControlTransfer( |
| 345 USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, UsbDeviceHandle::DEVICE, |
| 346 kGetDescriptorRequest, kBosDescriptorType << 8, 0, new_buffer, |
| 347 new_buffer->size(), kControlTransferTimeout, |
| 348 base::Bind(&OnReadBosDescriptor, device_handle, callback)); |
| 349 } |
| 350 |
| 351 void ReadBosDescriptor(scoped_refptr<UsbDeviceHandle> device_handle, |
| 352 const base::Closure& callback) { |
| 353 scoped_refptr<IOBufferWithSize> buffer = new IOBufferWithSize(5); |
| 354 device_handle->ControlTransfer( |
| 355 USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, UsbDeviceHandle::DEVICE, |
| 356 kGetDescriptorRequest, kBosDescriptorType << 8, 0, buffer, buffer->size(), |
| 357 kControlTransferTimeout, |
| 358 base::Bind(&OnReadBosDescriptorHeader, device_handle, callback)); |
262 } | 359 } |
263 | 360 |
264 void CloseHandleAndRunContinuation(scoped_refptr<UsbDeviceHandle> device_handle, | 361 void CloseHandleAndRunContinuation(scoped_refptr<UsbDeviceHandle> device_handle, |
265 const base::Closure& continuation) { | 362 const base::Closure& continuation) { |
266 device_handle->Close(); | 363 device_handle->Close(); |
267 continuation.Run(); | 364 continuation.Run(); |
268 } | 365 } |
269 | 366 |
270 void SaveStringAndRunContinuation( | 367 void SaveStringAndRunContinuation( |
271 const base::Callback<void(const base::string16&)>& save_callback, | 368 const base::Callback<void(const base::string16&)>& save_callback, |
272 const base::Closure& continuation, | 369 const base::Closure& continuation, |
273 const base::string16& value) { | 370 const base::string16& value) { |
274 if (!value.empty()) { | 371 if (!value.empty()) { |
275 save_callback.Run(value); | 372 save_callback.Run(value); |
276 } | 373 } |
277 continuation.Run(); | 374 continuation.Run(); |
278 } | 375 } |
279 | 376 |
| 377 // This function runs |barrier| once for every string it tries to read. |
280 void OnReadLanguageIds(scoped_refptr<UsbDeviceHandle> device_handle, | 378 void OnReadLanguageIds(scoped_refptr<UsbDeviceHandle> device_handle, |
281 uint8 manufacturer, | 379 uint8 manufacturer, |
282 uint8 product, | 380 uint8 product, |
283 uint8 serial_number, | 381 uint8 serial_number, |
284 const base::Closure& success_closure, | 382 const base::Closure& barrier, |
285 const base::string16& languages) { | 383 const base::string16& languages) { |
286 // Default to English unless the device provides a language and then just pick | 384 // Default to English unless the device provides a language and then just pick |
287 // the first one. | 385 // the first one. |
288 uint16 language_id = 0x0409; | 386 uint16 language_id = 0x0409; |
289 if (!languages.empty()) { | 387 if (!languages.empty()) { |
290 language_id = languages[0]; | 388 language_id = languages[0]; |
291 } | 389 } |
292 | 390 |
293 scoped_refptr<UsbDeviceImpl> device = | 391 scoped_refptr<UsbDeviceImpl> device = |
294 static_cast<UsbDeviceImpl*>(device_handle->GetDevice().get()); | 392 static_cast<UsbDeviceImpl*>(device_handle->GetDevice().get()); |
295 base::Closure continuation = | |
296 base::BarrierClosure(3, base::Bind(&CloseHandleAndRunContinuation, | |
297 device_handle, success_closure)); | |
298 | 393 |
299 if (manufacturer == 0) { | 394 if (manufacturer != 0) { |
300 continuation.Run(); | |
301 } else { | |
302 ReadStringDescriptor( | 395 ReadStringDescriptor( |
303 device_handle, manufacturer, language_id, | 396 device_handle, manufacturer, language_id, |
304 base::Bind(&SaveStringAndRunContinuation, | 397 base::Bind(&SaveStringAndRunContinuation, |
305 base::Bind(&UsbDeviceImpl::set_manufacturer_string, device), | 398 base::Bind(&UsbDeviceImpl::set_manufacturer_string, device), |
306 continuation)); | 399 barrier)); |
307 } | 400 } |
308 | 401 |
309 if (product == 0) { | 402 if (product != 0) { |
310 continuation.Run(); | |
311 } else { | |
312 ReadStringDescriptor( | 403 ReadStringDescriptor( |
313 device_handle, product, language_id, | 404 device_handle, product, language_id, |
314 base::Bind(&SaveStringAndRunContinuation, | 405 base::Bind(&SaveStringAndRunContinuation, |
315 base::Bind(&UsbDeviceImpl::set_product_string, device), | 406 base::Bind(&UsbDeviceImpl::set_product_string, device), |
316 continuation)); | 407 barrier)); |
317 } | 408 } |
318 | 409 |
319 if (serial_number == 0) { | 410 if (serial_number != 0) { |
320 continuation.Run(); | |
321 } else { | |
322 ReadStringDescriptor( | 411 ReadStringDescriptor( |
323 device_handle, serial_number, language_id, | 412 device_handle, serial_number, language_id, |
324 base::Bind(&SaveStringAndRunContinuation, | 413 base::Bind(&SaveStringAndRunContinuation, |
325 base::Bind(&UsbDeviceImpl::set_serial_number, device), | 414 base::Bind(&UsbDeviceImpl::set_serial_number, device), |
326 continuation)); | 415 barrier)); |
327 } | 416 } |
328 } | 417 } |
329 | 418 |
330 void ReadDeviceLanguage(uint8 manufacturer, | 419 void OnDeviceOpenedReadDescriptors( |
331 uint8 product, | 420 uint8 manufacturer, |
332 uint8 serial_number, | 421 uint8 product, |
333 const base::Closure& success_closure, | 422 uint8 serial_number, |
334 const base::Closure& failure_closure, | 423 bool read_bos_descriptors, |
335 scoped_refptr<UsbDeviceHandle> device_handle) { | 424 const base::Closure& success_closure, |
| 425 const base::Closure& failure_closure, |
| 426 scoped_refptr<UsbDeviceHandle> device_handle) { |
336 if (device_handle) { | 427 if (device_handle) { |
337 ReadStringDescriptor( | 428 int count = 0; |
338 device_handle, 0, 0, | 429 if (manufacturer != 0) |
339 base::Bind(&OnReadLanguageIds, device_handle, manufacturer, product, | 430 count++; |
340 serial_number, success_closure)); | 431 if (product != 0) |
| 432 count++; |
| 433 if (serial_number != 0) |
| 434 count++; |
| 435 if (read_bos_descriptors) |
| 436 count++; |
| 437 DCHECK_GT(count, 0); |
| 438 |
| 439 base::Closure barrier = |
| 440 base::BarrierClosure(count, base::Bind(&CloseHandleAndRunContinuation, |
| 441 device_handle, success_closure)); |
| 442 |
| 443 if (manufacturer != 0 || product != 0 || serial_number != 0) { |
| 444 ReadStringDescriptor( |
| 445 device_handle, 0, 0, |
| 446 base::Bind(&OnReadLanguageIds, device_handle, manufacturer, product, |
| 447 serial_number, barrier)); |
| 448 } |
| 449 |
| 450 if (read_bos_descriptors) { |
| 451 ReadBosDescriptor(device_handle, barrier); |
| 452 } |
341 } else { | 453 } else { |
342 failure_closure.Run(); | 454 failure_closure.Run(); |
343 } | 455 } |
344 } | 456 } |
345 | 457 |
| 458 #if defined(USE_UDEV) |
| 459 |
| 460 void EnumerateUdevDevice(scoped_refptr<UsbDeviceImpl> device, |
| 461 bool read_bos_descriptors, |
| 462 scoped_refptr<base::SequencedTaskRunner> task_runner, |
| 463 const base::Closure& success_closure, |
| 464 const base::Closure& failure_closure) { |
| 465 ScopedUdevPtr udev(udev_new()); |
| 466 ScopedUdevEnumeratePtr udev_enumerate(udev_enumerate_new(udev.get())); |
| 467 |
| 468 udev_enumerate_add_match_subsystem(udev_enumerate.get(), "usb"); |
| 469 if (udev_enumerate_scan_devices(udev_enumerate.get()) != 0) { |
| 470 task_runner->PostTask(FROM_HERE, failure_closure); |
| 471 return; |
| 472 } |
| 473 |
| 474 std::string bus_number = |
| 475 base::IntToString(libusb_get_bus_number(device->platform_device())); |
| 476 std::string device_address = |
| 477 base::IntToString(libusb_get_device_address(device->platform_device())); |
| 478 udev_list_entry* devices = |
| 479 udev_enumerate_get_list_entry(udev_enumerate.get()); |
| 480 for (udev_list_entry* i = devices; i != NULL; |
| 481 i = udev_list_entry_get_next(i)) { |
| 482 ScopedUdevDevicePtr udev_device( |
| 483 udev_device_new_from_syspath(udev.get(), udev_list_entry_get_name(i))); |
| 484 if (udev_device) { |
| 485 const char* value = |
| 486 udev_device_get_sysattr_value(udev_device.get(), "busnum"); |
| 487 if (!value || bus_number != value) { |
| 488 continue; |
| 489 } |
| 490 value = udev_device_get_sysattr_value(udev_device.get(), "devnum"); |
| 491 if (!value || device_address != value) { |
| 492 continue; |
| 493 } |
| 494 |
| 495 value = udev_device_get_sysattr_value(udev_device.get(), "manufacturer"); |
| 496 if (value) { |
| 497 device->set_manufacturer_string(base::UTF8ToUTF16(value)); |
| 498 } |
| 499 value = udev_device_get_sysattr_value(udev_device.get(), "product"); |
| 500 if (value) { |
| 501 device->set_product_string(base::UTF8ToUTF16(value)); |
| 502 } |
| 503 value = udev_device_get_sysattr_value(udev_device.get(), "serial"); |
| 504 if (value) { |
| 505 device->set_serial_number(base::UTF8ToUTF16(value)); |
| 506 } |
| 507 |
| 508 value = udev_device_get_devnode(udev_device.get()); |
| 509 if (value) { |
| 510 device->set_device_path(value); |
| 511 |
| 512 if (read_bos_descriptors) { |
| 513 task_runner->PostTask( |
| 514 FROM_HERE, |
| 515 base::Bind(&UsbDevice::Open, device, |
| 516 base::Bind(&OnDeviceOpenedReadDescriptors, 0, 0, 0, |
| 517 true, success_closure, failure_closure))); |
| 518 } else { |
| 519 task_runner->PostTask(FROM_HERE, success_closure); |
| 520 } |
| 521 return; |
| 522 } |
| 523 |
| 524 break; |
| 525 } |
| 526 } |
| 527 |
| 528 task_runner->PostTask(FROM_HERE, failure_closure); |
| 529 } |
| 530 |
346 #endif // USE_UDEV | 531 #endif // USE_UDEV |
347 | 532 |
348 } // namespace | 533 } // namespace |
349 | 534 |
350 // static | 535 // static |
351 UsbService* UsbServiceImpl::Create( | 536 UsbService* UsbServiceImpl::Create( |
352 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) { | 537 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) { |
353 PlatformUsbContext context = NULL; | 538 PlatformUsbContext context = NULL; |
354 const int rv = libusb_init(&context); | 539 const int rv = libusb_init(&context); |
355 if (rv != LIBUSB_SUCCESS) { | 540 if (rv != LIBUSB_SUCCESS) { |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
566 libusb_device_descriptor descriptor; | 751 libusb_device_descriptor descriptor; |
567 int rv = libusb_get_device_descriptor(platform_device, &descriptor); | 752 int rv = libusb_get_device_descriptor(platform_device, &descriptor); |
568 if (rv == LIBUSB_SUCCESS) { | 753 if (rv == LIBUSB_SUCCESS) { |
569 scoped_refptr<UsbDeviceImpl> device( | 754 scoped_refptr<UsbDeviceImpl> device( |
570 new UsbDeviceImpl(context_, platform_device, descriptor.idVendor, | 755 new UsbDeviceImpl(context_, platform_device, descriptor.idVendor, |
571 descriptor.idProduct, blocking_task_runner_)); | 756 descriptor.idProduct, blocking_task_runner_)); |
572 | 757 |
573 base::Closure add_device = | 758 base::Closure add_device = |
574 base::Bind(&UsbServiceImpl::AddDevice, weak_factory_.GetWeakPtr(), | 759 base::Bind(&UsbServiceImpl::AddDevice, weak_factory_.GetWeakPtr(), |
575 refresh_complete, device); | 760 refresh_complete, device); |
| 761 bool read_bos_descriptors = descriptor.bcdUSB >= kUsbVersion2_1; |
576 | 762 |
577 #if defined(USE_UDEV) | 763 #if defined(USE_UDEV) |
578 blocking_task_runner_->PostTask( | 764 blocking_task_runner_->PostTask( |
579 FROM_HERE, base::Bind(&EnumerateUdevDevice, device, task_runner_, | 765 FROM_HERE, |
580 add_device, refresh_complete)); | 766 base::Bind(&EnumerateUdevDevice, device, read_bos_descriptors, |
| 767 task_runner_, add_device, refresh_complete)); |
581 #else | 768 #else |
582 if (descriptor.iManufacturer == 0 && descriptor.iProduct == 0 && | 769 if (descriptor.iManufacturer == 0 && descriptor.iProduct == 0 && |
583 descriptor.iSerialNumber == 0) { | 770 descriptor.iSerialNumber == 0 && !read_bos_descriptors) { |
584 // Don't bother disturbing the device if it has no string descriptors to | 771 // Don't bother disturbing the device if it has no descriptors to offer. |
585 // offer. | |
586 add_device.Run(); | 772 add_device.Run(); |
587 } else { | 773 } else { |
588 device->Open(base::Bind(&ReadDeviceLanguage, descriptor.iManufacturer, | 774 device->Open(base::Bind(&OnDeviceOpenedReadDescriptors, |
589 descriptor.iProduct, descriptor.iSerialNumber, | 775 descriptor.iManufacturer, descriptor.iProduct, |
| 776 descriptor.iSerialNumber, read_bos_descriptors, |
590 add_device, refresh_complete)); | 777 add_device, refresh_complete)); |
591 } | 778 } |
592 #endif | 779 #endif |
593 } else { | 780 } else { |
594 USB_LOG(EVENT) << "Failed to get device descriptor: " | 781 USB_LOG(EVENT) << "Failed to get device descriptor: " |
595 << ConvertPlatformUsbErrorToString(rv); | 782 << ConvertPlatformUsbErrorToString(rv); |
596 refresh_complete.Run(); | 783 refresh_complete.Run(); |
597 } | 784 } |
598 } | 785 } |
599 | 786 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
685 if (it != platform_devices_.end()) { | 872 if (it != platform_devices_.end()) { |
686 RemoveDevice(it->second); | 873 RemoveDevice(it->second); |
687 } else { | 874 } else { |
688 DCHECK(ContainsKey(devices_being_enumerated_, platform_device)); | 875 DCHECK(ContainsKey(devices_being_enumerated_, platform_device)); |
689 devices_being_enumerated_.erase(platform_device); | 876 devices_being_enumerated_.erase(platform_device); |
690 } | 877 } |
691 libusb_unref_device(platform_device); | 878 libusb_unref_device(platform_device); |
692 } | 879 } |
693 | 880 |
694 } // namespace device | 881 } // namespace device |
OLD | NEW |