OLD | NEW |
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/extensions/api/usb/usb_api.h" | 5 #include "chrome/browser/extensions/api/usb/usb_api.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 static const char* kErrorCannotReleaseInterface = "Error releasing interface."; | 55 static const char* kErrorCannotReleaseInterface = "Error releasing interface."; |
56 static const char* kErrorCannotSetInterfaceAlternateSetting = | 56 static const char* kErrorCannotSetInterfaceAlternateSetting = |
57 "Error setting alternate interface setting."; | 57 "Error setting alternate interface setting."; |
58 static const char* kErrorConvertDirection = "Invalid transfer direction."; | 58 static const char* kErrorConvertDirection = "Invalid transfer direction."; |
59 static const char* kErrorConvertRecipient = "Invalid transfer recipient."; | 59 static const char* kErrorConvertRecipient = "Invalid transfer recipient."; |
60 static const char* kErrorConvertRequestType = "Invalid request type."; | 60 static const char* kErrorConvertRequestType = "Invalid request type."; |
61 static const char* kErrorMalformedParameters = "Error parsing parameters."; | 61 static const char* kErrorMalformedParameters = "Error parsing parameters."; |
62 static const char* kErrorNoDevice = "No such device."; | 62 static const char* kErrorNoDevice = "No such device."; |
63 static const char* kErrorPermissionDenied = | 63 static const char* kErrorPermissionDenied = |
64 "Permission to access device was denied"; | 64 "Permission to access device was denied"; |
| 65 static const char* kErrorInvalidTransferLength = "Transfer length must be a " |
| 66 "positive number less than 104,857,600."; |
65 | 67 |
| 68 static const size_t kMaxTransferLength = 100 * 1024 * 1024; |
66 static UsbDevice* device_for_test_ = NULL; | 69 static UsbDevice* device_for_test_ = NULL; |
67 | 70 |
68 static bool ConvertDirection(const Direction& input, | 71 static bool ConvertDirection(const Direction& input, |
69 UsbDevice::TransferDirection* output) { | 72 UsbDevice::TransferDirection* output) { |
70 switch (input) { | 73 switch (input) { |
71 case usb::DIRECTION_IN: | 74 case usb::DIRECTION_IN: |
72 *output = UsbDevice::INBOUND; | 75 *output = UsbDevice::INBOUND; |
73 return true; | 76 return true; |
74 case usb::DIRECTION_OUT: | 77 case usb::DIRECTION_OUT: |
75 *output = UsbDevice::OUTBOUND; | 78 *output = UsbDevice::OUTBOUND; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 return false; | 125 return false; |
123 } | 126 } |
124 NOTREACHED(); | 127 NOTREACHED(); |
125 return false; | 128 return false; |
126 } | 129 } |
127 | 130 |
128 template<class T> | 131 template<class T> |
129 static bool GetTransferSize(const T& input, size_t* output) { | 132 static bool GetTransferSize(const T& input, size_t* output) { |
130 if (input.direction == usb::DIRECTION_IN) { | 133 if (input.direction == usb::DIRECTION_IN) { |
131 const int* length = input.length.get(); | 134 const int* length = input.length.get(); |
132 if (length) { | 135 if (length && *length >= 0 && |
| 136 static_cast<size_t>(*length) < kMaxTransferLength) { |
133 *output = *length; | 137 *output = *length; |
134 return true; | 138 return true; |
135 } | 139 } |
136 } else if (input.direction == usb::DIRECTION_OUT) { | 140 } else if (input.direction == usb::DIRECTION_OUT) { |
137 if (input.data.get()) { | 141 if (input.data.get()) { |
138 *output = input.data->size(); | 142 *output = input.data->size(); |
139 return true; | 143 return true; |
140 } | 144 } |
141 } | 145 } |
142 return false; | 146 return false; |
143 } | 147 } |
144 | 148 |
145 template<class T> | 149 template<class T> |
146 static scoped_refptr<net::IOBuffer> CreateBufferForTransfer(const T& input) { | 150 static scoped_refptr<net::IOBuffer> CreateBufferForTransfer( |
147 size_t size = 0; | 151 const T& input, UsbDevice::TransferDirection direction, size_t size) { |
148 if (!GetTransferSize(input, &size)) | 152 |
| 153 if (size > kMaxTransferLength) |
149 return NULL; | 154 return NULL; |
150 | 155 |
151 // Allocate a |size|-bytes buffer, or a one-byte buffer if |size| is 0. This | 156 // Allocate a |size|-bytes buffer, or a one-byte buffer if |size| is 0. This |
152 // is due to an impedance mismatch between IOBuffer and URBs. An IOBuffer | 157 // is due to an impedance mismatch between IOBuffer and URBs. An IOBuffer |
153 // cannot represent a zero-length buffer, while an URB can. | 158 // cannot represent a zero-length buffer, while an URB can. |
154 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(std::max( | 159 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(std::max( |
155 static_cast<size_t>(1), size)); | 160 static_cast<size_t>(1), size)); |
156 if (!input.data.get()) | 161 |
| 162 if (direction == UsbDevice::INBOUND) { |
157 return buffer; | 163 return buffer; |
158 | 164 } else if (direction == UsbDevice::OUTBOUND) { |
159 memcpy(buffer->data(), input.data->data(), size); | 165 if (input.data.get() && size <= input.data->size()) { |
160 return buffer; | 166 memcpy(buffer->data(), input.data->data(), size); |
| 167 return buffer; |
| 168 } |
| 169 } |
| 170 NOTREACHED(); |
| 171 return NULL; |
161 } | 172 } |
162 | 173 |
163 static const char* ConvertTransferStatusToErrorString( | 174 static const char* ConvertTransferStatusToErrorString( |
164 const UsbTransferStatus status) { | 175 const UsbTransferStatus status) { |
165 switch (status) { | 176 switch (status) { |
166 case USB_TRANSFER_COMPLETED: | 177 case USB_TRANSFER_COMPLETED: |
167 return ""; | 178 return ""; |
168 case USB_TRANSFER_ERROR: | 179 case USB_TRANSFER_ERROR: |
169 return kErrorGeneric; | 180 return kErrorGeneric; |
170 case USB_TRANSFER_TIMEOUT: | 181 case USB_TRANSFER_TIMEOUT: |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 if (!device) { | 479 if (!device) { |
469 CompleteWithError(kErrorNoDevice); | 480 CompleteWithError(kErrorNoDevice); |
470 return; | 481 return; |
471 } | 482 } |
472 | 483 |
473 const ControlTransferInfo& transfer = parameters_->transfer_info; | 484 const ControlTransferInfo& transfer = parameters_->transfer_info; |
474 | 485 |
475 UsbDevice::TransferDirection direction; | 486 UsbDevice::TransferDirection direction; |
476 UsbDevice::TransferRequestType request_type; | 487 UsbDevice::TransferRequestType request_type; |
477 UsbDevice::TransferRecipient recipient; | 488 UsbDevice::TransferRecipient recipient; |
478 size_t size; | 489 size_t size = 0; |
479 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(transfer); | |
480 | 490 |
481 if (!ConvertDirectionSafely(transfer.direction, &direction) || | 491 if (!ConvertDirectionSafely(transfer.direction, &direction) || |
482 !ConvertRequestTypeSafely(transfer.request_type, &request_type) || | 492 !ConvertRequestTypeSafely(transfer.request_type, &request_type) || |
483 !ConvertRecipientSafely(transfer.recipient, &recipient)) { | 493 !ConvertRecipientSafely(transfer.recipient, &recipient)) { |
484 AsyncWorkCompleted(); | 494 AsyncWorkCompleted(); |
485 return; | 495 return; |
486 } | 496 } |
487 | 497 |
488 if (!GetTransferSize(transfer, &size) || !buffer) { | 498 if (!GetTransferSize(transfer, &size)) { |
| 499 CompleteWithError(kErrorInvalidTransferLength); |
| 500 return; |
| 501 } |
| 502 |
| 503 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer( |
| 504 transfer, direction, size); |
| 505 if (!buffer) { |
489 CompleteWithError(kErrorMalformedParameters); | 506 CompleteWithError(kErrorMalformedParameters); |
490 return; | 507 return; |
491 } | 508 } |
492 | 509 |
493 device->device()->ControlTransfer(direction, request_type, recipient, | 510 device->device()->ControlTransfer(direction, request_type, recipient, |
494 transfer.request, transfer.value, transfer.index, buffer, size, 0, | 511 transfer.request, transfer.value, transfer.index, buffer, size, 0, |
495 base::Bind(&UsbControlTransferFunction::OnCompleted, this)); | 512 base::Bind(&UsbControlTransferFunction::OnCompleted, this)); |
496 } | 513 } |
497 | 514 |
498 UsbBulkTransferFunction::UsbBulkTransferFunction() {} | 515 UsbBulkTransferFunction::UsbBulkTransferFunction() {} |
(...skipping 10 matching lines...) Expand all Loading... |
509 UsbDeviceResource* const device = GetUsbDeviceResource( | 526 UsbDeviceResource* const device = GetUsbDeviceResource( |
510 parameters_->device.handle); | 527 parameters_->device.handle); |
511 if (!device) { | 528 if (!device) { |
512 CompleteWithError(kErrorNoDevice); | 529 CompleteWithError(kErrorNoDevice); |
513 return; | 530 return; |
514 } | 531 } |
515 | 532 |
516 const GenericTransferInfo& transfer = parameters_->transfer_info; | 533 const GenericTransferInfo& transfer = parameters_->transfer_info; |
517 | 534 |
518 UsbDevice::TransferDirection direction; | 535 UsbDevice::TransferDirection direction; |
519 size_t size; | 536 size_t size = 0; |
520 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(transfer); | |
521 | 537 |
522 if (!ConvertDirectionSafely(transfer.direction, &direction)) { | 538 if (!ConvertDirectionSafely(transfer.direction, &direction)) { |
523 AsyncWorkCompleted(); | 539 AsyncWorkCompleted(); |
524 return; | 540 return; |
525 } | 541 } |
526 | 542 |
527 if (!GetTransferSize(transfer, &size) || !buffer) { | 543 if (!GetTransferSize(transfer, &size)) { |
| 544 CompleteWithError(kErrorInvalidTransferLength); |
| 545 return; |
| 546 } |
| 547 |
| 548 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer( |
| 549 transfer, direction, size); |
| 550 if (!buffer) { |
528 CompleteWithError(kErrorMalformedParameters); | 551 CompleteWithError(kErrorMalformedParameters); |
529 return; | 552 return; |
530 } | 553 } |
531 | 554 |
532 device->device()->BulkTransfer(direction, transfer.endpoint, buffer, size, 0, | 555 device->device()->BulkTransfer(direction, transfer.endpoint, buffer, size, 0, |
533 base::Bind(&UsbBulkTransferFunction::OnCompleted, this)); | 556 base::Bind(&UsbBulkTransferFunction::OnCompleted, this)); |
534 } | 557 } |
535 | 558 |
536 UsbInterruptTransferFunction::UsbInterruptTransferFunction() {} | 559 UsbInterruptTransferFunction::UsbInterruptTransferFunction() {} |
537 | 560 |
538 UsbInterruptTransferFunction::~UsbInterruptTransferFunction() {} | 561 UsbInterruptTransferFunction::~UsbInterruptTransferFunction() {} |
539 | 562 |
540 bool UsbInterruptTransferFunction::Prepare() { | 563 bool UsbInterruptTransferFunction::Prepare() { |
541 parameters_ = InterruptTransfer::Params::Create(*args_); | 564 parameters_ = InterruptTransfer::Params::Create(*args_); |
542 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | 565 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); |
543 return true; | 566 return true; |
544 } | 567 } |
545 | 568 |
546 void UsbInterruptTransferFunction::AsyncWorkStart() { | 569 void UsbInterruptTransferFunction::AsyncWorkStart() { |
547 UsbDeviceResource* const device = GetUsbDeviceResource( | 570 UsbDeviceResource* const device = GetUsbDeviceResource( |
548 parameters_->device.handle); | 571 parameters_->device.handle); |
549 if (!device) { | 572 if (!device) { |
550 CompleteWithError(kErrorNoDevice); | 573 CompleteWithError(kErrorNoDevice); |
551 return; | 574 return; |
552 } | 575 } |
553 | 576 |
554 const GenericTransferInfo& transfer = parameters_->transfer_info; | 577 const GenericTransferInfo& transfer = parameters_->transfer_info; |
555 | 578 |
556 UsbDevice::TransferDirection direction; | 579 UsbDevice::TransferDirection direction; |
557 size_t size; | 580 size_t size = 0; |
558 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(transfer); | |
559 | 581 |
560 if (!ConvertDirectionSafely(transfer.direction, &direction)) { | 582 if (!ConvertDirectionSafely(transfer.direction, &direction)) { |
561 AsyncWorkCompleted(); | 583 AsyncWorkCompleted(); |
562 return; | 584 return; |
563 } | 585 } |
564 | 586 |
565 if (!GetTransferSize(transfer, &size) || !buffer) { | 587 if (!GetTransferSize(transfer, &size)) { |
| 588 CompleteWithError(kErrorInvalidTransferLength); |
| 589 return; |
| 590 } |
| 591 |
| 592 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer( |
| 593 transfer, direction, size); |
| 594 if (!buffer) { |
566 CompleteWithError(kErrorMalformedParameters); | 595 CompleteWithError(kErrorMalformedParameters); |
567 return; | 596 return; |
568 } | 597 } |
569 | 598 |
570 device->device()->InterruptTransfer(direction, transfer.endpoint, buffer, | 599 device->device()->InterruptTransfer(direction, transfer.endpoint, buffer, |
571 size, 0, base::Bind(&UsbInterruptTransferFunction::OnCompleted, this)); | 600 size, 0, base::Bind(&UsbInterruptTransferFunction::OnCompleted, this)); |
572 } | 601 } |
573 | 602 |
574 UsbIsochronousTransferFunction::UsbIsochronousTransferFunction() {} | 603 UsbIsochronousTransferFunction::UsbIsochronousTransferFunction() {} |
575 | 604 |
576 UsbIsochronousTransferFunction::~UsbIsochronousTransferFunction() {} | 605 UsbIsochronousTransferFunction::~UsbIsochronousTransferFunction() {} |
577 | 606 |
578 bool UsbIsochronousTransferFunction::Prepare() { | 607 bool UsbIsochronousTransferFunction::Prepare() { |
579 parameters_ = IsochronousTransfer::Params::Create(*args_); | 608 parameters_ = IsochronousTransfer::Params::Create(*args_); |
580 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | 609 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); |
581 return true; | 610 return true; |
582 } | 611 } |
583 | 612 |
584 void UsbIsochronousTransferFunction::AsyncWorkStart() { | 613 void UsbIsochronousTransferFunction::AsyncWorkStart() { |
585 UsbDeviceResource* const device = GetUsbDeviceResource( | 614 UsbDeviceResource* const device = GetUsbDeviceResource( |
586 parameters_->device.handle); | 615 parameters_->device.handle); |
587 if (!device) { | 616 if (!device) { |
588 CompleteWithError(kErrorNoDevice); | 617 CompleteWithError(kErrorNoDevice); |
589 return; | 618 return; |
590 } | 619 } |
591 | 620 |
592 const IsochronousTransferInfo& transfer = parameters_->transfer_info; | 621 const IsochronousTransferInfo& transfer = parameters_->transfer_info; |
593 const GenericTransferInfo& generic_transfer = transfer.transfer_info; | 622 const GenericTransferInfo& generic_transfer = transfer.transfer_info; |
594 | 623 |
595 size_t size; | 624 size_t size = 0; |
596 UsbDevice::TransferDirection direction; | 625 UsbDevice::TransferDirection direction; |
597 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer( | |
598 generic_transfer); | |
599 | 626 |
600 if (!ConvertDirectionSafely(generic_transfer.direction, &direction)) { | 627 if (!ConvertDirectionSafely(generic_transfer.direction, &direction)) { |
601 AsyncWorkCompleted(); | 628 AsyncWorkCompleted(); |
602 return; | 629 return; |
603 } | 630 } |
604 | 631 |
605 if (!GetTransferSize(generic_transfer, &size) || !buffer) { | 632 if (!GetTransferSize(generic_transfer, &size)) { |
606 CompleteWithError(kErrorNoDevice); | 633 CompleteWithError(kErrorInvalidTransferLength); |
| 634 return; |
| 635 } |
| 636 |
| 637 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer( |
| 638 generic_transfer, direction, size); |
| 639 if (!buffer) { |
| 640 CompleteWithError(kErrorMalformedParameters); |
607 return; | 641 return; |
608 } | 642 } |
609 | 643 |
610 device->device()->IsochronousTransfer(direction, generic_transfer.endpoint, | 644 device->device()->IsochronousTransfer(direction, generic_transfer.endpoint, |
611 buffer, size, transfer.packets, transfer.packet_length, 0, base::Bind( | 645 buffer, size, transfer.packets, transfer.packet_length, 0, base::Bind( |
612 &UsbIsochronousTransferFunction::OnCompleted, this)); | 646 &UsbIsochronousTransferFunction::OnCompleted, this)); |
613 } | 647 } |
614 | 648 |
615 } // namespace extensions | 649 } // namespace extensions |
OLD | NEW |