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