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