OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012 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 "chrome/browser/usb/usb_device.h" |
| 6 |
| 7 #include "base/stl_util.h" |
| 8 #include "base/synchronization/lock.h" |
| 9 #include "chrome/browser/usb/usb_service.h" |
| 10 #include "third_party/libusb/libusb/libusb.h" |
| 11 |
| 12 namespace { |
| 13 |
| 14 static uint8 ConvertTransferDirection( |
| 15 const UsbDevice::TransferDirection direction) { |
| 16 switch (direction) { |
| 17 case UsbDevice::IN: |
| 18 return LIBUSB_ENDPOINT_IN; |
| 19 case UsbDevice::OUT: |
| 20 return LIBUSB_ENDPOINT_OUT; |
| 21 } |
| 22 NOTREACHED(); |
| 23 } |
| 24 |
| 25 static uint8 CreateRequestType(const UsbDevice::TransferDirection direction, |
| 26 const UsbDevice::TransferRequestType request_type, |
| 27 const UsbDevice::TransferRecipient recipient) { |
| 28 uint8 result = ConvertTransferDirection(direction); |
| 29 |
| 30 switch (request_type) { |
| 31 case UsbDevice::STANDARD: |
| 32 result |= LIBUSB_REQUEST_TYPE_STANDARD; |
| 33 break; |
| 34 case UsbDevice::CLASS: |
| 35 result |= LIBUSB_REQUEST_TYPE_CLASS; |
| 36 break; |
| 37 case UsbDevice::VENDOR: |
| 38 result |= LIBUSB_REQUEST_TYPE_VENDOR; |
| 39 break; |
| 40 case UsbDevice::RESERVED: |
| 41 result |= LIBUSB_REQUEST_TYPE_RESERVED; |
| 42 break; |
| 43 } |
| 44 |
| 45 switch (recipient) { |
| 46 case UsbDevice::DEVICE: |
| 47 result |= LIBUSB_RECIPIENT_DEVICE; |
| 48 break; |
| 49 case UsbDevice::INTERFACE: |
| 50 result |= LIBUSB_RECIPIENT_INTERFACE; |
| 51 break; |
| 52 case UsbDevice::ENDPOINT: |
| 53 result |= LIBUSB_RECIPIENT_ENDPOINT; |
| 54 break; |
| 55 case UsbDevice::OTHER: |
| 56 result |= LIBUSB_RECIPIENT_OTHER; |
| 57 break; |
| 58 } |
| 59 |
| 60 return result; |
| 61 } |
| 62 |
| 63 static void HandleTransferCompletion(struct libusb_transfer* transfer) { |
| 64 UsbDevice* const device = reinterpret_cast<UsbDevice*>(transfer->user_data); |
| 65 device->TransferComplete(transfer); |
| 66 } |
| 67 |
| 68 } // namespace |
| 69 |
| 70 UsbDevice::Transfer::Transfer() {} |
| 71 |
| 72 UsbDevice::Transfer::~Transfer() {} |
| 73 |
| 74 UsbDevice::UsbDevice(UsbService* service, PlatformUsbDeviceHandle handle) |
| 75 : service_(service), handle_(handle) { |
| 76 DCHECK(handle) << "Cannot create device with NULL handle."; |
| 77 } |
| 78 |
| 79 UsbDevice::~UsbDevice() {} |
| 80 |
| 81 void UsbDevice::Close() { |
| 82 CheckDevice(); |
| 83 service_->CloseDevice(this); |
| 84 handle_ = NULL; |
| 85 } |
| 86 |
| 87 void UsbDevice::TransferComplete(PlatformUsbTransferHandle handle) { |
| 88 base::AutoLock lock(lock_); |
| 89 |
| 90 DCHECK(ContainsKey(transfers_, handle)) << "Missing transfer completed"; |
| 91 Transfer* const transfer = &transfers_[handle]; |
| 92 if (transfer->buffer.get()) { |
| 93 transfer->callback.Run(true); |
| 94 } |
| 95 |
| 96 transfers_.erase(handle); |
| 97 libusb_free_transfer(handle); |
| 98 } |
| 99 |
| 100 void UsbDevice::ControlTransfer(const TransferDirection direction, |
| 101 const TransferRequestType request_type, const TransferRecipient recipient, |
| 102 const uint8 request, const uint16 value, const uint16 index, |
| 103 net::IOBuffer* buffer, const size_t length, const unsigned int timeout, |
| 104 const net::CompletionCallback& callback) { |
| 105 CheckDevice(); |
| 106 |
| 107 struct libusb_transfer* const transfer = libusb_alloc_transfer(0); |
| 108 const uint8 converted_type = CreateRequestType(direction, request_type, |
| 109 recipient); |
| 110 libusb_fill_control_setup(reinterpret_cast<uint8*>(buffer->data()), |
| 111 converted_type, request, value, index, length); |
| 112 libusb_fill_control_transfer(transfer, handle_, reinterpret_cast<uint8*>( |
| 113 buffer->data()), &HandleTransferCompletion, this, timeout); |
| 114 AddTransfer(transfer, buffer, callback); |
| 115 libusb_submit_transfer(transfer); |
| 116 } |
| 117 |
| 118 void UsbDevice::BulkTransfer(const TransferDirection direction, |
| 119 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, |
| 120 const unsigned int timeout, const net::CompletionCallback& callback) { |
| 121 CheckDevice(); |
| 122 |
| 123 struct libusb_transfer* const transfer = libusb_alloc_transfer(0); |
| 124 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; |
| 125 libusb_fill_bulk_transfer(transfer, handle_, new_endpoint, |
| 126 reinterpret_cast<uint8*>(buffer->data()), length, |
| 127 &HandleTransferCompletion, this, timeout); |
| 128 AddTransfer(transfer, buffer, callback); |
| 129 libusb_submit_transfer(transfer); |
| 130 } |
| 131 |
| 132 void UsbDevice::InterruptTransfer(const TransferDirection direction, |
| 133 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, |
| 134 const unsigned int timeout, const net::CompletionCallback& callback) { |
| 135 CheckDevice(); |
| 136 |
| 137 struct libusb_transfer* const transfer = libusb_alloc_transfer(0); |
| 138 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; |
| 139 libusb_fill_interrupt_transfer(transfer, handle_, new_endpoint, |
| 140 reinterpret_cast<uint8*>(buffer->data()), length, |
| 141 &HandleTransferCompletion, this, timeout); |
| 142 AddTransfer(transfer, buffer, callback); |
| 143 libusb_submit_transfer(transfer); |
| 144 } |
| 145 |
| 146 void UsbDevice::CheckDevice() { |
| 147 DCHECK(handle_) << "Device is already closed."; |
| 148 } |
| 149 |
| 150 void UsbDevice::AddTransfer(PlatformUsbTransferHandle handle, |
| 151 net::IOBuffer* buffer, |
| 152 const net::CompletionCallback& callback) { |
| 153 Transfer transfer; |
| 154 transfer.buffer = buffer; |
| 155 transfer.callback = callback; |
| 156 |
| 157 { |
| 158 base::AutoLock lock(lock_); |
| 159 transfers_[handle] = transfer; |
| 160 } |
| 161 } |
OLD | NEW |