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