| 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;
|
| + }
|
| +}
|
|
|