1/*
2 * Copyright (C) 2009 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 AdbLegacyInterfaceObject
19  that encapsulates an interface on our USB device that is accessible
20*/
21
22#include "stdafx.h"
23#include "adb_api_legacy.h"
24#include "adb_legacy_interface.h"
25#include "adb_legacy_endpoint_object.h"
26
27AdbLegacyInterfaceObject::AdbLegacyInterfaceObject(const wchar_t* interf_name)
28    : AdbInterfaceObject(interf_name),
29      def_read_endpoint_(0xFF),
30      read_endpoint_id_(0xFF),
31      def_write_endpoint_(0xFF),
32      write_endpoint_id_(0xFF) {
33}
34
35AdbLegacyInterfaceObject::~AdbLegacyInterfaceObject() {
36}
37
38ADBAPIHANDLE AdbLegacyInterfaceObject::CreateHandle() {
39  // Open USB device for this intefface
40  HANDLE usb_device_handle = CreateFile(interface_name().c_str(),
41                                        GENERIC_READ | GENERIC_WRITE,
42                                        FILE_SHARE_READ | FILE_SHARE_WRITE,
43                                        NULL,
44                                        OPEN_EXISTING,
45                                        0,
46                                        NULL);
47  if (INVALID_HANDLE_VALUE == usb_device_handle) {
48    return NULL;
49  }
50
51  // Now, we ensured that our usb device / interface is up and running.
52  // Lets collect device, interface and pipe information
53  bool ok = true;
54  if (!CacheUsbDeviceDescriptor(usb_device_handle) ||
55      !CacheUsbConfigurationDescriptor(usb_device_handle) ||
56      !CacheUsbInterfaceDescriptor(usb_device_handle)) {
57    ok = false;
58  }
59
60  // Preserve error accross handle close
61  ULONG error = ok ? NO_ERROR : GetLastError();
62
63  ::CloseHandle(usb_device_handle);
64
65  if (NO_ERROR != error) {
66    SetLastError(error);
67  }
68
69  if (!ok) {
70    return false;
71  }
72
73  // Save indexes and IDs for bulk read / write endpoints. We will use them to
74  // convert ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX and
75  // ADB_QUERY_BULK_READ_ENDPOINT_INDEX into actual endpoint indexes and IDs.
76  for (UCHAR endpoint = 0; endpoint < usb_interface_descriptor_.bNumEndpoints;
77       endpoint++) {
78    // Get endpoint information
79    AdbEndpointInformation pipe_info;
80    if (!GetEndpointInformation(endpoint, &pipe_info)) {
81      return false;
82    }
83
84    if (AdbEndpointTypeBulk == pipe_info.endpoint_type) {
85      // This is a bulk endpoint. Cache its index and ID.
86      if (0 != (pipe_info.endpoint_address & USB_ENDPOINT_DIRECTION_MASK)) {
87        // Use this endpoint as default bulk read endpoint
88        ATLASSERT(0xFF == def_read_endpoint_);
89        def_read_endpoint_ = endpoint;
90        read_endpoint_id_ = pipe_info.endpoint_address;
91      } else {
92        // Use this endpoint as default bulk write endpoint
93        ATLASSERT(0xFF == def_write_endpoint_);
94        def_write_endpoint_ = endpoint;
95        write_endpoint_id_ = pipe_info.endpoint_address;
96      }
97    }
98  }
99
100  return AdbObjectHandle::CreateHandle();
101}
102
103bool AdbLegacyInterfaceObject::GetSerialNumber(void* buffer,
104                                               unsigned long* buffer_char_size,
105                                               bool ansi) {
106  if (!IsOpened()) {
107    SetLastError(ERROR_INVALID_HANDLE);
108    return false;
109  }
110
111  // Open USB device for this intefface
112  HANDLE usb_device_handle = CreateFile(interface_name().c_str(),
113                                        GENERIC_READ,
114                                        FILE_SHARE_READ | FILE_SHARE_WRITE,
115                                        NULL,
116                                        OPEN_EXISTING,
117                                        0,
118                                        NULL);
119  if (INVALID_HANDLE_VALUE == usb_device_handle) {
120    return NULL;
121  }
122
123  WCHAR serial_number[512];
124
125  // Send IOCTL
126  DWORD ret_bytes = 0;
127  BOOL ret = DeviceIoControl(usb_device_handle,
128                             ADB_IOCTL_GET_SERIAL_NUMBER,
129                             NULL, 0,
130                             serial_number, sizeof(serial_number),
131                             &ret_bytes,
132                             NULL);
133
134  // Preserve error accross CloseHandle
135  ULONG error = ret ? NO_ERROR : GetLastError();
136
137  ::CloseHandle(usb_device_handle);
138
139  if (NO_ERROR != error) {
140    SetLastError(error);
141    return false;
142  }
143
144  unsigned long str_len =
145    static_cast<unsigned long>(wcslen(serial_number) + 1);
146
147  if ((NULL == buffer) || (*buffer_char_size < str_len)) {
148    *buffer_char_size = str_len;
149    SetLastError(ERROR_INSUFFICIENT_BUFFER);
150    return false;
151  }
152
153  if (!ansi) {
154    // If user asked for wide char name just return it
155    wcscpy(reinterpret_cast<wchar_t*>(buffer), serial_number);
156    return true;
157  }
158
159  // We need to convert name from wide char to ansi string
160  int res = WideCharToMultiByte(CP_ACP,
161                                0,
162                                serial_number,
163                                static_cast<int>(str_len),
164                                reinterpret_cast<PSTR>(buffer),
165                                static_cast<int>(*buffer_char_size),
166                                NULL,
167                                NULL);
168  return (res != 0);
169}
170
171bool AdbLegacyInterfaceObject::GetEndpointInformation(
172    UCHAR endpoint_index,
173    AdbEndpointInformation* info) {
174  // Open USB device for this intefface
175  HANDLE usb_device_handle = CreateFile(interface_name().c_str(),
176                                        GENERIC_READ,
177                                        FILE_SHARE_READ | FILE_SHARE_WRITE,
178                                        NULL,
179                                        OPEN_EXISTING,
180                                        0,
181                                        NULL);
182  if (INVALID_HANDLE_VALUE == usb_device_handle) {
183    return NULL;
184  }
185
186  // Init ICTL param
187  AdbQueryEndpointInformation param;
188  param.endpoint_index = endpoint_index;
189
190  // Send IOCTL
191  DWORD ret_bytes = 0;
192  BOOL ret = DeviceIoControl(usb_device_handle,
193                             ADB_IOCTL_GET_ENDPOINT_INFORMATION,
194                             &param, sizeof(param),
195                             info, sizeof(AdbEndpointInformation),
196                             &ret_bytes,
197                             NULL);
198  ATLASSERT(!ret || (sizeof(AdbEndpointInformation) == ret_bytes));
199
200  // Preserve error accross CloseHandle
201  ULONG error = ret ? NO_ERROR : GetLastError();
202
203  ::CloseHandle(usb_device_handle);
204
205  if (NO_ERROR != error) {
206    SetLastError(error);
207  }
208
209  return ret ? true : false;
210}
211
212ADBAPIHANDLE AdbLegacyInterfaceObject::OpenEndpoint(
213    UCHAR endpoint_index,
214    AdbOpenAccessType access_type,
215    AdbOpenSharingMode sharing_mode) {
216  // Convert index into name and ID.
217  std::wstring endpoint_name;
218  UCHAR endpoint_id;
219
220  try {
221    if ((ADB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index) ||
222        (def_read_endpoint_ == endpoint_index)) {
223      endpoint_name = DEVICE_BULK_READ_PIPE_NAME;
224      endpoint_id = read_endpoint_id_;
225      endpoint_index = def_read_endpoint_;
226    } else if ((ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX == endpoint_index) ||
227               (def_write_endpoint_ == endpoint_index)) {
228      endpoint_name = DEVICE_BULK_WRITE_PIPE_NAME;
229      endpoint_id = write_endpoint_id_;
230      endpoint_index = def_write_endpoint_;
231    } else {
232      SetLastError(ERROR_INVALID_PARAMETER);
233      return false;
234    }
235  } catch (...) {
236    // We don't expect exceptions other than OOM thrown here.
237    SetLastError(ERROR_OUTOFMEMORY);
238    return NULL;
239  }
240
241  return OpenEndpoint(endpoint_name.c_str(), endpoint_id, endpoint_index,
242                      access_type, sharing_mode);
243}
244
245ADBAPIHANDLE AdbLegacyInterfaceObject::OpenEndpoint(
246    const wchar_t* endpoint_name,
247    UCHAR endpoint_id,
248    UCHAR endpoint_index,
249    AdbOpenAccessType access_type,
250    AdbOpenSharingMode sharing_mode) {
251  if (!IsOpened()) {
252    SetLastError(ERROR_INVALID_HANDLE);
253    return false;
254  }
255
256  AdbLegacyEndpointObject* adb_endpoint = NULL;
257
258  try {
259    adb_endpoint =
260        new AdbLegacyEndpointObject(this, endpoint_id, endpoint_index);
261  } catch (...) {
262    // We don't expect exceptions other than OOM thrown here.
263    SetLastError(ERROR_OUTOFMEMORY);
264    return NULL;
265  }
266
267  // Build full path to the object
268  std::wstring endpoint_path = interface_name();
269  endpoint_path += L"\\";
270  endpoint_path += endpoint_name;
271
272  ADBAPIHANDLE ret = adb_endpoint->CreateHandle(endpoint_path.c_str(),
273                                                access_type,
274                                                sharing_mode);
275
276  adb_endpoint->Release();
277
278  return ret;
279}
280
281bool AdbLegacyInterfaceObject::CacheUsbDeviceDescriptor(
282    HANDLE usb_device_handle) {
283  DWORD ret_bytes = 0;
284  BOOL ret = DeviceIoControl(usb_device_handle,
285                             ADB_IOCTL_GET_USB_DEVICE_DESCRIPTOR,
286                             NULL, 0,
287                             &usb_device_descriptor_,
288                             sizeof(usb_device_descriptor_),
289                             &ret_bytes,
290                             NULL);
291  ATLASSERT(!ret || (sizeof(USB_DEVICE_DESCRIPTOR) == ret_bytes));
292
293  return ret ? true : false;
294}
295
296bool AdbLegacyInterfaceObject::CacheUsbConfigurationDescriptor(
297    HANDLE usb_device_handle) {
298  DWORD ret_bytes = 0;
299  BOOL ret = DeviceIoControl(usb_device_handle,
300                             ADB_IOCTL_GET_USB_CONFIGURATION_DESCRIPTOR,
301                             NULL, 0,
302                             &usb_config_descriptor_,
303                             sizeof(usb_config_descriptor_),
304                             &ret_bytes,
305                             NULL);
306  ATLASSERT(!ret || (sizeof(USB_CONFIGURATION_DESCRIPTOR) == ret_bytes));
307
308  return ret ? true : false;
309}
310
311bool AdbLegacyInterfaceObject::CacheUsbInterfaceDescriptor(
312    HANDLE usb_device_handle) {
313  DWORD ret_bytes = 0;
314  BOOL ret = DeviceIoControl(usb_device_handle,
315                             ADB_IOCTL_GET_USB_INTERFACE_DESCRIPTOR,
316                             NULL, 0,
317                             &usb_interface_descriptor_,
318                             sizeof(usb_interface_descriptor_),
319                             &ret_bytes,
320                             NULL);
321  ATLASSERT(!ret || (sizeof(USB_INTERFACE_DESCRIPTOR) == ret_bytes));
322
323  return ret ? true : false;
324}
325