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