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