Index: chrome/browser/usb/usb_device.cc |
diff --git a/chrome/browser/usb/usb_device.cc b/chrome/browser/usb/usb_device.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..77e10c9c5ec5e671d8679a296e58ea073de1bf54 |
--- /dev/null |
+++ b/chrome/browser/usb/usb_device.cc |
@@ -0,0 +1,158 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/usb/usb_device.h" |
+ |
+#include "base/stl_util.h" |
+#include "base/synchronization/lock.h" |
+#include "chrome/browser/usb/usb_service.h" |
+#include "third_party/libusb/libusb/libusb.h" |
+ |
+namespace { |
+ |
+static uint8 ConvertTransferDirection( |
+ const UsbDevice::TransferDirection direction) { |
+ switch (direction) { |
+ case UsbDevice::IN: |
+ return LIBUSB_ENDPOINT_IN; |
+ case UsbDevice::OUT: |
+ return LIBUSB_ENDPOINT_OUT; |
+ } |
+ NOTREACHED(); |
+} |
+ |
+static uint8 CreateRequestType(const UsbDevice::TransferDirection direction, |
+ const UsbDevice::TransferRequestType request_type, |
+ const UsbDevice::TransferRecipient recipient) { |
+ uint8 result = ConvertTransferDirection(direction); |
+ |
+ switch (request_type) { |
+ case UsbDevice::STANDARD: |
+ result |= LIBUSB_REQUEST_TYPE_STANDARD; |
+ break; |
+ case UsbDevice::CLASS: |
+ result |= LIBUSB_REQUEST_TYPE_CLASS; |
+ break; |
+ case UsbDevice::VENDOR: |
+ result |= LIBUSB_REQUEST_TYPE_VENDOR; |
+ break; |
+ case UsbDevice::RESERVED: |
+ result |= LIBUSB_REQUEST_TYPE_RESERVED; |
+ break; |
+ } |
+ |
+ switch (recipient) { |
+ case UsbDevice::DEVICE: |
+ result |= LIBUSB_RECIPIENT_DEVICE; |
+ break; |
+ case UsbDevice::INTERFACE: |
+ result |= LIBUSB_RECIPIENT_INTERFACE; |
+ break; |
+ case UsbDevice::ENDPOINT: |
+ result |= LIBUSB_RECIPIENT_ENDPOINT; |
+ break; |
+ case UsbDevice::OTHER: |
+ result |= LIBUSB_RECIPIENT_OTHER; |
+ break; |
+ } |
+ |
+ return result; |
+} |
+ |
+static void HandleTransferCompletion(struct libusb_transfer *transfer) { |
+ UsbDevice *const device = reinterpret_cast<UsbDevice *>(transfer->user_data); |
+ device->TransferComplete(transfer); |
+} |
+ |
+} // namespace |
+ |
+UsbDevice::UsbDevice(UsbService *service, PlatformUsbDeviceHandle handle) |
+ : service_(service), handle_(handle) { |
+ DCHECK(handle) << "Cannot create device with NULL handle."; |
+} |
+ |
+UsbDevice::~UsbDevice() {} |
+ |
+void UsbDevice::Close() { |
+ CheckDevice(); |
+ service_->CloseDevice(this); |
+ handle_ = NULL; |
+} |
+ |
+void UsbDevice::TransferComplete(PlatformUsbTransferHandle handle) { |
+ base::AutoLock lock(lock_); |
+ |
+ DCHECK(ContainsKey(transfers_, handle)) << "Missing transfer completed"; |
+ Transfer *const transfer = &transfers_[handle]; |
+ if (transfer->buffer.get()) { |
+ transfer->callback.Run(true); |
+ } |
+ |
+ transfers_.erase(handle); |
+ libusb_free_transfer(handle); |
+} |
+ |
+void UsbDevice::ControlTransfer(const TransferDirection direction, |
+ const TransferRequestType request_type, const TransferRecipient recipient, |
+ const uint8 request, const uint16 value, const uint16 index, |
+ net::IOBuffer *buffer, const size_t length, const unsigned int timeout, |
+ const net::CompletionCallback &callback) { |
+ CheckDevice(); |
+ |
+ struct libusb_transfer *const transfer = libusb_alloc_transfer(0); |
+ const uint8 converted_type = CreateRequestType(direction, request_type, |
+ recipient); |
+ libusb_fill_control_setup(reinterpret_cast<unsigned char *>(buffer->data()), |
+ converted_type, request, value, index, length); |
+ libusb_fill_control_transfer(transfer, handle_, |
+ reinterpret_cast<unsigned char *>(buffer->data()), |
+ &HandleTransferCompletion, this, timeout); |
+ AddTransfer(transfer, buffer, callback); |
+ libusb_submit_transfer(transfer); |
+} |
+ |
+void UsbDevice::BulkTransfer(const TransferDirection direction, |
+ const uint8 endpoint, net::IOBuffer *buffer, const size_t length, |
+ const unsigned int timeout, const net::CompletionCallback &callback) { |
+ CheckDevice(); |
+ |
+ struct libusb_transfer *const transfer = libusb_alloc_transfer(0); |
+ const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; |
+ libusb_fill_bulk_transfer(transfer, handle_, new_endpoint, |
+ reinterpret_cast<unsigned char *>(buffer->data()), length, |
+ &HandleTransferCompletion, this, timeout); |
+ AddTransfer(transfer, buffer, callback); |
+ libusb_submit_transfer(transfer); |
+} |
+ |
+void UsbDevice::InterruptTransfer(const TransferDirection direction, |
+ const uint8 endpoint, net::IOBuffer *buffer, const size_t length, |
+ const unsigned int timeout, const net::CompletionCallback &callback) { |
+ CheckDevice(); |
+ |
+ struct libusb_transfer *const transfer = libusb_alloc_transfer(0); |
+ const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; |
+ libusb_fill_interrupt_transfer(transfer, handle_, new_endpoint, |
+ reinterpret_cast<unsigned char *>(buffer->data()), length, |
+ &HandleTransferCompletion, this, timeout); |
+ AddTransfer(transfer, buffer, callback); |
+ libusb_submit_transfer(transfer); |
+} |
+ |
+void UsbDevice::CheckDevice() { |
+ DCHECK(handle_) << "Device is already closed."; |
+} |
+ |
+void UsbDevice::AddTransfer(PlatformUsbTransferHandle handle, |
+ net::IOBuffer *buffer, |
+ const net::CompletionCallback &callback) { |
+ Transfer transfer; |
+ transfer.buffer = buffer; |
+ transfer.callback = callback; |
+ |
+ { |
+ base::AutoLock lock(lock_); |
+ transfers_[handle] = transfer; |
+ } |
+} |