blob: a09610f5c4cd2372cac8aa8789f06694b479ba6e [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
Anatol Pomazau5ae3f932012-02-28 07:21:08 -080012 * the documentation and/or other materials provided with the
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080013 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
Anatol Pomazau5ae3f932012-02-28 07:21:08 -080022 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080023 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <windows.h>
30#include <winerror.h>
31#include <errno.h>
32#include <usb100.h>
33#include <adb_api.h>
34#include <stdio.h>
Christopher Ferris67a7a4a2014-11-06 14:34:24 -080035#include <stdlib.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080036
37#include "usb.h"
38
39//#define TRACE_USB 1
40#if TRACE_USB
41#define DBG(x...) fprintf(stderr, x)
42#else
43#define DBG(x...)
44#endif
45
David Krause913eb8b2011-03-08 14:10:16 +080046#define MAX_USBFS_BULK_SIZE (1024 * 1024)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080047
48/** Structure usb_handle describes our connection to the usb device via
49 AdbWinApi.dll. This structure is returned from usb_open() routine and
50 is expected in each subsequent call that is accessing the device.
51*/
52struct usb_handle {
53 /// Handle to USB interface
54 ADBAPIHANDLE adb_interface;
Anatol Pomazau5ae3f932012-02-28 07:21:08 -080055
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080056 /// Handle to USB read pipe (endpoint)
57 ADBAPIHANDLE adb_read_pipe;
Anatol Pomazau5ae3f932012-02-28 07:21:08 -080058
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080059 /// Handle to USB write pipe (endpoint)
60 ADBAPIHANDLE adb_write_pipe;
Anatol Pomazau5ae3f932012-02-28 07:21:08 -080061
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080062 /// Interface name
63 char* interface_name;
64};
65
66/// Class ID assigned to the device by androidusb.sys
67static const GUID usb_class_id = ANDROID_USB_CLASS_ID;
68
69
70/// Checks if interface (device) matches certain criteria
71int recognized_device(usb_handle* handle, ifc_match_func callback);
72
73/// Opens usb interface (device) by interface (device) name.
74usb_handle* do_usb_open(const wchar_t* interface_name);
75
76/// Writes data to the opened usb handle
77int usb_write(usb_handle* handle, const void* data, int len);
78
79/// Reads data using the opened usb handle
80int usb_read(usb_handle *handle, void* data, int len);
81
82/// Cleans up opened usb handle
83void usb_cleanup_handle(usb_handle* handle);
84
85/// Cleans up (but don't close) opened usb handle
86void usb_kick(usb_handle* handle);
87
88/// Closes opened usb handle
89int usb_close(usb_handle* handle);
90
91
92usb_handle* do_usb_open(const wchar_t* interface_name) {
93 // Allocate our handle
94 usb_handle* ret = (usb_handle*)malloc(sizeof(usb_handle));
95 if (NULL == ret)
96 return NULL;
97
98 // Create interface.
99 ret->adb_interface = AdbCreateInterfaceByName(interface_name);
100
101 if (NULL == ret->adb_interface) {
102 free(ret);
103 errno = GetLastError();
104 return NULL;
105 }
106
107 // Open read pipe (endpoint)
108 ret->adb_read_pipe =
109 AdbOpenDefaultBulkReadEndpoint(ret->adb_interface,
110 AdbOpenAccessTypeReadWrite,
111 AdbOpenSharingModeReadWrite);
112 if (NULL != ret->adb_read_pipe) {
113 // Open write pipe (endpoint)
114 ret->adb_write_pipe =
115 AdbOpenDefaultBulkWriteEndpoint(ret->adb_interface,
116 AdbOpenAccessTypeReadWrite,
117 AdbOpenSharingModeReadWrite);
118 if (NULL != ret->adb_write_pipe) {
119 // Save interface name
120 unsigned long name_len = 0;
121
122 // First get expected name length
123 AdbGetInterfaceName(ret->adb_interface,
124 NULL,
125 &name_len,
126 true);
127 if (0 != name_len) {
128 ret->interface_name = (char*)malloc(name_len);
129
130 if (NULL != ret->interface_name) {
131 // Now save the name
132 if (AdbGetInterfaceName(ret->adb_interface,
133 ret->interface_name,
134 &name_len,
135 true)) {
136 // We're done at this point
137 return ret;
138 }
139 } else {
140 SetLastError(ERROR_OUTOFMEMORY);
141 }
142 }
143 }
144 }
145
146 // Something went wrong.
147 errno = GetLastError();
148 usb_cleanup_handle(ret);
149 free(ret);
150 SetLastError(errno);
151
152 return NULL;
153}
154
155int usb_write(usb_handle* handle, const void* data, int len) {
Jiebing Libbb79812012-08-07 14:29:21 +0800156 unsigned long time_out = 5000;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800157 unsigned long written = 0;
158 unsigned count = 0;
159 int ret;
160
161 DBG("usb_write %d\n", len);
162 if (NULL != handle) {
163 // Perform write
164 while(len > 0) {
David Krause913eb8b2011-03-08 14:10:16 +0800165 int xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800166 ret = AdbWriteEndpointSync(handle->adb_write_pipe,
167 (void*)data,
168 (unsigned long)xfer,
169 &written,
170 time_out);
171 errno = GetLastError();
172 DBG("AdbWriteEndpointSync returned %d, errno: %d\n", ret, errno);
173 if (ret == 0) {
174 // assume ERROR_INVALID_HANDLE indicates we are disconnected
175 if (errno == ERROR_INVALID_HANDLE)
176 usb_kick(handle);
177 return -1;
178 }
179
180 count += written;
181 len -= written;
Mark Salyzyn5957c1f2014-04-30 14:05:28 -0700182 data = (const char *)data + written;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800183
184 if (len == 0)
185 return count;
186 }
187 } else {
188 DBG("usb_write NULL handle\n");
189 SetLastError(ERROR_INVALID_HANDLE);
190 }
191
192 DBG("usb_write failed: %d\n", errno);
193
194 return -1;
195}
196
197int usb_read(usb_handle *handle, void* data, int len) {
Jiebing Libbb79812012-08-07 14:29:21 +0800198 unsigned long time_out = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800199 unsigned long read = 0;
200 int ret;
201
202 DBG("usb_read %d\n", len);
203 if (NULL != handle) {
204 while (1) {
David Krause913eb8b2011-03-08 14:10:16 +0800205 int xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800206
207 ret = AdbReadEndpointSync(handle->adb_read_pipe,
208 (void*)data,
209 (unsigned long)xfer,
210 &read,
211 time_out);
212 errno = GetLastError();
213 DBG("usb_read got: %ld, expected: %d, errno: %d\n", read, xfer, errno);
214 if (ret) {
215 return read;
Jiebing Libbb79812012-08-07 14:29:21 +0800216 } else {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800217 // assume ERROR_INVALID_HANDLE indicates we are disconnected
218 if (errno == ERROR_INVALID_HANDLE)
219 usb_kick(handle);
220 break;
221 }
222 // else we timed out - try again
223 }
224 } else {
225 DBG("usb_read NULL handle\n");
226 SetLastError(ERROR_INVALID_HANDLE);
227 }
228
229 DBG("usb_read failed: %d\n", errno);
230
231 return -1;
232}
233
234void usb_cleanup_handle(usb_handle* handle) {
235 if (NULL != handle) {
236 if (NULL != handle->interface_name)
237 free(handle->interface_name);
238 if (NULL != handle->adb_write_pipe)
239 AdbCloseHandle(handle->adb_write_pipe);
240 if (NULL != handle->adb_read_pipe)
241 AdbCloseHandle(handle->adb_read_pipe);
242 if (NULL != handle->adb_interface)
243 AdbCloseHandle(handle->adb_interface);
244
245 handle->interface_name = NULL;
246 handle->adb_write_pipe = NULL;
247 handle->adb_read_pipe = NULL;
248 handle->adb_interface = NULL;
249 }
250}
251
252void usb_kick(usb_handle* handle) {
253 if (NULL != handle) {
254 usb_cleanup_handle(handle);
255 } else {
256 SetLastError(ERROR_INVALID_HANDLE);
257 errno = ERROR_INVALID_HANDLE;
258 }
259}
260
261int usb_close(usb_handle* handle) {
262 DBG("usb_close\n");
263
264 if (NULL != handle) {
265 // Cleanup handle
266 usb_cleanup_handle(handle);
267 free(handle);
268 }
269
270 return 0;
271}
272
Mark Wachsler157b0012013-10-02 09:35:38 -0400273int usb_wait_for_disconnect(usb_handle *usb) {
274 /* TODO: Punt for now */
275 return 0;
276}
277
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800278int recognized_device(usb_handle* handle, ifc_match_func callback) {
279 struct usb_ifc_info info;
280 USB_DEVICE_DESCRIPTOR device_desc;
281 USB_INTERFACE_DESCRIPTOR interf_desc;
282
283 if (NULL == handle)
284 return 0;
285
286 // Check vendor and product id first
287 if (!AdbGetUsbDeviceDescriptor(handle->adb_interface,
288 &device_desc)) {
289 return 0;
290 }
291
292 // Then check interface properties
293 if (!AdbGetUsbInterfaceDescriptor(handle->adb_interface,
294 &interf_desc)) {
295 return 0;
296 }
297
298 // Must have two endpoints
299 if (2 != interf_desc.bNumEndpoints) {
300 return 0;
301 }
302
303 info.dev_vendor = device_desc.idVendor;
304 info.dev_product = device_desc.idProduct;
305 info.dev_class = device_desc.bDeviceClass;
306 info.dev_subclass = device_desc.bDeviceSubClass;
307 info.dev_protocol = device_desc.bDeviceProtocol;
308 info.ifc_class = interf_desc.bInterfaceClass;
309 info.ifc_subclass = interf_desc.bInterfaceSubClass;
310 info.ifc_protocol = interf_desc.bInterfaceProtocol;
Elliott Hughesb4add9b2009-10-06 18:07:49 -0700311 info.writable = 1;
Anatol Pomazau5ae3f932012-02-28 07:21:08 -0800312
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800313 // read serial number (if there is one)
314 unsigned long serial_number_len = sizeof(info.serial_number);
315 if (!AdbGetSerialNumber(handle->adb_interface, info.serial_number,
316 &serial_number_len, true)) {
317 info.serial_number[0] = 0;
318 }
319
Scott Anderson13081c62012-04-06 12:39:30 -0700320 info.device_path[0] = 0;
321
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800322 if (callback(&info) == 0) {
323 return 1;
324 }
325
326 return 0;
327}
328
329static usb_handle *find_usb_device(ifc_match_func callback) {
330 usb_handle* handle = NULL;
331 char entry_buffer[2048];
332 char interf_name[2048];
333 AdbInterfaceInfo* next_interface = (AdbInterfaceInfo*)(&entry_buffer[0]);
334 unsigned long entry_buffer_size = sizeof(entry_buffer);
335 char* copy_name;
336
337 // Enumerate all present and active interfaces.
338 ADBAPIHANDLE enum_handle =
339 AdbEnumInterfaces(usb_class_id, true, true, true);
340
341 if (NULL == enum_handle)
342 return NULL;
343
344 while (AdbNextInterface(enum_handle, next_interface, &entry_buffer_size)) {
345 // TODO(vchtchetkine): FIXME - temp hack converting wchar_t into char.
346 // It would be better to change AdbNextInterface so it will return
347 // interface name as single char string.
348 const wchar_t* wchar_name = next_interface->device_name;
349 for(copy_name = interf_name;
350 L'\0' != *wchar_name;
351 wchar_name++, copy_name++) {
352 *copy_name = (char)(*wchar_name);
353 }
354 *copy_name = '\0';
355
356 handle = do_usb_open(next_interface->device_name);
357 if (NULL != handle) {
358 // Lets see if this interface (device) belongs to us
359 if (recognized_device(handle, callback)) {
360 // found it!
361 break;
362 } else {
363 usb_cleanup_handle(handle);
364 free(handle);
365 handle = NULL;
366 }
367 }
368
369 entry_buffer_size = sizeof(entry_buffer);
370 }
371
372 AdbCloseHandle(enum_handle);
373 return handle;
374}
375
376usb_handle *usb_open(ifc_match_func callback)
377{
378 return find_usb_device(callback);
379}
380
381// called from fastboot.c
382void sleep(int seconds)
383{
384 Sleep(seconds * 1000);
385}