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

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

Powered by Google App Engine
This is Rietveld 408576698