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