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 17aed3c61c4437ebb05eadfb3bf85d6962c30b9935Yabin Cui#define TRACE_TAG USB 183313426fad9eaaf53017cdbde889ebcec91358ecDan Albert 193313426fad9eaaf53017cdbde889ebcec91358ecDan Albert#include "sysdeps.h" 203313426fad9eaaf53017cdbde889ebcec91358ecDan Albert 217664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include <ctype.h> 227664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include <dirent.h> 237664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include <errno.h> 247664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include <fcntl.h> 25812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes#include <linux/usb/ch9.h> 267664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include <linux/usbdevice_fs.h> 277664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include <linux/version.h> 28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h> 29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h> 30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h> 31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/ioctl.h> 32fe582b5d32d08d075be87f4c9193e24029963361Mike Lockwood#include <sys/time.h> 337664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include <sys/types.h> 347664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include <unistd.h> 35812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes 36812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes#include <chrono> 37812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes#include <condition_variable> 38812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes#include <list> 39812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes#include <mutex> 40812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes#include <string> 41dbe91eee26300be10d6f1a0b42451dd46ea68538Elliott Hughes#include <thread> 429309ecbcec428edfcb487ef697862bce59a1aed5Elliott Hughes 434f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/file.h> 444f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/stringprintf.h> 454f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/strings.h> 46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "adb.h" 487664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include "transport.h" 491c70e1bcbcced190b351d4fb418f32b4e428f496Josh Gao#include "usb.h" 50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 51dbe91eee26300be10d6f1a0b42451dd46ea68538Elliott Hughesusing namespace std::chrono_literals; 52812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughesusing namespace std::literals; 53812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes 54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* usb scan debugging is waaaay too verbose */ 55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define DBGX(x...) 56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 571c70e1bcbcced190b351d4fb418f32b4e428f496Josh Gaonamespace native { 581c70e1bcbcced190b351d4fb418f32b4e428f496Josh Gaostruct usb_handle : public ::usb_handle { 59812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes ~usb_handle() { 60812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (fd != -1) unix_close(fd); 61812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes } 62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 63812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes std::string path; 64812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes int fd = -1; 65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned char ep_in; 66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned char ep_out; 67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned zero_mask; 69812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes unsigned writeable = 1; 70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 71812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes usbdevfs_urb urb_in; 72812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes usbdevfs_urb urb_out; 73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 74812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes bool urb_in_busy = false; 75812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes bool urb_out_busy = false; 76812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes bool dead = false; 77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 78812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes std::condition_variable cv; 79812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes std::mutex mutex; 80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // for garbage collecting disconnected devices 82812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes bool mark; 83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // ID of thread currently in REAPURB 85812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes pthread_t reaper_thread = 0; 86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}; 87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 88b7b1edf974a93cc4bb9a2de7a5e9c9bce9ad178bJosh Gaostatic auto& g_usb_handles_mutex = *new std::mutex(); 89b7b1edf974a93cc4bb9a2de7a5e9c9bce9ad178bJosh Gaostatic auto& g_usb_handles = *new std::list<usb_handle*>(); 90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 91812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughesstatic int is_known_device(const char* dev_name) { 92812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes std::lock_guard<std::mutex> lock(g_usb_handles_mutex); 93812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes for (usb_handle* usb : g_usb_handles) { 94812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (usb->path == dev_name) { 95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // set mark flag to indicate this device is still alive 96812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes usb->mark = true; 97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 1; 98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 103812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughesstatic void kick_disconnected_devices() { 104812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes std::lock_guard<std::mutex> lock(g_usb_handles_mutex); 105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // kick any devices in the device list that were not found in the device scan 106812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes for (usb_handle* usb : g_usb_handles) { 107812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (!usb->mark) { 108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project usb_kick(usb); 109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 110812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes usb->mark = false; 111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 115812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughesstatic inline bool contains_non_digit(const char* name) { 116812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes while (*name) { 117812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (!isdigit(*name++)) return true; 118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 119812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes return false; 120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 122812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughesstatic void find_usb_device(const std::string& base, 1230927bf9690127bc45cf8837a1467759e9720399aMike Lockwood void (*register_device_callback) 124812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes (const char*, const char*, unsigned char, unsigned char, int, int, unsigned)) 125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 126812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes std::unique_ptr<DIR, int(*)(DIR*)> bus_dir(opendir(base.c_str()), closedir); 127812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (!bus_dir) return; 128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 129812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes dirent* de; 130812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes while ((de = readdir(bus_dir.get())) != 0) { 131812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (contains_non_digit(de->d_name)) continue; 132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 133812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes std::string bus_name = base + "/" + de->d_name; 134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 135812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes std::unique_ptr<DIR, int(*)(DIR*)> dev_dir(opendir(bus_name.c_str()), closedir); 136812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (!dev_dir) continue; 137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 138812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes while ((de = readdir(dev_dir.get()))) { 139b596608f098937049fd98c5896cf72ebbf3584aeMike Lockwood unsigned char devdesc[4096]; 140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned char* bufptr = devdesc; 14107e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood unsigned char* bufend; 142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usb_device_descriptor* device; 143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usb_config_descriptor* config; 144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usb_interface_descriptor* interface; 145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usb_endpoint_descriptor *ep1, *ep2; 146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned zero_mask = 0; 147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned vid, pid; 148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 149812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (contains_non_digit(de->d_name)) continue; 150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 151812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes std::string dev_name = bus_name + "/" + de->d_name; 152812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (is_known_device(dev_name.c_str())) { 153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 156812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes int fd = unix_open(dev_name.c_str(), O_RDONLY | O_CLOEXEC); 157812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (fd == -1) { 158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 161812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes size_t desclength = unix_read(fd, devdesc, sizeof(devdesc)); 16207e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood bufend = bufptr + desclength; 163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // should have device and configuration descriptors, and atleast two endpoints 165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (desclength < USB_DT_DEVICE_SIZE + USB_DT_CONFIG_SIZE) { 1667a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("desclength %zu is too small", desclength); 1676ac5d7dc56a016718d2a26803435505e983e5d80Spencer Low unix_close(fd); 168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project device = (struct usb_device_descriptor*)bufptr; 172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bufptr += USB_DT_DEVICE_SIZE; 173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if((device->bLength != USB_DT_DEVICE_SIZE) || (device->bDescriptorType != USB_DT_DEVICE)) { 1756ac5d7dc56a016718d2a26803435505e983e5d80Spencer Low unix_close(fd); 176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1796f703a2e85a3098b3546a0ce254349b72b440628Marcus Comstedt vid = device->idVendor; 1806f703a2e85a3098b3546a0ce254349b72b440628Marcus Comstedt pid = device->idProduct; 181812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes DBGX("[ %s is V:%04x P:%04x ]\n", dev_name.c_str(), vid, pid); 182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // should have config descriptor next 184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project config = (struct usb_config_descriptor *)bufptr; 185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bufptr += USB_DT_CONFIG_SIZE; 186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (config->bLength != USB_DT_CONFIG_SIZE || config->bDescriptorType != USB_DT_CONFIG) { 1877a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("usb_config_descriptor not found"); 1886ac5d7dc56a016718d2a26803435505e983e5d80Spencer Low unix_close(fd); 189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 19207e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood // loop through all the descriptors and look for the ADB interface 19307e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood while (bufptr < bufend) { 19407e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood unsigned char length = bufptr[0]; 19507e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood unsigned char type = bufptr[1]; 196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 19707e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood if (type == USB_DT_INTERFACE) { 19807e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood interface = (struct usb_interface_descriptor *)bufptr; 19907e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood bufptr += length; 200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 20107e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood if (length != USB_DT_INTERFACE_SIZE) { 2027a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("interface descriptor has wrong size"); 20307e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood break; 204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 20607e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood DBGX("bInterfaceClass: %d, bInterfaceSubClass: %d," 20707e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood "bInterfaceProtocol: %d, bNumEndpoints: %d\n", 20807e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood interface->bInterfaceClass, interface->bInterfaceSubClass, 20907e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood interface->bInterfaceProtocol, interface->bNumEndpoints); 21007e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood 21107e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood if (interface->bNumEndpoints == 2 && 21230186df0f05ca2df10af7a64604eb93a1e1a27dcJosh Gao is_adb_interface(interface->bInterfaceClass, interface->bInterfaceSubClass, 21330186df0f05ca2df10af7a64604eb93a1e1a27dcJosh Gao interface->bInterfaceProtocol)) { 214e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson struct stat st; 215e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson char pathbuf[128]; 216e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson char link[256]; 217812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes char *devpath = nullptr; 218e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson 21907e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood DBGX("looking for bulk endpoints\n"); 22007e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood // looks like ADB... 22107e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood ep1 = (struct usb_endpoint_descriptor *)bufptr; 22207e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood bufptr += USB_DT_ENDPOINT_SIZE; 22358b01e01875e2f6ae593ded197430bc23713dd0aIngo Rohloff // For USB 3.0 SuperSpeed devices, skip potential 22458b01e01875e2f6ae593ded197430bc23713dd0aIngo Rohloff // USB 3.0 SuperSpeed Endpoint Companion descriptor 22558b01e01875e2f6ae593ded197430bc23713dd0aIngo Rohloff if (bufptr+2 <= devdesc + desclength && 22658b01e01875e2f6ae593ded197430bc23713dd0aIngo Rohloff bufptr[0] == USB_DT_SS_EP_COMP_SIZE && 22758b01e01875e2f6ae593ded197430bc23713dd0aIngo Rohloff bufptr[1] == USB_DT_SS_ENDPOINT_COMP) { 22858b01e01875e2f6ae593ded197430bc23713dd0aIngo Rohloff bufptr += USB_DT_SS_EP_COMP_SIZE; 22958b01e01875e2f6ae593ded197430bc23713dd0aIngo Rohloff } 23007e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood ep2 = (struct usb_endpoint_descriptor *)bufptr; 23107e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood bufptr += USB_DT_ENDPOINT_SIZE; 23258b01e01875e2f6ae593ded197430bc23713dd0aIngo Rohloff if (bufptr+2 <= devdesc + desclength && 23358b01e01875e2f6ae593ded197430bc23713dd0aIngo Rohloff bufptr[0] == USB_DT_SS_EP_COMP_SIZE && 23458b01e01875e2f6ae593ded197430bc23713dd0aIngo Rohloff bufptr[1] == USB_DT_SS_ENDPOINT_COMP) { 23558b01e01875e2f6ae593ded197430bc23713dd0aIngo Rohloff bufptr += USB_DT_SS_EP_COMP_SIZE; 23658b01e01875e2f6ae593ded197430bc23713dd0aIngo Rohloff } 23707e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood 23807e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood if (bufptr > devdesc + desclength || 23907e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood ep1->bLength != USB_DT_ENDPOINT_SIZE || 24007e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood ep1->bDescriptorType != USB_DT_ENDPOINT || 24107e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood ep2->bLength != USB_DT_ENDPOINT_SIZE || 24207e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood ep2->bDescriptorType != USB_DT_ENDPOINT) { 2437a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("endpoints not found"); 24407e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood break; 24507e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood } 24607e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood 24707e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood // both endpoints should be bulk 24807e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood if (ep1->bmAttributes != USB_ENDPOINT_XFER_BULK || 24907e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood ep2->bmAttributes != USB_ENDPOINT_XFER_BULK) { 2507a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("bulk endpoints not found"); 25107e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood continue; 25207e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood } 25307e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood /* aproto 01 needs 0 termination */ 25407e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood if(interface->bInterfaceProtocol == 0x01) { 25507e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood zero_mask = ep1->wMaxPacketSize - 1; 25607e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood } 25707e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood 25807e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood // we have a match. now we just need to figure out which is in and which is out. 259812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes unsigned char local_ep_in, local_ep_out; 26007e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood if (ep1->bEndpointAddress & USB_ENDPOINT_DIR_MASK) { 26107e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood local_ep_in = ep1->bEndpointAddress; 26207e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood local_ep_out = ep2->bEndpointAddress; 26307e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood } else { 26407e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood local_ep_in = ep2->bEndpointAddress; 26507e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood local_ep_out = ep1->bEndpointAddress; 26607e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood } 26707e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood 268e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson // Determine the device path 269e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson if (!fstat(fd, &st) && S_ISCHR(st.st_mode)) { 270e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson snprintf(pathbuf, sizeof(pathbuf), "/sys/dev/char/%d:%d", 271e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson major(st.st_rdev), minor(st.st_rdev)); 2723e7048c027ffa081d2fea84b661a6da895a9f1fbElliott Hughes ssize_t link_len = readlink(pathbuf, link, sizeof(link) - 1); 273e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson if (link_len > 0) { 274e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson link[link_len] = '\0'; 2753e7048c027ffa081d2fea84b661a6da895a9f1fbElliott Hughes const char* slash = strrchr(link, '/'); 276e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson if (slash) { 277e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson snprintf(pathbuf, sizeof(pathbuf), 278e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson "usb:%s", slash + 1); 279e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson devpath = pathbuf; 280e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson } 281e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson } 282e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson } 283e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson 284812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes register_device_callback(dev_name.c_str(), devpath, 285e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson local_ep_in, local_ep_out, 28607e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood interface->bInterfaceNumber, device->iSerialNumber, zero_mask); 28707e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood break; 288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 29007e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood bufptr += length; 29107e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood } 29207e8f7e8758d5ce44fe6cf3bacb670962750a92eMike Lockwood } // end of while 293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 2946ac5d7dc56a016718d2a26803435505e983e5d80Spencer Low unix_close(fd); 295812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes } 296812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes } 297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 299812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughesstatic int usb_bulk_write(usb_handle* h, const void* data, int len) { 300812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes std::unique_lock<std::mutex> lock(h->mutex); 3017a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("++ usb_bulk_write ++"); 302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 303812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes usbdevfs_urb* urb = &h->urb_out; 304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(urb, 0, sizeof(*urb)); 305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project urb->type = USBDEVFS_URB_TYPE_BULK; 306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project urb->endpoint = h->ep_out; 307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project urb->status = -1; 308812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes urb->buffer = const_cast<void*>(data); 309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project urb->buffer_length = len; 310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 311812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (h->dead) { 312812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes errno = EINVAL; 313812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes return -1; 314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 316812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (TEMP_FAILURE_RETRY(ioctl(h->fd, USBDEVFS_SUBMITURB, urb)) == -1) { 317812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes return -1; 318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 320812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes h->urb_out_busy = true; 321812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes while (true) { 322812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes auto now = std::chrono::system_clock::now(); 323812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (h->cv.wait_until(lock, now + 5s) == std::cv_status::timeout || h->dead) { 324812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes // TODO: call USBDEVFS_DISCARDURB? 325812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes errno = ETIMEDOUT; 326812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes return -1; 327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 328812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (!h->urb_out_busy) { 329812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (urb->status != 0) { 330812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes errno = -urb->status; 331812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes return -1; 332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 333812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes return urb->actual_length; 334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 338812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughesstatic int usb_bulk_read(usb_handle* h, void* data, int len) { 339812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes std::unique_lock<std::mutex> lock(h->mutex); 3407a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("++ usb_bulk_read ++"); 341812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes 342812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes usbdevfs_urb* urb = &h->urb_in; 343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(urb, 0, sizeof(*urb)); 344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project urb->type = USBDEVFS_URB_TYPE_BULK; 345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project urb->endpoint = h->ep_in; 346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project urb->status = -1; 347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project urb->buffer = data; 348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project urb->buffer_length = len; 349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 350812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (h->dead) { 351812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes errno = EINVAL; 352812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes return -1; 353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 355812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (TEMP_FAILURE_RETRY(ioctl(h->fd, USBDEVFS_SUBMITURB, urb)) == -1) { 356812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes return -1; 357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 359812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes h->urb_in_busy = true; 360812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes while (true) { 3617a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("[ reap urb - wait ]"); 362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project h->reaper_thread = pthread_self(); 363812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes int fd = h->fd; 364812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes lock.unlock(); 365812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes 366812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes // This ioctl must not have TEMP_FAILURE_RETRY because we send SIGALRM to break out. 367812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes usbdevfs_urb* out = nullptr; 368812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes int res = ioctl(fd, USBDEVFS_REAPURB, &out); 369408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall int saved_errno = errno; 370812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes 371812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes lock.lock(); 372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project h->reaper_thread = 0; 373812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (h->dead) { 374812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes errno = EINVAL; 375812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes return -1; 376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 377812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (res < 0) { 378812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (saved_errno == EINTR) { 379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 380dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 3817a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("[ reap urb - error ]"); 382812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes errno = saved_errno; 383812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes return -1; 384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 3857a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("[ urb @%p status = %d, actual = %d ]", out, out->status, out->actual_length); 386dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 387812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (out == &h->urb_in) { 3887a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("[ reap urb - IN complete ]"); 389812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes h->urb_in_busy = false; 390812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (urb->status != 0) { 391812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes errno = -urb->status; 392812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes return -1; 393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 394812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes return urb->actual_length; 395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 396812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (out == &h->urb_out) { 3977a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("[ reap urb - OUT compelete ]"); 398812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes h->urb_out_busy = false; 399812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes h->cv.notify_all(); 400dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_write(usb_handle *h, const void *_data, int len) 406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 4077a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("++ usb_write ++"); 4083d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer 409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned char *data = (unsigned char*) _data; 4103d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer int n = usb_bulk_write(h, data, len); 411812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (n != len) { 4127a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("ERROR: n = %d, errno = %d (%s)", n, errno, strerror(errno)); 4133d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer return -1; 4143d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer } 415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 416812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (h->zero_mask && !(len & h->zero_mask)) { 417812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes // If we need 0-markers and our transfer is an even multiple of the packet size, 418812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes // then send a zero marker. 419812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes return usb_bulk_write(h, _data, 0); 420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 4227a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("-- usb_write --"); 423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_read(usb_handle *h, void *_data, int len) 427dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned char *data = (unsigned char*) _data; 429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int n; 430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 4317a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("++ usb_read ++"); 432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while(len > 0) { 4333d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer int xfer = len; 434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 4357a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("[ usb read %d fd = %d], path=%s", xfer, h->fd, h->path.c_str()); 436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project n = usb_bulk_read(h, data, xfer); 4377a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("[ usb read %d ] = %d, path=%s", xfer, n, h->path.c_str()); 438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(n != xfer) { 439812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if((errno == ETIMEDOUT) && (h->fd != -1)) { 4407a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("[ timeout ]"); 441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(n > 0){ 442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project data += n; 443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len -= n; 444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 4477a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("ERROR: n = %d, errno = %d (%s)", 448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project n, errno, strerror(errno)); 449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len -= xfer; 453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project data += xfer; 454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 4567a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("-- usb_read --"); 457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 460812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughesvoid usb_kick(usb_handle* h) { 461812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes std::lock_guard<std::mutex> lock(h->mutex); 4627a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("[ kicking %p (fd = %d) ]", h, h->fd); 463812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (!h->dead) { 464812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes h->dead = true; 465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 4660927bf9690127bc45cf8837a1467759e9720399aMike Lockwood if (h->writeable) { 4670927bf9690127bc45cf8837a1467759e9720399aMike Lockwood /* HACK ALERT! 4680927bf9690127bc45cf8837a1467759e9720399aMike Lockwood ** Sometimes we get stuck in ioctl(USBDEVFS_REAPURB). 4690927bf9690127bc45cf8837a1467759e9720399aMike Lockwood ** This is a workaround for that problem. 4700927bf9690127bc45cf8837a1467759e9720399aMike Lockwood */ 4710927bf9690127bc45cf8837a1467759e9720399aMike Lockwood if (h->reaper_thread) { 4720927bf9690127bc45cf8837a1467759e9720399aMike Lockwood pthread_kill(h->reaper_thread, SIGALRM); 4730927bf9690127bc45cf8837a1467759e9720399aMike Lockwood } 474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 4750927bf9690127bc45cf8837a1467759e9720399aMike Lockwood /* cancel any pending transactions 4760927bf9690127bc45cf8837a1467759e9720399aMike Lockwood ** these will quietly fail if the txns are not active, 4770927bf9690127bc45cf8837a1467759e9720399aMike Lockwood ** but this ensures that a reader blocked on REAPURB 4780927bf9690127bc45cf8837a1467759e9720399aMike Lockwood ** will get unblocked 4790927bf9690127bc45cf8837a1467759e9720399aMike Lockwood */ 480812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes ioctl(h->fd, USBDEVFS_DISCARDURB, &h->urb_in); 481812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes ioctl(h->fd, USBDEVFS_DISCARDURB, &h->urb_out); 4820927bf9690127bc45cf8837a1467759e9720399aMike Lockwood h->urb_in.status = -ENODEV; 4830927bf9690127bc45cf8837a1467759e9720399aMike Lockwood h->urb_out.status = -ENODEV; 484812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes h->urb_in_busy = false; 485812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes h->urb_out_busy = false; 486812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes h->cv.notify_all(); 4870927bf9690127bc45cf8837a1467759e9720399aMike Lockwood } else { 4880927bf9690127bc45cf8837a1467759e9720399aMike Lockwood unregister_usb_transport(h); 4890927bf9690127bc45cf8837a1467759e9720399aMike Lockwood } 490dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 493812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughesint usb_close(usb_handle* h) { 494812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes std::lock_guard<std::mutex> lock(g_usb_handles_mutex); 495812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes g_usb_handles.remove(h); 496812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes 4977a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("-- usb close %p (fd = %d) --", h, h->fd); 498812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes 499812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes delete h; 500812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes 501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 5049309ecbcec428edfcb487ef697862bce59a1aed5Elliott Hughesstatic void register_device(const char* dev_name, const char* dev_path, 505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned char ep_in, unsigned char ep_out, 506d99d902abdbcb86fd0f1db5d6204c02126d1e818Dan Albert int interface, int serial_index, 507d99d902abdbcb86fd0f1db5d6204c02126d1e818Dan Albert unsigned zero_mask) { 508d99d902abdbcb86fd0f1db5d6204c02126d1e818Dan Albert // Since Linux will not reassign the device ID (and dev_name) as long as the 509d99d902abdbcb86fd0f1db5d6204c02126d1e818Dan Albert // device is open, we can add to the list here once we open it and remove 510d99d902abdbcb86fd0f1db5d6204c02126d1e818Dan Albert // from the list when we're finally closed and everything will work out 511d99d902abdbcb86fd0f1db5d6204c02126d1e818Dan Albert // fine. 512d99d902abdbcb86fd0f1db5d6204c02126d1e818Dan Albert // 513812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes // If we have a usb_handle on the list of handles with a matching name, we 514d99d902abdbcb86fd0f1db5d6204c02126d1e818Dan Albert // have no further work to do. 515812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes { 516812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes std::lock_guard<std::mutex> lock(g_usb_handles_mutex); 517812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes for (usb_handle* usb: g_usb_handles) { 518812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (usb->path == dev_name) { 519812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes return; 520812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes } 521dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 522dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 523dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 5247a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("[ usb located new device %s (%d/%d/%d) ]", dev_name, ep_in, ep_out, interface); 525812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes std::unique_ptr<usb_handle> usb(new usb_handle); 526812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes usb->path = dev_name; 527dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project usb->ep_in = ep_in; 528dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project usb->ep_out = ep_out; 529dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project usb->zero_mask = zero_mask; 530dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 531812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes // Initialize mark so we don't get garbage collected after the device scan. 532812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes usb->mark = true; 533dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 534812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes usb->fd = unix_open(usb->path.c_str(), O_RDWR | O_CLOEXEC); 535812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (usb->fd == -1) { 536ce6363bbbcd05ff16111040eecacd174f9327745Elliott Hughes // Opening RW failed, so see if we have RO access. 537812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes usb->fd = unix_open(usb->path.c_str(), O_RDONLY | O_CLOEXEC); 538812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (usb->fd == -1) { 5397a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("[ usb open %s failed: %s]", usb->path.c_str(), strerror(errno)); 540ce6363bbbcd05ff16111040eecacd174f9327745Elliott Hughes return; 541ce6363bbbcd05ff16111040eecacd174f9327745Elliott Hughes } 5420927bf9690127bc45cf8837a1467759e9720399aMike Lockwood usb->writeable = 0; 543ce6363bbbcd05ff16111040eecacd174f9327745Elliott Hughes } 544ce6363bbbcd05ff16111040eecacd174f9327745Elliott Hughes 5457a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("[ usb opened %s%s, fd=%d]", 546812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes usb->path.c_str(), (usb->writeable ? "" : " (read-only)"), usb->fd); 547ce6363bbbcd05ff16111040eecacd174f9327745Elliott Hughes 548ce6363bbbcd05ff16111040eecacd174f9327745Elliott Hughes if (usb->writeable) { 549812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes if (ioctl(usb->fd, USBDEVFS_CLAIMINTERFACE, &interface) != 0) { 5507a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("[ usb ioctl(%d, USBDEVFS_CLAIMINTERFACE) failed: %s]", usb->fd, strerror(errno)); 551ce6363bbbcd05ff16111040eecacd174f9327745Elliott Hughes return; 552ce6363bbbcd05ff16111040eecacd174f9327745Elliott Hughes } 5530927bf9690127bc45cf8837a1467759e9720399aMike Lockwood } 5540927bf9690127bc45cf8837a1467759e9720399aMike Lockwood 5559309ecbcec428edfcb487ef697862bce59a1aed5Elliott Hughes // Read the device's serial number. 556d99d902abdbcb86fd0f1db5d6204c02126d1e818Dan Albert std::string serial_path = android::base::StringPrintf( 557d99d902abdbcb86fd0f1db5d6204c02126d1e818Dan Albert "/sys/bus/usb/devices/%s/serial", dev_path + 4); 5589309ecbcec428edfcb487ef697862bce59a1aed5Elliott Hughes std::string serial; 5599309ecbcec428edfcb487ef697862bce59a1aed5Elliott Hughes if (!android::base::ReadFileToString(serial_path, &serial)) { 5607a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("[ usb read %s failed: %s ]", serial_path.c_str(), strerror(errno)); 561d99d902abdbcb86fd0f1db5d6204c02126d1e818Dan Albert // We don't actually want to treat an unknown serial as an error because 562d99d902abdbcb86fd0f1db5d6204c02126d1e818Dan Albert // devices aren't able to communicate a serial number in early bringup. 563d99d902abdbcb86fd0f1db5d6204c02126d1e818Dan Albert // http://b/20883914 564d99d902abdbcb86fd0f1db5d6204c02126d1e818Dan Albert serial = ""; 5650927bf9690127bc45cf8837a1467759e9720399aMike Lockwood } 5669309ecbcec428edfcb487ef697862bce59a1aed5Elliott Hughes serial = android::base::Trim(serial); 567dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 568d99d902abdbcb86fd0f1db5d6204c02126d1e818Dan Albert // Add to the end of the active handles. 569812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes usb_handle* done_usb = usb.release(); 570812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes { 571812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes std::lock_guard<std::mutex> lock(g_usb_handles_mutex); 572812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes g_usb_handles.push_back(done_usb); 573812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes } 574812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes register_usb_transport(done_usb, serial.c_str(), dev_path, done_usb->writeable); 575dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 576dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 577b5fea14e13bb6e41b36f374c954dc55faeef4627Josh Gaostatic void device_poll_thread(void*) { 57849ee7cf9a10f66ffa9a3490c69db5fa46e0a966bSiva Velusamy adb_thread_setname("device poll"); 5797a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui D("Created device thread"); 580d99d902abdbcb86fd0f1db5d6204c02126d1e818Dan Albert while (true) { 581d99d902abdbcb86fd0f1db5d6204c02126d1e818Dan Albert // TODO: Use inotify. 582dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project find_usb_device("/dev/bus/usb", register_device); 583dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project kick_disconnected_devices(); 584dbe91eee26300be10d6f1a0b42451dd46ea68538Elliott Hughes std::this_thread::sleep_for(1s); 585dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 586dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 587dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 588812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughesvoid usb_init() { 589812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes struct sigaction actions; 590dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(&actions, 0, sizeof(actions)); 591dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sigemptyset(&actions.sa_mask); 592dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project actions.sa_flags = 0; 593812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes actions.sa_handler = [](int) {}; 594812f030477bcd2ba064fef51d58e0c74fa361da7Elliott Hughes sigaction(SIGALRM, &actions, nullptr); 595dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 5969b0f354fa25e3d5add516000c761e07c81c3bbc1Elliott Hughes if (!adb_thread_create(device_poll_thread, nullptr)) { 597d6ab3c2245b6c71605bad746a535028b717e899aYabin Cui fatal_errno("cannot create device_poll thread"); 598dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 599dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 6001c70e1bcbcced190b351d4fb418f32b4e428f496Josh Gao} // namespace native 601