| 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 |