| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "chrome/browser/usb/usb_device.h" | 5 #include "chrome/browser/usb/usb_device.h" |
| 6 | 6 |
| 7 #include "base/stl_util.h" | 7 #include "base/stl_util.h" |
| 8 #include "base/synchronization/lock.h" | 8 #include "base/synchronization/lock.h" |
| 9 #include "chrome/browser/usb/usb_service.h" | 9 #include "chrome/browser/usb/usb_service.h" |
| 10 #include "third_party/libusb/libusb.h" | 10 #include "third_party/libusb/libusb.h" |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 service_->CloseDevice(this); | 108 service_->CloseDevice(this); |
| 109 handle_ = NULL; | 109 handle_ = NULL; |
| 110 } | 110 } |
| 111 | 111 |
| 112 void UsbDevice::TransferComplete(PlatformUsbTransferHandle handle) { | 112 void UsbDevice::TransferComplete(PlatformUsbTransferHandle handle) { |
| 113 base::AutoLock lock(lock_); | 113 base::AutoLock lock(lock_); |
| 114 | 114 |
| 115 // TODO(gdk): Handle device disconnect. | 115 // TODO(gdk): Handle device disconnect. |
| 116 DCHECK(ContainsKey(transfers_, handle)) << "Missing transfer completed"; | 116 DCHECK(ContainsKey(transfers_, handle)) << "Missing transfer completed"; |
| 117 Transfer* const transfer = &transfers_[handle]; | 117 Transfer* const transfer = &transfers_[handle]; |
| 118 if (transfer->buffer.get()) { | 118 |
| 119 transfer->callback.Run(ConvertTransferStatus(handle->status)); | 119 // If the transfer is a control transfer we do not expose the control transfer |
| 120 // setup header to the caller, this logic strips off the header from the |
| 121 // buffer before invoking the callback provided with the transfer with it. |
| 122 scoped_refptr<net::IOBuffer> buffer = transfer->buffer; |
| 123 if (transfer->control_transfer) { |
| 124 scoped_refptr<net::IOBuffer> resized_buffer = new net::IOBuffer( |
| 125 handle->actual_length - LIBUSB_CONTROL_SETUP_SIZE); |
| 126 memcpy(resized_buffer->data(), buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, |
| 127 handle->actual_length - LIBUSB_CONTROL_SETUP_SIZE); |
| 128 buffer = resized_buffer; |
| 120 } | 129 } |
| 121 | 130 |
| 131 transfer->callback.Run(ConvertTransferStatus(handle->status), buffer, |
| 132 handle->actual_length); |
| 133 |
| 122 transfers_.erase(handle); | 134 transfers_.erase(handle); |
| 123 libusb_free_transfer(handle); | 135 libusb_free_transfer(handle); |
| 124 } | 136 } |
| 125 | 137 |
| 126 void UsbDevice::ControlTransfer(const TransferDirection direction, | 138 void UsbDevice::ControlTransfer(const TransferDirection direction, |
| 127 const TransferRequestType request_type, const TransferRecipient recipient, | 139 const TransferRequestType request_type, const TransferRecipient recipient, |
| 128 const uint8 request, const uint16 value, const uint16 index, | 140 const uint8 request, const uint16 value, const uint16 index, |
| 129 net::IOBuffer* buffer, const size_t length, const unsigned int timeout, | 141 net::IOBuffer* buffer, const size_t length, const unsigned int timeout, |
| 130 const UsbTransferCallback& callback) { | 142 const UsbTransferCallback& callback) { |
| 131 CheckDevice(); | 143 CheckDevice(); |
| 132 | 144 |
| 145 const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + length; |
| 133 scoped_refptr<net::IOBuffer> resized_buffer(new net::IOBufferWithSize( | 146 scoped_refptr<net::IOBuffer> resized_buffer(new net::IOBufferWithSize( |
| 134 LIBUSB_CONTROL_SETUP_SIZE + length)); | 147 resized_length)); |
| 135 memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, buffer->data(), | 148 memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, buffer->data(), |
| 136 length); | 149 length); |
| 137 | 150 |
| 138 struct libusb_transfer* const transfer = libusb_alloc_transfer(0); | 151 struct libusb_transfer* const transfer = libusb_alloc_transfer(0); |
| 139 const uint8 converted_type = CreateRequestType(direction, request_type, | 152 const uint8 converted_type = CreateRequestType(direction, request_type, |
| 140 recipient); | 153 recipient); |
| 141 libusb_fill_control_setup(reinterpret_cast<uint8*>(resized_buffer->data()), | 154 libusb_fill_control_setup(reinterpret_cast<uint8*>(resized_buffer->data()), |
| 142 converted_type, request, value, index, length); | 155 converted_type, request, value, index, length); |
| 143 libusb_fill_control_transfer(transfer, handle_, reinterpret_cast<uint8*>( | 156 libusb_fill_control_transfer(transfer, handle_, reinterpret_cast<uint8*>( |
| 144 resized_buffer->data()), reinterpret_cast<libusb_transfer_cb_fn>( | 157 resized_buffer->data()), reinterpret_cast<libusb_transfer_cb_fn>( |
| 145 &HandleTransferCompletion), this, timeout); | 158 &HandleTransferCompletion), this, timeout); |
| 146 SubmitTransfer(transfer, resized_buffer, callback); | 159 SubmitTransfer(transfer, true, resized_buffer, resized_length, callback); |
| 147 } | 160 } |
| 148 | 161 |
| 149 void UsbDevice::BulkTransfer(const TransferDirection direction, | 162 void UsbDevice::BulkTransfer(const TransferDirection direction, |
| 150 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, | 163 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, |
| 151 const unsigned int timeout, const UsbTransferCallback& callback) { | 164 const unsigned int timeout, const UsbTransferCallback& callback) { |
| 152 CheckDevice(); | 165 CheckDevice(); |
| 153 | 166 |
| 154 struct libusb_transfer* const transfer = libusb_alloc_transfer(0); | 167 struct libusb_transfer* const transfer = libusb_alloc_transfer(0); |
| 155 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; | 168 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; |
| 156 libusb_fill_bulk_transfer(transfer, handle_, new_endpoint, | 169 libusb_fill_bulk_transfer(transfer, handle_, new_endpoint, |
| 157 reinterpret_cast<uint8*>(buffer->data()), length, | 170 reinterpret_cast<uint8*>(buffer->data()), length, |
| 158 reinterpret_cast<libusb_transfer_cb_fn>(&HandleTransferCompletion), this, | 171 reinterpret_cast<libusb_transfer_cb_fn>(&HandleTransferCompletion), this, |
| 159 timeout); | 172 timeout); |
| 160 SubmitTransfer(transfer, buffer, callback); | 173 SubmitTransfer(transfer, false, buffer, length, callback); |
| 161 } | 174 } |
| 162 | 175 |
| 163 void UsbDevice::InterruptTransfer(const TransferDirection direction, | 176 void UsbDevice::InterruptTransfer(const TransferDirection direction, |
| 164 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, | 177 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, |
| 165 const unsigned int timeout, const UsbTransferCallback& callback) { | 178 const unsigned int timeout, const UsbTransferCallback& callback) { |
| 166 CheckDevice(); | 179 CheckDevice(); |
| 167 | 180 |
| 168 struct libusb_transfer* const transfer = libusb_alloc_transfer(0); | 181 struct libusb_transfer* const transfer = libusb_alloc_transfer(0); |
| 169 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; | 182 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; |
| 170 libusb_fill_interrupt_transfer(transfer, handle_, new_endpoint, | 183 libusb_fill_interrupt_transfer(transfer, handle_, new_endpoint, |
| 171 reinterpret_cast<uint8*>(buffer->data()), length, | 184 reinterpret_cast<uint8*>(buffer->data()), length, |
| 172 reinterpret_cast<libusb_transfer_cb_fn>(&HandleTransferCompletion), this, | 185 reinterpret_cast<libusb_transfer_cb_fn>(&HandleTransferCompletion), this, |
| 173 timeout); | 186 timeout); |
| 174 SubmitTransfer(transfer, buffer, callback); | 187 SubmitTransfer(transfer, false, buffer, length, callback); |
| 175 } | 188 } |
| 176 | 189 |
| 177 void UsbDevice::IsochronousTransfer(const TransferDirection direction, | 190 void UsbDevice::IsochronousTransfer(const TransferDirection direction, |
| 178 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, | 191 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, |
| 179 const unsigned int packets, const unsigned int packet_length, | 192 const unsigned int packets, const unsigned int packet_length, |
| 180 const unsigned int timeout, const UsbTransferCallback& callback) { | 193 const unsigned int timeout, const UsbTransferCallback& callback) { |
| 181 CheckDevice(); | 194 CheckDevice(); |
| 182 | 195 |
| 183 const uint64 total_length = packets * packet_length; | 196 const uint64 total_length = packets * packet_length; |
| 184 if (total_length > length) { | 197 if (total_length > length) { |
| 185 callback.Run(USB_TRANSFER_LENGTH_SHORT); | 198 callback.Run(USB_TRANSFER_LENGTH_SHORT, NULL, 0); |
| 186 return; | 199 return; |
| 187 } | 200 } |
| 188 | 201 |
| 189 struct libusb_transfer* const transfer = libusb_alloc_transfer(packets); | 202 struct libusb_transfer* const transfer = libusb_alloc_transfer(packets); |
| 190 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; | 203 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; |
| 191 libusb_fill_iso_transfer(transfer, handle_, new_endpoint, | 204 libusb_fill_iso_transfer(transfer, handle_, new_endpoint, |
| 192 reinterpret_cast<uint8*>(buffer->data()), length, packets, | 205 reinterpret_cast<uint8*>(buffer->data()), length, packets, |
| 193 reinterpret_cast<libusb_transfer_cb_fn>(&HandleTransferCompletion), this, | 206 reinterpret_cast<libusb_transfer_cb_fn>(&HandleTransferCompletion), this, |
| 194 timeout); | 207 timeout); |
| 195 libusb_set_iso_packet_lengths(transfer, packet_length); | 208 libusb_set_iso_packet_lengths(transfer, packet_length); |
| 196 | 209 |
| 197 SubmitTransfer(transfer, buffer, callback); | 210 SubmitTransfer(transfer, false, buffer, length, callback); |
| 198 } | 211 } |
| 199 | 212 |
| 200 void UsbDevice::CheckDevice() { | 213 void UsbDevice::CheckDevice() { |
| 201 DCHECK(handle_) << "Device is already closed."; | 214 DCHECK(handle_) << "Device is already closed."; |
| 202 } | 215 } |
| 203 | 216 |
| 204 void UsbDevice::SubmitTransfer(PlatformUsbTransferHandle handle, | 217 void UsbDevice::SubmitTransfer(PlatformUsbTransferHandle handle, |
| 218 bool control_transfer, |
| 205 net::IOBuffer* buffer, | 219 net::IOBuffer* buffer, |
| 220 const size_t length, |
| 206 const UsbTransferCallback& callback) { | 221 const UsbTransferCallback& callback) { |
| 207 libusb_submit_transfer(handle); | |
| 208 | |
| 209 Transfer transfer; | 222 Transfer transfer; |
| 223 transfer.control_transfer = control_transfer; |
| 210 transfer.buffer = buffer; | 224 transfer.buffer = buffer; |
| 225 transfer.length = length; |
| 211 transfer.callback = callback; | 226 transfer.callback = callback; |
| 212 | 227 |
| 213 { | 228 { |
| 214 base::AutoLock lock(lock_); | 229 base::AutoLock lock(lock_); |
| 215 transfers_[handle] = transfer; | 230 transfers_[handle] = transfer; |
| 231 libusb_submit_transfer(handle); |
| 216 } | 232 } |
| 217 } | 233 } |
| OLD | NEW |