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