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

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

Issue 18593002: Usb backend refactor step 2: Separate Usb Device Handle and Usb Device (deprecate) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 5 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.h"
6 6
7 #include <algorithm>
7 #include <vector> 8 #include <vector>
8 9
10 #include "base/port.h"
9 #include "base/stl_util.h" 11 #include "base/stl_util.h"
10 #include "base/synchronization/lock.h" 12 #include "base/threading/thread_checker.h"
11 #include "chrome/browser/usb/usb_interface.h" 13 #include "chrome/browser/usb/usb_interface.h"
12 #include "chrome/browser/usb/usb_service.h" 14 #include "chrome/browser/usb/usb_service.h"
15 #include "content/public/browser/browser_thread.h"
13 #include "third_party/libusb/src/libusb/libusb.h" 16 #include "third_party/libusb/src/libusb/libusb.h"
14 17
18 using content::BrowserThread;
19
15 namespace { 20 namespace {
16 21
17 static uint8 ConvertTransferDirection( 22 static uint8 ConvertTransferDirection(
18 const UsbEndpointDirection direction) { 23 const UsbEndpointDirection direction) {
19 switch (direction) { 24 switch (direction) {
20 case USB_DIRECTION_INBOUND: 25 case USB_DIRECTION_INBOUND:
21 return LIBUSB_ENDPOINT_IN; 26 return LIBUSB_ENDPOINT_IN;
22 case USB_DIRECTION_OUTBOUND: 27 case USB_DIRECTION_OUTBOUND:
23 return LIBUSB_ENDPOINT_OUT; 28 return LIBUSB_ENDPOINT_OUT;
24 default: 29 default:
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 case LIBUSB_TRANSFER_OVERFLOW: 86 case LIBUSB_TRANSFER_OVERFLOW:
82 return USB_TRANSFER_OVERFLOW; 87 return USB_TRANSFER_OVERFLOW;
83 case LIBUSB_TRANSFER_CANCELLED: 88 case LIBUSB_TRANSFER_CANCELLED:
84 return USB_TRANSFER_CANCELLED; 89 return USB_TRANSFER_CANCELLED;
85 default: 90 default:
86 NOTREACHED(); 91 NOTREACHED();
87 return USB_TRANSFER_ERROR; 92 return USB_TRANSFER_ERROR;
88 } 93 }
89 } 94 }
90 95
91 static void LIBUSB_CALL HandleTransferCompletion(
92 struct libusb_transfer* transfer) {
93 UsbDevice* const device = reinterpret_cast<UsbDevice*>(transfer->user_data);
94 device->TransferComplete(transfer);
95 }
96
97 } // namespace 96 } // namespace
98 97
99 UsbDevice::Transfer::Transfer() : length(0) {} 98 struct UsbDevice::TransferInfo {
99 UsbTransferType transfer_type;
100 scoped_refptr<net::IOBuffer> buffer;
101 size_t length;
102 UsbTransferCallback callback;
103 TransferInfo();
pfeldman 2013/07/22 08:39:45 Constructor should go first
Bei Zhang 2013/07/23 17:58:44 Done.
104 };
100 105
101 UsbDevice::Transfer::~Transfer() {} 106 UsbDevice::TransferInfo::TransferInfo()
107 : transfer_type(USB_TRANSFER_CONTROL),
108 length(0) {}
102 109
103 UsbDevice::UsbDevice(UsbService* service, PlatformUsbDeviceHandle handle) 110 UsbDevice::UsbDevice(UsbService* service,
104 : service_(service), handle_(handle) { 111 int device,
112 PlatformUsbDeviceHandle handle)
113 : service_(service), device_(device), handle_(handle) {
114 DCHECK(thread_checker_.CalledOnValidThread());
105 DCHECK(handle) << "Cannot create device with NULL handle."; 115 DCHECK(handle) << "Cannot create device with NULL handle.";
106 } 116 }
107 117
108 UsbDevice::UsbDevice() : service_(NULL), handle_(NULL) {} 118 UsbDevice::UsbDevice() : service_(NULL), device_(0), handle_(NULL) {
119 DCHECK(thread_checker_.CalledOnValidThread());
120 }
109 121
110 UsbDevice::~UsbDevice() {} 122 UsbDevice::~UsbDevice() {
123 DCHECK(thread_checker_.CalledOnValidThread());
124 InternalClose();
125 }
111 126
112 void UsbDevice::Close(const base::Callback<void()>& callback) { 127 void UsbDevice::Close(const base::Callback<void()>& callback) {
113 CheckDevice(); 128 DCHECK(thread_checker_.CalledOnValidThread());
129 if (handle_ == NULL) return;
114 service_->CloseDevice(this); 130 service_->CloseDevice(this);
115 handle_ = NULL; 131 handle_ = NULL;
116 callback.Run(); 132 callback.Run();
117 } 133 }
118 134
119 void UsbDevice::TransferComplete(PlatformUsbTransferHandle handle) { 135 void UsbDevice::HandleTransferCompletionFileThread(
120 base::AutoLock lock(lock_); 136 PlatformUsbTransferHandle transfer) {
137 UsbDevice* const device = reinterpret_cast<UsbDevice*>(transfer->user_data);
138 if (device) device->TransferComplete(transfer);
139 // We should free the transfer even if the device is removed.
140 libusb_free_transfer(transfer);
141 }
121 142
122 // TODO(gdk): Handle device disconnect. 143 void API_CALL UsbDevice::HandleTransferCompletion(
123 DCHECK(ContainsKey(transfers_, handle)) << "Missing transfer completed"; 144 PlatformUsbTransferHandle transfer) {
124 Transfer* const transfer = &transfers_[handle]; 145 BrowserThread::PostTask(
146 BrowserThread::FILE, FROM_HERE,
147 base::Bind(&HandleTransferCompletionFileThread, transfer));
148 }
125 149
126 DCHECK(handle->actual_length >= 0) << "Negative actual length received"; 150 void UsbDevice::TransferComplete(PlatformUsbTransferHandle transfer_handle) {
151 DCHECK(thread_checker_.CalledOnValidThread());
152 DCHECK(handle_ != NULL) <<
153 "handle_ can only be reset after transfers are unregistered";
154
155 TransferInfo transfer = transfers_[transfer_handle];
156 transfers_.erase(transfer_handle);
157
158 DCHECK_GE(transfer_handle->actual_length, 0) <<
159 "Negative actual length received";
160
127 size_t actual_length = 161 size_t actual_length =
128 static_cast<size_t>(std::max(handle->actual_length, 0)); 162 static_cast<size_t>(std::max(transfer_handle->actual_length, 0));
129 163
130 DCHECK(transfer->length >= actual_length) << 164 DCHECK_GE(transfer.length, actual_length) <<
131 "data too big for our buffer (libusb failure?)"; 165 "data too big for our buffer (libusb failure?)";
132 166
133 scoped_refptr<net::IOBuffer> buffer = transfer->buffer; 167 scoped_refptr<net::IOBuffer> buffer = transfer.buffer;
134 switch (transfer->transfer_type) { 168 switch (transfer.transfer_type) {
135 case USB_TRANSFER_CONTROL: 169 case USB_TRANSFER_CONTROL:
136 // If the transfer is a control transfer we do not expose the control 170 // 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 171 // setup header to the caller. This logic strips off the header if
138 // present before invoking the callback provided with the transfer. 172 // present before invoking the callback provided with the transfer.
139 if (actual_length > 0) { 173 if (actual_length > 0) {
140 CHECK(transfer->length >= LIBUSB_CONTROL_SETUP_SIZE) << 174 CHECK(transfer.length >= LIBUSB_CONTROL_SETUP_SIZE) <<
141 "buffer was not correctly set: too small for the control header"; 175 "buffer was not correctly set: too small for the control header";
142 176
143 if (transfer->length >= actual_length && 177 if (transfer.length >= actual_length &&
144 actual_length >= LIBUSB_CONTROL_SETUP_SIZE) { 178 actual_length >= LIBUSB_CONTROL_SETUP_SIZE) {
145 // If the payload is zero bytes long, pad out the allocated buffer 179 // 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. 180 // size to one byte so that an IOBuffer of that size can be allocated.
147 scoped_refptr<net::IOBuffer> resized_buffer = new net::IOBuffer( 181 scoped_refptr<net::IOBuffer> resized_buffer = new net::IOBuffer(
148 std::max(actual_length, static_cast<size_t>(1))); 182 std::max(actual_length, static_cast<size_t>(1)));
149 memcpy(resized_buffer->data(), 183 memcpy(resized_buffer->data(),
150 buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, 184 buffer->data() + LIBUSB_CONTROL_SETUP_SIZE,
151 actual_length); 185 actual_length);
152 buffer = resized_buffer; 186 buffer = resized_buffer;
153 } 187 }
154 } 188 }
155 break; 189 break;
156 190
157 case USB_TRANSFER_ISOCHRONOUS: 191 case USB_TRANSFER_ISOCHRONOUS:
158 // Isochronous replies might carry data in the different isoc packets even 192 // 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 193 // 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 194 // received packets might contain data, so we need to calculate how many
161 // data bytes we are effectively providing and pack the results. 195 // data bytes we are effectively providing and pack the results.
162 if (actual_length == 0) { 196 if (actual_length == 0) {
163 size_t packet_buffer_start = 0; 197 size_t packet_buffer_start = 0;
164 for (int i = 0; i < handle->num_iso_packets; ++i) { 198 for (int i = 0; i < transfer_handle->num_iso_packets; ++i) {
165 PlatformUsbIsoPacketDescriptor packet = &handle->iso_packet_desc[i]; 199 PlatformUsbIsoPacketDescriptor packet =
200 &transfer_handle->iso_packet_desc[i];
166 if (packet->actual_length > 0) { 201 if (packet->actual_length > 0) {
167 // We don't need to copy as long as all packets until now provide 202 // We don't need to copy as long as all packets until now provide
168 // all the data the packet can hold. 203 // all the data the packet can hold.
169 if (actual_length < packet_buffer_start) { 204 if (actual_length < packet_buffer_start) {
170 CHECK(packet_buffer_start + packet->actual_length <= 205 CHECK(packet_buffer_start + packet->actual_length <=
171 transfer->length); 206 transfer.length);
172 memmove(buffer->data() + actual_length, 207 memmove(buffer->data() + actual_length,
173 buffer->data() + packet_buffer_start, 208 buffer->data() + packet_buffer_start,
174 packet->actual_length); 209 packet->actual_length);
175 } 210 }
176 actual_length += packet->actual_length; 211 actual_length += packet->actual_length;
177 } 212 }
178 213
179 packet_buffer_start += packet->length; 214 packet_buffer_start += packet->length;
180 } 215 }
181 } 216 }
182 break; 217 break;
183 218
184 case USB_TRANSFER_BULK: 219 case USB_TRANSFER_BULK:
185 case USB_TRANSFER_INTERRUPT: 220 case USB_TRANSFER_INTERRUPT:
186 break; 221 break;
187 222
188 default: 223 default:
189 NOTREACHED() << "Invalid usb transfer type"; 224 NOTREACHED() << "Invalid usb transfer type";
190 } 225 }
191 226
192 transfer->callback.Run(ConvertTransferStatus(handle->status), buffer, 227 transfer.callback.Run(ConvertTransferStatus(transfer_handle->status), buffer,
193 actual_length); 228 actual_length);
194
195 transfers_.erase(handle);
196 libusb_free_transfer(handle);
197 } 229 }
198 230
199 void UsbDevice::ListInterfaces(UsbConfigDescriptor* config, 231 void UsbDevice::ListInterfaces(UsbConfigDescriptor* config,
pfeldman 2013/07/22 18:23:13 Why is this using callback? It returns synchronous
Bei Zhang 2013/07/23 17:58:44 I see... That'll do. On 2013/07/22 18:23:13, pfel
200 const UsbInterfaceCallback& callback) { 232 const UsbInterfaceCallback& callback) {
201 CheckDevice(); 233 DCHECK(thread_checker_.CalledOnValidThread());
234 if (handle_ == NULL) {
235 callback.Run(false);
236 return;
237 }
202 238
203 PlatformUsbDevice device = libusb_get_device(handle_); 239 PlatformUsbDevice device = libusb_get_device(handle_);
204 240
205 PlatformUsbConfigDescriptor platform_config; 241 PlatformUsbConfigDescriptor platform_config;
206 const int list_result = libusb_get_active_config_descriptor(device, 242 const int list_result = libusb_get_active_config_descriptor(device,
207 &platform_config); 243 &platform_config);
208 if (list_result == 0) { 244 if (list_result == 0) {
209 config->Reset(platform_config); 245 config->Reset(platform_config);
210 } 246 }
211 callback.Run(list_result == 0); 247 callback.Run(list_result == 0);
212 } 248 }
213 249
214 void UsbDevice::ClaimInterface(const int interface_number, 250 void UsbDevice::ClaimInterface(const int interface_number,
215 const UsbInterfaceCallback& callback) { 251 const UsbInterfaceCallback& callback) {
216 CheckDevice(); 252 DCHECK(thread_checker_.CalledOnValidThread());
pfeldman 2013/07/22 18:23:13 ditto
253 if (handle_ == NULL) {
254 callback.Run(false);
255 return;
256 }
217 257
218 const int claim_result = libusb_claim_interface(handle_, interface_number); 258 const int claim_result = libusb_claim_interface(handle_, interface_number);
219 callback.Run(claim_result == 0); 259 callback.Run(claim_result == 0);
220 } 260 }
221 261
222 void UsbDevice::ReleaseInterface(const int interface_number, 262 void UsbDevice::ReleaseInterface(const int interface_number,
223 const UsbInterfaceCallback& callback) { 263 const UsbInterfaceCallback& callback) {
224 CheckDevice(); 264 DCHECK(thread_checker_.CalledOnValidThread());
pfeldman 2013/07/22 18:23:13 ditto
265 if (handle_ == NULL) {
266 callback.Run(false);
267 return;
268 }
225 269
226 const int release_result = libusb_release_interface(handle_, 270 const int release_result = libusb_release_interface(handle_,
227 interface_number); 271 interface_number);
228 callback.Run(release_result == 0); 272 callback.Run(release_result == 0);
229 } 273 }
230 274
231 void UsbDevice::SetInterfaceAlternateSetting( 275 void UsbDevice::SetInterfaceAlternateSetting(
232 const int interface_number, 276 const int interface_number,
233 const int alternate_setting, 277 const int alternate_setting,
234 const UsbInterfaceCallback& callback) { 278 const UsbInterfaceCallback& callback) {
235 CheckDevice(); 279 DCHECK(thread_checker_.CalledOnValidThread());
pfeldman 2013/07/22 18:23:13 ditto
280 if (handle_ == NULL) {
281 callback.Run(false);
282 return;
283 }
236 284
237 const int setting_result = libusb_set_interface_alt_setting(handle_, 285 const int setting_result = libusb_set_interface_alt_setting(handle_,
238 interface_number, alternate_setting); 286 interface_number, alternate_setting);
239 287
240 callback.Run(setting_result == 0); 288 callback.Run(setting_result == 0);
241 } 289 }
242 290
243 void UsbDevice::ControlTransfer(const UsbEndpointDirection direction, 291 void UsbDevice::ControlTransfer(const UsbEndpointDirection direction,
244 const TransferRequestType request_type, const TransferRecipient recipient, 292 const TransferRequestType request_type, const TransferRecipient recipient,
245 const uint8 request, const uint16 value, const uint16 index, 293 const uint8 request, const uint16 value, const uint16 index,
246 net::IOBuffer* buffer, const size_t length, const unsigned int timeout, 294 net::IOBuffer* buffer, const size_t length, const unsigned int timeout,
247 const UsbTransferCallback& callback) { 295 const UsbTransferCallback& callback) {
248 CheckDevice(); 296 if (handle_ == NULL) {
249 297 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
298 return;
299 }
250 const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + length; 300 const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + length;
251 scoped_refptr<net::IOBuffer> resized_buffer(new net::IOBufferWithSize( 301 scoped_refptr<net::IOBuffer> resized_buffer(new net::IOBufferWithSize(
252 resized_length)); 302 resized_length));
253 memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, buffer->data(), 303 memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, buffer->data(),
254 length); 304 length);
255 305
256 struct libusb_transfer* const transfer = libusb_alloc_transfer(0); 306 struct libusb_transfer* const transfer = libusb_alloc_transfer(0);
257 const uint8 converted_type = CreateRequestType(direction, request_type, 307 const uint8 converted_type = CreateRequestType(direction, request_type,
258 recipient); 308 recipient);
259 libusb_fill_control_setup(reinterpret_cast<uint8*>(resized_buffer->data()), 309 libusb_fill_control_setup(reinterpret_cast<uint8*>(resized_buffer->data()),
260 converted_type, request, value, index, length); 310 converted_type, request, value, index, length);
261 libusb_fill_control_transfer(transfer, handle_, reinterpret_cast<uint8*>( 311 libusb_fill_control_transfer(transfer, handle_, reinterpret_cast<uint8*>(
262 resized_buffer->data()), HandleTransferCompletion, this, timeout); 312 resized_buffer->data()), HandleTransferCompletion, this, timeout);
263 SubmitTransfer(transfer, 313 BrowserThread::PostTask(
314 BrowserThread::FILE,
315 FROM_HERE,
316 base::Bind(&UsbDevice::SubmitTransfer,
pfeldman 2013/07/22 18:23:13 Why scheduling submit? libusb_submit_transfer clai
Bei Zhang 2013/07/23 17:58:44 There is a map to the transfers which is not threa
317 this,
318 transfer,
264 USB_TRANSFER_CONTROL, 319 USB_TRANSFER_CONTROL,
265 resized_buffer.get(), 320 resized_buffer,
266 resized_length, 321 resized_length,
267 callback); 322 callback));
268 } 323 }
269 324
270 void UsbDevice::BulkTransfer(const UsbEndpointDirection direction, 325 void UsbDevice::BulkTransfer(const UsbEndpointDirection direction,
271 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, 326 const uint8 endpoint, net::IOBuffer* buffer, const size_t length,
272 const unsigned int timeout, const UsbTransferCallback& callback) { 327 const unsigned int timeout, const UsbTransferCallback& callback) {
273 CheckDevice(); 328 if (handle_ == NULL) {
274 329 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
330 return;
331 }
275 struct libusb_transfer* const transfer = libusb_alloc_transfer(0); 332 struct libusb_transfer* const transfer = libusb_alloc_transfer(0);
276 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; 333 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint;
277 libusb_fill_bulk_transfer(transfer, handle_, new_endpoint, 334 libusb_fill_bulk_transfer(transfer, handle_, new_endpoint,
278 reinterpret_cast<uint8*>(buffer->data()), length, 335 reinterpret_cast<uint8*>(buffer->data()), length,
279 HandleTransferCompletion, this, timeout); 336 HandleTransferCompletion, this, timeout);
280 SubmitTransfer(transfer, USB_TRANSFER_BULK, buffer, length, callback); 337 BrowserThread::PostTask(
338 BrowserThread::FILE,
339 FROM_HERE,
340 base::Bind(&UsbDevice::SubmitTransfer,
pfeldman 2013/07/22 18:23:13 ditto
341 this,
342 transfer,
343 USB_TRANSFER_BULK,
344 make_scoped_refptr(buffer),
345 length,
346 callback));
281 } 347 }
282 348
283 void UsbDevice::InterruptTransfer(const UsbEndpointDirection direction, 349 void UsbDevice::InterruptTransfer(const UsbEndpointDirection direction,
284 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, 350 const uint8 endpoint, net::IOBuffer* buffer, const size_t length,
285 const unsigned int timeout, const UsbTransferCallback& callback) { 351 const unsigned int timeout, const UsbTransferCallback& callback) {
286 CheckDevice(); 352 if (handle_ == NULL) {
287 353 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
354 return;
355 }
288 struct libusb_transfer* const transfer = libusb_alloc_transfer(0); 356 struct libusb_transfer* const transfer = libusb_alloc_transfer(0);
289 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; 357 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint;
290 libusb_fill_interrupt_transfer(transfer, handle_, new_endpoint, 358 libusb_fill_interrupt_transfer(transfer, handle_, new_endpoint,
291 reinterpret_cast<uint8*>(buffer->data()), length, 359 reinterpret_cast<uint8*>(buffer->data()), length,
292 HandleTransferCompletion, this, timeout); 360 HandleTransferCompletion, this, timeout);
293 SubmitTransfer(transfer, USB_TRANSFER_INTERRUPT, buffer, length, callback); 361 BrowserThread::PostTask(
362 BrowserThread::FILE,
363 FROM_HERE,
364 base::Bind(&UsbDevice::SubmitTransfer,
365 this,
366 transfer,
367 USB_TRANSFER_INTERRUPT,
368 make_scoped_refptr(buffer),
369 length,
370 callback));
294 } 371 }
295 372
296 void UsbDevice::IsochronousTransfer(const UsbEndpointDirection direction, 373 void UsbDevice::IsochronousTransfer(const UsbEndpointDirection direction,
297 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, 374 const uint8 endpoint, net::IOBuffer* buffer, const size_t length,
298 const unsigned int packets, const unsigned int packet_length, 375 const unsigned int packets, const unsigned int packet_length,
299 const unsigned int timeout, const UsbTransferCallback& callback) { 376 const unsigned int timeout, const UsbTransferCallback& callback) {
300 CheckDevice(); 377 if (handle_ == NULL) {
301 378 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
379 return;
380 }
302 const uint64 total_length = packets * packet_length; 381 const uint64 total_length = packets * packet_length;
303 CHECK(packets <= length && total_length <= length) << 382 CHECK(packets <= length && total_length <= length) <<
304 "transfer length is too small"; 383 "transfer length is too small";
305 384
306 struct libusb_transfer* const transfer = libusb_alloc_transfer(packets); 385 struct libusb_transfer* const transfer = libusb_alloc_transfer(packets);
307 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; 386 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint;
308 libusb_fill_iso_transfer(transfer, handle_, new_endpoint, 387 libusb_fill_iso_transfer(transfer, handle_, new_endpoint,
309 reinterpret_cast<uint8*>(buffer->data()), length, packets, 388 reinterpret_cast<uint8*>(buffer->data()), length, packets,
310 HandleTransferCompletion, this, timeout); 389 HandleTransferCompletion, this, timeout);
311 libusb_set_iso_packet_lengths(transfer, packet_length); 390 libusb_set_iso_packet_lengths(transfer, packet_length);
312 391
313 SubmitTransfer(transfer, USB_TRANSFER_ISOCHRONOUS, buffer, length, callback); 392 BrowserThread::PostTask(
393 BrowserThread::FILE,
394 FROM_HERE,
395 base::Bind(&UsbDevice::SubmitTransfer,
396 this,
397 transfer,
398 USB_TRANSFER_ISOCHRONOUS,
399 make_scoped_refptr(buffer),
400 length,
401 callback));
314 } 402 }
315 403
316 void UsbDevice::ResetDevice(const base::Callback<void(bool)>& callback) { 404 void UsbDevice::ResetDevice(const UsbResetDeviceCallback& callback) {
317 CheckDevice(); 405 DCHECK(thread_checker_.CalledOnValidThread());
406 if (handle_ == NULL) {
407 callback.Run(false);
408 return;
409 }
318 callback.Run(libusb_reset_device(handle_) == 0); 410 callback.Run(libusb_reset_device(handle_) == 0);
319 } 411 }
320 412
321 void UsbDevice::CheckDevice() { 413 void UsbDevice::InternalClose() {
322 DCHECK(handle_) << "Device is already closed."; 414 DCHECK(thread_checker_.CalledOnValidThread());
415 if (handle_ == NULL) return;
416
417 // The following four lines makes this function re-enterable in case the
418 // callbacks call InternalClose again by, e.g., removing the
419 // UsbDeviceStub from UsbService.
420 PlatformUsbDeviceHandle handle = handle_;
421 handle_ = NULL;
422 std::map<PlatformUsbTransferHandle, TransferInfo> transfers;
423 std::swap(transfers, transfers_);
424
425 // Cancel all the transfers before libusb_close.
426 // Otherwise the callback will not be invoked.
427 for (std::map<PlatformUsbTransferHandle, TransferInfo>::const_iterator it =
428 transfers.begin();
429 it != transfers.end(); it++) {
430 it->first->user_data = NULL;
431 it->second.callback.Run(
432 USB_TRANSFER_CANCELLED,
433 it->second.buffer,
434 0);
435 libusb_cancel_transfer(it->first);
436 }
437 libusb_close(handle);
323 } 438 }
324 439
325 void UsbDevice::SubmitTransfer(PlatformUsbTransferHandle handle, 440 void UsbDevice::SubmitTransfer(PlatformUsbTransferHandle handle,
326 UsbTransferType transfer_type, 441 UsbTransferType transfer_type,
327 net::IOBuffer* buffer, 442 net::IOBuffer* buffer,
328 const size_t length, 443 const size_t length,
329 const UsbTransferCallback& callback) { 444 const UsbTransferCallback& callback) {
330 Transfer transfer; 445 DCHECK(thread_checker_.CalledOnValidThread());
446 TransferInfo transfer;
331 transfer.transfer_type = transfer_type; 447 transfer.transfer_type = transfer_type;
332 transfer.buffer = buffer; 448 transfer.buffer = buffer;
333 transfer.length = length; 449 transfer.length = length;
334 transfer.callback = callback; 450 transfer.callback = callback;
335 451
336 { 452 transfers_[handle] = transfer;
337 base::AutoLock lock(lock_); 453 if (0 != libusb_submit_transfer(handle)) {
338 transfers_[handle] = transfer; 454 transfers_.erase(handle);
339 libusb_submit_transfer(handle); 455 libusb_free_transfer(handle);
456 callback.Run(USB_TRANSFER_ERROR, buffer, 0);
340 } 457 }
341 } 458 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698