1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "device/usb/usb_device_handle_impl.h" 6 7 #include <algorithm> 8 #include <vector> 9 10 #include "base/bind.h" 11 #include "base/location.h" 12 #include "base/single_thread_task_runner.h" 13 #include "base/stl_util.h" 14 #include "base/strings/string16.h" 15 #include "base/synchronization/lock.h" 16 #include "base/thread_task_runner_handle.h" 17 #include "device/usb/usb_context.h" 18 #include "device/usb/usb_descriptors.h" 19 #include "device/usb/usb_device_impl.h" 20 #include "device/usb/usb_error.h" 21 #include "device/usb/usb_service.h" 22 #include "third_party/libusb/src/libusb/libusb.h" 23 24 namespace device { 25 26 typedef libusb_device* PlatformUsbDevice; 27 28 void HandleTransferCompletion(PlatformUsbTransferHandle transfer); 29 30 namespace { 31 32 static uint8 ConvertTransferDirection(const UsbEndpointDirection direction) { 33 switch (direction) { 34 case USB_DIRECTION_INBOUND: 35 return LIBUSB_ENDPOINT_IN; 36 case USB_DIRECTION_OUTBOUND: 37 return LIBUSB_ENDPOINT_OUT; 38 default: 39 NOTREACHED(); 40 return LIBUSB_ENDPOINT_IN; 41 } 42 } 43 44 static uint8 CreateRequestType( 45 const UsbEndpointDirection direction, 46 const UsbDeviceHandle::TransferRequestType request_type, 47 const UsbDeviceHandle::TransferRecipient recipient) { 48 uint8 result = ConvertTransferDirection(direction); 49 50 switch (request_type) { 51 case UsbDeviceHandle::STANDARD: 52 result |= LIBUSB_REQUEST_TYPE_STANDARD; 53 break; 54 case UsbDeviceHandle::CLASS: 55 result |= LIBUSB_REQUEST_TYPE_CLASS; 56 break; 57 case UsbDeviceHandle::VENDOR: 58 result |= LIBUSB_REQUEST_TYPE_VENDOR; 59 break; 60 case UsbDeviceHandle::RESERVED: 61 result |= LIBUSB_REQUEST_TYPE_RESERVED; 62 break; 63 } 64 65 switch (recipient) { 66 case UsbDeviceHandle::DEVICE: 67 result |= LIBUSB_RECIPIENT_DEVICE; 68 break; 69 case UsbDeviceHandle::INTERFACE: 70 result |= LIBUSB_RECIPIENT_INTERFACE; 71 break; 72 case UsbDeviceHandle::ENDPOINT: 73 result |= LIBUSB_RECIPIENT_ENDPOINT; 74 break; 75 case UsbDeviceHandle::OTHER: 76 result |= LIBUSB_RECIPIENT_OTHER; 77 break; 78 } 79 80 return result; 81 } 82 83 static UsbTransferStatus ConvertTransferStatus( 84 const libusb_transfer_status status) { 85 switch (status) { 86 case LIBUSB_TRANSFER_COMPLETED: 87 return USB_TRANSFER_COMPLETED; 88 case LIBUSB_TRANSFER_ERROR: 89 return USB_TRANSFER_ERROR; 90 case LIBUSB_TRANSFER_TIMED_OUT: 91 return USB_TRANSFER_TIMEOUT; 92 case LIBUSB_TRANSFER_STALL: 93 return USB_TRANSFER_STALLED; 94 case LIBUSB_TRANSFER_NO_DEVICE: 95 return USB_TRANSFER_DISCONNECT; 96 case LIBUSB_TRANSFER_OVERFLOW: 97 return USB_TRANSFER_OVERFLOW; 98 case LIBUSB_TRANSFER_CANCELLED: 99 return USB_TRANSFER_CANCELLED; 100 default: 101 NOTREACHED(); 102 return USB_TRANSFER_ERROR; 103 } 104 } 105 106 } // namespace 107 108 class UsbDeviceHandleImpl::InterfaceClaimer 109 : public base::RefCountedThreadSafe<UsbDeviceHandleImpl::InterfaceClaimer> { 110 public: 111 InterfaceClaimer(const scoped_refptr<UsbDeviceHandleImpl> handle, 112 const int interface_number); 113 114 bool Claim() const; 115 116 int alternate_setting() const { return alternate_setting_; } 117 void set_alternate_setting(const int alternate_setting) { 118 alternate_setting_ = alternate_setting; 119 } 120 121 private: 122 friend class UsbDevice; 123 friend class base::RefCountedThreadSafe<InterfaceClaimer>; 124 ~InterfaceClaimer(); 125 126 const scoped_refptr<UsbDeviceHandleImpl> handle_; 127 const int interface_number_; 128 int alternate_setting_; 129 130 DISALLOW_COPY_AND_ASSIGN(InterfaceClaimer); 131 }; 132 133 UsbDeviceHandleImpl::InterfaceClaimer::InterfaceClaimer( 134 const scoped_refptr<UsbDeviceHandleImpl> handle, 135 const int interface_number) 136 : handle_(handle), 137 interface_number_(interface_number), 138 alternate_setting_(0) { 139 } 140 141 UsbDeviceHandleImpl::InterfaceClaimer::~InterfaceClaimer() { 142 libusb_release_interface(handle_->handle(), interface_number_); 143 } 144 145 bool UsbDeviceHandleImpl::InterfaceClaimer::Claim() const { 146 const int rv = libusb_claim_interface(handle_->handle(), interface_number_); 147 if (rv != LIBUSB_SUCCESS) { 148 VLOG(1) << "Failed to claim interface: " 149 << ConvertPlatformUsbErrorToString(rv); 150 } 151 return rv == LIBUSB_SUCCESS; 152 } 153 154 struct UsbDeviceHandleImpl::Transfer { 155 Transfer(); 156 ~Transfer(); 157 158 void Complete(UsbTransferStatus status, size_t bytes_transferred); 159 160 UsbTransferType transfer_type; 161 scoped_refptr<net::IOBuffer> buffer; 162 scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer> claimed_interface; 163 scoped_refptr<base::SingleThreadTaskRunner> task_runner; 164 size_t length; 165 UsbTransferCallback callback; 166 }; 167 168 UsbDeviceHandleImpl::Transfer::Transfer() 169 : transfer_type(USB_TRANSFER_CONTROL), length(0) { 170 } 171 172 UsbDeviceHandleImpl::Transfer::~Transfer() { 173 } 174 175 void UsbDeviceHandleImpl::Transfer::Complete(UsbTransferStatus status, 176 size_t bytes_transferred) { 177 if (task_runner->RunsTasksOnCurrentThread()) { 178 callback.Run(status, buffer, bytes_transferred); 179 } else { 180 task_runner->PostTask( 181 FROM_HERE, base::Bind(callback, status, buffer, bytes_transferred)); 182 } 183 } 184 185 UsbDeviceHandleImpl::UsbDeviceHandleImpl(scoped_refptr<UsbContext> context, 186 UsbDeviceImpl* device, 187 PlatformUsbDeviceHandle handle, 188 const UsbConfigDescriptor& config) 189 : device_(device), 190 handle_(handle), 191 config_(config), 192 context_(context), 193 task_runner_(base::ThreadTaskRunnerHandle::Get()) { 194 DCHECK(handle) << "Cannot create device with NULL handle."; 195 } 196 197 UsbDeviceHandleImpl::~UsbDeviceHandleImpl() { 198 DCHECK(thread_checker_.CalledOnValidThread()); 199 200 libusb_close(handle_); 201 handle_ = NULL; 202 } 203 204 scoped_refptr<UsbDevice> UsbDeviceHandleImpl::GetDevice() const { 205 return static_cast<UsbDevice*>(device_); 206 } 207 208 void UsbDeviceHandleImpl::Close() { 209 DCHECK(thread_checker_.CalledOnValidThread()); 210 if (device_) 211 device_->Close(this); 212 } 213 214 bool UsbDeviceHandleImpl::ClaimInterface(const int interface_number) { 215 DCHECK(thread_checker_.CalledOnValidThread()); 216 if (!device_) 217 return false; 218 if (ContainsKey(claimed_interfaces_, interface_number)) 219 return true; 220 221 scoped_refptr<InterfaceClaimer> claimer = 222 new InterfaceClaimer(this, interface_number); 223 224 if (claimer->Claim()) { 225 claimed_interfaces_[interface_number] = claimer; 226 RefreshEndpointMap(); 227 return true; 228 } 229 return false; 230 } 231 232 bool UsbDeviceHandleImpl::ReleaseInterface(const int interface_number) { 233 DCHECK(thread_checker_.CalledOnValidThread()); 234 if (!device_) 235 return false; 236 if (!ContainsKey(claimed_interfaces_, interface_number)) 237 return false; 238 239 // Cancel all the transfers on that interface. 240 InterfaceClaimer* interface_claimer = 241 claimed_interfaces_[interface_number].get(); 242 for (TransferMap::iterator it = transfers_.begin(); it != transfers_.end(); 243 ++it) { 244 if (it->second.claimed_interface.get() == interface_claimer) 245 libusb_cancel_transfer(it->first); 246 } 247 claimed_interfaces_.erase(interface_number); 248 249 RefreshEndpointMap(); 250 return true; 251 } 252 253 bool UsbDeviceHandleImpl::SetInterfaceAlternateSetting( 254 const int interface_number, 255 const int alternate_setting) { 256 DCHECK(thread_checker_.CalledOnValidThread()); 257 if (!device_) 258 return false; 259 if (!ContainsKey(claimed_interfaces_, interface_number)) 260 return false; 261 const int rv = libusb_set_interface_alt_setting( 262 handle_, interface_number, alternate_setting); 263 if (rv == LIBUSB_SUCCESS) { 264 claimed_interfaces_[interface_number]->set_alternate_setting( 265 alternate_setting); 266 RefreshEndpointMap(); 267 } else { 268 VLOG(1) << "Failed to set interface (" << interface_number << ", " 269 << alternate_setting 270 << "): " << ConvertPlatformUsbErrorToString(rv); 271 } 272 return rv == LIBUSB_SUCCESS; 273 } 274 275 bool UsbDeviceHandleImpl::ResetDevice() { 276 DCHECK(thread_checker_.CalledOnValidThread()); 277 if (!device_) 278 return false; 279 280 const int rv = libusb_reset_device(handle_); 281 if (rv != LIBUSB_SUCCESS) { 282 VLOG(1) << "Failed to reset device: " 283 << ConvertPlatformUsbErrorToString(rv); 284 } 285 return rv == LIBUSB_SUCCESS; 286 } 287 288 bool UsbDeviceHandleImpl::GetStringDescriptor(uint8 string_id, 289 base::string16* string) { 290 if (!GetSupportedLanguages()) { 291 return false; 292 } 293 294 std::map<uint8, base::string16>::const_iterator it = strings_.find(string_id); 295 if (it != strings_.end()) { 296 *string = it->second; 297 return true; 298 } 299 300 for (size_t i = 0; i < languages_.size(); ++i) { 301 // Get the string using language ID. 302 uint16 language_id = languages_[i]; 303 // The 1-byte length field limits the descriptor to 256-bytes (128 char16s). 304 base::char16 text[128]; 305 int size = 306 libusb_get_string_descriptor(handle_, 307 string_id, 308 language_id, 309 reinterpret_cast<unsigned char*>(&text[0]), 310 sizeof(text)); 311 if (size < 0) { 312 VLOG(1) << "Failed to get string descriptor " << string_id << " (langid " 313 << language_id << "): " << ConvertPlatformUsbErrorToString(size); 314 continue; 315 } else if (size < 2) { 316 VLOG(1) << "String descriptor " << string_id << " (langid " << language_id 317 << ") has no header."; 318 continue; 319 // The first 2 bytes of the descriptor are the total length and type tag. 320 } else if ((text[0] & 0xff) != size) { 321 VLOG(1) << "String descriptor " << string_id << " (langid " << language_id 322 << ") size mismatch: " << (text[0] & 0xff) << " != " << size; 323 continue; 324 } else if ((text[0] >> 8) != LIBUSB_DT_STRING) { 325 VLOG(1) << "String descriptor " << string_id << " (langid " << language_id 326 << ") is not a string descriptor."; 327 continue; 328 } 329 330 *string = base::string16(text + 1, (size - 2) / 2); 331 strings_[string_id] = *string; 332 return true; 333 } 334 335 return false; 336 } 337 338 void UsbDeviceHandleImpl::ControlTransfer( 339 const UsbEndpointDirection direction, 340 const TransferRequestType request_type, 341 const TransferRecipient recipient, 342 const uint8 request, 343 const uint16 value, 344 const uint16 index, 345 net::IOBuffer* buffer, 346 const size_t length, 347 const unsigned int timeout, 348 const UsbTransferCallback& callback) { 349 if (!device_) { 350 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); 351 return; 352 } 353 354 const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + length; 355 scoped_refptr<net::IOBuffer> resized_buffer( 356 new net::IOBufferWithSize(static_cast<int>(resized_length))); 357 if (!resized_buffer.get()) { 358 callback.Run(USB_TRANSFER_ERROR, buffer, 0); 359 return; 360 } 361 memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, 362 buffer->data(), 363 static_cast<int>(length)); 364 365 PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0); 366 const uint8 converted_type = 367 CreateRequestType(direction, request_type, recipient); 368 libusb_fill_control_setup(reinterpret_cast<uint8*>(resized_buffer->data()), 369 converted_type, 370 request, 371 value, 372 index, 373 static_cast<int16>(length)); 374 libusb_fill_control_transfer(transfer, 375 handle_, 376 reinterpret_cast<uint8*>(resized_buffer->data()), 377 &UsbDeviceHandleImpl::PlatformTransferCallback, 378 this, 379 timeout); 380 381 PostOrSubmitTransfer(transfer, 382 USB_TRANSFER_CONTROL, 383 resized_buffer.get(), 384 resized_length, 385 callback); 386 } 387 388 void UsbDeviceHandleImpl::BulkTransfer(const UsbEndpointDirection direction, 389 const uint8 endpoint, 390 net::IOBuffer* buffer, 391 const size_t length, 392 const unsigned int timeout, 393 const UsbTransferCallback& callback) { 394 if (!device_) { 395 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); 396 return; 397 } 398 399 PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0); 400 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; 401 libusb_fill_bulk_transfer(transfer, 402 handle_, 403 new_endpoint, 404 reinterpret_cast<uint8*>(buffer->data()), 405 static_cast<int>(length), 406 &UsbDeviceHandleImpl::PlatformTransferCallback, 407 this, 408 timeout); 409 410 PostOrSubmitTransfer(transfer, USB_TRANSFER_BULK, buffer, length, callback); 411 } 412 413 void UsbDeviceHandleImpl::InterruptTransfer( 414 const UsbEndpointDirection direction, 415 const uint8 endpoint, 416 net::IOBuffer* buffer, 417 const size_t length, 418 const unsigned int timeout, 419 const UsbTransferCallback& callback) { 420 if (!device_) { 421 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); 422 return; 423 } 424 425 PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0); 426 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; 427 libusb_fill_interrupt_transfer(transfer, 428 handle_, 429 new_endpoint, 430 reinterpret_cast<uint8*>(buffer->data()), 431 static_cast<int>(length), 432 &UsbDeviceHandleImpl::PlatformTransferCallback, 433 this, 434 timeout); 435 436 PostOrSubmitTransfer( 437 transfer, USB_TRANSFER_INTERRUPT, buffer, length, callback); 438 } 439 440 void UsbDeviceHandleImpl::IsochronousTransfer( 441 const UsbEndpointDirection direction, 442 const uint8 endpoint, 443 net::IOBuffer* buffer, 444 const size_t length, 445 const unsigned int packets, 446 const unsigned int packet_length, 447 const unsigned int timeout, 448 const UsbTransferCallback& callback) { 449 if (!device_) { 450 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); 451 return; 452 } 453 454 const uint64 total_length = packets * packet_length; 455 CHECK(packets <= length && total_length <= length) 456 << "transfer length is too small"; 457 458 PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(packets); 459 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; 460 libusb_fill_iso_transfer(transfer, 461 handle_, 462 new_endpoint, 463 reinterpret_cast<uint8*>(buffer->data()), 464 static_cast<int>(length), 465 packets, 466 &UsbDeviceHandleImpl::PlatformTransferCallback, 467 this, 468 timeout); 469 libusb_set_iso_packet_lengths(transfer, packet_length); 470 471 PostOrSubmitTransfer( 472 transfer, USB_TRANSFER_ISOCHRONOUS, buffer, length, callback); 473 } 474 475 void UsbDeviceHandleImpl::RefreshEndpointMap() { 476 DCHECK(thread_checker_.CalledOnValidThread()); 477 endpoint_map_.clear(); 478 for (ClaimedInterfaceMap::iterator claimedIt = claimed_interfaces_.begin(); 479 claimedIt != claimed_interfaces_.end(); 480 ++claimedIt) { 481 for (UsbInterfaceDescriptor::Iterator ifaceIt = config_.interfaces.begin(); 482 ifaceIt != config_.interfaces.end(); 483 ++ifaceIt) { 484 if (ifaceIt->interface_number == claimedIt->first && 485 ifaceIt->alternate_setting == 486 claimedIt->second->alternate_setting()) { 487 for (UsbEndpointDescriptor::Iterator endpointIt = 488 ifaceIt->endpoints.begin(); 489 endpointIt != ifaceIt->endpoints.end(); 490 ++endpointIt) { 491 endpoint_map_[endpointIt->address] = claimedIt->first; 492 } 493 break; 494 } 495 } 496 } 497 } 498 499 scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer> 500 UsbDeviceHandleImpl::GetClaimedInterfaceForEndpoint(unsigned char endpoint) { 501 if (ContainsKey(endpoint_map_, endpoint)) 502 return claimed_interfaces_[endpoint_map_[endpoint]]; 503 return NULL; 504 } 505 506 void UsbDeviceHandleImpl::PostOrSubmitTransfer( 507 PlatformUsbTransferHandle transfer, 508 UsbTransferType transfer_type, 509 net::IOBuffer* buffer, 510 size_t length, 511 const UsbTransferCallback& callback) { 512 if (task_runner_->RunsTasksOnCurrentThread()) { 513 SubmitTransfer(transfer, 514 transfer_type, 515 buffer, 516 length, 517 base::ThreadTaskRunnerHandle::Get(), 518 callback); 519 } else { 520 task_runner_->PostTask(FROM_HERE, 521 base::Bind(&UsbDeviceHandleImpl::SubmitTransfer, 522 this, 523 transfer, 524 transfer_type, 525 make_scoped_refptr(buffer), 526 length, 527 base::ThreadTaskRunnerHandle::Get(), 528 callback)); 529 } 530 } 531 532 void UsbDeviceHandleImpl::SubmitTransfer( 533 PlatformUsbTransferHandle handle, 534 UsbTransferType transfer_type, 535 net::IOBuffer* buffer, 536 const size_t length, 537 scoped_refptr<base::SingleThreadTaskRunner> task_runner, 538 const UsbTransferCallback& callback) { 539 DCHECK(thread_checker_.CalledOnValidThread()); 540 541 Transfer transfer; 542 transfer.transfer_type = transfer_type; 543 transfer.buffer = buffer; 544 transfer.length = length; 545 transfer.callback = callback; 546 transfer.task_runner = task_runner; 547 548 if (!device_) { 549 transfer.Complete(USB_TRANSFER_DISCONNECT, 0); 550 return; 551 } 552 553 // It's OK for this method to return NULL. libusb_submit_transfer will fail if 554 // it requires an interface we didn't claim. 555 transfer.claimed_interface = GetClaimedInterfaceForEndpoint(handle->endpoint); 556 557 const int rv = libusb_submit_transfer(handle); 558 if (rv == LIBUSB_SUCCESS) { 559 transfers_[handle] = transfer; 560 } else { 561 VLOG(1) << "Failed to submit transfer: " 562 << ConvertPlatformUsbErrorToString(rv); 563 transfer.Complete(USB_TRANSFER_ERROR, 0); 564 } 565 } 566 567 /* static */ 568 void LIBUSB_CALL UsbDeviceHandleImpl::PlatformTransferCallback( 569 PlatformUsbTransferHandle transfer) { 570 UsbDeviceHandleImpl* device_handle = 571 reinterpret_cast<UsbDeviceHandleImpl*>(transfer->user_data); 572 device_handle->task_runner_->PostTask( 573 FROM_HERE, 574 base::Bind( 575 &UsbDeviceHandleImpl::CompleteTransfer, device_handle, transfer)); 576 } 577 578 void UsbDeviceHandleImpl::CompleteTransfer(PlatformUsbTransferHandle handle) { 579 DCHECK(ContainsKey(transfers_, handle)) << "Missing transfer completed"; 580 581 Transfer transfer = transfers_[handle]; 582 transfers_.erase(handle); 583 584 DCHECK_GE(handle->actual_length, 0) << "Negative actual length received"; 585 size_t actual_length = 586 static_cast<size_t>(std::max(handle->actual_length, 0)); 587 588 DCHECK(transfer.length >= actual_length) 589 << "data too big for our buffer (libusb failure?)"; 590 591 switch (transfer.transfer_type) { 592 case USB_TRANSFER_CONTROL: 593 // If the transfer is a control transfer we do not expose the control 594 // setup header to the caller. This logic strips off the header if 595 // present before invoking the callback provided with the transfer. 596 if (actual_length > 0) { 597 CHECK(transfer.length >= LIBUSB_CONTROL_SETUP_SIZE) 598 << "buffer was not correctly set: too small for the control header"; 599 600 if (transfer.length >= (LIBUSB_CONTROL_SETUP_SIZE + actual_length)) { 601 // If the payload is zero bytes long, pad out the allocated buffer 602 // size to one byte so that an IOBuffer of that size can be allocated. 603 scoped_refptr<net::IOBuffer> resized_buffer = 604 new net::IOBuffer(static_cast<int>( 605 std::max(actual_length, static_cast<size_t>(1)))); 606 memcpy(resized_buffer->data(), 607 transfer.buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, 608 actual_length); 609 transfer.buffer = resized_buffer; 610 } 611 } 612 break; 613 614 case USB_TRANSFER_ISOCHRONOUS: 615 // Isochronous replies might carry data in the different isoc packets even 616 // if the transfer actual_data value is zero. Furthermore, not all of the 617 // received packets might contain data, so we need to calculate how many 618 // data bytes we are effectively providing and pack the results. 619 if (actual_length == 0) { 620 size_t packet_buffer_start = 0; 621 for (int i = 0; i < handle->num_iso_packets; ++i) { 622 PlatformUsbIsoPacketDescriptor packet = &handle->iso_packet_desc[i]; 623 if (packet->actual_length > 0) { 624 // We don't need to copy as long as all packets until now provide 625 // all the data the packet can hold. 626 if (actual_length < packet_buffer_start) { 627 CHECK(packet_buffer_start + packet->actual_length <= 628 transfer.length); 629 memmove(transfer.buffer->data() + actual_length, 630 transfer.buffer->data() + packet_buffer_start, 631 packet->actual_length); 632 } 633 actual_length += packet->actual_length; 634 } 635 636 packet_buffer_start += packet->length; 637 } 638 } 639 break; 640 641 case USB_TRANSFER_BULK: 642 case USB_TRANSFER_INTERRUPT: 643 break; 644 645 default: 646 NOTREACHED() << "Invalid usb transfer type"; 647 break; 648 } 649 650 transfer.Complete(ConvertTransferStatus(handle->status), actual_length); 651 libusb_free_transfer(handle); 652 653 // Must release interface first before actually delete this. 654 transfer.claimed_interface = NULL; 655 } 656 657 bool UsbDeviceHandleImpl::GetSupportedLanguages() { 658 if (!languages_.empty()) { 659 return true; 660 } 661 662 // The 1-byte length field limits the descriptor to 256-bytes (128 uint16s). 663 uint16 languages[128]; 664 int size = libusb_get_string_descriptor( 665 handle_, 666 0, 667 0, 668 reinterpret_cast<unsigned char*>(&languages[0]), 669 sizeof(languages)); 670 if (size < 0) { 671 VLOG(1) << "Failed to get list of supported languages: " 672 << ConvertPlatformUsbErrorToString(size); 673 return false; 674 } else if (size < 2) { 675 VLOG(1) << "String descriptor zero has no header."; 676 return false; 677 // The first 2 bytes of the descriptor are the total length and type tag. 678 } else if ((languages[0] & 0xff) != size) { 679 VLOG(1) << "String descriptor zero size mismatch: " << (languages[0] & 0xff) 680 << " != " << size; 681 return false; 682 } else if ((languages[0] >> 8) != LIBUSB_DT_STRING) { 683 VLOG(1) << "String descriptor zero is not a string descriptor."; 684 return false; 685 } 686 687 languages_.assign(languages[1], languages[(size - 2) / 2]); 688 return true; 689 } 690 691 void UsbDeviceHandleImpl::InternalClose() { 692 DCHECK(thread_checker_.CalledOnValidThread()); 693 if (!device_) 694 return; 695 696 // Cancel all the transfers. 697 for (TransferMap::iterator it = transfers_.begin(); it != transfers_.end(); 698 ++it) { 699 // The callback will be called some time later. 700 libusb_cancel_transfer(it->first); 701 } 702 703 // Attempt-release all the interfaces. 704 // It will be retained until the transfer cancellation is finished. 705 claimed_interfaces_.clear(); 706 707 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to 708 // finish. 709 device_ = NULL; 710 } 711 712 } // namespace device 713