Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Side by Side Diff: chrome/browser/usb/usb_device_handle.cc

Issue 16316004: Separate usb device handle from usb device. (deprecate) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix Windows compile and a bug. Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/usb/usb_device.h" 5 #include "chrome/browser/usb/usb_device_handle.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/stl_util.h" 9 #include "base/stl_util.h"
10 #include "base/synchronization/lock.h" 10 #include "base/synchronization/lock.h"
11 #include "chrome/browser/usb/usb_interface.h" 11 #include "chrome/browser/usb/usb_interface.h"
12 #include "chrome/browser/usb/usb_service.h" 12 #include "chrome/browser/usb/usb_service.h"
13 #include "content/public/browser/browser_thread.h"
13 #include "third_party/libusb/src/libusb/libusb.h" 14 #include "third_party/libusb/src/libusb/libusb.h"
14 15
16 using content::BrowserThread;
17
18 #define CHECK_DEVICE(callback, args...) \
19 do { \
20 if (handle_ == NULL) { \
21 DVLOG(1) << "Device is disconnected: "; \
22 callback.Run(args);\
23 return; \
24 } \
25 } while (0)
26
27 #define CHECK_DEVICE_RETURN \
28 do { \
29 if (handle_ == NULL) { \
30 DVLOG(1) << "Device is disconnected: "; \
31 return; \
32 } \
33 } while (0)
34
15 namespace { 35 namespace {
16 36
17 static uint8 ConvertTransferDirection( 37 static uint8 ConvertTransferDirection(
18 const UsbEndpointDirection direction) { 38 const UsbEndpointDirection direction) {
19 switch (direction) { 39 switch (direction) {
20 case USB_DIRECTION_INBOUND: 40 case USB_DIRECTION_INBOUND:
21 return LIBUSB_ENDPOINT_IN; 41 return LIBUSB_ENDPOINT_IN;
22 case USB_DIRECTION_OUTBOUND: 42 case USB_DIRECTION_OUTBOUND:
23 return LIBUSB_ENDPOINT_OUT; 43 return LIBUSB_ENDPOINT_OUT;
24 default: 44 default:
25 NOTREACHED(); 45 NOTREACHED();
26 return LIBUSB_ENDPOINT_IN; 46 return LIBUSB_ENDPOINT_IN;
27 } 47 }
28 } 48 }
29 49
30 static uint8 CreateRequestType(const UsbEndpointDirection direction, 50 static uint8 CreateRequestType(const UsbEndpointDirection direction,
31 const UsbDevice::TransferRequestType request_type, 51 const UsbDeviceHandle::TransferRequestType request_type,
32 const UsbDevice::TransferRecipient recipient) { 52 const UsbDeviceHandle::TransferRecipient recipient) {
33 uint8 result = ConvertTransferDirection(direction); 53 uint8 result = ConvertTransferDirection(direction);
34 54
35 switch (request_type) { 55 switch (request_type) {
36 case UsbDevice::STANDARD: 56 case UsbDeviceHandle::STANDARD:
37 result |= LIBUSB_REQUEST_TYPE_STANDARD; 57 result |= LIBUSB_REQUEST_TYPE_STANDARD;
38 break; 58 break;
39 case UsbDevice::CLASS: 59 case UsbDeviceHandle::CLASS:
40 result |= LIBUSB_REQUEST_TYPE_CLASS; 60 result |= LIBUSB_REQUEST_TYPE_CLASS;
41 break; 61 break;
42 case UsbDevice::VENDOR: 62 case UsbDeviceHandle::VENDOR:
43 result |= LIBUSB_REQUEST_TYPE_VENDOR; 63 result |= LIBUSB_REQUEST_TYPE_VENDOR;
44 break; 64 break;
45 case UsbDevice::RESERVED: 65 case UsbDeviceHandle::RESERVED:
46 result |= LIBUSB_REQUEST_TYPE_RESERVED; 66 result |= LIBUSB_REQUEST_TYPE_RESERVED;
47 break; 67 break;
48 } 68 }
49 69
50 switch (recipient) { 70 switch (recipient) {
51 case UsbDevice::DEVICE: 71 case UsbDeviceHandle::DEVICE:
52 result |= LIBUSB_RECIPIENT_DEVICE; 72 result |= LIBUSB_RECIPIENT_DEVICE;
53 break; 73 break;
54 case UsbDevice::INTERFACE: 74 case UsbDeviceHandle::INTERFACE:
55 result |= LIBUSB_RECIPIENT_INTERFACE; 75 result |= LIBUSB_RECIPIENT_INTERFACE;
56 break; 76 break;
57 case UsbDevice::ENDPOINT: 77 case UsbDeviceHandle::ENDPOINT:
58 result |= LIBUSB_RECIPIENT_ENDPOINT; 78 result |= LIBUSB_RECIPIENT_ENDPOINT;
59 break; 79 break;
60 case UsbDevice::OTHER: 80 case UsbDeviceHandle::OTHER:
61 result |= LIBUSB_RECIPIENT_OTHER; 81 result |= LIBUSB_RECIPIENT_OTHER;
62 break; 82 break;
63 } 83 }
64 84
65 return result; 85 return result;
66 } 86 }
67 87
68 static UsbTransferStatus ConvertTransferStatus( 88 static UsbTransferStatus ConvertTransferStatus(
69 const libusb_transfer_status status) { 89 const libusb_transfer_status status) {
70 switch (status) { 90 switch (status) {
(...skipping 10 matching lines...) Expand all
81 case LIBUSB_TRANSFER_OVERFLOW: 101 case LIBUSB_TRANSFER_OVERFLOW:
82 return USB_TRANSFER_OVERFLOW; 102 return USB_TRANSFER_OVERFLOW;
83 case LIBUSB_TRANSFER_CANCELLED: 103 case LIBUSB_TRANSFER_CANCELLED:
84 return USB_TRANSFER_CANCELLED; 104 return USB_TRANSFER_CANCELLED;
85 default: 105 default:
86 NOTREACHED(); 106 NOTREACHED();
87 return USB_TRANSFER_ERROR; 107 return USB_TRANSFER_ERROR;
88 } 108 }
89 } 109 }
90 110
111 // This function dispatches a completed transfer to its handle.
112 // It is called from UsbEventDispatcher using libusb_handle_events_timeout.
91 static void LIBUSB_CALL HandleTransferCompletion( 113 static void LIBUSB_CALL HandleTransferCompletion(
92 struct libusb_transfer* transfer) { 114 struct libusb_transfer* transfer) {
93 UsbDevice* const device = reinterpret_cast<UsbDevice*>(transfer->user_data); 115 UsbDeviceHandle* const device =
116 reinterpret_cast<UsbDeviceHandle*>(transfer->user_data);
117
94 device->TransferComplete(transfer); 118 device->TransferComplete(transfer);
119 libusb_free_transfer(transfer);
95 } 120 }
96 121
97 } // namespace 122 } // namespace
98 123
99 UsbDevice::Transfer::Transfer() : length(0) {} 124 UsbDeviceHandle::Transfer::Transfer()
125 : transfer_type(USB_TRANSFER_CONTROL), length(0) {}
100 126
101 UsbDevice::Transfer::~Transfer() {} 127 UsbDeviceHandle::Transfer::~Transfer() {}
102 128
103 UsbDevice::UsbDevice(UsbService* service, PlatformUsbDeviceHandle handle) 129 UsbDeviceHandle::UsbDeviceHandle(UsbService* service,
104 : service_(service), handle_(handle) { 130 int device,
131 PlatformUsbDeviceHandle handle)
132 : service_(service), device_(device), handle_(handle) {
105 DCHECK(handle) << "Cannot create device with NULL handle."; 133 DCHECK(handle) << "Cannot create device with NULL handle.";
106 } 134 }
107 135
108 UsbDevice::UsbDevice() : service_(NULL), handle_(NULL) {} 136 UsbDeviceHandle::UsbDeviceHandle()
109 137 : service_(NULL), device_(0), handle_(NULL) {
110 UsbDevice::~UsbDevice() {}
111
112 void UsbDevice::Close(const base::Callback<void()>& callback) {
113 CheckDevice();
114 service_->CloseDevice(this);
115 handle_ = NULL;
116 callback.Run();
117 } 138 }
118 139
119 void UsbDevice::TransferComplete(PlatformUsbTransferHandle handle) { 140 UsbDeviceHandle::~UsbDeviceHandle() {
120 base::AutoLock lock(lock_); 141 InternalClose();
142 }
121 143
122 // TODO(gdk): Handle device disconnect. 144 void UsbDeviceHandle::Close(const base::Callback<void()>& callback) {
123 DCHECK(ContainsKey(transfers_, handle)) << "Missing transfer completed"; 145 if (handle_ == 0)
124 Transfer* const transfer = &transfers_[handle]; 146 return;
147 BrowserThread::PostTask(
148 BrowserThread::FILE,
149 FROM_HERE,
150 base::Bind(&UsbService::CloseDeviceHandle,
151 base::Unretained(service_),
152 make_scoped_refptr(this),
153 callback));
154 }
155
156 void UsbDeviceHandle::TransferComplete(PlatformUsbTransferHandle handle) {
157 Transfer transfer;
158 base::AutoLock handle_guard(handle_lock_);
159 // If handle->user_data is cleared after we obtained it, the handles will be
160 // removed and callbacks is already called in InternalClose. This case we can
161 // simply return.
162 if (handle->user_data == NULL)
163 return;
164
165 {
166 base::AutoLock guard(transfer_lock_);
167 transfer = transfers_[handle];
168 transfers_.erase(handle);
169 }
170
171 CHECK_DEVICE(transfer.callback,
172 USB_TRANSFER_DISCONNECT,
173 scoped_refptr<net::IOBuffer>(), 0);
174
175 if (handle->status != LIBUSB_TRANSFER_COMPLETED &&
176 handle->status != LIBUSB_TRANSFER_CANCELLED) {
177 service_->ScheduleEnumerateDevice();
178 }
125 179
126 DCHECK(handle->actual_length >= 0) << "Negative actual length received"; 180 DCHECK(handle->actual_length >= 0) << "Negative actual length received";
127 size_t actual_length = 181 size_t actual_length =
128 static_cast<size_t>(std::max(handle->actual_length, 0)); 182 static_cast<size_t>(std::max(handle->actual_length, 0));
129 183
130 DCHECK(transfer->length >= actual_length) << 184 DCHECK(transfer.length >= actual_length) <<
131 "data too big for our buffer (libusb failure?)"; 185 "data too big for our buffer (libusb failure?)";
132 186
133 scoped_refptr<net::IOBuffer> buffer = transfer->buffer; 187 scoped_refptr<net::IOBuffer> buffer = transfer.buffer;
134 switch (transfer->transfer_type) { 188 switch (transfer.transfer_type) {
135 case USB_TRANSFER_CONTROL: 189 case USB_TRANSFER_CONTROL:
136 // If the transfer is a control transfer we do not expose the control 190 // If the transfer is a control transfer we do not expose the control
137 // setup header to the caller. This logic strips off the header if 191 // setup header to the caller. This logic strips off the header if
138 // present before invoking the callback provided with the transfer. 192 // present before invoking the callback provided with the transfer.
139 if (actual_length > 0) { 193 if (actual_length > 0) {
140 CHECK(transfer->length >= LIBUSB_CONTROL_SETUP_SIZE) << 194 CHECK(transfer.length >= LIBUSB_CONTROL_SETUP_SIZE) <<
141 "buffer was not correctly set: too small for the control header"; 195 "buffer was not correctly set: too small for the control header";
142 196
143 if (transfer->length >= actual_length && 197 if (transfer.length >= actual_length &&
144 actual_length >= LIBUSB_CONTROL_SETUP_SIZE) { 198 actual_length >= LIBUSB_CONTROL_SETUP_SIZE) {
145 // If the payload is zero bytes long, pad out the allocated buffer 199 // If the payload is zero bytes long, pad out the allocated buffer
146 // size to one byte so that an IOBuffer of that size can be allocated. 200 // size to one byte so that an IOBuffer of that size can be allocated.
147 scoped_refptr<net::IOBuffer> resized_buffer = new net::IOBuffer( 201 scoped_refptr<net::IOBuffer> resized_buffer = new net::IOBuffer(
148 std::max(actual_length, static_cast<size_t>(1))); 202 std::max(actual_length, static_cast<size_t>(1)));
149 memcpy(resized_buffer->data(), 203 memcpy(resized_buffer->data(),
150 buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, 204 buffer->data() + LIBUSB_CONTROL_SETUP_SIZE,
151 actual_length); 205 actual_length);
152 buffer = resized_buffer; 206 buffer = resized_buffer;
153 } 207 }
154 } 208 }
155 break; 209 break;
156 210
157 case USB_TRANSFER_ISOCHRONOUS: 211 case USB_TRANSFER_ISOCHRONOUS:
158 // Isochronous replies might carry data in the different isoc packets even 212 // Isochronous replies might carry data in the different isoc packets even
159 // if the transfer actual_data value is zero. Furthermore, not all of the 213 // if the transfer actual_data value is zero. Furthermore, not all of the
160 // received packets might contain data, so we need to calculate how many 214 // received packets might contain data, so we need to calculate how many
161 // data bytes we are effectively providing and pack the results. 215 // data bytes we are effectively providing and pack the results.
162 if (actual_length == 0) { 216 if (actual_length == 0) {
163 size_t packet_buffer_start = 0; 217 size_t packet_buffer_start = 0;
164 for (int i = 0; i < handle->num_iso_packets; ++i) { 218 for (int i = 0; i < handle->num_iso_packets; ++i) {
165 PlatformUsbIsoPacketDescriptor packet = &handle->iso_packet_desc[i]; 219 PlatformUsbIsoPacketDescriptor packet = &handle->iso_packet_desc[i];
166 if (packet->actual_length > 0) { 220 if (packet->actual_length > 0) {
167 // We don't need to copy as long as all packets until now provide 221 // We don't need to copy as long as all packets until now provide
168 // all the data the packet can hold. 222 // all the data the packet can hold.
169 if (actual_length < packet_buffer_start) { 223 if (actual_length < packet_buffer_start) {
170 CHECK(packet_buffer_start + packet->actual_length <= 224 CHECK(packet_buffer_start + packet->actual_length <=
171 transfer->length); 225 transfer.length);
172 memmove(buffer->data() + actual_length, 226 memmove(buffer->data() + actual_length,
173 buffer->data() + packet_buffer_start, 227 buffer->data() + packet_buffer_start,
174 packet->actual_length); 228 packet->actual_length);
175 } 229 }
176 actual_length += packet->actual_length; 230 actual_length += packet->actual_length;
177 } 231 }
178 232
179 packet_buffer_start += packet->length; 233 packet_buffer_start += packet->length;
180 } 234 }
181 } 235 }
182 break; 236 break;
183 237
184 case USB_TRANSFER_BULK: 238 case USB_TRANSFER_BULK:
185 case USB_TRANSFER_INTERRUPT: 239 case USB_TRANSFER_INTERRUPT:
186 break; 240 break;
187 241
188 default: 242 default:
189 NOTREACHED() << "Invalid usb transfer type"; 243 NOTREACHED() << "Invalid usb transfer type";
190 } 244 }
191 245
192 transfer->callback.Run(ConvertTransferStatus(handle->status), buffer, 246 transfer.callback.Run(ConvertTransferStatus(handle->status), buffer,
193 actual_length); 247 actual_length);
194
195 transfers_.erase(handle);
196 libusb_free_transfer(handle);
197 } 248 }
198 249
199 void UsbDevice::ListInterfaces(UsbConfigDescriptor* config, 250 void UsbDeviceHandle::ListInterfaces(UsbConfigDescriptor* config,
200 const UsbInterfaceCallback& callback) { 251 const UsbInterfaceCallback& callback) {
201 CheckDevice(); 252 CHECK_DEVICE(callback, false);
202 253
203 PlatformUsbDevice device = libusb_get_device(handle_); 254 PlatformUsbDevice device = libusb_get_device(handle_);
204 255
205 PlatformUsbConfigDescriptor platform_config; 256 PlatformUsbConfigDescriptor platform_config;
206 const int list_result = libusb_get_active_config_descriptor(device, 257 const int list_result = libusb_get_active_config_descriptor(device,
207 &platform_config); 258 &platform_config);
208 if (list_result == 0) { 259 if (list_result == 0) {
209 config->Reset(platform_config); 260 config->Reset(platform_config);
210 } 261 }
211 callback.Run(list_result == 0); 262 callback.Run(list_result == 0);
212 } 263 }
213 264
214 void UsbDevice::ClaimInterface(const int interface_number, 265 void UsbDeviceHandle::ClaimInterface(const int interface_number,
215 const UsbInterfaceCallback& callback) { 266 const UsbInterfaceCallback& callback) {
216 CheckDevice(); 267 CHECK_DEVICE(callback, false);
217 268
218 const int claim_result = libusb_claim_interface(handle_, interface_number); 269 const int claim_result = libusb_claim_interface(handle_, interface_number);
219 callback.Run(claim_result == 0); 270 callback.Run(claim_result == 0);
220 } 271 }
221 272
222 void UsbDevice::ReleaseInterface(const int interface_number, 273 void UsbDeviceHandle::ReleaseInterface(const int interface_number,
223 const UsbInterfaceCallback& callback) { 274 const UsbInterfaceCallback& callback) {
224 CheckDevice(); 275 CHECK_DEVICE(callback, false);
225 276
226 const int release_result = libusb_release_interface(handle_, 277 const int release_result = libusb_release_interface(handle_,
227 interface_number); 278 interface_number);
228 callback.Run(release_result == 0); 279 callback.Run(release_result == 0);
229 } 280 }
230 281
231 void UsbDevice::SetInterfaceAlternateSetting( 282 void UsbDeviceHandle::SetInterfaceAlternateSetting(
232 const int interface_number, 283 const int interface_number,
233 const int alternate_setting, 284 const int alternate_setting,
234 const UsbInterfaceCallback& callback) { 285 const UsbInterfaceCallback& callback) {
235 CheckDevice(); 286 CHECK_DEVICE(callback, false);
236 287
237 const int setting_result = libusb_set_interface_alt_setting(handle_, 288 const int setting_result = libusb_set_interface_alt_setting(handle_,
238 interface_number, alternate_setting); 289 interface_number, alternate_setting);
239 290
240 callback.Run(setting_result == 0); 291 callback.Run(setting_result == 0);
241 } 292 }
242 293
243 void UsbDevice::ControlTransfer(const UsbEndpointDirection direction, 294 void UsbDeviceHandle::ControlTransfer(const UsbEndpointDirection direction,
244 const TransferRequestType request_type, const TransferRecipient recipient, 295 const TransferRequestType request_type, const TransferRecipient recipient,
245 const uint8 request, const uint16 value, const uint16 index, 296 const uint8 request, const uint16 value, const uint16 index,
246 net::IOBuffer* buffer, const size_t length, const unsigned int timeout, 297 net::IOBuffer* buffer, const size_t length, const unsigned int timeout,
247 const UsbTransferCallback& callback) { 298 const UsbTransferCallback& callback) {
248 CheckDevice(); 299 CHECK_DEVICE(callback, USB_TRANSFER_DISCONNECT,
300 scoped_refptr<net::IOBuffer>(), 0);
249 301
250 const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + length; 302 const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + length;
251 scoped_refptr<net::IOBuffer> resized_buffer(new net::IOBufferWithSize( 303 scoped_refptr<net::IOBuffer> resized_buffer(new net::IOBufferWithSize(
252 resized_length)); 304 resized_length));
253 memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, buffer->data(), 305 memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, buffer->data(),
254 length); 306 length);
255 307
256 struct libusb_transfer* const transfer = libusb_alloc_transfer(0); 308 struct libusb_transfer* const transfer = libusb_alloc_transfer(0);
257 const uint8 converted_type = CreateRequestType(direction, request_type, 309 const uint8 converted_type = CreateRequestType(direction, request_type,
258 recipient); 310 recipient);
259 libusb_fill_control_setup(reinterpret_cast<uint8*>(resized_buffer->data()), 311 libusb_fill_control_setup(reinterpret_cast<uint8*>(resized_buffer->data()),
260 converted_type, request, value, index, length); 312 converted_type, request, value, index, length);
261 libusb_fill_control_transfer(transfer, handle_, reinterpret_cast<uint8*>( 313 libusb_fill_control_transfer(transfer, handle_, reinterpret_cast<uint8*>(
262 resized_buffer->data()), HandleTransferCompletion, this, timeout); 314 resized_buffer->data()), HandleTransferCompletion, this, timeout);
263 SubmitTransfer(transfer, 315 SubmitTransfer(transfer,
264 USB_TRANSFER_CONTROL, 316 USB_TRANSFER_CONTROL,
265 resized_buffer.get(), 317 resized_buffer.get(),
266 resized_length, 318 resized_length,
267 callback); 319 callback);
268 } 320 }
269 321
270 void UsbDevice::BulkTransfer(const UsbEndpointDirection direction, 322 void UsbDeviceHandle::BulkTransfer(const UsbEndpointDirection direction,
271 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, 323 const uint8 endpoint, net::IOBuffer* buffer, const size_t length,
272 const unsigned int timeout, const UsbTransferCallback& callback) { 324 const unsigned int timeout, const UsbTransferCallback& callback) {
273 CheckDevice(); 325 CHECK_DEVICE(callback, USB_TRANSFER_DISCONNECT,
326 scoped_refptr<net::IOBuffer>(), 0);
274 327
275 struct libusb_transfer* const transfer = libusb_alloc_transfer(0); 328 struct libusb_transfer* const transfer = libusb_alloc_transfer(0);
276 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; 329 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint;
277 libusb_fill_bulk_transfer(transfer, handle_, new_endpoint, 330 libusb_fill_bulk_transfer(transfer, handle_, new_endpoint,
278 reinterpret_cast<uint8*>(buffer->data()), length, 331 reinterpret_cast<uint8*>(buffer->data()), length,
279 HandleTransferCompletion, this, timeout); 332 HandleTransferCompletion, this, timeout);
280 SubmitTransfer(transfer, USB_TRANSFER_BULK, buffer, length, callback); 333 SubmitTransfer(transfer, USB_TRANSFER_BULK, buffer, length, callback);
281 } 334 }
282 335
283 void UsbDevice::InterruptTransfer(const UsbEndpointDirection direction, 336 void UsbDeviceHandle::InterruptTransfer(const UsbEndpointDirection direction,
284 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, 337 const uint8 endpoint, net::IOBuffer* buffer, const size_t length,
285 const unsigned int timeout, const UsbTransferCallback& callback) { 338 const unsigned int timeout, const UsbTransferCallback& callback) {
286 CheckDevice(); 339 CHECK_DEVICE(callback, USB_TRANSFER_DISCONNECT,
340 scoped_refptr<net::IOBuffer>(), 0);
287 341
288 struct libusb_transfer* const transfer = libusb_alloc_transfer(0); 342 struct libusb_transfer* const transfer = libusb_alloc_transfer(0);
289 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; 343 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint;
290 libusb_fill_interrupt_transfer(transfer, handle_, new_endpoint, 344 libusb_fill_interrupt_transfer(transfer, handle_, new_endpoint,
291 reinterpret_cast<uint8*>(buffer->data()), length, 345 reinterpret_cast<uint8*>(buffer->data()), length,
292 HandleTransferCompletion, this, timeout); 346 HandleTransferCompletion, this, timeout);
293 SubmitTransfer(transfer, USB_TRANSFER_INTERRUPT, buffer, length, callback); 347 SubmitTransfer(transfer, USB_TRANSFER_INTERRUPT, buffer, length, callback);
294 } 348 }
295 349
296 void UsbDevice::IsochronousTransfer(const UsbEndpointDirection direction, 350 void UsbDeviceHandle::IsochronousTransfer(const UsbEndpointDirection direction,
297 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, 351 const uint8 endpoint, net::IOBuffer* buffer, const size_t length,
298 const unsigned int packets, const unsigned int packet_length, 352 const unsigned int packets, const unsigned int packet_length,
299 const unsigned int timeout, const UsbTransferCallback& callback) { 353 const unsigned int timeout, const UsbTransferCallback& callback) {
300 CheckDevice(); 354 CHECK_DEVICE(callback, USB_TRANSFER_DISCONNECT,
355 scoped_refptr<net::IOBuffer>(), 0);
301 356
302 const uint64 total_length = packets * packet_length; 357 const uint64 total_length = packets * packet_length;
303 CHECK(packets <= length && total_length <= length) << 358 CHECK(packets <= length && total_length <= length) <<
304 "transfer length is too small"; 359 "transfer length is too small";
305 360
306 struct libusb_transfer* const transfer = libusb_alloc_transfer(packets); 361 struct libusb_transfer* const transfer = libusb_alloc_transfer(packets);
307 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; 362 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint;
308 libusb_fill_iso_transfer(transfer, handle_, new_endpoint, 363 libusb_fill_iso_transfer(transfer, handle_, new_endpoint,
309 reinterpret_cast<uint8*>(buffer->data()), length, packets, 364 reinterpret_cast<uint8*>(buffer->data()), length, packets,
310 HandleTransferCompletion, this, timeout); 365 HandleTransferCompletion, this, timeout);
311 libusb_set_iso_packet_lengths(transfer, packet_length); 366 libusb_set_iso_packet_lengths(transfer, packet_length);
312 367
313 SubmitTransfer(transfer, USB_TRANSFER_ISOCHRONOUS, buffer, length, callback); 368 SubmitTransfer(transfer, USB_TRANSFER_ISOCHRONOUS, buffer, length, callback);
314 } 369 }
315 370
316 void UsbDevice::ResetDevice(const base::Callback<void(bool)>& callback) { 371 void UsbDeviceHandle::ResetDevice(const base::Callback<void(bool)>& callback) {
317 CheckDevice(); 372 // Blocking operation. Run it on the FILE thread.
373 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
374 CHECK_DEVICE(callback, false);
318 callback.Run(libusb_reset_device(handle_) == 0); 375 callback.Run(libusb_reset_device(handle_) == 0);
319 } 376 }
320 377
321 void UsbDevice::CheckDevice() { 378 void UsbDeviceHandle::InternalClose() {
322 DCHECK(handle_) << "Device is already closed."; 379 base::AutoLock handle_guard(handle_lock_);
380 base::AutoLock guard(transfer_lock_);
381 if (handle_ == NULL)
382 return;
383
384 // Cancel all the transfers.
385 for (std::map<PlatformUsbTransferHandle, Transfer>::iterator it
386 = transfers_.begin(); it != transfers_.end(); it++) {
387 it->first->user_data = NULL;
388 it->second.callback.Run(USB_TRANSFER_DISCONNECT,
389 scoped_refptr<net::IOBuffer>(), 0);
390 }
391 transfers_.clear();
392 libusb_close(handle_);
393 handle_ = NULL;
323 } 394 }
324 395
325 void UsbDevice::SubmitTransfer(PlatformUsbTransferHandle handle, 396 void UsbDeviceHandle::SubmitTransfer(PlatformUsbTransferHandle handle,
326 UsbTransferType transfer_type, 397 UsbTransferType transfer_type,
327 net::IOBuffer* buffer, 398 net::IOBuffer* buffer,
328 const size_t length, 399 const size_t length,
329 const UsbTransferCallback& callback) { 400 const UsbTransferCallback& callback) {
401 base::AutoLock lock(transfer_lock_);
402 // This check must be done after the lock.
403 if (!handle_)
404 return;
405
330 Transfer transfer; 406 Transfer transfer;
331 transfer.transfer_type = transfer_type; 407 transfer.transfer_type = transfer_type;
332 transfer.buffer = buffer; 408 transfer.buffer = buffer;
333 transfer.length = length; 409 transfer.length = length;
334 transfer.callback = callback; 410 transfer.callback = callback;
335 411
336 { 412 transfers_[handle] = transfer;
337 base::AutoLock lock(lock_); 413 libusb_submit_transfer(handle);
338 transfers_[handle] = transfer;
339 libusb_submit_transfer(handle);
340 }
341 } 414 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698