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

Side by Side Diff: device/usb/usb_device_handle_impl.cc

Issue 980023002: Move device/usb classes from the FILE thread to UI thread. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add more thread assertions. Created 5 years, 8 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
« no previous file with comments | « device/usb/usb_device_handle_impl.h ('k') | device/usb/usb_device_handle_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "device/usb/usb_device_handle_impl.h" 5 #include "device/usb/usb_device_handle_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 << ConvertPlatformUsbErrorToString(rv); 150 << ConvertPlatformUsbErrorToString(rv);
151 } 151 }
152 return rv == LIBUSB_SUCCESS; 152 return rv == LIBUSB_SUCCESS;
153 } 153 }
154 154
155 // This inner class owns the underlying libusb_transfer and may outlast 155 // This inner class owns the underlying libusb_transfer and may outlast
156 // the UsbDeviceHandle that created it. 156 // the UsbDeviceHandle that created it.
157 class UsbDeviceHandleImpl::Transfer { 157 class UsbDeviceHandleImpl::Transfer {
158 public: 158 public:
159 static scoped_ptr<Transfer> CreateControlTransfer( 159 static scoped_ptr<Transfer> CreateControlTransfer(
160 scoped_refptr<UsbDeviceHandleImpl> device_handle,
160 uint8 type, 161 uint8 type,
161 uint8 request, 162 uint8 request,
162 uint16 value, 163 uint16 value,
163 uint16 index, 164 uint16 index,
164 uint16 length, 165 uint16 length,
165 scoped_refptr<net::IOBuffer> buffer, 166 scoped_refptr<net::IOBuffer> buffer,
166 unsigned int timeout, 167 unsigned int timeout,
167 const UsbTransferCallback& callback); 168 scoped_refptr<base::TaskRunner> callback_task_runner,
169 const TransferCallback& callback);
168 static scoped_ptr<Transfer> CreateBulkTransfer( 170 static scoped_ptr<Transfer> CreateBulkTransfer(
171 scoped_refptr<UsbDeviceHandleImpl> device_handle,
169 uint8 endpoint, 172 uint8 endpoint,
170 scoped_refptr<net::IOBuffer> buffer, 173 scoped_refptr<net::IOBuffer> buffer,
171 int length, 174 int length,
172 unsigned int timeout, 175 unsigned int timeout,
173 const UsbTransferCallback& callback); 176 scoped_refptr<base::TaskRunner> callback_task_runner,
177 const TransferCallback& callback);
174 static scoped_ptr<Transfer> CreateInterruptTransfer( 178 static scoped_ptr<Transfer> CreateInterruptTransfer(
179 scoped_refptr<UsbDeviceHandleImpl> device_handle,
175 uint8 endpoint, 180 uint8 endpoint,
176 scoped_refptr<net::IOBuffer> buffer, 181 scoped_refptr<net::IOBuffer> buffer,
177 int length, 182 int length,
178 unsigned int timeout, 183 unsigned int timeout,
179 const UsbTransferCallback& callback); 184 scoped_refptr<base::TaskRunner> callback_task_runner,
185 const TransferCallback& callback);
180 static scoped_ptr<Transfer> CreateIsochronousTransfer( 186 static scoped_ptr<Transfer> CreateIsochronousTransfer(
187 scoped_refptr<UsbDeviceHandleImpl> device_handle,
181 uint8 endpoint, 188 uint8 endpoint,
182 scoped_refptr<net::IOBuffer> buffer, 189 scoped_refptr<net::IOBuffer> buffer,
183 size_t length, 190 size_t length,
184 unsigned int packets, 191 unsigned int packets,
185 unsigned int packet_length, 192 unsigned int packet_length,
186 unsigned int timeout, 193 unsigned int timeout,
187 const UsbTransferCallback& callback); 194 scoped_refptr<base::TaskRunner> task_runner,
195 const TransferCallback& callback);
188 196
189 ~Transfer(); 197 ~Transfer();
190 198
191 bool Submit(base::WeakPtr<UsbDeviceHandleImpl> device_handle); 199 void Submit();
192 void Cancel(); 200 void Cancel();
193 void ProcessCompletion(); 201 void ProcessCompletion();
194 void Complete(UsbTransferStatus status, size_t bytes_transferred); 202 void TransferComplete(UsbTransferStatus status, size_t bytes_transferred);
195 203
196 const UsbDeviceHandleImpl::InterfaceClaimer* claimed_interface() const { 204 const UsbDeviceHandleImpl::InterfaceClaimer* claimed_interface() const {
197 return claimed_interface_.get(); 205 return claimed_interface_.get();
198 } 206 }
199 207
208 scoped_refptr<base::TaskRunner> callback_task_runner() const {
209 return callback_task_runner_;
210 }
211
200 private: 212 private:
201 Transfer(UsbTransferType transfer_type, 213 Transfer(scoped_refptr<UsbDeviceHandleImpl> device_handle,
214 scoped_refptr<InterfaceClaimer> claimed_interface,
215 UsbTransferType transfer_type,
202 scoped_refptr<net::IOBuffer> buffer, 216 scoped_refptr<net::IOBuffer> buffer,
203 size_t length, 217 size_t length,
204 const UsbTransferCallback& callback); 218 scoped_refptr<base::TaskRunner> callback_task_runner,
219 const TransferCallback& callback);
205 220
206 static void LIBUSB_CALL PlatformCallback(PlatformUsbTransferHandle handle); 221 static void LIBUSB_CALL PlatformCallback(PlatformUsbTransferHandle handle);
207 222
208 UsbTransferType transfer_type_; 223 UsbTransferType transfer_type_;
209 base::WeakPtr<UsbDeviceHandleImpl> device_handle_; 224 scoped_refptr<UsbDeviceHandleImpl> device_handle_;
210 PlatformUsbTransferHandle platform_transfer_; 225 PlatformUsbTransferHandle platform_transfer_ = nullptr;
211 scoped_refptr<net::IOBuffer> buffer_; 226 scoped_refptr<net::IOBuffer> buffer_;
212 scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer> claimed_interface_; 227 scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer> claimed_interface_;
213 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
214 size_t length_; 228 size_t length_;
215 bool cancelled_; 229 bool cancelled_ = false;
216 UsbTransferCallback callback_; 230 scoped_refptr<base::SequencedTaskRunner> task_runner_;
217 scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner_; 231 scoped_refptr<base::TaskRunner> callback_task_runner_;
232 TransferCallback callback_;
218 }; 233 };
219 234
220 // static 235 // static
221 scoped_ptr<UsbDeviceHandleImpl::Transfer> 236 scoped_ptr<UsbDeviceHandleImpl::Transfer>
222 UsbDeviceHandleImpl::Transfer::CreateControlTransfer( 237 UsbDeviceHandleImpl::Transfer::CreateControlTransfer(
238 scoped_refptr<UsbDeviceHandleImpl> device_handle,
223 uint8 type, 239 uint8 type,
224 uint8 request, 240 uint8 request,
225 uint16 value, 241 uint16 value,
226 uint16 index, 242 uint16 index,
227 uint16 length, 243 uint16 length,
228 scoped_refptr<net::IOBuffer> buffer, 244 scoped_refptr<net::IOBuffer> buffer,
229 unsigned int timeout, 245 unsigned int timeout,
230 const UsbTransferCallback& callback) { 246 scoped_refptr<base::TaskRunner> callback_task_runner,
231 scoped_ptr<Transfer> transfer(new Transfer(USB_TRANSFER_CONTROL, buffer, 247 const TransferCallback& callback) {
232 length + LIBUSB_CONTROL_SETUP_SIZE, 248 scoped_ptr<Transfer> transfer(new Transfer(
233 callback)); 249 device_handle, nullptr, USB_TRANSFER_CONTROL, buffer,
250 length + LIBUSB_CONTROL_SETUP_SIZE, callback_task_runner, callback));
234 251
235 transfer->platform_transfer_ = libusb_alloc_transfer(0); 252 transfer->platform_transfer_ = libusb_alloc_transfer(0);
236 if (!transfer->platform_transfer_) { 253 if (!transfer->platform_transfer_) {
237 USB_LOG(ERROR) << "Failed to allocate control transfer."; 254 USB_LOG(ERROR) << "Failed to allocate control transfer.";
238 return nullptr; 255 return nullptr;
239 } 256 }
240 257
241 libusb_fill_control_setup(reinterpret_cast<uint8*>(buffer->data()), type, 258 libusb_fill_control_setup(reinterpret_cast<uint8*>(buffer->data()), type,
242 request, value, index, length); 259 request, value, index, length);
243 libusb_fill_control_transfer(transfer->platform_transfer_, 260 libusb_fill_control_transfer(transfer->platform_transfer_,
244 nullptr, /* filled in by Submit() */ 261 device_handle->handle_,
245 reinterpret_cast<uint8*>(buffer->data()), 262 reinterpret_cast<uint8*>(buffer->data()),
246 &UsbDeviceHandleImpl::Transfer::PlatformCallback, 263 &UsbDeviceHandleImpl::Transfer::PlatformCallback,
247 transfer.get(), timeout); 264 transfer.get(), timeout);
248 265
249 return transfer.Pass(); 266 return transfer.Pass();
250 } 267 }
251 268
252 // static 269 // static
253 scoped_ptr<UsbDeviceHandleImpl::Transfer> 270 scoped_ptr<UsbDeviceHandleImpl::Transfer>
254 UsbDeviceHandleImpl::Transfer::CreateBulkTransfer( 271 UsbDeviceHandleImpl::Transfer::CreateBulkTransfer(
272 scoped_refptr<UsbDeviceHandleImpl> device_handle,
255 uint8 endpoint, 273 uint8 endpoint,
256 scoped_refptr<net::IOBuffer> buffer, 274 scoped_refptr<net::IOBuffer> buffer,
257 int length, 275 int length,
258 unsigned int timeout, 276 unsigned int timeout,
259 const UsbTransferCallback& callback) { 277 scoped_refptr<base::TaskRunner> callback_task_runner,
260 scoped_ptr<Transfer> transfer( 278 const TransferCallback& callback) {
261 new Transfer(USB_TRANSFER_BULK, buffer, length, callback)); 279 scoped_ptr<Transfer> transfer(new Transfer(
280 device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint),
281 USB_TRANSFER_BULK, buffer, length, callback_task_runner, callback));
262 282
263 transfer->platform_transfer_ = libusb_alloc_transfer(0); 283 transfer->platform_transfer_ = libusb_alloc_transfer(0);
264 if (!transfer->platform_transfer_) { 284 if (!transfer->platform_transfer_) {
265 USB_LOG(ERROR) << "Failed to allocate bulk transfer."; 285 USB_LOG(ERROR) << "Failed to allocate bulk transfer.";
266 return nullptr; 286 return nullptr;
267 } 287 }
268 288
269 libusb_fill_bulk_transfer(transfer->platform_transfer_, 289 libusb_fill_bulk_transfer(
270 nullptr, /* filled in by Submit() */ 290 transfer->platform_transfer_, device_handle->handle_, endpoint,
271 endpoint, reinterpret_cast<uint8*>(buffer->data()), 291 reinterpret_cast<uint8*>(buffer->data()), static_cast<int>(length),
272 static_cast<int>(length), 292 &UsbDeviceHandleImpl::Transfer::PlatformCallback, transfer.get(),
273 &UsbDeviceHandleImpl::Transfer::PlatformCallback, 293 timeout);
274 transfer.get(), timeout);
275 294
276 return transfer.Pass(); 295 return transfer.Pass();
277 } 296 }
278 297
279 // static 298 // static
280 scoped_ptr<UsbDeviceHandleImpl::Transfer> 299 scoped_ptr<UsbDeviceHandleImpl::Transfer>
281 UsbDeviceHandleImpl::Transfer::CreateInterruptTransfer( 300 UsbDeviceHandleImpl::Transfer::CreateInterruptTransfer(
301 scoped_refptr<UsbDeviceHandleImpl> device_handle,
282 uint8 endpoint, 302 uint8 endpoint,
283 scoped_refptr<net::IOBuffer> buffer, 303 scoped_refptr<net::IOBuffer> buffer,
284 int length, 304 int length,
285 unsigned int timeout, 305 unsigned int timeout,
286 const UsbTransferCallback& callback) { 306 scoped_refptr<base::TaskRunner> callback_task_runner,
287 scoped_ptr<Transfer> transfer( 307 const TransferCallback& callback) {
288 new Transfer(USB_TRANSFER_INTERRUPT, buffer, length, callback)); 308 scoped_ptr<Transfer> transfer(new Transfer(
309 device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint),
310 USB_TRANSFER_INTERRUPT, buffer, length, callback_task_runner, callback));
289 311
290 transfer->platform_transfer_ = libusb_alloc_transfer(0); 312 transfer->platform_transfer_ = libusb_alloc_transfer(0);
291 if (!transfer->platform_transfer_) { 313 if (!transfer->platform_transfer_) {
292 USB_LOG(ERROR) << "Failed to allocate interrupt transfer."; 314 USB_LOG(ERROR) << "Failed to allocate interrupt transfer.";
293 return nullptr; 315 return nullptr;
294 } 316 }
295 317
296 libusb_fill_interrupt_transfer( 318 libusb_fill_interrupt_transfer(
297 transfer->platform_transfer_, nullptr, /* filled in by Submit() */ 319 transfer->platform_transfer_, device_handle->handle_, endpoint,
298 endpoint, reinterpret_cast<uint8*>(buffer->data()), 320 reinterpret_cast<uint8*>(buffer->data()), static_cast<int>(length),
299 static_cast<int>(length),
300 &UsbDeviceHandleImpl::Transfer::PlatformCallback, transfer.get(), 321 &UsbDeviceHandleImpl::Transfer::PlatformCallback, transfer.get(),
301 timeout); 322 timeout);
302 323
303 return transfer.Pass(); 324 return transfer.Pass();
304 } 325 }
305 326
306 // static 327 // static
307 scoped_ptr<UsbDeviceHandleImpl::Transfer> 328 scoped_ptr<UsbDeviceHandleImpl::Transfer>
308 UsbDeviceHandleImpl::Transfer::CreateIsochronousTransfer( 329 UsbDeviceHandleImpl::Transfer::CreateIsochronousTransfer(
330 scoped_refptr<UsbDeviceHandleImpl> device_handle,
309 uint8 endpoint, 331 uint8 endpoint,
310 scoped_refptr<net::IOBuffer> buffer, 332 scoped_refptr<net::IOBuffer> buffer,
311 size_t length, 333 size_t length,
312 unsigned int packets, 334 unsigned int packets,
313 unsigned int packet_length, 335 unsigned int packet_length,
314 unsigned int timeout, 336 unsigned int timeout,
315 const UsbTransferCallback& callback) { 337 scoped_refptr<base::TaskRunner> callback_task_runner,
338 const TransferCallback& callback) {
316 DCHECK(packets <= length && (packets * packet_length) <= length) 339 DCHECK(packets <= length && (packets * packet_length) <= length)
317 << "transfer length is too small"; 340 << "transfer length is too small";
318 341
319 scoped_ptr<Transfer> transfer( 342 scoped_ptr<Transfer> transfer(new Transfer(
320 new Transfer(USB_TRANSFER_ISOCHRONOUS, buffer, length, callback)); 343 device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint),
344 USB_TRANSFER_ISOCHRONOUS, buffer, length, callback_task_runner,
345 callback));
321 346
322 transfer->platform_transfer_ = libusb_alloc_transfer(packets); 347 transfer->platform_transfer_ = libusb_alloc_transfer(packets);
323 if (!transfer->platform_transfer_) { 348 if (!transfer->platform_transfer_) {
324 USB_LOG(ERROR) << "Failed to allocate isochronous transfer."; 349 USB_LOG(ERROR) << "Failed to allocate isochronous transfer.";
325 return nullptr; 350 return nullptr;
326 } 351 }
327 352
328 libusb_fill_iso_transfer( 353 libusb_fill_iso_transfer(
329 transfer->platform_transfer_, nullptr, /* filled in by Submit() */ 354 transfer->platform_transfer_, device_handle->handle_, endpoint,
330 endpoint, reinterpret_cast<uint8*>(buffer->data()), 355 reinterpret_cast<uint8*>(buffer->data()), static_cast<int>(length),
331 static_cast<int>(length), packets, &Transfer::PlatformCallback, 356 packets, &Transfer::PlatformCallback, transfer.get(), timeout);
332 transfer.get(), timeout);
333 libusb_set_iso_packet_lengths(transfer->platform_transfer_, packet_length); 357 libusb_set_iso_packet_lengths(transfer->platform_transfer_, packet_length);
334 358
335 return transfer.Pass(); 359 return transfer.Pass();
336 } 360 }
337 361
338 UsbDeviceHandleImpl::Transfer::Transfer(UsbTransferType transfer_type, 362 UsbDeviceHandleImpl::Transfer::Transfer(
339 scoped_refptr<net::IOBuffer> buffer, 363 scoped_refptr<UsbDeviceHandleImpl> device_handle,
340 size_t length, 364 scoped_refptr<InterfaceClaimer> claimed_interface,
341 const UsbTransferCallback& callback) 365 UsbTransferType transfer_type,
366 scoped_refptr<net::IOBuffer> buffer,
367 size_t length,
368 scoped_refptr<base::TaskRunner> callback_task_runner,
369 const TransferCallback& callback)
342 : transfer_type_(transfer_type), 370 : transfer_type_(transfer_type),
371 device_handle_(device_handle),
343 buffer_(buffer), 372 buffer_(buffer),
373 claimed_interface_(claimed_interface),
344 length_(length), 374 length_(length),
345 cancelled_(false), 375 callback_task_runner_(callback_task_runner),
346 callback_(callback) { 376 callback_(callback) {
347 // Remember the thread from which this transfer was created so that |callback| 377 task_runner_ = base::ThreadTaskRunnerHandle::Get();
348 // can be dispatched there.
349 callback_task_runner_ = base::ThreadTaskRunnerHandle::Get();
350 } 378 }
351 379
352 UsbDeviceHandleImpl::Transfer::~Transfer() { 380 UsbDeviceHandleImpl::Transfer::~Transfer() {
353 if (platform_transfer_) { 381 if (platform_transfer_) {
354 libusb_free_transfer(platform_transfer_); 382 libusb_free_transfer(platform_transfer_);
355 } 383 }
356 } 384 }
357 385
358 bool UsbDeviceHandleImpl::Transfer::Submit( 386 void UsbDeviceHandleImpl::Transfer::Submit() {
359 base::WeakPtr<UsbDeviceHandleImpl> device_handle) {
360 device_handle_ = device_handle;
361 // Remember the thread from which this transfer was submitted so that it can
362 // be marked complete there.
363 task_runner_ = base::ThreadTaskRunnerHandle::Get();
364 // GetClaimedInterfaceForEndpoint may return nullptr. libusb_submit_transfer
365 // will fail if it requires an interface we didn't claim.
366 claimed_interface_ = device_handle->GetClaimedInterfaceForEndpoint(
367 platform_transfer_->endpoint);
368 platform_transfer_->dev_handle = device_handle_->handle_;
369
370 const int rv = libusb_submit_transfer(platform_transfer_); 387 const int rv = libusb_submit_transfer(platform_transfer_);
371 if (rv == LIBUSB_SUCCESS) { 388 if (rv != LIBUSB_SUCCESS) {
372 return true;
373 } else {
374 USB_LOG(EVENT) << "Failed to submit transfer: " 389 USB_LOG(EVENT) << "Failed to submit transfer: "
375 << ConvertPlatformUsbErrorToString(rv); 390 << ConvertPlatformUsbErrorToString(rv);
376 Complete(USB_TRANSFER_ERROR, 0); 391 TransferComplete(USB_TRANSFER_ERROR, 0);
377 return false;
378 } 392 }
379 } 393 }
380 394
381 void UsbDeviceHandleImpl::Transfer::Cancel() { 395 void UsbDeviceHandleImpl::Transfer::Cancel() {
382 if (!cancelled_) { 396 if (!cancelled_) {
383 libusb_cancel_transfer(platform_transfer_); 397 libusb_cancel_transfer(platform_transfer_);
384 claimed_interface_ = nullptr; 398 claimed_interface_ = nullptr;
385 } 399 }
386 cancelled_ = true; 400 cancelled_ = true;
387 } 401 }
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 460
447 case USB_TRANSFER_BULK: 461 case USB_TRANSFER_BULK:
448 case USB_TRANSFER_INTERRUPT: 462 case USB_TRANSFER_INTERRUPT:
449 break; 463 break;
450 464
451 default: 465 default:
452 NOTREACHED() << "Invalid usb transfer type"; 466 NOTREACHED() << "Invalid usb transfer type";
453 break; 467 break;
454 } 468 }
455 469
456 Complete(ConvertTransferStatus(platform_transfer_->status), actual_length); 470 TransferComplete(ConvertTransferStatus(platform_transfer_->status),
457 } 471 actual_length);
458
459 void UsbDeviceHandleImpl::Transfer::Complete(UsbTransferStatus status,
460 size_t bytes_transferred) {
461 if (callback_task_runner_->RunsTasksOnCurrentThread()) {
462 callback_.Run(status, buffer_, bytes_transferred);
463 } else {
464 callback_task_runner_->PostTask(
465 FROM_HERE, base::Bind(callback_, status, buffer_, bytes_transferred));
466 }
467 } 472 }
468 473
469 /* static */ 474 /* static */
470 void LIBUSB_CALL UsbDeviceHandleImpl::Transfer::PlatformCallback( 475 void LIBUSB_CALL UsbDeviceHandleImpl::Transfer::PlatformCallback(
471 PlatformUsbTransferHandle platform_transfer) { 476 PlatformUsbTransferHandle platform_transfer) {
472 scoped_ptr<Transfer> transfer( 477 Transfer* transfer =
473 reinterpret_cast<Transfer*>(platform_transfer->user_data)); 478 reinterpret_cast<Transfer*>(platform_transfer->user_data);
474 DCHECK(transfer->platform_transfer_ == platform_transfer); 479 DCHECK(transfer->platform_transfer_ == platform_transfer);
475 480 transfer->ProcessCompletion();
476 // Because device_handle_ is a weak pointer it is guaranteed that the callback
477 // will be discarded if the handle has been freed.
478 Transfer* tmp_transfer = transfer.get(); // base::Passed invalidates transfer
479 tmp_transfer->task_runner_->PostTask(
480 FROM_HERE, base::Bind(&UsbDeviceHandleImpl::CompleteTransfer,
481 tmp_transfer->device_handle_,
482 base::Passed(&transfer)));
483 } 481 }
484 482
485 UsbDeviceHandleImpl::UsbDeviceHandleImpl(scoped_refptr<UsbContext> context, 483 void UsbDeviceHandleImpl::Transfer::TransferComplete(UsbTransferStatus status,
486 scoped_refptr<UsbDeviceImpl> device, 484 size_t bytes_transferred) {
487 PlatformUsbDeviceHandle handle) 485 task_runner_->PostTask(
488 : device_(device), 486 FROM_HERE,
489 handle_(handle), 487 base::Bind(&UsbDeviceHandleImpl::TransferComplete, device_handle_,
490 context_(context), 488 base::Owned(this),
491 task_runner_(base::ThreadTaskRunnerHandle::Get()), 489 base::Bind(callback_, status, buffer_, bytes_transferred)));
492 weak_factory_(this) {
493 DCHECK(handle) << "Cannot create device with NULL handle.";
494 }
495
496 UsbDeviceHandleImpl::~UsbDeviceHandleImpl() {
497 DCHECK(thread_checker_.CalledOnValidThread());
498
499 libusb_close(handle_);
500 handle_ = NULL;
501 } 490 }
502 491
503 scoped_refptr<UsbDevice> UsbDeviceHandleImpl::GetDevice() const { 492 scoped_refptr<UsbDevice> UsbDeviceHandleImpl::GetDevice() const {
504 return device_; 493 return device_;
505 } 494 }
506 495
507 void UsbDeviceHandleImpl::Close() { 496 void UsbDeviceHandleImpl::Close() {
508 DCHECK(thread_checker_.CalledOnValidThread()); 497 DCHECK(thread_checker_.CalledOnValidThread());
509 if (device_) 498 if (device_)
510 device_->Close(this); 499 device_->Close(this);
511 } 500 }
512 501
513 bool UsbDeviceHandleImpl::SetConfiguration(int configuration_value) { 502 void UsbDeviceHandleImpl::SetConfiguration(int configuration_value,
503 const ResultCallback& callback) {
514 DCHECK(thread_checker_.CalledOnValidThread()); 504 DCHECK(thread_checker_.CalledOnValidThread());
515 if (!device_) { 505 if (!device_) {
516 return false; 506 callback.Run(false);
507 return;
517 } 508 }
518 509
519 for (Transfer* transfer : transfers_) { 510 for (Transfer* transfer : transfers_) {
520 transfer->Cancel(); 511 transfer->Cancel();
521 } 512 }
522 claimed_interfaces_.clear(); 513 claimed_interfaces_.clear();
523 514
524 int rv = libusb_set_configuration(handle_, configuration_value); 515 blocking_task_runner_->PostTask(
525 if (rv == LIBUSB_SUCCESS) { 516 FROM_HERE,
526 device_->RefreshConfiguration(); 517 base::Bind(&UsbDeviceHandleImpl::SetConfigurationOnBlockingThread, this,
527 RefreshEndpointMap(); 518 handle_, configuration_value, callback));
528 } else {
529 USB_LOG(EVENT) << "Failed to set configuration " << configuration_value
530 << ": " << ConvertPlatformUsbErrorToString(rv);
531 }
532 return rv == LIBUSB_SUCCESS;
533 } 519 }
534 520
535 bool UsbDeviceHandleImpl::ClaimInterface(const int interface_number) { 521 void UsbDeviceHandleImpl::ClaimInterface(int interface_number,
522 const ResultCallback& callback) {
523 DCHECK(thread_checker_.CalledOnValidThread());
524 if (!device_) {
525 callback.Run(false);
526 return;
527 }
528 if (ContainsKey(claimed_interfaces_, interface_number)) {
529 callback.Run(true);
530 return;
531 }
532
533 blocking_task_runner_->PostTask(
534 FROM_HERE,
535 base::Bind(&UsbDeviceHandleImpl::ClaimInterfaceOnBlockingThread, this,
536 handle_, interface_number, callback));
537 }
538
539 bool UsbDeviceHandleImpl::ReleaseInterface(int interface_number) {
536 DCHECK(thread_checker_.CalledOnValidThread()); 540 DCHECK(thread_checker_.CalledOnValidThread());
537 if (!device_) 541 if (!device_)
538 return false; 542 return false;
539 if (ContainsKey(claimed_interfaces_, interface_number))
540 return true;
541
542 scoped_refptr<InterfaceClaimer> claimer =
543 new InterfaceClaimer(this, interface_number);
544
545 if (claimer->Claim()) {
546 claimed_interfaces_[interface_number] = claimer;
547 RefreshEndpointMap();
548 return true;
549 }
550 return false;
551 }
552
553 bool UsbDeviceHandleImpl::ReleaseInterface(const int interface_number) {
554 DCHECK(thread_checker_.CalledOnValidThread());
555 if (!device_)
556 return false;
557 if (!ContainsKey(claimed_interfaces_, interface_number)) 543 if (!ContainsKey(claimed_interfaces_, interface_number))
558 return false; 544 return false;
559 545
560 // Cancel all the transfers on that interface. 546 // Cancel all the transfers on that interface.
561 InterfaceClaimer* interface_claimer = 547 InterfaceClaimer* interface_claimer =
562 claimed_interfaces_[interface_number].get(); 548 claimed_interfaces_[interface_number].get();
563 for (Transfer* transfer : transfers_) { 549 for (Transfer* transfer : transfers_) {
564 if (transfer->claimed_interface() == interface_claimer) { 550 if (transfer->claimed_interface() == interface_claimer) {
565 transfer->Cancel(); 551 transfer->Cancel();
566 } 552 }
567 } 553 }
568 claimed_interfaces_.erase(interface_number); 554 claimed_interfaces_.erase(interface_number);
569 555
570 RefreshEndpointMap(); 556 RefreshEndpointMap();
571 return true; 557 return true;
572 } 558 }
573 559
574 bool UsbDeviceHandleImpl::SetInterfaceAlternateSetting( 560 void UsbDeviceHandleImpl::SetInterfaceAlternateSetting(
575 const int interface_number, 561 int interface_number,
576 const int alternate_setting) { 562 int alternate_setting,
577 DCHECK(thread_checker_.CalledOnValidThread()); 563 const ResultCallback& callback) {
578 if (!device_) 564 DCHECK(thread_checker_.CalledOnValidThread());
579 return false; 565 if (!device_ || !ContainsKey(claimed_interfaces_, interface_number)) {
580 if (!ContainsKey(claimed_interfaces_, interface_number)) 566 callback.Run(false);
581 return false; 567 return;
582 const int rv = libusb_set_interface_alt_setting( 568 }
583 handle_, interface_number, alternate_setting); 569
584 if (rv == LIBUSB_SUCCESS) { 570 blocking_task_runner_->PostTask(
585 claimed_interfaces_[interface_number]->set_alternate_setting( 571 FROM_HERE,
586 alternate_setting); 572 base::Bind(
587 RefreshEndpointMap(); 573 &UsbDeviceHandleImpl::SetInterfaceAlternateSettingOnBlockingThread,
588 } else { 574 this, handle_, interface_number, alternate_setting, callback));
589 USB_LOG(EVENT) << "Failed to set interface " << interface_number 575 }
590 << " to alternate setting " << alternate_setting << ": " 576
591 << ConvertPlatformUsbErrorToString(rv); 577 void UsbDeviceHandleImpl::ResetDevice(const ResultCallback& callback) {
592 } 578 DCHECK(thread_checker_.CalledOnValidThread());
593 return rv == LIBUSB_SUCCESS; 579 if (!device_) {
594 } 580 callback.Run(false);
595 581 return;
596 bool UsbDeviceHandleImpl::ResetDevice() { 582 }
597 DCHECK(thread_checker_.CalledOnValidThread()); 583
598 if (!device_) 584 blocking_task_runner_->PostTask(
599 return false; 585 FROM_HERE, base::Bind(&UsbDeviceHandleImpl::ResetDeviceOnBlockingThread,
600 586 this, handle_, callback));
601 const int rv = libusb_reset_device(handle_);
602 if (rv != LIBUSB_SUCCESS) {
603 USB_LOG(EVENT) << "Failed to reset device: "
604 << ConvertPlatformUsbErrorToString(rv);
605 }
606 return rv == LIBUSB_SUCCESS;
607 }
608
609 bool UsbDeviceHandleImpl::GetStringDescriptor(uint8 string_id,
610 base::string16* string) {
611 if (!GetSupportedLanguages()) {
612 return false;
613 }
614
615 std::map<uint8, base::string16>::const_iterator it = strings_.find(string_id);
616 if (it != strings_.end()) {
617 *string = it->second;
618 return true;
619 }
620
621 for (size_t i = 0; i < languages_.size(); ++i) {
622 // Get the string using language ID.
623 uint16 language_id = languages_[i];
624 // The 1-byte length field limits the descriptor to 256-bytes (128 char16s).
625 base::char16 text[128];
626 int size =
627 libusb_get_string_descriptor(handle_,
628 string_id,
629 language_id,
630 reinterpret_cast<unsigned char*>(&text[0]),
631 sizeof(text));
632 if (size < 0) {
633 USB_LOG(EVENT) << "Failed to get string descriptor " << string_id
634 << " (langid " << language_id
635 << "): " << ConvertPlatformUsbErrorToString(size);
636 continue;
637 } else if (size < 2) {
638 USB_LOG(EVENT) << "String descriptor " << string_id << " (langid "
639 << language_id << ") has no header.";
640 continue;
641 // The first 2 bytes of the descriptor are the total length and type tag.
642 } else if ((text[0] & 0xff) != size) {
643 USB_LOG(EVENT) << "String descriptor " << string_id << " (langid "
644 << language_id << ") size mismatch: " << (text[0] & 0xff)
645 << " != " << size;
646 continue;
647 } else if ((text[0] >> 8) != LIBUSB_DT_STRING) {
648 USB_LOG(EVENT) << "String descriptor " << string_id << " (langid "
649 << language_id << ") is not a string descriptor.";
650 continue;
651 }
652
653 *string = base::string16(text + 1, (size - 2) / 2);
654 strings_[string_id] = *string;
655 return true;
656 }
657
658 return false;
659 } 587 }
660 588
661 void UsbDeviceHandleImpl::ControlTransfer(UsbEndpointDirection direction, 589 void UsbDeviceHandleImpl::ControlTransfer(UsbEndpointDirection direction,
662 TransferRequestType request_type, 590 TransferRequestType request_type,
663 TransferRecipient recipient, 591 TransferRecipient recipient,
664 uint8 request, 592 uint8 request,
665 uint16 value, 593 uint16 value,
666 uint16 index, 594 uint16 index,
667 net::IOBuffer* buffer, 595 scoped_refptr<net::IOBuffer> buffer,
668 size_t length, 596 size_t length,
669 unsigned int timeout, 597 unsigned int timeout,
670 const UsbTransferCallback& callback) { 598 const TransferCallback& callback) {
599 if (task_runner_->BelongsToCurrentThread()) {
600 ControlTransferInternal(direction, request_type, recipient, request, value,
601 index, buffer, length, timeout, task_runner_,
602 callback);
603 } else {
604 task_runner_->PostTask(
605 FROM_HERE, base::Bind(&UsbDeviceHandleImpl::ControlTransferInternal,
606 this, direction, request_type, recipient, request,
607 value, index, buffer, length, timeout,
608 base::ThreadTaskRunnerHandle::Get(), callback));
609 }
610 }
611
612 void UsbDeviceHandleImpl::BulkTransfer(UsbEndpointDirection direction,
613 uint8 endpoint,
614 scoped_refptr<net::IOBuffer> buffer,
615 size_t length,
616 unsigned int timeout,
617 const TransferCallback& callback) {
618 if (task_runner_->BelongsToCurrentThread()) {
619 BulkTransferInternal(direction, endpoint, buffer, length, timeout,
620 task_runner_, callback);
621 } else {
622 task_runner_->PostTask(
623 FROM_HERE, base::Bind(&UsbDeviceHandleImpl::BulkTransferInternal, this,
624 direction, endpoint, buffer, length, timeout,
625 base::ThreadTaskRunnerHandle::Get(), callback));
626 }
627 }
628
629 void UsbDeviceHandleImpl::InterruptTransfer(UsbEndpointDirection direction,
630 uint8 endpoint,
631 scoped_refptr<net::IOBuffer> buffer,
632 size_t length,
633 unsigned int timeout,
634 const TransferCallback& callback) {
635 if (task_runner_->BelongsToCurrentThread()) {
636 InterruptTransferInternal(direction, endpoint, buffer, length, timeout,
637 task_runner_, callback);
638 } else {
639 task_runner_->PostTask(
640 FROM_HERE,
641 base::Bind(&UsbDeviceHandleImpl::InterruptTransferInternal, this,
642 direction, endpoint, buffer, length, timeout,
643 base::ThreadTaskRunnerHandle::Get(), callback));
644 }
645 }
646
647 void UsbDeviceHandleImpl::IsochronousTransfer(
648 UsbEndpointDirection direction,
649 uint8 endpoint,
650 scoped_refptr<net::IOBuffer> buffer,
651 size_t length,
652 unsigned int packets,
653 unsigned int packet_length,
654 unsigned int timeout,
655 const TransferCallback& callback) {
656 if (task_runner_->BelongsToCurrentThread()) {
657 IsochronousTransferInternal(direction, endpoint, buffer, length, packets,
658 packet_length, timeout, task_runner_, callback);
659 } else {
660 task_runner_->PostTask(
661 FROM_HERE,
662 base::Bind(&UsbDeviceHandleImpl::IsochronousTransferInternal, this,
663 direction, endpoint, buffer, length, packets, packet_length,
664 timeout, base::ThreadTaskRunnerHandle::Get(), callback));
665 }
666 }
667
668 UsbDeviceHandleImpl::UsbDeviceHandleImpl(
669 scoped_refptr<UsbContext> context,
670 scoped_refptr<UsbDeviceImpl> device,
671 PlatformUsbDeviceHandle handle,
672 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner)
673 : device_(device),
674 handle_(handle),
675 context_(context),
676 task_runner_(base::ThreadTaskRunnerHandle::Get()),
677 blocking_task_runner_(blocking_task_runner) {
678 DCHECK(handle) << "Cannot create device with NULL handle.";
679 }
680
681 UsbDeviceHandleImpl::~UsbDeviceHandleImpl() {
682 DCHECK(thread_checker_.CalledOnValidThread());
683
684 libusb_close(handle_);
685 handle_ = NULL;
686 }
687
688 void UsbDeviceHandleImpl::SetConfigurationOnBlockingThread(
689 PlatformUsbDeviceHandle handle,
690 int configuration_value,
691 const ResultCallback& callback) {
692 int rv = libusb_set_configuration(handle_, configuration_value);
693 if (rv != LIBUSB_SUCCESS) {
694 USB_LOG(EVENT) << "Failed to set configuration " << configuration_value
695 << ": " << ConvertPlatformUsbErrorToString(rv);
696 }
697 task_runner_->PostTask(
698 FROM_HERE, base::Bind(&UsbDeviceHandleImpl::SetConfigurationComplete,
699 this, rv == LIBUSB_SUCCESS, callback));
700 }
701
702 void UsbDeviceHandleImpl::SetConfigurationComplete(
703 bool success,
704 const ResultCallback& callback) {
705 if (success) {
706 device_->RefreshConfiguration();
707 RefreshEndpointMap();
708 }
709 callback.Run(success);
710 }
711
712 void UsbDeviceHandleImpl::ClaimInterfaceOnBlockingThread(
713 PlatformUsbDeviceHandle handle,
714 int interface_number,
715 const ResultCallback& callback) {
716 int rv = libusb_claim_interface(handle, interface_number);
717 if (rv != LIBUSB_SUCCESS) {
718 VLOG(1) << "Failed to claim interface: "
719 << ConvertPlatformUsbErrorToString(rv);
720 }
721 task_runner_->PostTask(
722 FROM_HERE, base::Bind(&UsbDeviceHandleImpl::ClaimInterfaceComplete, this,
723 interface_number, rv == LIBUSB_SUCCESS, callback));
724 }
725
726 void UsbDeviceHandleImpl::ClaimInterfaceComplete(
727 int interface_number,
728 bool success,
729 const ResultCallback& callback) {
730 if (success) {
731 claimed_interfaces_[interface_number] =
732 new InterfaceClaimer(this, interface_number);
733 RefreshEndpointMap();
734 }
735 callback.Run(success);
736 }
737
738 void UsbDeviceHandleImpl::SetInterfaceAlternateSettingOnBlockingThread(
739 PlatformUsbDeviceHandle handle,
740 int interface_number,
741 int alternate_setting,
742 const ResultCallback& callback) {
743 int rv = libusb_set_interface_alt_setting(handle, interface_number,
744 alternate_setting);
745 if (rv != LIBUSB_SUCCESS) {
746 USB_LOG(EVENT) << "Failed to set interface " << interface_number
747 << " to alternate setting " << alternate_setting << ": "
748 << ConvertPlatformUsbErrorToString(rv);
749 }
750 task_runner_->PostTask(
751 FROM_HERE,
752 base::Bind(&UsbDeviceHandleImpl::SetInterfaceAlternateSettingComplete,
753 this, interface_number, alternate_setting,
754 rv == LIBUSB_SUCCESS, callback));
755 }
756
757 void UsbDeviceHandleImpl::SetInterfaceAlternateSettingComplete(
758 int interface_number,
759 int alternate_setting,
760 bool success,
761 const ResultCallback& callback) {
762 if (success) {
763 claimed_interfaces_[interface_number]->set_alternate_setting(
764 alternate_setting);
765 RefreshEndpointMap();
766 }
767 callback.Run(success);
768 }
769
770 void UsbDeviceHandleImpl::ResetDeviceOnBlockingThread(
771 PlatformUsbDeviceHandle handle,
772 const ResultCallback& callback) {
773 int rv = libusb_reset_device(handle);
774 if (rv != LIBUSB_SUCCESS) {
775 USB_LOG(EVENT) << "Failed to reset device: "
776 << ConvertPlatformUsbErrorToString(rv);
777 }
778 task_runner_->PostTask(
779 FROM_HERE, base::Bind(&UsbDeviceHandleImpl::ResetDeviceComplete, this,
780 rv == LIBUSB_SUCCESS, callback));
781 }
782
783 void UsbDeviceHandleImpl::ResetDeviceComplete(bool success,
784 const ResultCallback& callback) {
785 callback.Run(success);
786 }
787
788 void UsbDeviceHandleImpl::RefreshEndpointMap() {
789 DCHECK(thread_checker_.CalledOnValidThread());
790 endpoint_map_.clear();
791 const UsbConfigDescriptor* config = device_->GetConfiguration();
792 if (config) {
793 for (const auto& map_entry : claimed_interfaces_) {
794 int interface_number = map_entry.first;
795 const scoped_refptr<InterfaceClaimer>& claimed_iface = map_entry.second;
796
797 for (const UsbInterfaceDescriptor& iface : config->interfaces) {
798 if (iface.interface_number == interface_number &&
799 iface.alternate_setting == claimed_iface->alternate_setting()) {
800 for (const UsbEndpointDescriptor& endpoint : iface.endpoints) {
801 endpoint_map_[endpoint.address] = interface_number;
802 }
803 break;
804 }
805 }
806 }
807 }
808 }
809
810 scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer>
811 UsbDeviceHandleImpl::GetClaimedInterfaceForEndpoint(unsigned char endpoint) {
812 if (ContainsKey(endpoint_map_, endpoint))
813 return claimed_interfaces_[endpoint_map_[endpoint]];
814 return NULL;
815 }
816
817 void UsbDeviceHandleImpl::ControlTransferInternal(
818 UsbEndpointDirection direction,
819 TransferRequestType request_type,
820 TransferRecipient recipient,
821 uint8 request,
822 uint16 value,
823 uint16 index,
824 scoped_refptr<net::IOBuffer> buffer,
825 size_t length,
826 unsigned int timeout,
827 scoped_refptr<base::TaskRunner> callback_task_runner,
828 const TransferCallback& callback) {
829 DCHECK(thread_checker_.CalledOnValidThread());
830
831 if (!device_) {
832 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
833 return;
834 }
835
671 if (length > UINT16_MAX) { 836 if (length > UINT16_MAX) {
672 USB_LOG(USER) << "Transfer too long."; 837 USB_LOG(USER) << "Transfer too long.";
673 callback.Run(USB_TRANSFER_ERROR, buffer, 0); 838 callback.Run(USB_TRANSFER_ERROR, buffer, 0);
674 return; 839 return;
675 } 840 }
676 841
677 const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + length; 842 const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + length;
678 scoped_refptr<net::IOBuffer> resized_buffer( 843 scoped_refptr<net::IOBuffer> resized_buffer(
679 new net::IOBufferWithSize(static_cast<int>(resized_length))); 844 new net::IOBufferWithSize(static_cast<int>(resized_length)));
680 if (!resized_buffer.get()) { 845 if (!resized_buffer.get()) {
681 callback.Run(USB_TRANSFER_ERROR, buffer, 0); 846 callback.Run(USB_TRANSFER_ERROR, buffer, 0);
682 return; 847 return;
683 } 848 }
684 memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, buffer->data(), 849 memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, buffer->data(),
685 length); 850 length);
686 851
687 scoped_ptr<Transfer> transfer = Transfer::CreateControlTransfer( 852 scoped_ptr<Transfer> transfer = Transfer::CreateControlTransfer(
688 CreateRequestType(direction, request_type, recipient), request, value, 853 this, CreateRequestType(direction, request_type, recipient), request,
689 index, static_cast<uint16>(length), resized_buffer, timeout, callback); 854 value, index, static_cast<uint16>(length), resized_buffer, timeout,
855 callback_task_runner, callback);
690 if (!transfer) { 856 if (!transfer) {
691 callback.Run(USB_TRANSFER_ERROR, buffer, 0); 857 callback.Run(USB_TRANSFER_ERROR, buffer, 0);
692 return; 858 return;
693 } 859 }
694 860
695 PostOrSubmitTransfer(transfer.Pass()); 861 SubmitTransfer(transfer.Pass());
696 } 862 }
697 863
698 void UsbDeviceHandleImpl::BulkTransfer(const UsbEndpointDirection direction, 864 void UsbDeviceHandleImpl::BulkTransferInternal(
699 const uint8 endpoint, 865 const UsbEndpointDirection direction,
700 net::IOBuffer* buffer, 866 const uint8 endpoint,
701 const size_t length, 867 scoped_refptr<net::IOBuffer> buffer,
702 const unsigned int timeout, 868 const size_t length,
703 const UsbTransferCallback& callback) { 869 const unsigned int timeout,
870 scoped_refptr<base::TaskRunner> callback_task_runner,
871 const TransferCallback& callback) {
872 DCHECK(thread_checker_.CalledOnValidThread());
873
874 if (!device_) {
875 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
876 return;
877 }
878
704 if (length > INT_MAX) { 879 if (length > INT_MAX) {
705 USB_LOG(USER) << "Transfer too long."; 880 USB_LOG(USER) << "Transfer too long.";
706 callback.Run(USB_TRANSFER_ERROR, buffer, 0); 881 callback.Run(USB_TRANSFER_ERROR, buffer, 0);
707 return; 882 return;
708 } 883 }
709 884
710 scoped_ptr<Transfer> transfer = Transfer::CreateBulkTransfer( 885 scoped_ptr<Transfer> transfer = Transfer::CreateBulkTransfer(
711 ConvertTransferDirection(direction) | endpoint, buffer, 886 this, ConvertTransferDirection(direction) | endpoint, buffer,
712 static_cast<int>(length), timeout, callback); 887 static_cast<int>(length), timeout, callback_task_runner, callback);
713 888
714 PostOrSubmitTransfer(transfer.Pass()); 889 SubmitTransfer(transfer.Pass());
715 } 890 }
716 891
717 void UsbDeviceHandleImpl::InterruptTransfer( 892 void UsbDeviceHandleImpl::InterruptTransferInternal(
718 UsbEndpointDirection direction, 893 UsbEndpointDirection direction,
719 uint8 endpoint, 894 uint8 endpoint,
720 net::IOBuffer* buffer, 895 scoped_refptr<net::IOBuffer> buffer,
721 size_t length, 896 size_t length,
722 unsigned int timeout, 897 unsigned int timeout,
723 const UsbTransferCallback& callback) { 898 scoped_refptr<base::TaskRunner> callback_task_runner,
899 const TransferCallback& callback) {
900 DCHECK(thread_checker_.CalledOnValidThread());
901
902 if (!device_) {
903 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
904 return;
905 }
906
724 if (length > INT_MAX) { 907 if (length > INT_MAX) {
725 USB_LOG(USER) << "Transfer too long."; 908 USB_LOG(USER) << "Transfer too long.";
726 callback.Run(USB_TRANSFER_ERROR, buffer, 0); 909 callback.Run(USB_TRANSFER_ERROR, buffer, 0);
727 return; 910 return;
728 } 911 }
729 912
730 scoped_ptr<Transfer> transfer = Transfer::CreateInterruptTransfer( 913 scoped_ptr<Transfer> transfer = Transfer::CreateInterruptTransfer(
731 ConvertTransferDirection(direction) | endpoint, buffer, 914 this, ConvertTransferDirection(direction) | endpoint, buffer,
732 static_cast<int>(length), timeout, callback); 915 static_cast<int>(length), timeout, callback_task_runner, callback);
733 916
734 PostOrSubmitTransfer(transfer.Pass()); 917 SubmitTransfer(transfer.Pass());
735 } 918 }
736 919
737 void UsbDeviceHandleImpl::IsochronousTransfer( 920 void UsbDeviceHandleImpl::IsochronousTransferInternal(
738 const UsbEndpointDirection direction, 921 const UsbEndpointDirection direction,
739 const uint8 endpoint, 922 uint8 endpoint,
740 net::IOBuffer* buffer, 923 scoped_refptr<net::IOBuffer> buffer,
741 const size_t length, 924 size_t length,
742 const unsigned int packets, 925 unsigned int packets,
743 const unsigned int packet_length, 926 unsigned int packet_length,
744 const unsigned int timeout, 927 unsigned int timeout,
745 const UsbTransferCallback& callback) { 928 scoped_refptr<base::TaskRunner> callback_task_runner,
929 const TransferCallback& callback) {
930 DCHECK(thread_checker_.CalledOnValidThread());
931
932 if (!device_) {
933 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
934 return;
935 }
936
746 if (length > INT_MAX) { 937 if (length > INT_MAX) {
747 USB_LOG(USER) << "Transfer too long."; 938 USB_LOG(USER) << "Transfer too long.";
748 callback.Run(USB_TRANSFER_ERROR, buffer, 0); 939 callback.Run(USB_TRANSFER_ERROR, buffer, 0);
749 return; 940 return;
750 } 941 }
751 942
752 scoped_ptr<Transfer> transfer = Transfer::CreateIsochronousTransfer( 943 scoped_ptr<Transfer> transfer = Transfer::CreateIsochronousTransfer(
753 ConvertTransferDirection(direction) | endpoint, buffer, 944 this, ConvertTransferDirection(direction) | endpoint, buffer,
754 static_cast<int>(length), packets, packet_length, timeout, callback); 945 static_cast<int>(length), packets, packet_length, timeout,
946 callback_task_runner, callback);
755 947
756 PostOrSubmitTransfer(transfer.Pass()); 948 SubmitTransfer(transfer.Pass());
757 }
758
759 void UsbDeviceHandleImpl::RefreshEndpointMap() {
760 DCHECK(thread_checker_.CalledOnValidThread());
761 endpoint_map_.clear();
762 const UsbConfigDescriptor* config = device_->GetConfiguration();
763 if (config) {
764 for (const auto& map_entry : claimed_interfaces_) {
765 int interface_number = map_entry.first;
766 const scoped_refptr<InterfaceClaimer>& claimed_iface = map_entry.second;
767
768 for (const UsbInterfaceDescriptor& iface : config->interfaces) {
769 if (iface.interface_number == interface_number &&
770 iface.alternate_setting == claimed_iface->alternate_setting()) {
771 for (const UsbEndpointDescriptor& endpoint : iface.endpoints) {
772 endpoint_map_[endpoint.address] = interface_number;
773 }
774 break;
775 }
776 }
777 }
778 }
779 }
780
781 scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer>
782 UsbDeviceHandleImpl::GetClaimedInterfaceForEndpoint(unsigned char endpoint) {
783 if (ContainsKey(endpoint_map_, endpoint))
784 return claimed_interfaces_[endpoint_map_[endpoint]];
785 return NULL;
786 }
787
788 void UsbDeviceHandleImpl::PostOrSubmitTransfer(scoped_ptr<Transfer> transfer) {
789 if (task_runner_->RunsTasksOnCurrentThread()) {
790 SubmitTransfer(transfer.Pass());
791 } else {
792 task_runner_->PostTask(
793 FROM_HERE, base::Bind(&UsbDeviceHandleImpl::SubmitTransfer, this,
794 base::Passed(&transfer)));
795 }
796 } 949 }
797 950
798 void UsbDeviceHandleImpl::SubmitTransfer(scoped_ptr<Transfer> transfer) { 951 void UsbDeviceHandleImpl::SubmitTransfer(scoped_ptr<Transfer> transfer) {
799 DCHECK(thread_checker_.CalledOnValidThread()); 952 DCHECK(thread_checker_.CalledOnValidThread());
800 953
801 if (device_) { 954 // Transfer is owned by libusb until its completion callback is run. This
802 if (transfer->Submit(weak_factory_.GetWeakPtr())) { 955 // object holds a weak reference.
803 // Transfer is now owned by libusb until its completion callback is run. 956 transfers_.insert(transfer.get());
804 // This object holds a weak reference. 957 blocking_task_runner_->PostTask(
805 transfers_.insert(transfer.release()); 958 FROM_HERE,
806 } 959 base::Bind(&Transfer::Submit, base::Unretained(transfer.release())));
960 }
961
962 void UsbDeviceHandleImpl::TransferComplete(Transfer* transfer,
963 const base::Closure& callback) {
964 DCHECK(thread_checker_.CalledOnValidThread());
965 DCHECK(ContainsKey(transfers_, transfer)) << "Missing transfer completed";
966 transfers_.erase(transfer);
967
968 if (transfer->callback_task_runner()->RunsTasksOnCurrentThread()) {
969 callback.Run();
807 } else { 970 } else {
808 transfer->Complete(USB_TRANSFER_DISCONNECT, 0); 971 transfer->callback_task_runner()->PostTask(FROM_HERE, callback);
809 } 972 }
810 } 973 }
811 974
812 void UsbDeviceHandleImpl::CompleteTransfer(scoped_ptr<Transfer> transfer) {
813 DCHECK(ContainsKey(transfers_, transfer.get()))
814 << "Missing transfer completed";
815 transfers_.erase(transfer.get());
816 transfer->ProcessCompletion();
817 }
818
819 bool UsbDeviceHandleImpl::GetSupportedLanguages() {
820 if (!languages_.empty()) {
821 return true;
822 }
823
824 // The 1-byte length field limits the descriptor to 256-bytes (128 uint16s).
825 uint16 languages[128];
826 int size = libusb_get_string_descriptor(
827 handle_,
828 0,
829 0,
830 reinterpret_cast<unsigned char*>(&languages[0]),
831 sizeof(languages));
832 if (size < 0) {
833 USB_LOG(EVENT) << "Failed to get list of supported languages: "
834 << ConvertPlatformUsbErrorToString(size);
835 return false;
836 } else if (size < 2) {
837 USB_LOG(EVENT) << "String descriptor zero has no header.";
838 return false;
839 // The first 2 bytes of the descriptor are the total length and type tag.
840 } else if ((languages[0] & 0xff) != size) {
841 USB_LOG(EVENT) << "String descriptor zero size mismatch: "
842 << (languages[0] & 0xff) << " != " << size;
843 return false;
844 } else if ((languages[0] >> 8) != LIBUSB_DT_STRING) {
845 USB_LOG(EVENT) << "String descriptor zero is not a string descriptor.";
846 return false;
847 }
848
849 languages_.assign(languages[1], languages[(size - 2) / 2]);
850 return true;
851 }
852
853 void UsbDeviceHandleImpl::InternalClose() { 975 void UsbDeviceHandleImpl::InternalClose() {
854 DCHECK(thread_checker_.CalledOnValidThread()); 976 DCHECK(thread_checker_.CalledOnValidThread());
855 if (!device_) 977 if (!device_)
856 return; 978 return;
857 979
858 // Cancel all the transfers. 980 // Cancel all the transfers.
859 for (Transfer* transfer : transfers_) { 981 for (Transfer* transfer : transfers_) {
860 // The callback will be called some time later. 982 // The callback will be called some time later.
861 transfer->Cancel(); 983 transfer->Cancel();
862 } 984 }
863 985
864 // Attempt-release all the interfaces. 986 // Attempt-release all the interfaces.
865 // It will be retained until the transfer cancellation is finished. 987 // It will be retained until the transfer cancellation is finished.
866 claimed_interfaces_.clear(); 988 claimed_interfaces_.clear();
867 989
868 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to 990 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to
869 // finish. 991 // finish.
870 device_ = NULL; 992 device_ = NULL;
871 } 993 }
872 994
873 } // namespace device 995 } // namespace device
OLDNEW
« no previous file with comments | « device/usb/usb_device_handle_impl.h ('k') | device/usb/usb_device_handle_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698