blob: 3c5533b4fdf18c9f5a45686cf439ffe83e24f615 [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2007 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
Dan Albert76649012015-02-24 15:51:19 -080017#include <winsock2.h> // winsock.h *must* be included before windows.h.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080018#include <adb_api.h>
Dan Albert76649012015-02-24 15:51:19 -080019#include <errno.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080020#include <stdio.h>
Christopher Ferris67a7a4a2014-11-06 14:34:24 -080021#include <stdlib.h>
Dan Albert76649012015-02-24 15:51:19 -080022#include <usb100.h>
23#include <windows.h>
24#include <winerror.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080025
26#include "sysdeps.h"
27
28#define TRACE_TAG TRACE_USB
29#include "adb.h"
Dan Albert76649012015-02-24 15:51:19 -080030#include "transport.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080031
32/** Structure usb_handle describes our connection to the usb device via
33 AdbWinApi.dll. This structure is returned from usb_open() routine and
34 is expected in each subsequent call that is accessing the device.
35*/
36struct usb_handle {
37 /// Previous entry in the list of opened usb handles
38 usb_handle *prev;
39
40 /// Next entry in the list of opened usb handles
41 usb_handle *next;
42
43 /// Handle to USB interface
44 ADBAPIHANDLE adb_interface;
45
46 /// Handle to USB read pipe (endpoint)
47 ADBAPIHANDLE adb_read_pipe;
48
49 /// Handle to USB write pipe (endpoint)
50 ADBAPIHANDLE adb_write_pipe;
51
52 /// Interface name
53 char* interface_name;
54
55 /// Mask for determining when to use zero length packets
56 unsigned zero_mask;
57};
58
59/// Class ID assigned to the device by androidusb.sys
60static const GUID usb_class_id = ANDROID_USB_CLASS_ID;
61
62/// List of opened usb handles
63static usb_handle handle_list = {
64 .prev = &handle_list,
65 .next = &handle_list,
66};
67
68/// Locker for the list of opened usb handles
69ADB_MUTEX_DEFINE( usb_lock );
70
71/// Checks if there is opened usb handle in handle_list for this device.
72int known_device(const char* dev_name);
73
74/// Checks if there is opened usb handle in handle_list for this device.
75/// usb_lock mutex must be held before calling this routine.
76int known_device_locked(const char* dev_name);
77
78/// Registers opened usb handle (adds it to handle_list).
79int register_new_device(usb_handle* handle);
80
81/// Checks if interface (device) matches certain criteria
82int recognized_device(usb_handle* handle);
83
84/// Enumerates present and available interfaces (devices), opens new ones and
85/// registers usb transport for them.
86void find_devices();
87
88/// Entry point for thread that polls (every second) for new usb interfaces.
89/// This routine calls find_devices in infinite loop.
90void* device_poll_thread(void* unused);
91
92/// Initializes this module
93void usb_init();
94
95/// Cleans up this module
96void usb_cleanup();
97
98/// Opens usb interface (device) by interface (device) name.
99usb_handle* do_usb_open(const wchar_t* interface_name);
100
101/// Writes data to the opened usb handle
102int usb_write(usb_handle* handle, const void* data, int len);
103
104/// Reads data using the opened usb handle
105int usb_read(usb_handle *handle, void* data, int len);
106
107/// Cleans up opened usb handle
108void usb_cleanup_handle(usb_handle* handle);
109
110/// Cleans up (but don't close) opened usb handle
111void usb_kick(usb_handle* handle);
112
113/// Closes opened usb handle
114int usb_close(usb_handle* handle);
115
116/// Gets interface (device) name for an opened usb handle
117const char *usb_name(usb_handle* handle);
118
119int known_device_locked(const char* dev_name) {
120 usb_handle* usb;
121
122 if (NULL != dev_name) {
123 // Iterate through the list looking for the name match.
124 for(usb = handle_list.next; usb != &handle_list; usb = usb->next) {
125 // In Windows names are not case sensetive!
126 if((NULL != usb->interface_name) &&
127 (0 == stricmp(usb->interface_name, dev_name))) {
128 return 1;
129 }
130 }
131 }
132
133 return 0;
134}
135
136int known_device(const char* dev_name) {
137 int ret = 0;
138
139 if (NULL != dev_name) {
140 adb_mutex_lock(&usb_lock);
141 ret = known_device_locked(dev_name);
142 adb_mutex_unlock(&usb_lock);
143 }
144
145 return ret;
146}
147
148int register_new_device(usb_handle* handle) {
149 if (NULL == handle)
150 return 0;
151
152 adb_mutex_lock(&usb_lock);
153
154 // Check if device is already in the list
155 if (known_device_locked(handle->interface_name)) {
156 adb_mutex_unlock(&usb_lock);
157 return 0;
158 }
159
160 // Not in the list. Add this handle to the list.
161 handle->next = &handle_list;
162 handle->prev = handle_list.prev;
163 handle->prev->next = handle;
164 handle->next->prev = handle;
165
166 adb_mutex_unlock(&usb_lock);
167
168 return 1;
169}
170
171void* device_poll_thread(void* unused) {
172 D("Created device thread\n");
173
174 while(1) {
175 find_devices();
176 adb_sleep_ms(1000);
177 }
178
179 return NULL;
180}
181
182void usb_init() {
183 adb_thread_t tid;
184
185 if(adb_thread_create(&tid, device_poll_thread, NULL)) {
186 fatal_errno("cannot create input thread");
187 }
188}
189
190void usb_cleanup() {
191}
192
193usb_handle* do_usb_open(const wchar_t* interface_name) {
194 // Allocate our handle
195 usb_handle* ret = (usb_handle*)malloc(sizeof(usb_handle));
196 if (NULL == ret)
197 return NULL;
198
199 // Set linkers back to the handle
200 ret->next = ret;
201 ret->prev = ret;
202
203 // Create interface.
204 ret->adb_interface = AdbCreateInterfaceByName(interface_name);
205
206 if (NULL == ret->adb_interface) {
207 free(ret);
208 errno = GetLastError();
209 return NULL;
210 }
211
212 // Open read pipe (endpoint)
213 ret->adb_read_pipe =
214 AdbOpenDefaultBulkReadEndpoint(ret->adb_interface,
215 AdbOpenAccessTypeReadWrite,
216 AdbOpenSharingModeReadWrite);
217 if (NULL != ret->adb_read_pipe) {
218 // Open write pipe (endpoint)
219 ret->adb_write_pipe =
220 AdbOpenDefaultBulkWriteEndpoint(ret->adb_interface,
221 AdbOpenAccessTypeReadWrite,
222 AdbOpenSharingModeReadWrite);
223 if (NULL != ret->adb_write_pipe) {
224 // Save interface name
225 unsigned long name_len = 0;
226
227 // First get expected name length
228 AdbGetInterfaceName(ret->adb_interface,
229 NULL,
230 &name_len,
231 true);
232 if (0 != name_len) {
233 ret->interface_name = (char*)malloc(name_len);
234
235 if (NULL != ret->interface_name) {
236 // Now save the name
237 if (AdbGetInterfaceName(ret->adb_interface,
238 ret->interface_name,
239 &name_len,
240 true)) {
241 // We're done at this point
242 return ret;
243 }
244 } else {
245 SetLastError(ERROR_OUTOFMEMORY);
246 }
247 }
248 }
249 }
250
251 // Something went wrong.
JP Abgrall408fa572011-03-16 15:57:42 -0700252 int saved_errno = GetLastError();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800253 usb_cleanup_handle(ret);
254 free(ret);
JP Abgrall408fa572011-03-16 15:57:42 -0700255 SetLastError(saved_errno);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800256
257 return NULL;
258}
259
260int usb_write(usb_handle* handle, const void* data, int len) {
Jack Ren1c4b7602011-08-12 18:39:04 +0800261 unsigned long time_out = 5000;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800262 unsigned long written = 0;
263 int ret;
264
265 D("usb_write %d\n", len);
266 if (NULL != handle) {
267 // Perform write
268 ret = AdbWriteEndpointSync(handle->adb_write_pipe,
269 (void*)data,
270 (unsigned long)len,
271 &written,
272 time_out);
JP Abgrall408fa572011-03-16 15:57:42 -0700273 int saved_errno = GetLastError();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800274
275 if (ret) {
276 // Make sure that we've written what we were asked to write
277 D("usb_write got: %ld, expected: %d\n", written, len);
278 if (written == (unsigned long)len) {
279 if(handle->zero_mask && (len & handle->zero_mask) == 0) {
280 // Send a zero length packet
281 AdbWriteEndpointSync(handle->adb_write_pipe,
282 (void*)data,
283 0,
284 &written,
285 time_out);
286 }
287 return 0;
288 }
289 } else {
290 // assume ERROR_INVALID_HANDLE indicates we are disconnected
JP Abgrall408fa572011-03-16 15:57:42 -0700291 if (saved_errno == ERROR_INVALID_HANDLE)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800292 usb_kick(handle);
293 }
JP Abgrall408fa572011-03-16 15:57:42 -0700294 errno = saved_errno;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800295 } else {
296 D("usb_write NULL handle\n");
297 SetLastError(ERROR_INVALID_HANDLE);
298 }
299
300 D("usb_write failed: %d\n", errno);
301
302 return -1;
303}
304
305int usb_read(usb_handle *handle, void* data, int len) {
Jack Ren1c4b7602011-08-12 18:39:04 +0800306 unsigned long time_out = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800307 unsigned long read = 0;
308 int ret;
309
310 D("usb_read %d\n", len);
311 if (NULL != handle) {
312 while (len > 0) {
313 int xfer = (len > 4096) ? 4096 : len;
314
315 ret = AdbReadEndpointSync(handle->adb_read_pipe,
Mark Salyzyn60299df2014-04-30 09:10:31 -0700316 data,
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800317 (unsigned long)xfer,
318 &read,
319 time_out);
JP Abgrall408fa572011-03-16 15:57:42 -0700320 int saved_errno = GetLastError();
321 D("usb_write got: %ld, expected: %d, errno: %d\n", read, xfer, saved_errno);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800322 if (ret) {
Mark Salyzyn60299df2014-04-30 09:10:31 -0700323 data = (char *)data + read;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800324 len -= read;
325
326 if (len == 0)
327 return 0;
Jack Ren1c4b7602011-08-12 18:39:04 +0800328 } else {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800329 // assume ERROR_INVALID_HANDLE indicates we are disconnected
JP Abgrall408fa572011-03-16 15:57:42 -0700330 if (saved_errno == ERROR_INVALID_HANDLE)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800331 usb_kick(handle);
332 break;
333 }
JP Abgrall408fa572011-03-16 15:57:42 -0700334 errno = saved_errno;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800335 }
336 } else {
337 D("usb_read NULL handle\n");
338 SetLastError(ERROR_INVALID_HANDLE);
339 }
340
341 D("usb_read failed: %d\n", errno);
342
343 return -1;
344}
345
346void usb_cleanup_handle(usb_handle* handle) {
347 if (NULL != handle) {
348 if (NULL != handle->interface_name)
349 free(handle->interface_name);
350 if (NULL != handle->adb_write_pipe)
351 AdbCloseHandle(handle->adb_write_pipe);
352 if (NULL != handle->adb_read_pipe)
353 AdbCloseHandle(handle->adb_read_pipe);
354 if (NULL != handle->adb_interface)
355 AdbCloseHandle(handle->adb_interface);
356
357 handle->interface_name = NULL;
358 handle->adb_write_pipe = NULL;
359 handle->adb_read_pipe = NULL;
360 handle->adb_interface = NULL;
361 }
362}
363
364void usb_kick(usb_handle* handle) {
365 if (NULL != handle) {
366 adb_mutex_lock(&usb_lock);
367
368 usb_cleanup_handle(handle);
369
370 adb_mutex_unlock(&usb_lock);
371 } else {
372 SetLastError(ERROR_INVALID_HANDLE);
373 errno = ERROR_INVALID_HANDLE;
374 }
375}
376
377int usb_close(usb_handle* handle) {
378 D("usb_close\n");
379
380 if (NULL != handle) {
381 // Remove handle from the list
382 adb_mutex_lock(&usb_lock);
383
384 if ((handle->next != handle) && (handle->prev != handle)) {
385 handle->next->prev = handle->prev;
386 handle->prev->next = handle->next;
387 handle->prev = handle;
388 handle->next = handle;
389 }
390
391 adb_mutex_unlock(&usb_lock);
392
393 // Cleanup handle
394 usb_cleanup_handle(handle);
395 free(handle);
396 }
397
398 return 0;
399}
400
401const char *usb_name(usb_handle* handle) {
402 if (NULL == handle) {
403 SetLastError(ERROR_INVALID_HANDLE);
404 errno = ERROR_INVALID_HANDLE;
405 return NULL;
406 }
407
408 return (const char*)handle->interface_name;
409}
410
411int recognized_device(usb_handle* handle) {
412 if (NULL == handle)
413 return 0;
414
415 // Check vendor and product id first
416 USB_DEVICE_DESCRIPTOR device_desc;
417
418 if (!AdbGetUsbDeviceDescriptor(handle->adb_interface,
419 &device_desc)) {
420 return 0;
421 }
422
423 // Then check interface properties
424 USB_INTERFACE_DESCRIPTOR interf_desc;
425
426 if (!AdbGetUsbInterfaceDescriptor(handle->adb_interface,
427 &interf_desc)) {
428 return 0;
429 }
430
431 // Must have two endpoints
432 if (2 != interf_desc.bNumEndpoints) {
433 return 0;
434 }
435
436 if (is_adb_interface(device_desc.idVendor, device_desc.idProduct,
437 interf_desc.bInterfaceClass, interf_desc.bInterfaceSubClass, interf_desc.bInterfaceProtocol)) {
438
439 if(interf_desc.bInterfaceProtocol == 0x01) {
440 AdbEndpointInformation endpoint_info;
441 // assuming zero is a valid bulk endpoint ID
442 if (AdbGetEndpointInformation(handle->adb_interface, 0, &endpoint_info)) {
443 handle->zero_mask = endpoint_info.max_packet_size - 1;
444 }
445 }
446
447 return 1;
448 }
449
450 return 0;
451}
452
453void find_devices() {
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200454 usb_handle* handle = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800455 char entry_buffer[2048];
456 char interf_name[2048];
457 AdbInterfaceInfo* next_interface = (AdbInterfaceInfo*)(&entry_buffer[0]);
458 unsigned long entry_buffer_size = sizeof(entry_buffer);
459 char* copy_name;
460
461 // Enumerate all present and active interfaces.
462 ADBAPIHANDLE enum_handle =
463 AdbEnumInterfaces(usb_class_id, true, true, true);
464
465 if (NULL == enum_handle)
466 return;
467
468 while (AdbNextInterface(enum_handle, next_interface, &entry_buffer_size)) {
469 // TODO: FIXME - temp hack converting wchar_t into char.
470 // It would be better to change AdbNextInterface so it will return
471 // interface name as single char string.
472 const wchar_t* wchar_name = next_interface->device_name;
473 for(copy_name = interf_name;
474 L'\0' != *wchar_name;
475 wchar_name++, copy_name++) {
476 *copy_name = (char)(*wchar_name);
477 }
478 *copy_name = '\0';
479
480 // Lets see if we already have this device in the list
481 if (!known_device(interf_name)) {
482 // This seems to be a new device. Open it!
483 handle = do_usb_open(next_interface->device_name);
484 if (NULL != handle) {
485 // Lets see if this interface (device) belongs to us
486 if (recognized_device(handle)) {
487 D("adding a new device %s\n", interf_name);
488 char serial_number[512];
489 unsigned long serial_number_len = sizeof(serial_number);
490 if (AdbGetSerialNumber(handle->adb_interface,
491 serial_number,
492 &serial_number_len,
493 true)) {
494 // Lets make sure that we don't duplicate this device
495 if (register_new_device(handle)) {
Scott Andersone109d262012-04-20 11:21:14 -0700496 register_usb_transport(handle, serial_number, NULL, 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800497 } else {
498 D("register_new_device failed for %s\n", interf_name);
499 usb_cleanup_handle(handle);
500 free(handle);
501 }
502 } else {
503 D("cannot get serial number\n");
504 usb_cleanup_handle(handle);
505 free(handle);
506 }
507 } else {
508 usb_cleanup_handle(handle);
509 free(handle);
510 }
511 }
512 }
513
514 entry_buffer_size = sizeof(entry_buffer);
515 }
516
517 AdbCloseHandle(enum_handle);
518}