| 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 |