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 173313426fad9eaaf53017cdbde889ebcec91358ecDan Albert#define TRACE_TAG TRACE_USB 183313426fad9eaaf53017cdbde889ebcec91358ecDan Albert 193313426fad9eaaf53017cdbde889ebcec91358ecDan Albert#include "sysdeps.h" 203313426fad9eaaf53017cdbde889ebcec91358ecDan Albert 215f97370babbe465e82c2aefe9864848af6796113Badhri Jagan Sridharan#include <cutils/properties.h> 227664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include <dirent.h> 237664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include <errno.h> 247664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include <linux/usb/ch9.h> 257664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include <linux/usb/functionfs.h> 26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h> 27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h> 28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h> 29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/ioctl.h> 30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h> 317664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include <unistd.h> 32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "adb.h" 347664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include "transport.h" 35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 36fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz#define MAX_PACKET_SIZE_FS 64 37fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz#define MAX_PACKET_SIZE_HS 512 38d6ee9f26a5163af4121f4380264fcbd4e6851a17Zhuang Jin Can#define MAX_PACKET_SIZE_SS 1024 39fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 40fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz#define cpu_to_le16(x) htole16(x) 41fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz#define cpu_to_le32(x) htole32(x) 42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct usb_handle 44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_cond_t notify; 46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_mutex_t lock; 47fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 48fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz int (*write)(usb_handle *h, const void *data, int len); 49fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz int (*read)(usb_handle *h, void *data, int len); 50fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz void (*kick)(usb_handle *h); 51fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 52fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz // Legacy f_adb 53fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz int fd; 54fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 55fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz // FunctionFS 56fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz int control; 57fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz int bulk_out; /* "out" from the host's perspective => source for adbd */ 58fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz int bulk_in; /* "in" from the host's perspective => sink for adbd */ 59fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz}; 60fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 61ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharanstruct func_desc { 62ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan struct usb_interface_descriptor intf; 63ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan struct usb_endpoint_descriptor_no_audio source; 64ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan struct usb_endpoint_descriptor_no_audio sink; 65ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan} __attribute__((packed)); 66ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan 6747c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Phamstruct ss_func_desc { 6847c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham struct usb_interface_descriptor intf; 6947c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham struct usb_endpoint_descriptor_no_audio source; 7047c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham struct usb_ss_ep_comp_descriptor source_comp; 7147c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham struct usb_endpoint_descriptor_no_audio sink; 7247c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham struct usb_ss_ep_comp_descriptor sink_comp; 7347c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham} __attribute__((packed)); 7447c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham 75ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharanstruct desc_v1 { 76ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan struct usb_functionfs_descs_head_v1 { 77ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan __le32 magic; 78ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan __le32 length; 79ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan __le32 fs_count; 80ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan __le32 hs_count; 81ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan } __attribute__((packed)) header; 82ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan struct func_desc fs_descs, hs_descs; 83ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan} __attribute__((packed)); 84ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan 85ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharanstruct desc_v2 { 86c49f51c451516bf06afc6d71947eb11cc4627273Christopher Ferris struct usb_functionfs_descs_head_v2 header; 87c49f51c451516bf06afc6d71947eb11cc4627273Christopher Ferris // The rest of the structure depends on the flags in the header. 88c49f51c451516bf06afc6d71947eb11cc4627273Christopher Ferris __le32 fs_count; 89c49f51c451516bf06afc6d71947eb11cc4627273Christopher Ferris __le32 hs_count; 9047c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham __le32 ss_count; 91ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan struct func_desc fs_descs, hs_descs; 9247c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham struct ss_func_desc ss_descs; 93ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan} __attribute__((packed)); 94ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan 95ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharanstruct func_desc fs_descriptors = { 96ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .intf = { 97ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bLength = sizeof(fs_descriptors.intf), 98ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bDescriptorType = USB_DT_INTERFACE, 99ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bInterfaceNumber = 0, 100ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bNumEndpoints = 2, 101ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bInterfaceClass = ADB_CLASS, 102ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bInterfaceSubClass = ADB_SUBCLASS, 103ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bInterfaceProtocol = ADB_PROTOCOL, 104ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .iInterface = 1, /* first string from the provided table */ 105ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan }, 106ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .source = { 107ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bLength = sizeof(fs_descriptors.source), 108ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bDescriptorType = USB_DT_ENDPOINT, 109ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bEndpointAddress = 1 | USB_DIR_OUT, 110ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bmAttributes = USB_ENDPOINT_XFER_BULK, 111ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .wMaxPacketSize = MAX_PACKET_SIZE_FS, 112ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan }, 113ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .sink = { 114ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bLength = sizeof(fs_descriptors.sink), 115ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bDescriptorType = USB_DT_ENDPOINT, 116ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bEndpointAddress = 2 | USB_DIR_IN, 117ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bmAttributes = USB_ENDPOINT_XFER_BULK, 118ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .wMaxPacketSize = MAX_PACKET_SIZE_FS, 119fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz }, 120ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan}; 121ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan 122ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharanstruct func_desc hs_descriptors = { 123ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .intf = { 124ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bLength = sizeof(hs_descriptors.intf), 125ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bDescriptorType = USB_DT_INTERFACE, 126ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bInterfaceNumber = 0, 127ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bNumEndpoints = 2, 128ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bInterfaceClass = ADB_CLASS, 129ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bInterfaceSubClass = ADB_SUBCLASS, 130ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bInterfaceProtocol = ADB_PROTOCOL, 131ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .iInterface = 1, /* first string from the provided table */ 132ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan }, 133ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .source = { 134ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bLength = sizeof(hs_descriptors.source), 135ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bDescriptorType = USB_DT_ENDPOINT, 136ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bEndpointAddress = 1 | USB_DIR_OUT, 137ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bmAttributes = USB_ENDPOINT_XFER_BULK, 138ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .wMaxPacketSize = MAX_PACKET_SIZE_HS, 139fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz }, 140ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .sink = { 141ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bLength = sizeof(hs_descriptors.sink), 142ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bDescriptorType = USB_DT_ENDPOINT, 143ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bEndpointAddress = 2 | USB_DIR_IN, 144ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .bmAttributes = USB_ENDPOINT_XFER_BULK, 145ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan .wMaxPacketSize = MAX_PACKET_SIZE_HS, 146d6ee9f26a5163af4121f4380264fcbd4e6851a17Zhuang Jin Can }, 147fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz}; 148fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 14947c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Phamstatic struct ss_func_desc ss_descriptors = { 15047c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .intf = { 15147c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .bLength = sizeof(ss_descriptors.intf), 15247c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .bDescriptorType = USB_DT_INTERFACE, 15347c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .bInterfaceNumber = 0, 15447c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .bNumEndpoints = 2, 15547c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .bInterfaceClass = ADB_CLASS, 15647c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .bInterfaceSubClass = ADB_SUBCLASS, 15747c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .bInterfaceProtocol = ADB_PROTOCOL, 15847c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .iInterface = 1, /* first string from the provided table */ 15947c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham }, 16047c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .source = { 16147c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .bLength = sizeof(ss_descriptors.source), 16247c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .bDescriptorType = USB_DT_ENDPOINT, 16347c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .bEndpointAddress = 1 | USB_DIR_OUT, 16447c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .bmAttributes = USB_ENDPOINT_XFER_BULK, 16547c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .wMaxPacketSize = MAX_PACKET_SIZE_SS, 16647c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham }, 16747c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .source_comp = { 16847c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .bLength = sizeof(ss_descriptors.source_comp), 16947c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, 17047c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham }, 17147c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .sink = { 17247c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .bLength = sizeof(ss_descriptors.sink), 17347c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .bDescriptorType = USB_DT_ENDPOINT, 17447c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .bEndpointAddress = 2 | USB_DIR_IN, 17547c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .bmAttributes = USB_ENDPOINT_XFER_BULK, 17647c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .wMaxPacketSize = MAX_PACKET_SIZE_SS, 17747c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham }, 17847c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .sink_comp = { 17947c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .bLength = sizeof(ss_descriptors.sink_comp), 18047c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, 18147c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham }, 18247c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham}; 18347c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham 184fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz#define STR_INTERFACE_ "ADB Interface" 185fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 186fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic const struct { 187fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz struct usb_functionfs_strings_head header; 188fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz struct { 189fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz __le16 code; 190fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz const char str1[sizeof(STR_INTERFACE_)]; 191fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } __attribute__((packed)) lang0; 192fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} __attribute__((packed)) strings = { 193fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .header = { 194fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .magic = cpu_to_le32(FUNCTIONFS_STRINGS_MAGIC), 195fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .length = cpu_to_le32(sizeof(strings)), 196fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .str_count = cpu_to_le32(1), 197fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .lang_count = cpu_to_le32(1), 198fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz }, 199fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz .lang0 = { 200fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz cpu_to_le16(0x0409), /* en-us */ 201fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz STR_INTERFACE_, 202fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz }, 203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}; 204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 206fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 207fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic void *usb_adb_open_thread(void *x) 208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usb_handle *usb = (struct usb_handle *)x; 210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int fd; 211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 212a7090b94c181f3efe5b53d2c8367b78d99074dfeElliott Hughes while (true) { 213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // wait until the USB device needs opening 214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_mutex_lock(&usb->lock); 215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while (usb->fd != -1) 216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_cond_wait(&usb->notify, &usb->lock); 217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_mutex_unlock(&usb->lock); 218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project D("[ usb_thread - opening device ]\n"); 220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project do { 221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* XXX use inotify? */ 222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd = unix_open("/dev/android_adb", O_RDWR); 223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fd < 0) { 224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // to support older kernels 225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd = unix_open("/dev/android", O_RDWR); 226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fd < 0) { 228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_sleep_ms(1000); 229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } while (fd < 0); 231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project D("[ opening device succeeded ]\n"); 232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close_on_exec(fd); 234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project usb->fd = fd; 235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project D("[ usb_thread - registering device ]\n"); 237e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson register_usb_transport(usb, 0, 0, 1); 238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // never gets here 241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 244fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic int usb_adb_write(usb_handle *h, const void *data, int len) 245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int n; 247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 248408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("about to write (fd=%d, len=%d)\n", h->fd, len); 249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project n = adb_write(h->fd, data, len); 250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(n != len) { 251408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("ERROR: fd = %d, n = %d, errno = %d (%s)\n", 252408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall h->fd, n, errno, strerror(errno)); 253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 255408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("[ done fd=%d ]\n", h->fd); 256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 259fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic int usb_adb_read(usb_handle *h, void *data, int len) 260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int n; 262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 263408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("about to read (fd=%d, len=%d)\n", h->fd, len); 264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project n = adb_read(h->fd, data, len); 265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(n != len) { 266408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("ERROR: fd = %d, n = %d, errno = %d (%s)\n", 267408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall h->fd, n, errno, strerror(errno)); 268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 270408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("[ done fd=%d ]\n", h->fd); 271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 274fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic void usb_adb_kick(usb_handle *h) 275fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 276fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("usb_kick\n"); 277fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_mutex_lock(&h->lock); 278fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_close(h->fd); 279fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->fd = -1; 280fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 281fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz // notify usb_adb_open_thread that we are disconnected 282fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_cond_signal(&h->notify); 283fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_mutex_unlock(&h->lock); 284fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 285fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 286fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic void usb_adb_init() 287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 2882acec9153e40a558671ec0544bdd89d5a7fabf08Elliott Hughes usb_handle* h = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle))); 289dc3b459ff9f0ff71d404ba7198083e532a0dd894Elliott Hughes if (h == nullptr) fatal("couldn't allocate usb_handle"); 290dc3b459ff9f0ff71d404ba7198083e532a0dd894Elliott Hughes 291fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->write = usb_adb_write; 292fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->read = usb_adb_read; 293fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->kick = usb_adb_kick; 294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project h->fd = -1; 295fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_cond_init(&h->notify, 0); 297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_mutex_init(&h->lock, 0); 298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 2992acec9153e40a558671ec0544bdd89d5a7fabf08Elliott Hughes // Open the file /dev/android_adb_enable to trigger 300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // the enabling of the adb USB function in the kernel. 301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // We never touch this file again - just leave it open 302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // indefinitely so the kernel will know when we are running 303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // and when we are not. 3042acec9153e40a558671ec0544bdd89d5a7fabf08Elliott Hughes int fd = unix_open("/dev/android_adb_enable", O_RDWR); 305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fd < 0) { 306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project D("failed to open /dev/android_adb_enable\n"); 307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close_on_exec(fd); 309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project D("[ usb_init - starting thread ]\n"); 3122acec9153e40a558671ec0544bdd89d5a7fabf08Elliott Hughes adb_thread_t tid; 313fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if(adb_thread_create(&tid, usb_adb_open_thread, h)){ 314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fatal_errno("cannot create usb thread"); 315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 318fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 319fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic void init_functionfs(struct usb_handle *h) 320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 321fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz ssize_t ret; 322ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan struct desc_v1 v1_descriptor; 323ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan struct desc_v2 v2_descriptor; 324ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan 325ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan v2_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2); 326ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan v2_descriptor.header.length = cpu_to_le32(sizeof(v2_descriptor)); 32747c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham v2_descriptor.header.flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC | 32847c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham FUNCTIONFS_HAS_SS_DESC; 329c49f51c451516bf06afc6d71947eb11cc4627273Christopher Ferris v2_descriptor.fs_count = 3; 330c49f51c451516bf06afc6d71947eb11cc4627273Christopher Ferris v2_descriptor.hs_count = 3; 33147c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham v2_descriptor.ss_count = 5; 332ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan v2_descriptor.fs_descs = fs_descriptors; 333ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan v2_descriptor.hs_descs = hs_descriptors; 33447c3ce56edec14592d08f6f157a7aa354e74a4e0Jack Pham v2_descriptor.ss_descs = ss_descriptors; 335fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 3364cbf1d882236462482b8e22893061604b224e308Jack Pham if (h->control < 0) { // might have already done this before 3374cbf1d882236462482b8e22893061604b224e308Jack Pham D("OPENING %s\n", USB_FFS_ADB_EP0); 3384cbf1d882236462482b8e22893061604b224e308Jack Pham h->control = adb_open(USB_FFS_ADB_EP0, O_RDWR); 3394cbf1d882236462482b8e22893061604b224e308Jack Pham if (h->control < 0) { 3404cbf1d882236462482b8e22893061604b224e308Jack Pham D("[ %s: cannot open control endpoint: errno=%d]\n", USB_FFS_ADB_EP0, errno); 3414cbf1d882236462482b8e22893061604b224e308Jack Pham goto err; 3424cbf1d882236462482b8e22893061604b224e308Jack Pham } 343fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 344ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan ret = adb_write(h->control, &v2_descriptor, sizeof(v2_descriptor)); 3454cbf1d882236462482b8e22893061604b224e308Jack Pham if (ret < 0) { 346ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan v1_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC); 347ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan v1_descriptor.header.length = cpu_to_le32(sizeof(v1_descriptor)); 348ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan v1_descriptor.header.fs_count = 3; 349ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan v1_descriptor.header.hs_count = 3; 350ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan v1_descriptor.fs_descs = fs_descriptors; 351ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan v1_descriptor.hs_descs = hs_descriptors; 352ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan D("[ %s: Switching to V1_descriptor format errno=%d ]\n", USB_FFS_ADB_EP0, errno); 353ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan ret = adb_write(h->control, &v1_descriptor, sizeof(v1_descriptor)); 354ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan if (ret < 0) { 355ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan D("[ %s: write descriptors failed: errno=%d ]\n", USB_FFS_ADB_EP0, errno); 356ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan goto err; 357ab3446dd3400652ecf50682d0e5c4184628e9930Badhri Jagan Sridharan } 3584cbf1d882236462482b8e22893061604b224e308Jack Pham } 359fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 3604cbf1d882236462482b8e22893061604b224e308Jack Pham ret = adb_write(h->control, &strings, sizeof(strings)); 3614cbf1d882236462482b8e22893061604b224e308Jack Pham if (ret < 0) { 3624cbf1d882236462482b8e22893061604b224e308Jack Pham D("[ %s: writing strings failed: errno=%d]\n", USB_FFS_ADB_EP0, errno); 3634cbf1d882236462482b8e22893061604b224e308Jack Pham goto err; 3644cbf1d882236462482b8e22893061604b224e308Jack Pham } 365fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 366fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 367fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->bulk_out = adb_open(USB_FFS_ADB_OUT, O_RDWR); 368fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (h->bulk_out < 0) { 369fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("[ %s: cannot open bulk-out ep: errno=%d ]\n", USB_FFS_ADB_OUT, errno); 370fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz goto err; 371fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 372fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 373fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->bulk_in = adb_open(USB_FFS_ADB_IN, O_RDWR); 374fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (h->bulk_in < 0) { 375fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("[ %s: cannot open bulk-in ep: errno=%d ]\n", USB_FFS_ADB_IN, errno); 376fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz goto err; 377fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 378fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 379fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return; 380fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 381fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczerr: 382fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (h->bulk_in > 0) { 383fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_close(h->bulk_in); 384fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->bulk_in = -1; 385fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 386fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (h->bulk_out > 0) { 387fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_close(h->bulk_out); 388fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->bulk_out = -1; 389fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 390fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (h->control > 0) { 391fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_close(h->control); 392fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->control = -1; 393fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 394fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return; 395fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 396fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 397fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic void *usb_ffs_open_thread(void *x) 398fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 399fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz struct usb_handle *usb = (struct usb_handle *)x; 400fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 401a7090b94c181f3efe5b53d2c8367b78d99074dfeElliott Hughes while (true) { 402fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz // wait until the USB device needs opening 403fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_mutex_lock(&usb->lock); 4044cbf1d882236462482b8e22893061604b224e308Jack Pham while (usb->control != -1 && usb->bulk_in != -1 && usb->bulk_out != -1) 405fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_cond_wait(&usb->notify, &usb->lock); 406fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_mutex_unlock(&usb->lock); 407fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 408a7090b94c181f3efe5b53d2c8367b78d99074dfeElliott Hughes while (true) { 409fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz init_functionfs(usb); 410fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 4114cbf1d882236462482b8e22893061604b224e308Jack Pham if (usb->control >= 0 && usb->bulk_in >= 0 && usb->bulk_out >= 0) 412fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz break; 413fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 414fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_sleep_ms(1000); 415fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 4165f97370babbe465e82c2aefe9864848af6796113Badhri Jagan Sridharan property_set("sys.usb.ffs.ready", "1"); 417fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 418fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("[ usb_thread - registering device ]\n"); 419fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz register_usb_transport(usb, 0, 0, 1); 420fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 421fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 422fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz // never gets here 423fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return 0; 424fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 425fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 4262acec9153e40a558671ec0544bdd89d5a7fabf08Elliott Hughesstatic int bulk_write(int bulk_in, const uint8_t* buf, size_t length) 427fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 428fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz size_t count = 0; 429fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz int ret; 430fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 431fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz do { 432fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz ret = adb_write(bulk_in, buf + count, length - count); 433fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (ret < 0) { 434fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (errno != EINTR) 435fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return ret; 436fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } else { 437fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz count += ret; 438fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 439fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } while (count < length); 440fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 441fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("[ bulk_write done fd=%d ]\n", bulk_in); 442fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return count; 443fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 444fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 4452acec9153e40a558671ec0544bdd89d5a7fabf08Elliott Hughesstatic int usb_ffs_write(usb_handle* h, const void* data, int len) 446fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 447fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("about to write (fd=%d, len=%d)\n", h->bulk_in, len); 4482acec9153e40a558671ec0544bdd89d5a7fabf08Elliott Hughes int n = bulk_write(h->bulk_in, reinterpret_cast<const uint8_t*>(data), len); 449fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (n != len) { 4502acec9153e40a558671ec0544bdd89d5a7fabf08Elliott Hughes D("ERROR: fd = %d, n = %d: %s\n", h->bulk_in, n, strerror(errno)); 451fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return -1; 452fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 453fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("[ done fd=%d ]\n", h->bulk_in); 454fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return 0; 455fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 456fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 4572acec9153e40a558671ec0544bdd89d5a7fabf08Elliott Hughesstatic int bulk_read(int bulk_out, uint8_t* buf, size_t length) 458fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 459fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz size_t count = 0; 460fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz int ret; 461fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 462fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz do { 463fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz ret = adb_read(bulk_out, buf + count, length - count); 464fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (ret < 0) { 465fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (errno != EINTR) { 466ccecf1425412beb2bc3bb38d470293fdc244d6f1Elliott Hughes D("[ bulk_read failed fd=%d length=%zu count=%zu ]\n", 467fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz bulk_out, length, count); 468fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return ret; 469fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 470fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } else { 471fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz count += ret; 472fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 473fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } while (count < length); 474fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 475fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return count; 476fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 477fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 4782acec9153e40a558671ec0544bdd89d5a7fabf08Elliott Hughesstatic int usb_ffs_read(usb_handle* h, void* data, int len) 479fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 480fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("about to read (fd=%d, len=%d)\n", h->bulk_out, len); 4812acec9153e40a558671ec0544bdd89d5a7fabf08Elliott Hughes int n = bulk_read(h->bulk_out, reinterpret_cast<uint8_t*>(data), len); 482fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (n != len) { 4832acec9153e40a558671ec0544bdd89d5a7fabf08Elliott Hughes D("ERROR: fd = %d, n = %d: %s\n", h->bulk_out, n, strerror(errno)); 484fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return -1; 485fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 486fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("[ done fd=%d ]\n", h->bulk_out); 487fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return 0; 488fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 489fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 490fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic void usb_ffs_kick(usb_handle *h) 491fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 492fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz int err; 493fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 494fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz err = ioctl(h->bulk_in, FUNCTIONFS_CLEAR_HALT); 495fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (err < 0) 496fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("[ kick: source (fd=%d) clear halt failed (%d) ]", h->bulk_in, errno); 497fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 498fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz err = ioctl(h->bulk_out, FUNCTIONFS_CLEAR_HALT); 499fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (err < 0) 500fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("[ kick: sink (fd=%d) clear halt failed (%d) ]", h->bulk_out, errno); 501fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_mutex_lock(&h->lock); 5034cbf1d882236462482b8e22893061604b224e308Jack Pham 5044cbf1d882236462482b8e22893061604b224e308Jack Pham // don't close ep0 here, since we may not need to reinitialize it with 5054cbf1d882236462482b8e22893061604b224e308Jack Pham // the same descriptors again. if however ep1/ep2 fail to re-open in 5064cbf1d882236462482b8e22893061604b224e308Jack Pham // init_functionfs, only then would we close and open ep0 again. 507fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_close(h->bulk_out); 508fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_close(h->bulk_in); 5094cbf1d882236462482b8e22893061604b224e308Jack Pham h->bulk_out = h->bulk_in = -1; 510dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 511fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz // notify usb_ffs_open_thread that we are disconnected 512dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_cond_signal(&h->notify); 513dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_mutex_unlock(&h->lock); 514dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 515dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 516fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczstatic void usb_ffs_init() 517fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 518fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("[ usb_init - using FunctionFS ]\n"); 519fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 5202acec9153e40a558671ec0544bdd89d5a7fabf08Elliott Hughes usb_handle* h = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle))); 521dc3b459ff9f0ff71d404ba7198083e532a0dd894Elliott Hughes if (h == nullptr) fatal("couldn't allocate usb_handle"); 522dc3b459ff9f0ff71d404ba7198083e532a0dd894Elliott Hughes 523fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->write = usb_ffs_write; 524fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->read = usb_ffs_read; 525fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->kick = usb_ffs_kick; 5262acec9153e40a558671ec0544bdd89d5a7fabf08Elliott Hughes h->control = -1; 527fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->bulk_out = -1; 528fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->bulk_out = -1; 529fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 530fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_cond_init(&h->notify, 0); 531fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz adb_mutex_init(&h->lock, 0); 532fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 533fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz D("[ usb_init - starting thread ]\n"); 5342acec9153e40a558671ec0544bdd89d5a7fabf08Elliott Hughes adb_thread_t tid; 535fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (adb_thread_create(&tid, usb_ffs_open_thread, h)){ 536fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz fatal_errno("[ cannot create usb thread ]\n"); 537fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz } 538fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 539fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 540fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczvoid usb_init() 541fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 542fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz if (access(USB_FFS_ADB_EP0, F_OK) == 0) 543fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz usb_ffs_init(); 544fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz else 545fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz usb_adb_init(); 546fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 547fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 548fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczvoid usb_cleanup() 549fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 550fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 551fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 552fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczint usb_write(usb_handle *h, const void *data, int len) 553fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 554fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return h->write(h, data, len); 555fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 556fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 557fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczint usb_read(usb_handle *h, void *data, int len) 558fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 559fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz return h->read(h, data, len); 560fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 561dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_close(usb_handle *h) 562dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 563dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 564dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 565fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz 566fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewiczvoid usb_kick(usb_handle *h) 567fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz{ 568fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz h->kick(h); 569fd96db17b7f07eb6615af01fd1908b74383bf04bAndrzej Pietrasiewicz} 570