usb_linux_client.c revision fd96db17b7f07eb6615af01fd1908b74383bf04b
1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License. 6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at 7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and 14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License. 15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h> 18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h> 19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h> 20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h> 21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 22fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz#include <linux/usb/ch9.h> 23fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz#include <linux/usb/functionfs.h> 24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/ioctl.h> 25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h> 26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <dirent.h> 27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h> 28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "sysdeps.h" 30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define TRACE_TAG TRACE_USB 32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "adb.h" 33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 34fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz#define MAX_PACKET_SIZE_FS 64 35fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz#define MAX_PACKET_SIZE_HS 512 36fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 37fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz#define cpu_to_le16(x) htole16(x) 38fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz#define cpu_to_le32(x) htole32(x) 39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct usb_handle 41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_cond_t notify; 43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_mutex_t lock; 44fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 45fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz int (*write)(usb_handle *h, const void *data, int len); 46fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz int (*read)(usb_handle *h, void *data, int len); 47fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz void (*kick)(usb_handle *h); 48fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 49fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz // Legacy f_adb 50fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz int fd; 51fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 52fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz // FunctionFS 53fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz int control; 54fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz int bulk_out; /* "out" from the host's perspective => source for adbd */ 55fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz int bulk_in; /* "in" from the host's perspective => sink for adbd */ 56fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz}; 57fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 58fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic const struct { 59fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz struct usb_functionfs_descs_head header; 60fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz struct { 61fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz struct usb_interface_descriptor intf; 62fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz struct usb_endpoint_descriptor_no_audio source; 63fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz struct usb_endpoint_descriptor_no_audio sink; 64fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } __attribute__((packed)) fs_descs, hs_descs; 65fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} __attribute__((packed)) descriptors = { 66fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .header = { 67fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC), 68fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .length = cpu_to_le32(sizeof(descriptors)), 69fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .fs_count = 3, 70fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .hs_count = 3, 71fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz }, 72fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .fs_descs = { 73fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .intf = { 74fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bLength = sizeof(descriptors.fs_descs.intf), 75fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bDescriptorType = USB_DT_INTERFACE, 76fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bInterfaceNumber = 0, 77fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bNumEndpoints = 2, 78fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bInterfaceClass = ADB_CLASS, 79fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bInterfaceSubClass = ADB_SUBCLASS, 80fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bInterfaceProtocol = ADB_PROTOCOL, 81fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .iInterface = 1, /* first string from the provided table */ 82fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz }, 83fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .source = { 84fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bLength = sizeof(descriptors.fs_descs.source), 85fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bDescriptorType = USB_DT_ENDPOINT, 86fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bEndpointAddress = 1 | USB_DIR_OUT, 87fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bmAttributes = USB_ENDPOINT_XFER_BULK, 88fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .wMaxPacketSize = MAX_PACKET_SIZE_FS, 89fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz }, 90fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .sink = { 91fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bLength = sizeof(descriptors.fs_descs.sink), 92fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bDescriptorType = USB_DT_ENDPOINT, 93fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bEndpointAddress = 2 | USB_DIR_IN, 94fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bmAttributes = USB_ENDPOINT_XFER_BULK, 95fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .wMaxPacketSize = MAX_PACKET_SIZE_FS, 96fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz }, 97fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz }, 98fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .hs_descs = { 99fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .intf = { 100fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bLength = sizeof(descriptors.hs_descs.intf), 101fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bDescriptorType = USB_DT_INTERFACE, 102fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bInterfaceNumber = 0, 103fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bNumEndpoints = 2, 104fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bInterfaceClass = ADB_CLASS, 105fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bInterfaceSubClass = ADB_SUBCLASS, 106fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bInterfaceProtocol = ADB_PROTOCOL, 107fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .iInterface = 1, /* first string from the provided table */ 108fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz }, 109fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .source = { 110fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bLength = sizeof(descriptors.hs_descs.source), 111fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bDescriptorType = USB_DT_ENDPOINT, 112fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bEndpointAddress = 1 | USB_DIR_OUT, 113fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bmAttributes = USB_ENDPOINT_XFER_BULK, 114fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .wMaxPacketSize = MAX_PACKET_SIZE_HS, 115fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz }, 116fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .sink = { 117fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bLength = sizeof(descriptors.hs_descs.sink), 118fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bDescriptorType = USB_DT_ENDPOINT, 119fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bEndpointAddress = 2 | USB_DIR_IN, 120fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .bmAttributes = USB_ENDPOINT_XFER_BULK, 121fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .wMaxPacketSize = MAX_PACKET_SIZE_HS, 122fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz }, 123fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz }, 124fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz}; 125fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 126fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz#define STR_INTERFACE_ "ADB Interface" 127fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 128fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic const struct { 129fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz struct usb_functionfs_strings_head header; 130fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz struct { 131fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz __le16 code; 132fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz const char str1[sizeof(STR_INTERFACE_)]; 133fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } __attribute__((packed)) lang0; 134fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} __attribute__((packed)) strings = { 135fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .header = { 136fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .magic = cpu_to_le32(FUNCTIONFS_STRINGS_MAGIC), 137fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .length = cpu_to_le32(sizeof(strings)), 138fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .str_count = cpu_to_le32(1), 139fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .lang_count = cpu_to_le32(1), 140fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz }, 141fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .lang0 = { 142fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz cpu_to_le16(0x0409), /* en-us */ 143fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz STR_INTERFACE_, 144fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz }, 145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}; 146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 148fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 149fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic void *usb_adb_open_thread(void *x) 150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usb_handle *usb = (struct usb_handle *)x; 152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int fd; 153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while (1) { 155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // wait until the USB device needs opening 156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_mutex_lock(&usb->lock); 157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while (usb->fd != -1) 158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_cond_wait(&usb->notify, &usb->lock); 159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_mutex_unlock(&usb->lock); 160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project D("[ usb_thread - opening device ]\n"); 162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project do { 163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* XXX use inotify? */ 164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd = unix_open("/dev/android_adb", O_RDWR); 165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fd < 0) { 166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // to support older kernels 167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd = unix_open("/dev/android", O_RDWR); 168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fd < 0) { 170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_sleep_ms(1000); 171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } while (fd < 0); 173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project D("[ opening device succeeded ]\n"); 174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close_on_exec(fd); 176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project usb->fd = fd; 177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project D("[ usb_thread - registering device ]\n"); 179e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson register_usb_transport(usb, 0, 0, 1); 180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // never gets here 183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 186fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic int usb_adb_write(usb_handle *h, const void *data, int len) 187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int n; 189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 190408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("about to write (fd=%d, len=%d)\n", h->fd, len); 191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project n = adb_write(h->fd, data, len); 192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(n != len) { 193408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("ERROR: fd = %d, n = %d, errno = %d (%s)\n", 194408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall h->fd, n, errno, strerror(errno)); 195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 197408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("[ done fd=%d ]\n", h->fd); 198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 201fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic int usb_adb_read(usb_handle *h, void *data, int len) 202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int n; 204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 205408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("about to read (fd=%d, len=%d)\n", h->fd, len); 206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project n = adb_read(h->fd, data, len); 207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(n != len) { 208408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("ERROR: fd = %d, n = %d, errno = %d (%s)\n", 209408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall h->fd, n, errno, strerror(errno)); 210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 212408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("[ done fd=%d ]\n", h->fd); 213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 216fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic void usb_adb_kick(usb_handle *h) 217fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 218fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("usb_kick\n"); 219fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_mutex_lock(&h->lock); 220fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_close(h->fd); 221fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->fd = -1; 222fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 223fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz // notify usb_adb_open_thread that we are disconnected 224fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_cond_signal(&h->notify); 225fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_mutex_unlock(&h->lock); 226fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 227fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 228fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic void usb_adb_init() 229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project usb_handle *h; 231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_thread_t tid; 232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int fd; 233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project h = calloc(1, sizeof(usb_handle)); 235fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 236fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->write = usb_adb_write; 237fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->read = usb_adb_read; 238fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->kick = usb_adb_kick; 239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project h->fd = -1; 240fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_cond_init(&h->notify, 0); 242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_mutex_init(&h->lock, 0); 243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Open the file /dev/android_adb_enable to trigger 245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // the enabling of the adb USB function in the kernel. 246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // We never touch this file again - just leave it open 247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // indefinitely so the kernel will know when we are running 248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // and when we are not. 249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd = unix_open("/dev/android_adb_enable", O_RDWR); 250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fd < 0) { 251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project D("failed to open /dev/android_adb_enable\n"); 252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close_on_exec(fd); 254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project D("[ usb_init - starting thread ]\n"); 257fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if(adb_thread_create(&tid, usb_adb_open_thread, h)){ 258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fatal_errno("cannot create usb thread"); 259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 262fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 263fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic void init_functionfs(struct usb_handle *h) 264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 265fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz ssize_t ret; 266fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 267fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("OPENING %s\n", USB_FFS_ADB_EP0); 268fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->control = adb_open(USB_FFS_ADB_EP0, O_RDWR); 269fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (h->control < 0) { 270fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("[ %s: cannot open control endpoint: errno=%d]\n", USB_FFS_ADB_EP0, errno); 271fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz goto err; 272fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 273fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 274fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz ret = adb_write(h->control, &descriptors, sizeof(descriptors)); 275fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (ret < 0) { 276fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("[ %s: write descriptors failed: errno=%d ]\n", USB_FFS_ADB_EP0, errno); 277fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz goto err; 278fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 279fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 280fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz ret = adb_write(h->control, &strings, sizeof(strings)); 281fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (ret < 0) { 282fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("[ %s: writing strings failed: errno=%d]\n", USB_FFS_ADB_EP0, errno); 283fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz goto err; 284fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 285fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 286fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->bulk_out = adb_open(USB_FFS_ADB_OUT, O_RDWR); 287fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (h->bulk_out < 0) { 288fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("[ %s: cannot open bulk-out ep: errno=%d ]\n", USB_FFS_ADB_OUT, errno); 289fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz goto err; 290fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 291fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 292fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->bulk_in = adb_open(USB_FFS_ADB_IN, O_RDWR); 293fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (h->bulk_in < 0) { 294fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("[ %s: cannot open bulk-in ep: errno=%d ]\n", USB_FFS_ADB_IN, errno); 295fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz goto err; 296fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 297fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 298fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return; 299fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 300fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczerr: 301fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (h->bulk_in > 0) { 302fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_close(h->bulk_in); 303fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->bulk_in = -1; 304fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 305fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (h->bulk_out > 0) { 306fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_close(h->bulk_out); 307fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->bulk_out = -1; 308fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 309fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (h->control > 0) { 310fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_close(h->control); 311fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->control = -1; 312fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 313fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return; 314fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 315fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 316fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic void *usb_ffs_open_thread(void *x) 317fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 318fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz struct usb_handle *usb = (struct usb_handle *)x; 319fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 320fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz while (1) { 321fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz // wait until the USB device needs opening 322fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_mutex_lock(&usb->lock); 323fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz while (usb->control != -1) 324fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_cond_wait(&usb->notify, &usb->lock); 325fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_mutex_unlock(&usb->lock); 326fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 327fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz while (1) { 328fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz init_functionfs(usb); 329fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 330fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (usb->control >= 0) 331fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz break; 332fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 333fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_sleep_ms(1000); 334fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 335fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 336fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("[ usb_thread - registering device ]\n"); 337fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz register_usb_transport(usb, 0, 0, 1); 338fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 339fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 340fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz // never gets here 341fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return 0; 342fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 343fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 344fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic int bulk_write(int bulk_in, const char *buf, size_t length) 345fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 346fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz size_t count = 0; 347fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz int ret; 348fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 349fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz do { 350fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz ret = adb_write(bulk_in, buf + count, length - count); 351fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (ret < 0) { 352fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (errno != EINTR) 353fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return ret; 354fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } else { 355fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz count += ret; 356fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 357fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } while (count < length); 358fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 359fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("[ bulk_write done fd=%d ]\n", bulk_in); 360fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return count; 361fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 362fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 363fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic int usb_ffs_write(usb_handle *h, const void *data, int len) 364fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 365fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz int n; 366fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 367fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("about to write (fd=%d, len=%d)\n", h->bulk_in, len); 368fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz n = bulk_write(h->bulk_in, data, len); 369fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (n != len) { 370fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("ERROR: fd = %d, n = %d, errno = %d (%s)\n", 371fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->bulk_in, n, errno, strerror(errno)); 372fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return -1; 373fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 374fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("[ done fd=%d ]\n", h->bulk_in); 375fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return 0; 376fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 377fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 378fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic int bulk_read(int bulk_out, char *buf, size_t length) 379fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 380fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz size_t count = 0; 381fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz int ret; 382fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 383fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz do { 384fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz ret = adb_read(bulk_out, buf + count, length - count); 385fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (ret < 0) { 386fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (errno != EINTR) { 387fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("[ bulk_read failed fd=%d length=%d count=%d ]\n", 388fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz bulk_out, length, count); 389fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return ret; 390fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 391fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } else { 392fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz count += ret; 393fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 394fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } while (count < length); 395fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 396fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return count; 397fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 398fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 399fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic int usb_ffs_read(usb_handle *h, void *data, int len) 400fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 401fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz int n; 402fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 403fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("about to read (fd=%d, len=%d)\n", h->bulk_out, len); 404fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz n = bulk_read(h->bulk_out, data, len); 405fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (n != len) { 406fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("ERROR: fd = %d, n = %d, errno = %d (%s)\n", 407fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->bulk_out, n, errno, strerror(errno)); 408fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return -1; 409fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 410fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("[ done fd=%d ]\n", h->bulk_out); 411fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return 0; 412fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 413fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 414fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic void usb_ffs_kick(usb_handle *h) 415fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 416fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz int err; 417fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 418fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz err = ioctl(h->bulk_in, FUNCTIONFS_CLEAR_HALT); 419fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (err < 0) 420fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("[ kick: source (fd=%d) clear halt failed (%d) ]", h->bulk_in, errno); 421fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 422fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz err = ioctl(h->bulk_out, FUNCTIONFS_CLEAR_HALT); 423fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (err < 0) 424fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("[ kick: sink (fd=%d) clear halt failed (%d) ]", h->bulk_out, errno); 425fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_mutex_lock(&h->lock); 427fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_close(h->control); 428fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_close(h->bulk_out); 429fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_close(h->bulk_in); 430fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->control = h->bulk_out = h->bulk_in = -1; 431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 432fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz // notify usb_ffs_open_thread that we are disconnected 433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_cond_signal(&h->notify); 434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_mutex_unlock(&h->lock); 435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 437fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic void usb_ffs_init() 438fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 439fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz usb_handle *h; 440fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_thread_t tid; 441fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 442fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("[ usb_init - using FunctionFS ]\n"); 443fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 444fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h = calloc(1, sizeof(usb_handle)); 445fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 446fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->write = usb_ffs_write; 447fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->read = usb_ffs_read; 448fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->kick = usb_ffs_kick; 449fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 450fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->control = -1; 451fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->bulk_out = -1; 452fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->bulk_out = -1; 453fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 454fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_cond_init(&h->notify, 0); 455fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_mutex_init(&h->lock, 0); 456fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 457fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("[ usb_init - starting thread ]\n"); 458fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (adb_thread_create(&tid, usb_ffs_open_thread, h)){ 459fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz fatal_errno("[ cannot create usb thread ]\n"); 460fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 461fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 462fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 463fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczvoid usb_init() 464fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 465fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (access(USB_FFS_ADB_EP0, F_OK) == 0) 466fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz usb_ffs_init(); 467fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz else 468fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz usb_adb_init(); 469fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 470fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 471fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczvoid usb_cleanup() 472fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 473fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 474fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 475fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczint usb_write(usb_handle *h, const void *data, int len) 476fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 477fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return h->write(h, data, len); 478fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 479fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 480fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczint usb_read(usb_handle *h, void *data, int len) 481fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 482fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return h->read(h, data, len); 483fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_close(usb_handle *h) 485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 488fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 489fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczvoid usb_kick(usb_handle *h) 490fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 491fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->kick(h); 492fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 493