adb_interface.cpp revision dceaaa52cec11631c72cfea5fb74ee607602ecde
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/** \file
18  This file consists of implementation of class AdbInterfaceObject that
19  encapsulates an interface on our USB device.
20*/
21
22#include "stdafx.h"
23#include "adb_interface.h"
24#include "adb_endpoint_object.h"
25
26AdbInterfaceObject::AdbInterfaceObject(const wchar_t* interf_name)
27    : AdbObjectHandle(AdbObjectTypeInterface),
28      interface_name_(interf_name),
29      usb_device_handle_(INVALID_HANDLE_VALUE),
30      winusb_handle_(NULL),
31      interface_number_(0xFF),
32      def_read_endpoint_(0xFF),
33      read_endpoint_id_(0xFF),
34      def_write_endpoint_(0xFF),
35      write_endpoint_id_(0xFF) {
36  ATLASSERT(NULL != interf_name);
37}
38
39AdbInterfaceObject::~AdbInterfaceObject() {
40  ATLASSERT(NULL == winusb_handle_);
41  ATLASSERT(INVALID_HANDLE_VALUE == usb_device_handle_);
42}
43
44ADBAPIHANDLE AdbInterfaceObject::CreateHandle() {
45  // Open USB device for this inteface Note that WinUsb API
46  // requires the handle to be opened for overlapped I/O.
47  usb_device_handle_ = CreateFile(interface_name().c_str(),
48                                  GENERIC_READ | GENERIC_WRITE,
49                                  FILE_SHARE_READ | FILE_SHARE_WRITE,
50                                  NULL, OPEN_EXISTING,
51                                  FILE_FLAG_OVERLAPPED, NULL);
52  if (INVALID_HANDLE_VALUE == usb_device_handle_)
53    return NULL;
54
55  // Initialize WinUSB API for this interface
56  if (!WinUsb_Initialize(usb_device_handle_, &winusb_handle_))
57    return NULL;
58
59  // Cache current interface number that will be used in
60  // WinUsb_Xxx calls performed on this interface.
61  if (!WinUsb_GetCurrentAlternateSetting(winusb_handle(), &interface_number_))
62    return false;
63
64  // Cache interface properties
65  unsigned long bytes_written;
66
67  // Cache USB device descriptor
68  if (!WinUsb_GetDescriptor(winusb_handle(), USB_DEVICE_DESCRIPTOR_TYPE, 0, 0,
69                            reinterpret_cast<PUCHAR>(&usb_device_descriptor_),
70                            sizeof(usb_device_descriptor_), &bytes_written)) {
71    return false;
72  }
73
74  // Cache USB configuration descriptor
75  if (!WinUsb_GetDescriptor(winusb_handle(), USB_CONFIGURATION_DESCRIPTOR_TYPE,
76                            0, 0,
77                            reinterpret_cast<PUCHAR>(&usb_config_descriptor_),
78                            sizeof(usb_config_descriptor_), &bytes_written)) {
79    return false;
80  }
81
82  // Cache USB interface descriptor
83  if (!WinUsb_QueryInterfaceSettings(winusb_handle(), interface_number(),
84                                     &usb_interface_descriptor_)) {
85    return false;
86  }
87
88  // Save indexes and IDs for bulk read / write endpoints. We will use them to
89  // convert ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX and
90  // ADB_QUERY_BULK_READ_ENDPOINT_INDEX into actual endpoint indexes and IDs.
91  for (UCHAR endpoint = 0; endpoint < usb_interface_descriptor_.bNumEndpoints;
92       endpoint++) {
93    // Get endpoint information
94    WINUSB_PIPE_INFORMATION pipe_info;
95    if (!WinUsb_QueryPipe(winusb_handle(), interface_number(), endpoint,
96                          &pipe_info)) {
97      return false;
98    }
99
100    if (UsbdPipeTypeBulk == pipe_info.PipeType) {
101      // This is a bulk endpoint. Cache its index and ID.
102      if (0 != (pipe_info.PipeId & USB_ENDPOINT_DIRECTION_MASK)) {
103        // Use this endpoint as default bulk read endpoint
104        ATLASSERT(0xFF == def_read_endpoint_);
105        def_read_endpoint_ = endpoint;
106        read_endpoint_id_ = pipe_info.PipeId;
107      } else {
108        // Use this endpoint as default bulk write endpoint
109        ATLASSERT(0xFF == def_write_endpoint_);
110        def_write_endpoint_ = endpoint;
111        write_endpoint_id_ = pipe_info.PipeId;
112      }
113    }
114  }
115
116  return AdbObjectHandle::CreateHandle();
117}
118
119bool AdbInterfaceObject::CloseHandle() {
120  if (NULL != winusb_handle_) {
121    WinUsb_Free(winusb_handle_);
122    winusb_handle_ = NULL;
123  }
124  if (INVALID_HANDLE_VALUE != usb_device_handle_) {
125    ::CloseHandle(usb_device_handle_);
126    usb_device_handle_ = INVALID_HANDLE_VALUE;
127  }
128
129  return AdbObjectHandle::CloseHandle();
130}
131
132bool AdbInterfaceObject::GetInterfaceName(void* buffer,
133                                          unsigned long* buffer_char_size,
134                                          bool ansi) {
135  if (NULL == buffer_char_size) {
136    SetLastError(ERROR_INVALID_PARAMETER);
137    return false;
138  }
139
140  // Lets see if buffer is big enough
141  ULONG name_len = static_cast<ULONG>(interface_name_.length() + 1);
142  if ((NULL == buffer) || (*buffer_char_size < name_len)) {
143    *buffer_char_size = name_len;
144    SetLastError(ERROR_INSUFFICIENT_BUFFER);
145    return false;
146  }
147
148  if (!ansi) {
149    // If user asked for wide char name just return it
150    wcscpy(reinterpret_cast<wchar_t*>(buffer), interface_name().c_str());
151    return true;
152  }
153
154  // We need to convert name from wide char to ansi string
155  int res = WideCharToMultiByte(CP_ACP,
156                                0,
157                                interface_name().c_str(),
158                                static_cast<int>(name_len),
159                                reinterpret_cast<PSTR>(buffer),
160                                static_cast<int>(*buffer_char_size),
161                                NULL,
162                                NULL);
163  return (res != 0);
164}
165
166bool AdbInterfaceObject::GetSerialNumber(void* buffer,
167                                         unsigned long* buffer_char_size,
168                                         bool ansi) {
169  if (!IsOpened()) {
170    SetLastError(ERROR_INVALID_HANDLE);
171    return false;
172  }
173
174  if (NULL == buffer_char_size) {
175    SetLastError(ERROR_INVALID_PARAMETER);
176    return false;
177  }
178
179  // Calculate serial number string size. Note that WinUsb_GetDescriptor
180  // API will not return number of bytes needed to store serial number
181  // string. So we will have to start with a reasonably large preallocated
182  // buffer and then loop through WinUsb_GetDescriptor calls, doubling up
183  // string buffer size every time ERROR_INSUFFICIENT_BUFFER is returned.
184  union {
185    // Preallocate reasonably sized buffer on the stack.
186    char small_buffer[64];
187    USB_STRING_DESCRIPTOR initial_ser_num;
188  };
189  USB_STRING_DESCRIPTOR* ser_num = &initial_ser_num;
190  // Buffer byte size
191  unsigned long ser_num_size = sizeof(small_buffer);
192  // After successful call to WinUsb_GetDescriptor will contain serial
193  // number descriptor size.
194  unsigned long bytes_written;
195  while (!WinUsb_GetDescriptor(winusb_handle(), USB_STRING_DESCRIPTOR_TYPE,
196                               usb_device_descriptor_.iSerialNumber,
197                               0x0409, // English (US)
198                               reinterpret_cast<PUCHAR>(ser_num),
199                               ser_num_size, &bytes_written)) {
200    // Any error other than ERROR_INSUFFICIENT_BUFFER is terminal here.
201    if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) {
202      if (ser_num != &initial_ser_num)
203        delete[] reinterpret_cast<char*>(ser_num);
204      return false;
205    }
206
207    // Double up buffer size and reallocate string buffer
208    ser_num_size *= 2;
209    if (ser_num != &initial_ser_num)
210      delete[] reinterpret_cast<char*>(ser_num);
211    try {
212      ser_num =
213          reinterpret_cast<USB_STRING_DESCRIPTOR*>(new char[ser_num_size]);
214    } catch (...) {
215      SetLastError(ERROR_OUTOFMEMORY);
216      return false;
217    }
218  }
219
220  // Serial number string length
221  unsigned long str_len = (ser_num->bLength -
222                           FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString)) /
223                          sizeof(wchar_t);
224
225  // Lets see if requested buffer is big enough to fit the string
226  if ((NULL == buffer) || (*buffer_char_size < (str_len + 1))) {
227    // Requested buffer is too small.
228    if (ser_num != &initial_ser_num)
229      delete[] reinterpret_cast<char*>(ser_num);
230    *buffer_char_size = str_len + 1;
231    SetLastError(ERROR_INSUFFICIENT_BUFFER);
232    return false;
233  }
234
235  bool ret = true;
236  if (ansi) {
237    // We need to convert name from wide char to ansi string
238    if (0 != WideCharToMultiByte(CP_ACP, 0, ser_num->bString,
239                                 static_cast<int>(str_len),
240                                 reinterpret_cast<PSTR>(buffer),
241                                 static_cast<int>(*buffer_char_size),
242                                 NULL, NULL)) {
243      // Zero-terminate output string.
244      reinterpret_cast<char*>(buffer)[str_len] = '\0';
245    } else {
246      ret = false;
247    }
248  } else {
249    // For wide char output just copy string buffer,
250    // and zero-terminate output string.
251    CopyMemory(buffer, ser_num->bString, bytes_written);
252    reinterpret_cast<wchar_t*>(buffer)[str_len] = L'\0';
253  }
254
255  if (ser_num != &initial_ser_num)
256    delete[] reinterpret_cast<char*>(ser_num);
257
258  return ret;
259}
260
261bool AdbInterfaceObject::GetUsbDeviceDescriptor(USB_DEVICE_DESCRIPTOR* desc) {
262  if (!IsOpened()) {
263    SetLastError(ERROR_INVALID_HANDLE);
264    return false;
265  }
266
267  if (NULL == desc) {
268    SetLastError(ERROR_INVALID_PARAMETER);
269    return false;
270  }
271
272  CopyMemory(desc, usb_device_descriptor(), sizeof(USB_DEVICE_DESCRIPTOR));
273
274  return true;
275}
276
277bool AdbInterfaceObject::GetUsbConfigurationDescriptor(
278    USB_CONFIGURATION_DESCRIPTOR* desc) {
279  if (!IsOpened()) {
280    SetLastError(ERROR_INVALID_HANDLE);
281    return false;
282  }
283
284  if (NULL == desc) {
285    SetLastError(ERROR_INVALID_PARAMETER);
286    return false;
287  }
288
289  CopyMemory(desc, usb_config_descriptor(),
290             sizeof(USB_CONFIGURATION_DESCRIPTOR));
291
292  return true;
293}
294
295bool AdbInterfaceObject::GetUsbInterfaceDescriptor(
296    USB_INTERFACE_DESCRIPTOR* desc) {
297  if (!IsOpened()) {
298    SetLastError(ERROR_INVALID_HANDLE);
299    return false;
300  }
301
302  if (NULL == desc) {
303    SetLastError(ERROR_INVALID_PARAMETER);
304    return false;
305  }
306
307  CopyMemory(desc, usb_interface_descriptor(), sizeof(USB_INTERFACE_DESCRIPTOR));
308
309  return true;
310}
311
312bool AdbInterfaceObject::GetEndpointInformation(UCHAR endpoint_index,
313                                                AdbEndpointInformation* info) {
314  if (!IsOpened()) {
315    SetLastError(ERROR_INVALID_HANDLE);
316    return false;
317  }
318
319  if (NULL == info) {
320    SetLastError(ERROR_INVALID_PARAMETER);
321    return false;
322  }
323
324  // Get actual endpoint index for predefined read / write endpoints.
325  if (ADB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index) {
326    endpoint_index = def_read_endpoint_;
327  } else if (ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX == endpoint_index) {
328    endpoint_index = def_write_endpoint_;
329  }
330
331  // Query endpoint information
332  WINUSB_PIPE_INFORMATION pipe_info;
333  if (!WinUsb_QueryPipe(winusb_handle(), interface_number(), endpoint_index,
334                        &pipe_info)) {
335    return false;
336  }
337
338  // Save endpoint information into output.
339  info->max_packet_size = pipe_info.MaximumPacketSize;
340  info->max_transfer_size = 0xFFFFFFFF;
341  info->endpoint_address = pipe_info.PipeId;
342  info->polling_interval = pipe_info.Interval;
343  info->setting_index = interface_number();
344  switch (pipe_info.PipeType) {
345    case UsbdPipeTypeControl:
346      info->endpoint_type = AdbEndpointTypeControl;
347      break;
348
349    case UsbdPipeTypeIsochronous:
350      info->endpoint_type = AdbEndpointTypeIsochronous;
351      break;
352
353    case UsbdPipeTypeBulk:
354      info->endpoint_type = AdbEndpointTypeBulk;
355      break;
356
357    case UsbdPipeTypeInterrupt:
358      info->endpoint_type = AdbEndpointTypeInterrupt;
359      break;
360
361    default:
362      info->endpoint_type = AdbEndpointTypeInvalid;
363      break;
364  }
365
366  return true;
367}
368
369ADBAPIHANDLE AdbInterfaceObject::OpenEndpoint(
370    UCHAR endpoint_index,
371    AdbOpenAccessType access_type,
372    AdbOpenSharingMode sharing_mode) {
373  // Convert index into id
374  UCHAR endpoint_id;
375
376  if ((ADB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index) ||
377      (def_read_endpoint_ == endpoint_index)) {
378    endpoint_id = read_endpoint_id_;
379    endpoint_index = def_read_endpoint_;
380  } else if ((ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX == endpoint_index) ||
381             (def_write_endpoint_ == endpoint_index)) {
382    endpoint_id = write_endpoint_id_;
383    endpoint_index = def_write_endpoint_;
384  } else {
385    SetLastError(ERROR_INVALID_PARAMETER);
386    return false;
387  }
388
389  return OpenEndpoint(endpoint_id, endpoint_index);
390}
391
392ADBAPIHANDLE AdbInterfaceObject::OpenEndpoint(UCHAR endpoint_id,
393                                              UCHAR endpoint_index) {
394  if (!IsOpened()) {
395    SetLastError(ERROR_INVALID_HANDLE);
396    return false;
397  }
398
399  AdbEndpointObject* adb_endpoint = NULL;
400
401  try {
402    adb_endpoint = new AdbEndpointObject(this, endpoint_id, endpoint_index);
403  } catch (...) {
404    SetLastError(ERROR_OUTOFMEMORY);
405    return NULL;
406  }
407
408  ADBAPIHANDLE ret = adb_endpoint->CreateHandle();
409
410  adb_endpoint->Release();
411
412  return ret;
413}
414