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 helper routines used
19 in the API.
20 */
21
22 #include "stdafx.h"
23 #include "adb_api.h"
24 #include "adb_api_legacy.h"
25 #include "adb_helper_routines.h"
26 #include "adb_interface_enum.h"
27
GetSDKComplientParam(AdbOpenAccessType access_type,AdbOpenSharingMode sharing_mode,ULONG * desired_access,ULONG * desired_sharing)28 bool GetSDKComplientParam(AdbOpenAccessType access_type,
29 AdbOpenSharingMode sharing_mode,
30 ULONG* desired_access,
31 ULONG* desired_sharing) {
32 if (NULL != desired_access) {
33 switch (access_type) {
34 case AdbOpenAccessTypeReadWrite:
35 *desired_access = GENERIC_READ | GENERIC_WRITE;
36 break;
37
38 case AdbOpenAccessTypeRead:
39 *desired_access = GENERIC_READ;
40 break;
41
42 case AdbOpenAccessTypeWrite:
43 *desired_access = GENERIC_WRITE;
44 break;
45
46 case AdbOpenAccessTypeQueryInfo:
47 *desired_access = FILE_READ_ATTRIBUTES | FILE_READ_EA;
48 break;
49
50 default:
51 SetLastError(ERROR_INVALID_ACCESS);
52 return false;
53 }
54 }
55
56 if (NULL != desired_sharing) {
57 switch (sharing_mode) {
58 case AdbOpenSharingModeReadWrite:
59 *desired_sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
60 break;
61
62 case AdbOpenSharingModeRead:
63 *desired_sharing = FILE_SHARE_READ;
64 break;
65
66 case AdbOpenSharingModeWrite:
67 *desired_sharing = FILE_SHARE_WRITE;
68 break;
69
70 case AdbOpenSharingModeExclusive:
71 *desired_sharing = 0;
72 break;
73
74 default:
75 SetLastError(ERROR_INVALID_PARAMETER);
76 return false;
77 }
78 }
79
80 return true;
81 }
82
EnumerateDeviceInterfaces(HDEVINFO hardware_dev_info,GUID class_id,bool exclude_removed,bool active_only,AdbEnumInterfaceArray * interfaces)83 bool EnumerateDeviceInterfaces(HDEVINFO hardware_dev_info,
84 GUID class_id,
85 bool exclude_removed,
86 bool active_only,
87 AdbEnumInterfaceArray* interfaces) {
88 AdbEnumInterfaceArray tmp;
89 bool ret = false;
90
91 // Enumerate interfaces on this device
92 for (ULONG index = 0; ; index++) {
93 SP_DEVICE_INTERFACE_DATA interface_data;
94 interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
95
96 // SetupDiEnumDeviceInterfaces() returns information about device
97 // interfaces exposed by one or more devices defined by our interface
98 // class. Each call returns information about one interface. The routine
99 // can be called repeatedly to get information about several interfaces
100 // exposed by one or more devices.
101 if (SetupDiEnumDeviceInterfaces(hardware_dev_info,
102 0,
103 &class_id,
104 index,
105 &interface_data)) {
106 // Satisfy "exclude removed" and "active only" filters.
107 if ((!exclude_removed || (0 == (interface_data.Flags & SPINT_REMOVED))) &&
108 (!active_only || (interface_data.Flags & SPINT_ACTIVE))) {
109 std::wstring dev_name;
110
111 if (GetUsbDeviceName(hardware_dev_info, &interface_data, &dev_name)) {
112 try {
113 // Add new entry to the array
114 tmp.push_back(AdbInstanceEnumEntry(dev_name.c_str(),
115 interface_data.InterfaceClassGuid,
116 interface_data.Flags));
117 } catch (... ) {
118 SetLastError(ERROR_OUTOFMEMORY);
119 break;
120 }
121 } else {
122 // Something went wrong in getting device name
123 break;
124 }
125 }
126 } else {
127 if (ERROR_NO_MORE_ITEMS == GetLastError()) {
128 // There are no more items in the list. Enum is completed.
129 ret = true;
130 break;
131 } else {
132 // Something went wrong in SDK enum
133 break;
134 }
135 }
136 }
137
138 // On success, swap temp array with the returning one
139 if (ret)
140 interfaces->swap(tmp);
141
142 return ret;
143 }
144
EnumerateDeviceInterfaces(GUID class_id,ULONG flags,bool exclude_removed,bool active_only,AdbEnumInterfaceArray * interfaces)145 bool EnumerateDeviceInterfaces(GUID class_id,
146 ULONG flags,
147 bool exclude_removed,
148 bool active_only,
149 AdbEnumInterfaceArray* interfaces) {
150 // Open a handle to the plug and play dev node.
151 // SetupDiGetClassDevs() returns a device information set that
152 // contains info on all installed devices of a specified class.
153 HDEVINFO hardware_dev_info =
154 SetupDiGetClassDevs(&class_id, NULL, NULL, flags);
155
156 bool ret = false;
157
158 if (INVALID_HANDLE_VALUE != hardware_dev_info) {
159 // Do the enum
160 ret = EnumerateDeviceInterfaces(hardware_dev_info,
161 class_id,
162 exclude_removed,
163 active_only,
164 interfaces);
165
166 // Preserve last error accross hardware_dev_info destruction
167 ULONG error_to_report = ret ? NO_ERROR : GetLastError();
168
169 SetupDiDestroyDeviceInfoList(hardware_dev_info);
170
171 if (NO_ERROR != error_to_report)
172 SetLastError(error_to_report);
173 }
174
175 return ret;
176 }
177
GetUsbDeviceDetails(HDEVINFO hardware_dev_info,PSP_DEVICE_INTERFACE_DATA dev_info_data,PSP_DEVICE_INTERFACE_DETAIL_DATA * dev_info_detail_data)178 bool GetUsbDeviceDetails(
179 HDEVINFO hardware_dev_info,
180 PSP_DEVICE_INTERFACE_DATA dev_info_data,
181 PSP_DEVICE_INTERFACE_DETAIL_DATA* dev_info_detail_data) {
182 ULONG required_len = 0;
183
184 // First query for the structure size. At this point we expect this call
185 // to fail with ERROR_INSUFFICIENT_BUFFER error code.
186 if (SetupDiGetDeviceInterfaceDetail(hardware_dev_info,
187 dev_info_data,
188 NULL,
189 0,
190 &required_len,
191 NULL)) {
192 return false;
193 }
194
195 if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
196 return false;
197
198 // Allocate buffer for the structure
199 PSP_DEVICE_INTERFACE_DETAIL_DATA buffer =
200 reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(malloc(required_len));
201
202 if (NULL == buffer) {
203 SetLastError(ERROR_OUTOFMEMORY);
204 return false;
205 }
206
207 buffer->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
208
209 // Retrieve the information from Plug and Play.
210 if (SetupDiGetDeviceInterfaceDetail(hardware_dev_info,
211 dev_info_data,
212 buffer,
213 required_len,
214 &required_len,
215 NULL)) {
216 *dev_info_detail_data = buffer;
217 return true;
218 } else {
219 // Free the buffer if this call failed
220 free(buffer);
221
222 return false;
223 }
224 }
225
GetUsbDeviceName(HDEVINFO hardware_dev_info,PSP_DEVICE_INTERFACE_DATA dev_info_data,std::wstring * name)226 bool GetUsbDeviceName(HDEVINFO hardware_dev_info,
227 PSP_DEVICE_INTERFACE_DATA dev_info_data,
228 std::wstring* name) {
229 PSP_DEVICE_INTERFACE_DETAIL_DATA func_class_dev_data = NULL;
230 if (!GetUsbDeviceDetails(hardware_dev_info,
231 dev_info_data,
232 &func_class_dev_data)) {
233 return false;
234 }
235
236 try {
237 *name = func_class_dev_data->DevicePath;
238 } catch (...) {
239 SetLastError(ERROR_OUTOFMEMORY);
240 }
241
242 free(func_class_dev_data);
243
244 return !name->empty();
245 }
246
IsLegacyInterface(const wchar_t * interface_name)247 bool IsLegacyInterface(const wchar_t* interface_name) {
248 // Open USB device for this intefface
249 HANDLE usb_device_handle = CreateFile(interface_name,
250 GENERIC_READ | GENERIC_WRITE,
251 FILE_SHARE_READ | FILE_SHARE_WRITE,
252 NULL,
253 OPEN_EXISTING,
254 0,
255 NULL);
256 if (INVALID_HANDLE_VALUE == usb_device_handle)
257 return NULL;
258
259 // Try to issue ADB_IOCTL_GET_USB_DEVICE_DESCRIPTOR IOCTL that is supported
260 // by the legacy driver, but is not implemented in the WinUsb driver.
261 DWORD ret_bytes = 0;
262 USB_DEVICE_DESCRIPTOR descriptor;
263 BOOL ret = DeviceIoControl(usb_device_handle,
264 ADB_IOCTL_GET_USB_DEVICE_DESCRIPTOR,
265 NULL, 0,
266 &descriptor,
267 sizeof(descriptor),
268 &ret_bytes,
269 NULL);
270 ::CloseHandle(usb_device_handle);
271
272 // If IOCTL succeeded we've got legacy driver underneath.
273 return ret ? true : false;
274 }
275