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