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