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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/extensions/api/usb/usb_api.h" 6 7 #include <string> 8 #include <vector> 9 10 #include "base/memory/scoped_ptr.h" 11 #include "chrome/browser/extensions/api/usb/usb_device_resource.h" 12 #include "chrome/browser/extensions/extension_system.h" 13 #include "chrome/browser/profiles/profile.h" 14 #include "chrome/browser/usb/usb_device_handle.h" 15 #include "chrome/browser/usb/usb_service.h" 16 #include "chrome/common/extensions/api/usb.h" 17 #include "chrome/common/extensions/permissions/permissions_data.h" 18 #include "chrome/common/extensions/permissions/usb_device_permission.h" 19 20 namespace BulkTransfer = extensions::api::usb::BulkTransfer; 21 namespace ClaimInterface = extensions::api::usb::ClaimInterface; 22 namespace ListInterfaces = extensions::api::usb::ListInterfaces; 23 namespace CloseDevice = extensions::api::usb::CloseDevice; 24 namespace ControlTransfer = extensions::api::usb::ControlTransfer; 25 namespace FindDevices = extensions::api::usb::FindDevices; 26 namespace InterruptTransfer = extensions::api::usb::InterruptTransfer; 27 namespace IsochronousTransfer = extensions::api::usb::IsochronousTransfer; 28 namespace ReleaseInterface = extensions::api::usb::ReleaseInterface; 29 namespace ResetDevice = extensions::api::usb::ResetDevice; 30 namespace SetInterfaceAlternateSetting = 31 extensions::api::usb::SetInterfaceAlternateSetting; 32 namespace usb = extensions::api::usb; 33 34 using content::BrowserThread; 35 using std::string; 36 using std::vector; 37 using usb::ControlTransferInfo; 38 using usb::Device; 39 using usb::Direction; 40 using usb::EndpointDescriptor; 41 using usb::GenericTransferInfo; 42 using usb::InterfaceDescriptor; 43 using usb::IsochronousTransferInfo; 44 using usb::Recipient; 45 using usb::RequestType; 46 using usb::SynchronizationType; 47 using usb::TransferType; 48 using usb::UsageType; 49 50 namespace { 51 52 static const char kDataKey[] = "data"; 53 static const char kResultCodeKey[] = "resultCode"; 54 55 static const char kErrorCancelled[] = "Transfer was cancelled."; 56 static const char kErrorDisconnect[] = "Device disconnected."; 57 static const char kErrorGeneric[] = "Transfer failed."; 58 static const char kErrorOverflow[] = "Inbound transfer overflow."; 59 static const char kErrorStalled[] = "Transfer stalled."; 60 static const char kErrorTimeout[] = "Transfer timed out."; 61 static const char kErrorTransferLength[] = "Transfer length is insufficient."; 62 63 static const char kErrorCannotListInterfaces[] = "Error listing interfaces."; 64 static const char kErrorCannotClaimInterface[] = "Error claiming interface."; 65 static const char kErrorCannotReleaseInterface[] = "Error releasing interface."; 66 static const char kErrorCannotSetInterfaceAlternateSetting[] = 67 "Error setting alternate interface setting."; 68 static const char kErrorConvertDirection[] = "Invalid transfer direction."; 69 static const char kErrorConvertRecipient[] = "Invalid transfer recipient."; 70 static const char kErrorConvertRequestType[] = "Invalid request type."; 71 static const char kErrorConvertSynchronizationType[] = 72 "Invalid synchronization type"; 73 static const char kErrorConvertTransferType[] = "Invalid endpoint type."; 74 static const char kErrorConvertUsageType[] = "Invalid usage type."; 75 static const char kErrorMalformedParameters[] = "Error parsing parameters."; 76 static const char kErrorNoDevice[] = "No such device."; 77 static const char kErrorPermissionDenied[] = 78 "Permission to access device was denied"; 79 static const char kErrorInvalidTransferLength[] = "Transfer length must be a " 80 "positive number less than 104,857,600."; 81 static const char kErrorInvalidNumberOfPackets[] = "Number of packets must be " 82 "a positive number less than 4,194,304."; 83 static const char kErrorInvalidPacketLength[] = "Packet length must be a " 84 "positive number less than 65,536."; 85 static const char kErrorResetDevice[] = 86 "Error resetting the device. The device has been closed."; 87 88 static const size_t kMaxTransferLength = 100 * 1024 * 1024; 89 static const int kMaxPackets = 4 * 1024 * 1024; 90 static const int kMaxPacketLength = 64 * 1024; 91 92 static UsbDevice* device_for_test_ = NULL; 93 94 static bool ConvertDirectionToApi(const UsbEndpointDirection& input, 95 Direction* output) { 96 switch (input) { 97 case USB_DIRECTION_INBOUND: 98 *output = usb::DIRECTION_IN; 99 return true; 100 case USB_DIRECTION_OUTBOUND: 101 *output = usb::DIRECTION_OUT; 102 return true; 103 default: 104 NOTREACHED(); 105 return false; 106 } 107 } 108 109 static bool ConvertSynchronizationTypeToApi( 110 const UsbSynchronizationType& input, 111 extensions::api::usb::SynchronizationType* output) { 112 switch (input) { 113 case USB_SYNCHRONIZATION_NONE: 114 *output = usb::SYNCHRONIZATION_TYPE_NONE; 115 return true; 116 case USB_SYNCHRONIZATION_ASYNCHRONOUS: 117 *output = usb::SYNCHRONIZATION_TYPE_ASYNCHRONOUS; 118 return true; 119 case USB_SYNCHRONIZATION_ADAPTIVE: 120 *output = usb::SYNCHRONIZATION_TYPE_ADAPTIVE; 121 return true; 122 case USB_SYNCHRONIZATION_SYNCHRONOUS: 123 *output = usb::SYNCHRONIZATION_TYPE_SYNCHRONOUS; 124 return true; 125 default: 126 NOTREACHED(); 127 return false; 128 } 129 } 130 131 static bool ConvertTransferTypeToApi( 132 const UsbTransferType& input, 133 extensions::api::usb::TransferType* output) { 134 switch (input) { 135 case USB_TRANSFER_CONTROL: 136 *output = usb::TRANSFER_TYPE_CONTROL; 137 return true; 138 case USB_TRANSFER_INTERRUPT: 139 *output = usb::TRANSFER_TYPE_INTERRUPT; 140 return true; 141 case USB_TRANSFER_ISOCHRONOUS: 142 *output = usb::TRANSFER_TYPE_ISOCHRONOUS; 143 return true; 144 case USB_TRANSFER_BULK: 145 *output = usb::TRANSFER_TYPE_BULK; 146 return true; 147 default: 148 NOTREACHED(); 149 return false; 150 } 151 } 152 153 static bool ConvertUsageTypeToApi(const UsbUsageType& input, 154 extensions::api::usb::UsageType* output) { 155 switch (input) { 156 case USB_USAGE_DATA: 157 *output = usb::USAGE_TYPE_DATA; 158 return true; 159 case USB_USAGE_FEEDBACK: 160 *output = usb::USAGE_TYPE_FEEDBACK; 161 return true; 162 case USB_USAGE_EXPLICIT_FEEDBACK: 163 *output = usb::USAGE_TYPE_EXPLICITFEEDBACK; 164 return true; 165 default: 166 NOTREACHED(); 167 return false; 168 } 169 } 170 171 static bool ConvertDirection(const Direction& input, 172 UsbEndpointDirection* output) { 173 switch (input) { 174 case usb::DIRECTION_IN: 175 *output = USB_DIRECTION_INBOUND; 176 return true; 177 case usb::DIRECTION_OUT: 178 *output = USB_DIRECTION_OUTBOUND; 179 return true; 180 default: 181 NOTREACHED(); 182 return false; 183 } 184 } 185 186 static bool ConvertRequestType(const RequestType& input, 187 UsbDeviceHandle::TransferRequestType* output) { 188 switch (input) { 189 case usb::REQUEST_TYPE_STANDARD: 190 *output = UsbDeviceHandle::STANDARD; 191 return true; 192 case usb::REQUEST_TYPE_CLASS: 193 *output = UsbDeviceHandle::CLASS; 194 return true; 195 case usb::REQUEST_TYPE_VENDOR: 196 *output = UsbDeviceHandle::VENDOR; 197 return true; 198 case usb::REQUEST_TYPE_RESERVED: 199 *output = UsbDeviceHandle::RESERVED; 200 return true; 201 default: 202 NOTREACHED(); 203 return false; 204 } 205 } 206 207 static bool ConvertRecipient(const Recipient& input, 208 UsbDeviceHandle::TransferRecipient* output) { 209 switch (input) { 210 case usb::RECIPIENT_DEVICE: 211 *output = UsbDeviceHandle::DEVICE; 212 return true; 213 case usb::RECIPIENT_INTERFACE: 214 *output = UsbDeviceHandle::INTERFACE; 215 return true; 216 case usb::RECIPIENT_ENDPOINT: 217 *output = UsbDeviceHandle::ENDPOINT; 218 return true; 219 case usb::RECIPIENT_OTHER: 220 *output = UsbDeviceHandle::OTHER; 221 return true; 222 default: 223 NOTREACHED(); 224 return false; 225 } 226 } 227 228 template<class T> 229 static bool GetTransferSize(const T& input, size_t* output) { 230 if (input.direction == usb::DIRECTION_IN) { 231 const int* length = input.length.get(); 232 if (length && *length >= 0 && 233 static_cast<size_t>(*length) < kMaxTransferLength) { 234 *output = *length; 235 return true; 236 } 237 } else if (input.direction == usb::DIRECTION_OUT) { 238 if (input.data.get()) { 239 *output = input.data->size(); 240 return true; 241 } 242 } 243 return false; 244 } 245 246 template<class T> 247 static scoped_refptr<net::IOBuffer> CreateBufferForTransfer( 248 const T& input, UsbEndpointDirection direction, size_t size) { 249 250 if (size >= kMaxTransferLength) 251 return NULL; 252 253 // Allocate a |size|-bytes buffer, or a one-byte buffer if |size| is 0. This 254 // is due to an impedance mismatch between IOBuffer and URBs. An IOBuffer 255 // cannot represent a zero-length buffer, while an URB can. 256 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(std::max( 257 static_cast<size_t>(1), size)); 258 259 if (direction == USB_DIRECTION_INBOUND) { 260 return buffer; 261 } else if (direction == USB_DIRECTION_OUTBOUND) { 262 if (input.data.get() && size <= input.data->size()) { 263 memcpy(buffer->data(), input.data->data(), size); 264 return buffer; 265 } 266 } 267 NOTREACHED(); 268 return NULL; 269 } 270 271 static const char* ConvertTransferStatusToErrorString( 272 const UsbTransferStatus status) { 273 switch (status) { 274 case USB_TRANSFER_COMPLETED: 275 return ""; 276 case USB_TRANSFER_ERROR: 277 return kErrorGeneric; 278 case USB_TRANSFER_TIMEOUT: 279 return kErrorTimeout; 280 case USB_TRANSFER_CANCELLED: 281 return kErrorCancelled; 282 case USB_TRANSFER_STALLED: 283 return kErrorStalled; 284 case USB_TRANSFER_DISCONNECT: 285 return kErrorDisconnect; 286 case USB_TRANSFER_OVERFLOW: 287 return kErrorOverflow; 288 case USB_TRANSFER_LENGTH_SHORT: 289 return kErrorTransferLength; 290 default: 291 NOTREACHED(); 292 return ""; 293 } 294 } 295 296 static base::DictionaryValue* CreateTransferInfo( 297 UsbTransferStatus status, 298 scoped_refptr<net::IOBuffer> data, 299 size_t length) { 300 base::DictionaryValue* result = new base::DictionaryValue(); 301 result->SetInteger(kResultCodeKey, status); 302 result->Set(kDataKey, base::BinaryValue::CreateWithCopiedBuffer(data->data(), 303 length)); 304 return result; 305 } 306 307 static base::Value* PopulateDevice(int handle, int vendor_id, int product_id) { 308 Device device; 309 device.handle = handle; 310 device.vendor_id = vendor_id; 311 device.product_id = product_id; 312 return device.ToValue().release(); 313 } 314 315 static base::Value* PopulateInterfaceDescriptor(int interface_number, 316 int alternate_setting, int interface_class, int interface_subclass, 317 int interface_protocol, 318 std::vector<linked_ptr<EndpointDescriptor> >* endpoints) { 319 InterfaceDescriptor descriptor; 320 descriptor.interface_number = interface_number; 321 descriptor.alternate_setting = alternate_setting; 322 descriptor.interface_class = interface_class; 323 descriptor.interface_subclass = interface_subclass; 324 descriptor.interface_protocol = interface_protocol; 325 descriptor.endpoints = *endpoints; 326 return descriptor.ToValue().release(); 327 } 328 329 void GetUsbService(base::Callback<void(UsbService* service)> callback) { 330 BrowserThread::PostTaskAndReplyWithResult( 331 BrowserThread::FILE, 332 FROM_HERE, 333 base::Bind(UsbService::GetInstance), 334 callback); 335 } 336 337 } // namespace 338 339 namespace extensions { 340 341 UsbAsyncApiFunction::UsbAsyncApiFunction() 342 : manager_(NULL) { 343 } 344 345 UsbAsyncApiFunction::~UsbAsyncApiFunction() { 346 } 347 348 bool UsbAsyncApiFunction::PrePrepare() { 349 manager_ = ApiResourceManager<UsbDeviceResource>::Get(profile()); 350 return manager_ != NULL; 351 } 352 353 bool UsbAsyncApiFunction::Respond() { 354 return error_.empty(); 355 } 356 357 UsbDeviceResource* UsbAsyncApiFunction::GetUsbDeviceResource( 358 int api_resource_id) { 359 return manager_->Get(extension_->id(), api_resource_id); 360 } 361 362 void UsbAsyncApiFunction::RemoveUsbDeviceResource(int api_resource_id) { 363 manager_->Remove(extension_->id(), api_resource_id); 364 } 365 366 void UsbAsyncApiFunction::CompleteWithError(const std::string& error) { 367 SetError(error); 368 AsyncWorkCompleted(); 369 } 370 371 UsbAsyncApiTransferFunction::UsbAsyncApiTransferFunction() {} 372 373 UsbAsyncApiTransferFunction::~UsbAsyncApiTransferFunction() {} 374 375 void UsbAsyncApiTransferFunction::OnCompleted(UsbTransferStatus status, 376 scoped_refptr<net::IOBuffer> data, 377 size_t length) { 378 if (status != USB_TRANSFER_COMPLETED) 379 SetError(ConvertTransferStatusToErrorString(status)); 380 381 SetResult(CreateTransferInfo(status, data, length)); 382 AsyncWorkCompleted(); 383 } 384 385 bool UsbAsyncApiTransferFunction::ConvertDirectionSafely( 386 const Direction& input, UsbEndpointDirection* output) { 387 const bool converted = ConvertDirection(input, output); 388 if (!converted) 389 SetError(kErrorConvertDirection); 390 return converted; 391 } 392 393 bool UsbAsyncApiTransferFunction::ConvertRequestTypeSafely( 394 const RequestType& input, UsbDeviceHandle::TransferRequestType* output) { 395 const bool converted = ConvertRequestType(input, output); 396 if (!converted) 397 SetError(kErrorConvertRequestType); 398 return converted; 399 } 400 401 bool UsbAsyncApiTransferFunction::ConvertRecipientSafely( 402 const Recipient& input, UsbDeviceHandle::TransferRecipient* output) { 403 const bool converted = ConvertRecipient(input, output); 404 if (!converted) 405 SetError(kErrorConvertRecipient); 406 return converted; 407 } 408 409 UsbFindDevicesFunction::UsbFindDevicesFunction() {} 410 411 UsbFindDevicesFunction::~UsbFindDevicesFunction() {} 412 413 void UsbFindDevicesFunction::SetDeviceForTest(UsbDevice* device) { 414 device_for_test_ = device; 415 } 416 417 bool UsbFindDevicesFunction::Prepare() { 418 parameters_ = FindDevices::Params::Create(*args_); 419 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); 420 return true; 421 } 422 423 void UsbFindDevicesFunction::AsyncWorkStart() { 424 result_.reset(new base::ListValue()); 425 426 if (device_for_test_) { 427 UsbDeviceResource* const resource = new UsbDeviceResource( 428 extension_->id(), 429 device_for_test_->Open()); 430 431 Device device; 432 result_->Append(PopulateDevice(manager_->Add(resource), 0, 0)); 433 SetResult(result_.release()); 434 AsyncWorkCompleted(); 435 return; 436 } 437 438 const uint16_t vendor_id = parameters_->options.vendor_id; 439 const uint16_t product_id = parameters_->options.product_id; 440 int interface_id = parameters_->options.interface_id.get() ? 441 *parameters_->options.interface_id.get() : 442 UsbDevicePermissionData::ANY_INTERFACE; 443 UsbDevicePermission::CheckParam param(vendor_id, product_id, interface_id); 444 if (!PermissionsData::CheckAPIPermissionWithParam( 445 GetExtension(), APIPermission::kUsbDevice, ¶m)) { 446 LOG(WARNING) << "Insufficient permissions to access device."; 447 CompleteWithError(kErrorPermissionDenied); 448 return; 449 } 450 451 GetUsbService(base::Bind(&UsbFindDevicesFunction::EnumerateDevices, 452 this, 453 vendor_id, 454 product_id, 455 interface_id)); 456 } 457 458 void UsbFindDevicesFunction::EnumerateDevices( 459 uint16_t vendor_id, 460 uint16_t product_id, 461 int interface_id, 462 UsbService* service) { 463 BrowserThread::PostTask( 464 BrowserThread::FILE, 465 FROM_HERE, 466 base::Bind(&UsbService::FindDevices, 467 base::Unretained(service), 468 vendor_id, 469 product_id, 470 interface_id, 471 base::Bind(&UsbFindDevicesFunction::OnEnumerationCompleted, 472 this))); 473 } 474 475 void UsbFindDevicesFunction::OnEnumerationCompleted( 476 ScopedDeviceVector devices) { 477 for (size_t i = 0; i < devices->size(); ++i) { 478 scoped_refptr<UsbDeviceHandle> device_handle = 479 devices->at(i)->Open(); 480 if (device_handle) 481 device_handles_.push_back(device_handle); 482 } 483 484 BrowserThread::PostTask( 485 BrowserThread::IO, 486 FROM_HERE, 487 base::Bind(&UsbFindDevicesFunction::OnCompleted, this)); 488 } 489 490 void UsbFindDevicesFunction::OnCompleted() { 491 for (size_t i = 0; i < device_handles_.size(); ++i) { 492 UsbDeviceHandle* const device_handle = device_handles_[i].get(); 493 UsbDeviceResource* const resource = 494 new UsbDeviceResource(extension_->id(), device_handle); 495 496 result_->Append(PopulateDevice(manager_->Add(resource), 497 parameters_->options.vendor_id, 498 parameters_->options.product_id)); 499 } 500 501 SetResult(result_.release()); 502 AsyncWorkCompleted(); 503 } 504 505 UsbListInterfacesFunction::UsbListInterfacesFunction() {} 506 507 UsbListInterfacesFunction::~UsbListInterfacesFunction() {} 508 509 bool UsbListInterfacesFunction::Prepare() { 510 parameters_ = ListInterfaces::Params::Create(*args_); 511 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); 512 return true; 513 } 514 515 void UsbListInterfacesFunction::AsyncWorkStart() { 516 UsbDeviceResource* const resource = GetUsbDeviceResource( 517 parameters_->device.handle); 518 if (!resource) { 519 CompleteWithError(kErrorNoDevice); 520 return; 521 } 522 523 config_ = new UsbConfigDescriptor(); 524 BrowserThread::PostTaskAndReplyWithResult( 525 BrowserThread::FILE, 526 FROM_HERE, 527 base::Bind(&UsbDevice::ListInterfaces, 528 resource->device()->device(), 529 config_), 530 base::Bind(&UsbListInterfacesFunction::OnCompleted, this)); 531 } 532 533 void UsbListInterfacesFunction::OnCompleted(bool success) { 534 if (!success) { 535 SetError(kErrorCannotListInterfaces); 536 AsyncWorkCompleted(); 537 return; 538 } 539 540 result_.reset(new base::ListValue()); 541 542 for (size_t i = 0, numInterfaces = config_->GetNumInterfaces(); 543 i < numInterfaces; ++i) { 544 scoped_refptr<const UsbInterface> usbInterface(config_->GetInterface(i)); 545 for (size_t j = 0, numDescriptors = usbInterface->GetNumAltSettings(); 546 j < numDescriptors; ++j) { 547 scoped_refptr<const UsbInterfaceDescriptor> descriptor 548 = usbInterface->GetAltSetting(j); 549 std::vector<linked_ptr<EndpointDescriptor> > endpoints; 550 for (size_t k = 0, numEndpoints = descriptor->GetNumEndpoints(); 551 k < numEndpoints; k++) { 552 scoped_refptr<const UsbEndpointDescriptor> endpoint 553 = descriptor->GetEndpoint(k); 554 linked_ptr<EndpointDescriptor> endpoint_desc(new EndpointDescriptor()); 555 556 TransferType type; 557 Direction direction; 558 SynchronizationType synchronization; 559 UsageType usage; 560 561 if (!ConvertTransferTypeSafely(endpoint->GetTransferType(), &type) || 562 !ConvertDirectionSafely(endpoint->GetDirection(), &direction) || 563 !ConvertSynchronizationTypeSafely( 564 endpoint->GetSynchronizationType(), &synchronization) || 565 !ConvertUsageTypeSafely(endpoint->GetUsageType(), &usage)) { 566 SetError(kErrorCannotListInterfaces); 567 AsyncWorkCompleted(); 568 return; 569 } 570 571 endpoint_desc->address = endpoint->GetAddress(); 572 endpoint_desc->type = type; 573 endpoint_desc->direction = direction; 574 endpoint_desc->maximum_packet_size = endpoint->GetMaximumPacketSize(); 575 endpoint_desc->synchronization = synchronization; 576 endpoint_desc->usage = usage; 577 578 int* polling_interval = new int; 579 endpoint_desc->polling_interval.reset(polling_interval); 580 *polling_interval = endpoint->GetPollingInterval(); 581 582 endpoints.push_back(endpoint_desc); 583 } 584 585 result_->Append(PopulateInterfaceDescriptor( 586 descriptor->GetInterfaceNumber(), 587 descriptor->GetAlternateSetting(), 588 descriptor->GetInterfaceClass(), 589 descriptor->GetInterfaceSubclass(), 590 descriptor->GetInterfaceProtocol(), 591 &endpoints)); 592 } 593 } 594 595 SetResult(result_.release()); 596 AsyncWorkCompleted(); 597 } 598 599 bool UsbListInterfacesFunction::ConvertDirectionSafely( 600 const UsbEndpointDirection& input, 601 extensions::api::usb::Direction* output) { 602 const bool converted = ConvertDirectionToApi(input, output); 603 if (!converted) 604 SetError(kErrorConvertDirection); 605 return converted; 606 } 607 608 bool UsbListInterfacesFunction::ConvertSynchronizationTypeSafely( 609 const UsbSynchronizationType& input, 610 extensions::api::usb::SynchronizationType* output) { 611 const bool converted = ConvertSynchronizationTypeToApi(input, output); 612 if (!converted) 613 SetError(kErrorConvertSynchronizationType); 614 return converted; 615 } 616 617 bool UsbListInterfacesFunction::ConvertTransferTypeSafely( 618 const UsbTransferType& input, 619 extensions::api::usb::TransferType* output) { 620 const bool converted = ConvertTransferTypeToApi(input, output); 621 if (!converted) 622 SetError(kErrorConvertTransferType); 623 return converted; 624 } 625 626 bool UsbListInterfacesFunction::ConvertUsageTypeSafely( 627 const UsbUsageType& input, 628 extensions::api::usb::UsageType* output) { 629 const bool converted = ConvertUsageTypeToApi(input, output); 630 if (!converted) 631 SetError(kErrorConvertUsageType); 632 return converted; 633 } 634 635 UsbCloseDeviceFunction::UsbCloseDeviceFunction() {} 636 637 UsbCloseDeviceFunction::~UsbCloseDeviceFunction() {} 638 639 bool UsbCloseDeviceFunction::Prepare() { 640 parameters_ = CloseDevice::Params::Create(*args_); 641 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); 642 return true; 643 } 644 645 void UsbCloseDeviceFunction::AsyncWorkStart() { 646 UsbDeviceResource* const resource = GetUsbDeviceResource( 647 parameters_->device.handle); 648 if (!resource) { 649 CompleteWithError(kErrorNoDevice); 650 return; 651 } 652 653 BrowserThread::PostTaskAndReply( 654 BrowserThread::FILE, 655 FROM_HERE, 656 base::Bind(&UsbDeviceHandle::Close, resource->device()), 657 base::Bind(&UsbCloseDeviceFunction::OnCompleted, this)); 658 } 659 660 void UsbCloseDeviceFunction::OnCompleted() { 661 RemoveUsbDeviceResource(parameters_->device.handle); 662 AsyncWorkCompleted(); 663 } 664 665 UsbClaimInterfaceFunction::UsbClaimInterfaceFunction() {} 666 667 UsbClaimInterfaceFunction::~UsbClaimInterfaceFunction() {} 668 669 bool UsbClaimInterfaceFunction::Prepare() { 670 parameters_ = ClaimInterface::Params::Create(*args_); 671 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); 672 return true; 673 } 674 675 void UsbClaimInterfaceFunction::AsyncWorkStart() { 676 UsbDeviceResource* resource = 677 GetUsbDeviceResource(parameters_->device.handle); 678 if (!resource) { 679 CompleteWithError(kErrorNoDevice); 680 return; 681 } 682 683 BrowserThread::PostTaskAndReplyWithResult( 684 BrowserThread::FILE, 685 FROM_HERE, 686 base::Bind(&UsbDeviceHandle::ClaimInterface, 687 resource->device(), 688 parameters_->interface_number), 689 base::Bind(&UsbClaimInterfaceFunction::OnCompleted, this)); 690 } 691 692 void UsbClaimInterfaceFunction::OnCompleted(bool success) { 693 if (!success) 694 SetError(kErrorCannotClaimInterface); 695 AsyncWorkCompleted(); 696 } 697 698 UsbReleaseInterfaceFunction::UsbReleaseInterfaceFunction() {} 699 700 UsbReleaseInterfaceFunction::~UsbReleaseInterfaceFunction() {} 701 702 bool UsbReleaseInterfaceFunction::Prepare() { 703 parameters_ = ReleaseInterface::Params::Create(*args_); 704 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); 705 return true; 706 } 707 708 void UsbReleaseInterfaceFunction::AsyncWorkStart() { 709 UsbDeviceResource* resource = 710 GetUsbDeviceResource(parameters_->device.handle); 711 if (!resource) { 712 CompleteWithError(kErrorNoDevice); 713 return; 714 } 715 716 BrowserThread::PostTaskAndReplyWithResult( 717 BrowserThread::FILE, 718 FROM_HERE, 719 base::Bind(&UsbDeviceHandle::ReleaseInterface, 720 resource->device(), 721 parameters_->interface_number), 722 base::Bind(&UsbReleaseInterfaceFunction::OnCompleted, this)); 723 } 724 725 void UsbReleaseInterfaceFunction::OnCompleted(bool success) { 726 if (!success) 727 SetError(kErrorCannotReleaseInterface); 728 AsyncWorkCompleted(); 729 } 730 731 UsbSetInterfaceAlternateSettingFunction:: 732 UsbSetInterfaceAlternateSettingFunction() {} 733 734 UsbSetInterfaceAlternateSettingFunction:: 735 ~UsbSetInterfaceAlternateSettingFunction() {} 736 737 bool UsbSetInterfaceAlternateSettingFunction::Prepare() { 738 parameters_ = SetInterfaceAlternateSetting::Params::Create(*args_); 739 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); 740 return true; 741 } 742 743 void UsbSetInterfaceAlternateSettingFunction::AsyncWorkStart() { 744 UsbDeviceResource* resource = 745 GetUsbDeviceResource(parameters_->device.handle); 746 if (!resource) { 747 CompleteWithError(kErrorNoDevice); 748 return; 749 } 750 751 BrowserThread::PostTaskAndReplyWithResult( 752 BrowserThread::FILE, 753 FROM_HERE, 754 base::Bind(&UsbDeviceHandle::SetInterfaceAlternateSetting, 755 resource->device(), 756 parameters_->interface_number, 757 parameters_->alternate_setting), 758 base::Bind(&UsbSetInterfaceAlternateSettingFunction::OnCompleted, this)); 759 } 760 761 void UsbSetInterfaceAlternateSettingFunction::OnCompleted(bool success) { 762 if (!success) 763 SetError(kErrorCannotSetInterfaceAlternateSetting); 764 AsyncWorkCompleted(); 765 } 766 767 UsbControlTransferFunction::UsbControlTransferFunction() {} 768 769 UsbControlTransferFunction::~UsbControlTransferFunction() {} 770 771 bool UsbControlTransferFunction::Prepare() { 772 parameters_ = ControlTransfer::Params::Create(*args_); 773 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); 774 return true; 775 } 776 777 void UsbControlTransferFunction::AsyncWorkStart() { 778 UsbDeviceResource* const resource = GetUsbDeviceResource( 779 parameters_->device.handle); 780 if (!resource) { 781 CompleteWithError(kErrorNoDevice); 782 return; 783 } 784 785 const ControlTransferInfo& transfer = parameters_->transfer_info; 786 787 UsbEndpointDirection direction; 788 UsbDeviceHandle::TransferRequestType request_type; 789 UsbDeviceHandle::TransferRecipient recipient; 790 size_t size = 0; 791 792 if (!ConvertDirectionSafely(transfer.direction, &direction) || 793 !ConvertRequestTypeSafely(transfer.request_type, &request_type) || 794 !ConvertRecipientSafely(transfer.recipient, &recipient)) { 795 AsyncWorkCompleted(); 796 return; 797 } 798 799 if (!GetTransferSize(transfer, &size)) { 800 CompleteWithError(kErrorInvalidTransferLength); 801 return; 802 } 803 804 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer( 805 transfer, direction, size); 806 if (!buffer.get()) { 807 CompleteWithError(kErrorMalformedParameters); 808 return; 809 } 810 811 resource->device()->ControlTransfer( 812 direction, 813 request_type, 814 recipient, 815 transfer.request, 816 transfer.value, 817 transfer.index, 818 buffer.get(), 819 size, 820 0, 821 base::Bind(&UsbControlTransferFunction::OnCompleted, this)); 822 } 823 824 UsbBulkTransferFunction::UsbBulkTransferFunction() {} 825 826 UsbBulkTransferFunction::~UsbBulkTransferFunction() {} 827 828 bool UsbBulkTransferFunction::Prepare() { 829 parameters_ = BulkTransfer::Params::Create(*args_); 830 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); 831 return true; 832 } 833 834 void UsbBulkTransferFunction::AsyncWorkStart() { 835 UsbDeviceResource* const resource = GetUsbDeviceResource( 836 parameters_->device.handle); 837 if (!resource) { 838 CompleteWithError(kErrorNoDevice); 839 return; 840 } 841 842 const GenericTransferInfo& transfer = parameters_->transfer_info; 843 844 UsbEndpointDirection direction; 845 size_t size = 0; 846 847 if (!ConvertDirectionSafely(transfer.direction, &direction)) { 848 AsyncWorkCompleted(); 849 return; 850 } 851 852 if (!GetTransferSize(transfer, &size)) { 853 CompleteWithError(kErrorInvalidTransferLength); 854 return; 855 } 856 857 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer( 858 transfer, direction, size); 859 if (!buffer.get()) { 860 CompleteWithError(kErrorMalformedParameters); 861 return; 862 } 863 864 resource->device() 865 ->BulkTransfer(direction, 866 transfer.endpoint, 867 buffer.get(), 868 size, 869 0, 870 base::Bind(&UsbBulkTransferFunction::OnCompleted, this)); 871 } 872 873 UsbInterruptTransferFunction::UsbInterruptTransferFunction() {} 874 875 UsbInterruptTransferFunction::~UsbInterruptTransferFunction() {} 876 877 bool UsbInterruptTransferFunction::Prepare() { 878 parameters_ = InterruptTransfer::Params::Create(*args_); 879 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); 880 return true; 881 } 882 883 void UsbInterruptTransferFunction::AsyncWorkStart() { 884 UsbDeviceResource* const resource = GetUsbDeviceResource( 885 parameters_->device.handle); 886 if (!resource) { 887 CompleteWithError(kErrorNoDevice); 888 return; 889 } 890 891 const GenericTransferInfo& transfer = parameters_->transfer_info; 892 893 UsbEndpointDirection direction; 894 size_t size = 0; 895 896 if (!ConvertDirectionSafely(transfer.direction, &direction)) { 897 AsyncWorkCompleted(); 898 return; 899 } 900 901 if (!GetTransferSize(transfer, &size)) { 902 CompleteWithError(kErrorInvalidTransferLength); 903 return; 904 } 905 906 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer( 907 transfer, direction, size); 908 if (!buffer.get()) { 909 CompleteWithError(kErrorMalformedParameters); 910 return; 911 } 912 913 resource->device()->InterruptTransfer( 914 direction, 915 transfer.endpoint, 916 buffer.get(), 917 size, 918 0, 919 base::Bind(&UsbInterruptTransferFunction::OnCompleted, this)); 920 } 921 922 UsbIsochronousTransferFunction::UsbIsochronousTransferFunction() {} 923 924 UsbIsochronousTransferFunction::~UsbIsochronousTransferFunction() {} 925 926 bool UsbIsochronousTransferFunction::Prepare() { 927 parameters_ = IsochronousTransfer::Params::Create(*args_); 928 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); 929 return true; 930 } 931 932 void UsbIsochronousTransferFunction::AsyncWorkStart() { 933 UsbDeviceResource* const resource = GetUsbDeviceResource( 934 parameters_->device.handle); 935 if (!resource) { 936 CompleteWithError(kErrorNoDevice); 937 return; 938 } 939 940 const IsochronousTransferInfo& transfer = parameters_->transfer_info; 941 const GenericTransferInfo& generic_transfer = transfer.transfer_info; 942 943 size_t size = 0; 944 UsbEndpointDirection direction; 945 946 if (!ConvertDirectionSafely(generic_transfer.direction, &direction)) { 947 AsyncWorkCompleted(); 948 return; 949 } 950 if (!GetTransferSize(generic_transfer, &size)) { 951 CompleteWithError(kErrorInvalidTransferLength); 952 return; 953 } 954 if (transfer.packets < 0 || transfer.packets >= kMaxPackets) { 955 CompleteWithError(kErrorInvalidNumberOfPackets); 956 return; 957 } 958 unsigned int packets = transfer.packets; 959 if (transfer.packet_length < 0 || 960 transfer.packet_length >= kMaxPacketLength) { 961 CompleteWithError(kErrorInvalidPacketLength); 962 return; 963 } 964 unsigned int packet_length = transfer.packet_length; 965 const uint64 total_length = packets * packet_length; 966 if (packets > size || total_length > size) { 967 CompleteWithError(kErrorTransferLength); 968 return; 969 } 970 971 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer( 972 generic_transfer, direction, size); 973 if (!buffer.get()) { 974 CompleteWithError(kErrorMalformedParameters); 975 return; 976 } 977 978 resource->device()->IsochronousTransfer( 979 direction, 980 generic_transfer.endpoint, 981 buffer.get(), 982 size, 983 packets, 984 packet_length, 985 0, 986 base::Bind(&UsbIsochronousTransferFunction::OnCompleted, this)); 987 } 988 989 UsbResetDeviceFunction::UsbResetDeviceFunction() {} 990 991 UsbResetDeviceFunction::~UsbResetDeviceFunction() {} 992 993 bool UsbResetDeviceFunction::Prepare() { 994 parameters_ = ResetDevice::Params::Create(*args_); 995 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); 996 return true; 997 } 998 999 void UsbResetDeviceFunction::AsyncWorkStart() { 1000 UsbDeviceResource* const resource = GetUsbDeviceResource( 1001 parameters_->device.handle); 1002 if (!resource) { 1003 CompleteWithError(kErrorNoDevice); 1004 return; 1005 } 1006 1007 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 1008 base::Bind(&UsbResetDeviceFunction::OnStartResest, 1009 this, resource)); 1010 } 1011 1012 void UsbResetDeviceFunction::OnStartResest(UsbDeviceResource* resource) { 1013 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 1014 OnCompletedFileThread(resource->device()->ResetDevice()); 1015 } 1016 1017 void UsbResetDeviceFunction::OnCompletedFileThread(bool success) { 1018 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 1019 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 1020 base::Bind(&UsbResetDeviceFunction::OnCompleted, 1021 this, success)); 1022 return; 1023 } 1024 1025 void UsbResetDeviceFunction::OnCompleted(bool success) { 1026 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1027 if (!success) { 1028 UsbDeviceResource* const resource = GetUsbDeviceResource( 1029 parameters_->device.handle); 1030 if (!resource) { 1031 CompleteWithError(kErrorNoDevice); 1032 return; 1033 } 1034 // Close the device now because the handle is invalid after an 1035 // unsuccessful reset. 1036 BrowserThread::PostTaskAndReply( 1037 BrowserThread::FILE, 1038 FROM_HERE, 1039 base::Bind(&UsbDeviceHandle::Close, 1040 resource->device()), 1041 base::Bind(&UsbResetDeviceFunction::OnError, this)); 1042 return; 1043 } 1044 SetResult(Value::CreateBooleanValue(true)); 1045 AsyncWorkCompleted(); 1046 } 1047 1048 void UsbResetDeviceFunction::OnError() { 1049 RemoveUsbDeviceResource(parameters_->device.handle); 1050 SetError(kErrorResetDevice); 1051 SetResult(Value::CreateBooleanValue(false)); 1052 AsyncWorkCompleted(); 1053 } 1054 1055 } // namespace extensions 1056