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 |