15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/usb/usb_api.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/usb/usb_device_resource.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_system.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
14a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "chrome/browser/usb/usb_device_handle.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/usb/usb_service.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/api/usb.h"
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/common/extensions/permissions/permissions_data.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/permissions/usb_device_permission.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace BulkTransfer = extensions::api::usb::BulkTransfer;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ClaimInterface = extensions::api::usb::ClaimInterface;
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace ListInterfaces = extensions::api::usb::ListInterfaces;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace CloseDevice = extensions::api::usb::CloseDevice;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ControlTransfer = extensions::api::usb::ControlTransfer;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace FindDevices = extensions::api::usb::FindDevices;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace InterruptTransfer = extensions::api::usb::InterruptTransfer;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace IsochronousTransfer = extensions::api::usb::IsochronousTransfer;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ReleaseInterface = extensions::api::usb::ReleaseInterface;
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace ResetDevice = extensions::api::usb::ResetDevice;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace SetInterfaceAlternateSetting =
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions::api::usb::SetInterfaceAlternateSetting;
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace usb = extensions::api::usb;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)using content::BrowserThread;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::string;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::vector;
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using usb::ControlTransferInfo;
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using usb::Device;
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using usb::Direction;
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using usb::EndpointDescriptor;
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using usb::GenericTransferInfo;
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using usb::InterfaceDescriptor;
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using usb::IsochronousTransferInfo;
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using usb::Recipient;
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using usb::RequestType;
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using usb::SynchronizationType;
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using usb::TransferType;
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using usb::UsageType;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kDataKey[] = "data";
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kResultCodeKey[] = "resultCode";
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kErrorCancelled[] = "Transfer was cancelled.";
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kErrorDisconnect[] = "Device disconnected.";
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kErrorGeneric[] = "Transfer failed.";
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kErrorOverflow[] = "Inbound transfer overflow.";
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kErrorStalled[] = "Transfer stalled.";
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kErrorTimeout[] = "Transfer timed out.";
61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kErrorTransferLength[] = "Transfer length is insufficient.";
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kErrorCannotListInterfaces[] = "Error listing interfaces.";
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kErrorCannotClaimInterface[] = "Error claiming interface.";
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kErrorCannotReleaseInterface[] = "Error releasing interface.";
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kErrorCannotSetInterfaceAlternateSetting[] =
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Error setting alternate interface setting.";
68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kErrorConvertDirection[] = "Invalid transfer direction.";
69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kErrorConvertRecipient[] = "Invalid transfer recipient.";
70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kErrorConvertRequestType[] = "Invalid request type.";
71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kErrorConvertSynchronizationType[] =
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    "Invalid synchronization type";
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kErrorConvertTransferType[] = "Invalid endpoint type.";
74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kErrorConvertUsageType[] = "Invalid usage type.";
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kErrorMalformedParameters[] = "Error parsing parameters.";
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kErrorNoDevice[] = "No such device.";
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kErrorPermissionDenied[] =
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    "Permission to access device was denied";
79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kErrorInvalidTransferLength[] = "Transfer length must be a "
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    "positive number less than 104,857,600.";
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kErrorInvalidNumberOfPackets[] = "Number of packets must be "
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    "a positive number less than 4,194,304.";
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kErrorInvalidPacketLength[] = "Packet length must be a "
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    "positive number less than 65,536.";
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kErrorResetDevice[] =
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    "Error resetting the device. The device has been closed.";
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const size_t kMaxTransferLength = 100 * 1024 * 1024;
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kMaxPackets = 4 * 1024 * 1024;
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kMaxPacketLength = 64 * 1024;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
924311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdochstatic UsbDevice* device_for_test_ = NULL;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool ConvertDirectionToApi(const UsbEndpointDirection& input,
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                  Direction* output) {
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (input) {
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case USB_DIRECTION_INBOUND:
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *output = usb::DIRECTION_IN;
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case USB_DIRECTION_OUTBOUND:
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *output = usb::DIRECTION_OUT;
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    default:
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      NOTREACHED();
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return false;
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool ConvertSynchronizationTypeToApi(
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const UsbSynchronizationType& input,
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    extensions::api::usb::SynchronizationType* output) {
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (input) {
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case USB_SYNCHRONIZATION_NONE:
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *output = usb::SYNCHRONIZATION_TYPE_NONE;
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case USB_SYNCHRONIZATION_ASYNCHRONOUS:
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *output = usb::SYNCHRONIZATION_TYPE_ASYNCHRONOUS;
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case USB_SYNCHRONIZATION_ADAPTIVE:
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *output = usb::SYNCHRONIZATION_TYPE_ADAPTIVE;
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case USB_SYNCHRONIZATION_SYNCHRONOUS:
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *output = usb::SYNCHRONIZATION_TYPE_SYNCHRONOUS;
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    default:
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      NOTREACHED();
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return false;
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool ConvertTransferTypeToApi(
13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const UsbTransferType& input,
13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    extensions::api::usb::TransferType* output) {
13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (input) {
13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case USB_TRANSFER_CONTROL:
13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *output = usb::TRANSFER_TYPE_CONTROL;
13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case USB_TRANSFER_INTERRUPT:
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *output = usb::TRANSFER_TYPE_INTERRUPT;
14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case USB_TRANSFER_ISOCHRONOUS:
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *output = usb::TRANSFER_TYPE_ISOCHRONOUS;
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case USB_TRANSFER_BULK:
14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *output = usb::TRANSFER_TYPE_BULK;
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    default:
14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      NOTREACHED();
14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return false;
15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool ConvertUsageTypeToApi(const UsbUsageType& input,
15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    extensions::api::usb::UsageType* output) {
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (input) {
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case USB_USAGE_DATA:
15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *output = usb::USAGE_TYPE_DATA;
15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;
15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case USB_USAGE_FEEDBACK:
16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *output = usb::USAGE_TYPE_FEEDBACK;
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;
16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case USB_USAGE_EXPLICIT_FEEDBACK:
16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *output = usb::USAGE_TYPE_EXPLICITFEEDBACK;
16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    default:
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      NOTREACHED();
16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return false;
16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static bool ConvertDirection(const Direction& input,
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             UsbEndpointDirection* output) {
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (input) {
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case usb::DIRECTION_IN:
17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *output = USB_DIRECTION_INBOUND;
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case usb::DIRECTION_OUT:
17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *output = USB_DIRECTION_OUTBOUND;
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      NOTREACHED();
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static bool ConvertRequestType(const RequestType& input,
187a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                               UsbDeviceHandle::TransferRequestType* output) {
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (input) {
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case usb::REQUEST_TYPE_STANDARD:
190a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      *output = UsbDeviceHandle::STANDARD;
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case usb::REQUEST_TYPE_CLASS:
193a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      *output = UsbDeviceHandle::CLASS;
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case usb::REQUEST_TYPE_VENDOR:
196a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      *output = UsbDeviceHandle::VENDOR;
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case usb::REQUEST_TYPE_RESERVED:
199a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      *output = UsbDeviceHandle::RESERVED;
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      NOTREACHED();
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static bool ConvertRecipient(const Recipient& input,
208a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                             UsbDeviceHandle::TransferRecipient* output) {
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (input) {
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case usb::RECIPIENT_DEVICE:
211a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      *output = UsbDeviceHandle::DEVICE;
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case usb::RECIPIENT_INTERFACE:
214a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      *output = UsbDeviceHandle::INTERFACE;
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case usb::RECIPIENT_ENDPOINT:
217a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      *output = UsbDeviceHandle::ENDPOINT;
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case usb::RECIPIENT_OTHER:
220a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      *output = UsbDeviceHandle::OTHER;
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
22390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      NOTREACHED();
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<class T>
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool GetTransferSize(const T& input, size_t* output) {
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (input.direction == usb::DIRECTION_IN) {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int* length = input.length.get();
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (length && *length >= 0 &&
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        static_cast<size_t>(*length) < kMaxTransferLength) {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *output = *length;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (input.direction == usb::DIRECTION_OUT) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (input.data.get()) {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *output = input.data->size();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<class T>
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static scoped_refptr<net::IOBuffer> CreateBufferForTransfer(
24890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const T& input, UsbEndpointDirection direction, size_t size) {
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (size >= kMaxTransferLength)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate a |size|-bytes buffer, or a one-byte buffer if |size| is 0. This
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is due to an impedance mismatch between IOBuffer and URBs. An IOBuffer
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cannot represent a zero-length buffer, while an URB can.
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(std::max(
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<size_t>(1), size));
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (direction == USB_DIRECTION_INBOUND) {
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return buffer;
26190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else if (direction == USB_DIRECTION_OUTBOUND) {
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (input.data.get() && size <= input.data->size()) {
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      memcpy(buffer->data(), input.data->data(), size);
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return buffer;
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTREACHED();
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return NULL;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char* ConvertTransferStatusToErrorString(
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const UsbTransferStatus status) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (status) {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case USB_TRANSFER_COMPLETED:
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "";
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case USB_TRANSFER_ERROR:
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return kErrorGeneric;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case USB_TRANSFER_TIMEOUT:
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return kErrorTimeout;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case USB_TRANSFER_CANCELLED:
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return kErrorCancelled;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case USB_TRANSFER_STALLED:
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return kErrorStalled;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case USB_TRANSFER_DISCONNECT:
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return kErrorDisconnect;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case USB_TRANSFER_OVERFLOW:
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return kErrorOverflow;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case USB_TRANSFER_LENGTH_SHORT:
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return kErrorTransferLength;
29090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    default:
29190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      NOTREACHED();
29290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return "";
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static base::DictionaryValue* CreateTransferInfo(
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UsbTransferStatus status,
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<net::IOBuffer> data,
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t length) {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::DictionaryValue* result = new base::DictionaryValue();
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->SetInteger(kResultCodeKey, status);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->Set(kDataKey, base::BinaryValue::CreateWithCopiedBuffer(data->data(),
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                                  length));
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static base::Value* PopulateDevice(int handle, int vendor_id, int product_id) {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Device device;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  device.handle = handle;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  device.vendor_id = vendor_id;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  device.product_id = product_id;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return device.ToValue().release();
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static base::Value* PopulateInterfaceDescriptor(int interface_number,
31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        int alternate_setting, int interface_class, int interface_subclass,
31790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        int interface_protocol,
31890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        std::vector<linked_ptr<EndpointDescriptor> >* endpoints) {
31990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  InterfaceDescriptor descriptor;
32090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  descriptor.interface_number = interface_number;
32190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  descriptor.alternate_setting = alternate_setting;
32290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  descriptor.interface_class = interface_class;
32390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  descriptor.interface_subclass = interface_subclass;
324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  descriptor.interface_protocol = interface_protocol;
32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  descriptor.endpoints = *endpoints;
32690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return descriptor.ToValue().release();
32790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
32890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
329a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void GetUsbService(base::Callback<void(UsbService* service)> callback) {
330a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  BrowserThread::PostTaskAndReplyWithResult(
331a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      BrowserThread::FILE,
332a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      FROM_HERE,
333a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::Bind(UsbService::GetInstance),
334a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      callback);
335a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
336a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UsbAsyncApiFunction::UsbAsyncApiFunction()
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : manager_(NULL) {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UsbAsyncApiFunction::~UsbAsyncApiFunction() {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UsbAsyncApiFunction::PrePrepare() {
3497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  manager_ = ApiResourceManager<UsbDeviceResource>::Get(profile());
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return manager_ != NULL;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UsbAsyncApiFunction::Respond() {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return error_.empty();
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UsbDeviceResource* UsbAsyncApiFunction::GetUsbDeviceResource(
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int api_resource_id) {
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return manager_->Get(extension_->id(), api_resource_id);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UsbAsyncApiFunction::RemoveUsbDeviceResource(int api_resource_id) {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manager_->Remove(extension_->id(), api_resource_id);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UsbAsyncApiFunction::CompleteWithError(const std::string& error) {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetError(error);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AsyncWorkCompleted();
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UsbAsyncApiTransferFunction::UsbAsyncApiTransferFunction() {}
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UsbAsyncApiTransferFunction::~UsbAsyncApiTransferFunction() {}
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UsbAsyncApiTransferFunction::OnCompleted(UsbTransferStatus status,
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              scoped_refptr<net::IOBuffer> data,
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              size_t length) {
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (status != USB_TRANSFER_COMPLETED)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetError(ConvertTransferStatusToErrorString(status));
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetResult(CreateTransferInfo(status, data, length));
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AsyncWorkCompleted();
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UsbAsyncApiTransferFunction::ConvertDirectionSafely(
38690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const Direction& input, UsbEndpointDirection* output) {
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool converted = ConvertDirection(input, output);
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!converted)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetError(kErrorConvertDirection);
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return converted;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UsbAsyncApiTransferFunction::ConvertRequestTypeSafely(
394a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const RequestType& input, UsbDeviceHandle::TransferRequestType* output) {
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool converted = ConvertRequestType(input, output);
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!converted)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetError(kErrorConvertRequestType);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return converted;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UsbAsyncApiTransferFunction::ConvertRecipientSafely(
402a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const Recipient& input, UsbDeviceHandle::TransferRecipient* output) {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool converted = ConvertRecipient(input, output);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!converted)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetError(kErrorConvertRecipient);
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return converted;
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UsbFindDevicesFunction::UsbFindDevicesFunction() {}
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UsbFindDevicesFunction::~UsbFindDevicesFunction() {}
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4134311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdochvoid UsbFindDevicesFunction::SetDeviceForTest(UsbDevice* device) {
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  device_for_test_ = device;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UsbFindDevicesFunction::Prepare() {
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parameters_ = FindDevices::Params::Create(*args_);
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(parameters_.get());
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UsbFindDevicesFunction::AsyncWorkStart() {
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result_.reset(new base::ListValue());
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (device_for_test_) {
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UsbDeviceResource* const resource = new UsbDeviceResource(
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        extension_->id(),
4294311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch        device_for_test_->Open());
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Device device;
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result_->Append(PopulateDevice(manager_->Add(resource), 0, 0));
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SetResult(result_.release());
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AsyncWorkCompleted();
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const uint16_t vendor_id = parameters_->options.vendor_id;
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const uint16_t product_id = parameters_->options.product_id;
440868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int interface_id = parameters_->options.interface_id.get() ?
441868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      *parameters_->options.interface_id.get() :
442868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      UsbDevicePermissionData::ANY_INTERFACE;
443868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  UsbDevicePermission::CheckParam param(vendor_id, product_id, interface_id);
44490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!PermissionsData::CheckAPIPermissionWithParam(
44590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          GetExtension(), APIPermission::kUsbDevice, &param)) {
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(WARNING) << "Insufficient permissions to access device.";
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CompleteWithError(kErrorPermissionDenied);
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
451a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  GetUsbService(base::Bind(&UsbFindDevicesFunction::EnumerateDevices,
452a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                           this,
453a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                           vendor_id,
454a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                           product_id,
455a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                           interface_id));
456a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
457a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
458a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void UsbFindDevicesFunction::EnumerateDevices(
459a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    uint16_t vendor_id,
460a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    uint16_t product_id,
461a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    int interface_id,
462a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    UsbService* service) {
463a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  BrowserThread::PostTask(
464a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      BrowserThread::FILE,
465a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      FROM_HERE,
466a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::Bind(&UsbService::FindDevices,
467a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                 base::Unretained(service),
468a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                 vendor_id,
469a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                 product_id,
470a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                 interface_id,
471a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                 base::Bind(&UsbFindDevicesFunction::OnEnumerationCompleted,
472a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            this)));
473a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
474a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
475a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void UsbFindDevicesFunction::OnEnumerationCompleted(
476a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    ScopedDeviceVector devices) {
4774311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  for (size_t i = 0; i < devices->size(); ++i) {
4784311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    scoped_refptr<UsbDeviceHandle> device_handle =
4794311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      devices->at(i)->Open();
4804311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    if (device_handle)
4814311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      device_handles_.push_back(device_handle);
4824311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  }
4834311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch
484a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  BrowserThread::PostTask(
485a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      BrowserThread::IO,
486a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      FROM_HERE,
4874311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      base::Bind(&UsbFindDevicesFunction::OnCompleted, this));
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4904311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdochvoid UsbFindDevicesFunction::OnCompleted() {
4914311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  for (size_t i = 0; i < device_handles_.size(); ++i) {
4924311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    UsbDeviceHandle* const device_handle = device_handles_[i].get();
493868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    UsbDeviceResource* const resource =
4944311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch        new UsbDeviceResource(extension_->id(), device_handle);
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result_->Append(PopulateDevice(manager_->Add(resource),
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   parameters_->options.vendor_id,
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   parameters_->options.product_id));
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetResult(result_.release());
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AsyncWorkCompleted();
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)UsbListInterfacesFunction::UsbListInterfacesFunction() {}
50690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
50790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)UsbListInterfacesFunction::~UsbListInterfacesFunction() {}
50890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
50990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool UsbListInterfacesFunction::Prepare() {
51090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  parameters_ = ListInterfaces::Params::Create(*args_);
51190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(parameters_.get());
51290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return true;
51390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
51490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
51590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void UsbListInterfacesFunction::AsyncWorkStart() {
51690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  UsbDeviceResource* const resource = GetUsbDeviceResource(
51790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      parameters_->device.handle);
51890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!resource) {
51990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    CompleteWithError(kErrorNoDevice);
52090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
52190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
52290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
52390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  config_ = new UsbConfigDescriptor();
524a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  BrowserThread::PostTaskAndReplyWithResult(
525a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      BrowserThread::FILE,
526a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      FROM_HERE,
5274311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      base::Bind(&UsbDevice::ListInterfaces,
5284311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch                 resource->device()->device(),
529a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                 config_),
530a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      base::Bind(&UsbListInterfacesFunction::OnCompleted, this));
53190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
53290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
53390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void UsbListInterfacesFunction::OnCompleted(bool success) {
53490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!success) {
53590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SetError(kErrorCannotListInterfaces);
53690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    AsyncWorkCompleted();
53790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
53890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
53990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
54090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  result_.reset(new base::ListValue());
54190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
54290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (size_t i = 0, numInterfaces = config_->GetNumInterfaces();
54390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      i < numInterfaces; ++i) {
54490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    scoped_refptr<const UsbInterface> usbInterface(config_->GetInterface(i));
54590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (size_t j = 0, numDescriptors = usbInterface->GetNumAltSettings();
54690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            j < numDescriptors; ++j) {
54790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      scoped_refptr<const UsbInterfaceDescriptor> descriptor
54890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          = usbInterface->GetAltSetting(j);
54990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      std::vector<linked_ptr<EndpointDescriptor> > endpoints;
55090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      for (size_t k = 0, numEndpoints = descriptor->GetNumEndpoints();
55190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          k < numEndpoints; k++) {
55290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        scoped_refptr<const UsbEndpointDescriptor> endpoint
55390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            = descriptor->GetEndpoint(k);
55490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        linked_ptr<EndpointDescriptor> endpoint_desc(new EndpointDescriptor());
55590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
55690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        TransferType type;
55790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        Direction direction;
55890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        SynchronizationType synchronization;
55990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        UsageType usage;
56090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
56190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        if (!ConvertTransferTypeSafely(endpoint->GetTransferType(), &type) ||
56290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            !ConvertDirectionSafely(endpoint->GetDirection(), &direction) ||
56390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            !ConvertSynchronizationTypeSafely(
56490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                endpoint->GetSynchronizationType(), &synchronization) ||
56590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            !ConvertUsageTypeSafely(endpoint->GetUsageType(), &usage)) {
56690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          SetError(kErrorCannotListInterfaces);
56790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          AsyncWorkCompleted();
56890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          return;
56990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        }
57090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
57190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        endpoint_desc->address = endpoint->GetAddress();
57290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        endpoint_desc->type = type;
57390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        endpoint_desc->direction = direction;
57490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        endpoint_desc->maximum_packet_size = endpoint->GetMaximumPacketSize();
57590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        endpoint_desc->synchronization = synchronization;
57690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        endpoint_desc->usage = usage;
57790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
57890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        int* polling_interval = new int;
57990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        endpoint_desc->polling_interval.reset(polling_interval);
58090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        *polling_interval = endpoint->GetPollingInterval();
58190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
58290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        endpoints.push_back(endpoint_desc);
58390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
58490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
58590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      result_->Append(PopulateInterfaceDescriptor(
58690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          descriptor->GetInterfaceNumber(),
58790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          descriptor->GetAlternateSetting(),
58890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          descriptor->GetInterfaceClass(),
58990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          descriptor->GetInterfaceSubclass(),
59090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          descriptor->GetInterfaceProtocol(),
59190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          &endpoints));
59290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
59390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
59490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
59590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetResult(result_.release());
59690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  AsyncWorkCompleted();
59790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
59890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
59990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool UsbListInterfacesFunction::ConvertDirectionSafely(
60090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const UsbEndpointDirection& input,
60190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    extensions::api::usb::Direction* output) {
60290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const bool converted = ConvertDirectionToApi(input, output);
60390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!converted)
60490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SetError(kErrorConvertDirection);
60590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return converted;
60690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
60790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
60890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool UsbListInterfacesFunction::ConvertSynchronizationTypeSafely(
60990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const UsbSynchronizationType& input,
61090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    extensions::api::usb::SynchronizationType* output) {
61190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const bool converted = ConvertSynchronizationTypeToApi(input, output);
61290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!converted)
61390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SetError(kErrorConvertSynchronizationType);
61490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return converted;
61590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
61690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
61790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool UsbListInterfacesFunction::ConvertTransferTypeSafely(
61890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const UsbTransferType& input,
61990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    extensions::api::usb::TransferType* output) {
62090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const bool converted = ConvertTransferTypeToApi(input, output);
62190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!converted)
62290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SetError(kErrorConvertTransferType);
62390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return converted;
62490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
62590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
62690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool UsbListInterfacesFunction::ConvertUsageTypeSafely(
62790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const UsbUsageType& input,
62890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    extensions::api::usb::UsageType* output) {
62990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const bool converted = ConvertUsageTypeToApi(input, output);
63090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!converted)
63190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SetError(kErrorConvertUsageType);
63290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return converted;
63390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
63490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UsbCloseDeviceFunction::UsbCloseDeviceFunction() {}
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UsbCloseDeviceFunction::~UsbCloseDeviceFunction() {}
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UsbCloseDeviceFunction::Prepare() {
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parameters_ = CloseDevice::Params::Create(*args_);
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(parameters_.get());
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UsbCloseDeviceFunction::AsyncWorkStart() {
646c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UsbDeviceResource* const resource = GetUsbDeviceResource(
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parameters_->device.handle);
648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!resource) {
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CompleteWithError(kErrorNoDevice);
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
653a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  BrowserThread::PostTaskAndReply(
654a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      BrowserThread::FILE,
655a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      FROM_HERE,
656a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      base::Bind(&UsbDeviceHandle::Close, resource->device()),
657a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      base::Bind(&UsbCloseDeviceFunction::OnCompleted, this));
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UsbCloseDeviceFunction::OnCompleted() {
6614311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  RemoveUsbDeviceResource(parameters_->device.handle);
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AsyncWorkCompleted();
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UsbClaimInterfaceFunction::UsbClaimInterfaceFunction() {}
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UsbClaimInterfaceFunction::~UsbClaimInterfaceFunction() {}
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UsbClaimInterfaceFunction::Prepare() {
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parameters_ = ClaimInterface::Params::Create(*args_);
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(parameters_.get());
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UsbClaimInterfaceFunction::AsyncWorkStart() {
676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UsbDeviceResource* resource =
677c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetUsbDeviceResource(parameters_->device.handle);
678c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!resource) {
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CompleteWithError(kErrorNoDevice);
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
683a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  BrowserThread::PostTaskAndReplyWithResult(
684a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      BrowserThread::FILE,
685a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      FROM_HERE,
686a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      base::Bind(&UsbDeviceHandle::ClaimInterface,
687a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                 resource->device(),
688a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                 parameters_->interface_number),
689c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&UsbClaimInterfaceFunction::OnCompleted, this));
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UsbClaimInterfaceFunction::OnCompleted(bool success) {
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!success)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetError(kErrorCannotClaimInterface);
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AsyncWorkCompleted();
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UsbReleaseInterfaceFunction::UsbReleaseInterfaceFunction() {}
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UsbReleaseInterfaceFunction::~UsbReleaseInterfaceFunction() {}
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UsbReleaseInterfaceFunction::Prepare() {
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parameters_ = ReleaseInterface::Params::Create(*args_);
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(parameters_.get());
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UsbReleaseInterfaceFunction::AsyncWorkStart() {
709c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UsbDeviceResource* resource =
710c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetUsbDeviceResource(parameters_->device.handle);
711c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!resource) {
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CompleteWithError(kErrorNoDevice);
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
716a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  BrowserThread::PostTaskAndReplyWithResult(
717a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      BrowserThread::FILE,
718a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      FROM_HERE,
719a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      base::Bind(&UsbDeviceHandle::ReleaseInterface,
720a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                 resource->device(),
721a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                 parameters_->interface_number),
722c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&UsbReleaseInterfaceFunction::OnCompleted, this));
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UsbReleaseInterfaceFunction::OnCompleted(bool success) {
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!success)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetError(kErrorCannotReleaseInterface);
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AsyncWorkCompleted();
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UsbSetInterfaceAlternateSettingFunction::
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UsbSetInterfaceAlternateSettingFunction() {}
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UsbSetInterfaceAlternateSettingFunction::
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~UsbSetInterfaceAlternateSettingFunction() {}
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UsbSetInterfaceAlternateSettingFunction::Prepare() {
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parameters_ = SetInterfaceAlternateSetting::Params::Create(*args_);
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(parameters_.get());
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UsbSetInterfaceAlternateSettingFunction::AsyncWorkStart() {
744c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UsbDeviceResource* resource =
745c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetUsbDeviceResource(parameters_->device.handle);
746c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!resource) {
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CompleteWithError(kErrorNoDevice);
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
751a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  BrowserThread::PostTaskAndReplyWithResult(
752a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      BrowserThread::FILE,
753a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      FROM_HERE,
754a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      base::Bind(&UsbDeviceHandle::SetInterfaceAlternateSetting,
755a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                 resource->device(),
756a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                 parameters_->interface_number,
757a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                 parameters_->alternate_setting),
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&UsbSetInterfaceAlternateSettingFunction::OnCompleted, this));
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UsbSetInterfaceAlternateSettingFunction::OnCompleted(bool success) {
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!success)
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetError(kErrorCannotSetInterfaceAlternateSetting);
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AsyncWorkCompleted();
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UsbControlTransferFunction::UsbControlTransferFunction() {}
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UsbControlTransferFunction::~UsbControlTransferFunction() {}
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UsbControlTransferFunction::Prepare() {
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parameters_ = ControlTransfer::Params::Create(*args_);
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(parameters_.get());
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UsbControlTransferFunction::AsyncWorkStart() {
778c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UsbDeviceResource* const resource = GetUsbDeviceResource(
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parameters_->device.handle);
780c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!resource) {
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CompleteWithError(kErrorNoDevice);
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ControlTransferInfo& transfer = parameters_->transfer_info;
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
78790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  UsbEndpointDirection direction;
788a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  UsbDeviceHandle::TransferRequestType request_type;
789a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  UsbDeviceHandle::TransferRecipient recipient;
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t size = 0;
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ConvertDirectionSafely(transfer.direction, &direction) ||
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !ConvertRequestTypeSafely(transfer.request_type, &request_type) ||
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !ConvertRecipientSafely(transfer.recipient, &recipient)) {
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AsyncWorkCompleted();
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!GetTransferSize(transfer, &size)) {
8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CompleteWithError(kErrorInvalidTransferLength);
8012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(
8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      transfer, direction, size);
806868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!buffer.get()) {
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CompleteWithError(kErrorMalformedParameters);
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
811868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  resource->device()->ControlTransfer(
812868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      direction,
813868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      request_type,
814868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      recipient,
815868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transfer.request,
816868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transfer.value,
817868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transfer.index,
818868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      buffer.get(),
819868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      size,
820868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      0,
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&UsbControlTransferFunction::OnCompleted, this));
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UsbBulkTransferFunction::UsbBulkTransferFunction() {}
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UsbBulkTransferFunction::~UsbBulkTransferFunction() {}
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UsbBulkTransferFunction::Prepare() {
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parameters_ = BulkTransfer::Params::Create(*args_);
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(parameters_.get());
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UsbBulkTransferFunction::AsyncWorkStart() {
835c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UsbDeviceResource* const resource = GetUsbDeviceResource(
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parameters_->device.handle);
837c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!resource) {
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CompleteWithError(kErrorNoDevice);
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GenericTransferInfo& transfer = parameters_->transfer_info;
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
84490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  UsbEndpointDirection direction;
8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t size = 0;
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ConvertDirectionSafely(transfer.direction, &direction)) {
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AsyncWorkCompleted();
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!GetTransferSize(transfer, &size)) {
8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CompleteWithError(kErrorInvalidTransferLength);
8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(
8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      transfer, direction, size);
859868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!buffer.get()) {
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CompleteWithError(kErrorMalformedParameters);
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
864868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  resource->device()
865868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ->BulkTransfer(direction,
866868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     transfer.endpoint,
867868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     buffer.get(),
868868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     size,
869868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     0,
870868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     base::Bind(&UsbBulkTransferFunction::OnCompleted, this));
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UsbInterruptTransferFunction::UsbInterruptTransferFunction() {}
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UsbInterruptTransferFunction::~UsbInterruptTransferFunction() {}
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UsbInterruptTransferFunction::Prepare() {
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parameters_ = InterruptTransfer::Params::Create(*args_);
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(parameters_.get());
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UsbInterruptTransferFunction::AsyncWorkStart() {
884c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UsbDeviceResource* const resource = GetUsbDeviceResource(
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parameters_->device.handle);
886c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!resource) {
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CompleteWithError(kErrorNoDevice);
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GenericTransferInfo& transfer = parameters_->transfer_info;
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
89390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  UsbEndpointDirection direction;
8942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t size = 0;
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ConvertDirectionSafely(transfer.direction, &direction)) {
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AsyncWorkCompleted();
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!GetTransferSize(transfer, &size)) {
9022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CompleteWithError(kErrorInvalidTransferLength);
9032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
9042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(
9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      transfer, direction, size);
908868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!buffer.get()) {
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CompleteWithError(kErrorMalformedParameters);
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
913868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  resource->device()->InterruptTransfer(
914868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      direction,
915868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transfer.endpoint,
916868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      buffer.get(),
917868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      size,
918868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      0,
919868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::Bind(&UsbInterruptTransferFunction::OnCompleted, this));
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UsbIsochronousTransferFunction::UsbIsochronousTransferFunction() {}
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UsbIsochronousTransferFunction::~UsbIsochronousTransferFunction() {}
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UsbIsochronousTransferFunction::Prepare() {
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parameters_ = IsochronousTransfer::Params::Create(*args_);
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(parameters_.get());
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UsbIsochronousTransferFunction::AsyncWorkStart() {
933c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UsbDeviceResource* const resource = GetUsbDeviceResource(
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parameters_->device.handle);
935c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!resource) {
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CompleteWithError(kErrorNoDevice);
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const IsochronousTransferInfo& transfer = parameters_->transfer_info;
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GenericTransferInfo& generic_transfer = transfer.transfer_info;
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t size = 0;
94490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  UsbEndpointDirection direction;
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ConvertDirectionSafely(generic_transfer.direction, &direction)) {
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AsyncWorkCompleted();
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!GetTransferSize(generic_transfer, &size)) {
9512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CompleteWithError(kErrorInvalidTransferLength);
9522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
9532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (transfer.packets < 0 || transfer.packets >= kMaxPackets) {
9552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CompleteWithError(kErrorInvalidNumberOfPackets);
9562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned int packets = transfer.packets;
9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (transfer.packet_length < 0 ||
9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      transfer.packet_length >= kMaxPacketLength) {
9612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CompleteWithError(kErrorInvalidPacketLength);
9622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
9632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned int packet_length = transfer.packet_length;
9652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const uint64 total_length = packets * packet_length;
9662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (packets > size || total_length > size) {
9672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CompleteWithError(kErrorTransferLength);
9682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
9692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(
9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      generic_transfer, direction, size);
973868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!buffer.get()) {
9742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CompleteWithError(kErrorMalformedParameters);
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
978868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  resource->device()->IsochronousTransfer(
979868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      direction,
980868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      generic_transfer.endpoint,
981868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      buffer.get(),
982868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      size,
983868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      packets,
984868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      packet_length,
985868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      0,
986868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::Bind(&UsbIsochronousTransferFunction::OnCompleted, this));
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
989c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)UsbResetDeviceFunction::UsbResetDeviceFunction() {}
990c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
991c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)UsbResetDeviceFunction::~UsbResetDeviceFunction() {}
992c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
993c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool UsbResetDeviceFunction::Prepare() {
994c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  parameters_ = ResetDevice::Params::Create(*args_);
995c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(parameters_.get());
996c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
997c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
998c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
999c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void UsbResetDeviceFunction::AsyncWorkStart() {
1000c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UsbDeviceResource* const resource = GetUsbDeviceResource(
1001c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      parameters_->device.handle);
1002c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!resource) {
1003c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CompleteWithError(kErrorNoDevice);
1004c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
1005c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1006c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1007c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
1008c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          base::Bind(&UsbResetDeviceFunction::OnStartResest,
1009c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     this, resource));
1010c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1011c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1012c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void UsbResetDeviceFunction::OnStartResest(UsbDeviceResource* resource) {
1013c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
1014a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  OnCompletedFileThread(resource->device()->ResetDevice());
1015c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1016c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1017c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void UsbResetDeviceFunction::OnCompletedFileThread(bool success) {
1018c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
1019c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
1020c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          base::Bind(&UsbResetDeviceFunction::OnCompleted,
1021c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     this, success));
1022c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return;
1023c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1024c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1025c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void UsbResetDeviceFunction::OnCompleted(bool success) {
1026c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1027c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!success) {
1028c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UsbDeviceResource* const resource = GetUsbDeviceResource(
1029c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        parameters_->device.handle);
1030c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!resource) {
1031c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CompleteWithError(kErrorNoDevice);
1032c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
1033c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1034c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Close the device now because the handle is invalid after an
1035c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // unsuccessful reset.
1036a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    BrowserThread::PostTaskAndReply(
1037a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      BrowserThread::FILE,
1038a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      FROM_HERE,
1039a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      base::Bind(&UsbDeviceHandle::Close,
1040a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                 resource->device()),
1041a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      base::Bind(&UsbResetDeviceFunction::OnError, this));
1042c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
1043c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1044c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SetResult(Value::CreateBooleanValue(true));
1045c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  AsyncWorkCompleted();
1046c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1047c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1048c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void UsbResetDeviceFunction::OnError() {
1049c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RemoveUsbDeviceResource(parameters_->device.handle);
1050c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SetError(kErrorResetDevice);
1051c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SetResult(Value::CreateBooleanValue(false));
1052c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  AsyncWorkCompleted();
1053c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1054c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
1056