1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef DEVICE_USB_USB_DEVICE_HANDLE_IMPL_H_
6#define DEVICE_USB_USB_DEVICE_HANDLE_IMPL_H_
7
8#include <map>
9#include <vector>
10
11#include "base/callback.h"
12#include "base/memory/ref_counted.h"
13#include "base/strings/string16.h"
14#include "base/threading/thread_checker.h"
15#include "device/usb/usb_device_handle.h"
16#include "net/base/io_buffer.h"
17#include "third_party/libusb/src/libusb/libusb.h"
18
19namespace base {
20class SingleThreadTaskRunner;
21}
22
23namespace device {
24
25class UsbContext;
26struct UsbConfigDescriptor;
27class UsbDeviceImpl;
28
29typedef libusb_device_handle* PlatformUsbDeviceHandle;
30typedef libusb_iso_packet_descriptor* PlatformUsbIsoPacketDescriptor;
31typedef libusb_transfer* PlatformUsbTransferHandle;
32
33// UsbDeviceHandle class provides basic I/O related functionalities.
34class UsbDeviceHandleImpl : public UsbDeviceHandle {
35 public:
36  virtual scoped_refptr<UsbDevice> GetDevice() const OVERRIDE;
37  virtual void Close() OVERRIDE;
38  virtual bool ClaimInterface(int interface_number) OVERRIDE;
39  virtual bool ReleaseInterface(int interface_number) OVERRIDE;
40  virtual bool SetInterfaceAlternateSetting(int interface_number,
41                                            int alternate_setting) OVERRIDE;
42  virtual bool ResetDevice() OVERRIDE;
43  virtual bool GetStringDescriptor(uint8 string_id,
44                                   base::string16* string) OVERRIDE;
45
46  virtual void ControlTransfer(UsbEndpointDirection direction,
47                               TransferRequestType request_type,
48                               TransferRecipient recipient,
49                               uint8 request,
50                               uint16 value,
51                               uint16 index,
52                               net::IOBuffer* buffer,
53                               size_t length,
54                               unsigned int timeout,
55                               const UsbTransferCallback& callback) OVERRIDE;
56
57  virtual void BulkTransfer(UsbEndpointDirection direction,
58                            uint8 endpoint,
59                            net::IOBuffer* buffer,
60                            size_t length,
61                            unsigned int timeout,
62                            const UsbTransferCallback& callback) OVERRIDE;
63
64  virtual void InterruptTransfer(UsbEndpointDirection direction,
65                                 uint8 endpoint,
66                                 net::IOBuffer* buffer,
67                                 size_t length,
68                                 unsigned int timeout,
69                                 const UsbTransferCallback& callback) OVERRIDE;
70
71  virtual void IsochronousTransfer(
72      UsbEndpointDirection direction,
73      uint8 endpoint,
74      net::IOBuffer* buffer,
75      size_t length,
76      unsigned int packets,
77      unsigned int packet_length,
78      unsigned int timeout,
79      const UsbTransferCallback& callback) OVERRIDE;
80
81  PlatformUsbDeviceHandle handle() const { return handle_; }
82
83 protected:
84  friend class UsbDeviceImpl;
85
86  // This constructor is called by UsbDevice.
87  UsbDeviceHandleImpl(scoped_refptr<UsbContext> context,
88                      UsbDeviceImpl* device,
89                      PlatformUsbDeviceHandle handle,
90                      const UsbConfigDescriptor& config);
91
92  virtual ~UsbDeviceHandleImpl();
93
94 private:
95  class InterfaceClaimer;
96  struct Transfer;
97
98  // Refresh endpoint_map_ after ClaimInterface, ReleaseInterface and
99  // SetInterfaceAlternateSetting.
100  void RefreshEndpointMap();
101
102  // Look up the claimed interface by endpoint. Return NULL if the interface
103  // of the endpoint is not found.
104  scoped_refptr<InterfaceClaimer> GetClaimedInterfaceForEndpoint(
105      unsigned char endpoint);
106
107  // If the device's task runner is on the current thread then the transfer will
108  // be submitted directly, otherwise a task to do so it posted. The callback
109  // will be called on the current message loop of the thread where this
110  // function was called.
111  void PostOrSubmitTransfer(PlatformUsbTransferHandle handle,
112                            UsbTransferType transfer_type,
113                            net::IOBuffer* buffer,
114                            size_t length,
115                            const UsbTransferCallback& callback);
116
117  // Submits a transfer and starts tracking it. Retains the buffer and copies
118  // the completion callback until the transfer finishes, whereupon it invokes
119  // the callback then releases the buffer.
120  void SubmitTransfer(PlatformUsbTransferHandle handle,
121                      UsbTransferType transfer_type,
122                      net::IOBuffer* buffer,
123                      const size_t length,
124                      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
125                      const UsbTransferCallback& callback);
126
127  static void LIBUSB_CALL
128      PlatformTransferCallback(PlatformUsbTransferHandle handle);
129
130  // Invokes the callbacks associated with a given transfer, and removes it from
131  // the in-flight transfer set.
132  void CompleteTransfer(PlatformUsbTransferHandle transfer);
133
134  bool GetSupportedLanguages();
135
136  // Informs the object to drop internal references.
137  void InternalClose();
138
139  UsbDeviceImpl* device_;
140
141  PlatformUsbDeviceHandle handle_;
142
143  const UsbConfigDescriptor& config_;
144
145  std::vector<uint16> languages_;
146  std::map<uint8, base::string16> strings_;
147
148  typedef std::map<int, scoped_refptr<InterfaceClaimer> > ClaimedInterfaceMap;
149  ClaimedInterfaceMap claimed_interfaces_;
150
151  typedef std::map<PlatformUsbTransferHandle, Transfer> TransferMap;
152  TransferMap transfers_;
153
154  // A map from endpoints to interfaces
155  typedef std::map<int, int> EndpointMap;
156  EndpointMap endpoint_map_;
157
158  // Retain the UsbContext so that the platform context will not be destroyed
159  // before this handle.
160  scoped_refptr<UsbContext> context_;
161
162  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
163
164  base::ThreadChecker thread_checker_;
165
166  DISALLOW_COPY_AND_ASSIGN(UsbDeviceHandleImpl);
167};
168
169}  // namespace device
170
171#endif  // DEVICE_USB_USB_DEVICE_HANDLE_IMPL_H_
172