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 
AdbLegacyInterfaceObject(const wchar_t * interf_name)27 AdbLegacyInterfaceObject::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 
~AdbLegacyInterfaceObject()35 AdbLegacyInterfaceObject::~AdbLegacyInterfaceObject() {
36 }
37 
CreateHandle()38 ADBAPIHANDLE 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 
GetSerialNumber(void * buffer,unsigned long * buffer_char_size,bool ansi)103 bool 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 
GetEndpointInformation(UCHAR endpoint_index,AdbEndpointInformation * info)171 bool 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 
OpenEndpoint(UCHAR endpoint_index,AdbOpenAccessType access_type,AdbOpenSharingMode sharing_mode)212 ADBAPIHANDLE 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 
OpenEndpoint(const wchar_t * endpoint_name,UCHAR endpoint_id,UCHAR endpoint_index,AdbOpenAccessType access_type,AdbOpenSharingMode sharing_mode)245 ADBAPIHANDLE 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 
CacheUsbDeviceDescriptor(HANDLE usb_device_handle)281 bool 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 
CacheUsbConfigurationDescriptor(HANDLE usb_device_handle)296 bool 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 
CacheUsbInterfaceDescriptor(HANDLE usb_device_handle)311 bool 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