blob: 111cf3596bb6845ce30d19835d66c0b5f2f1dd5b [file] [log] [blame]
Colin Crossa3d386e2013-02-06 21:03:34 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <endian.h>
18#include <fcntl.h>
19#include <pthread.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <unistd.h>
24
25#include <sys/ioctl.h>
26#include <sys/types.h>
27
28#include <linux/usb/ch9.h>
29#include <linux/usb/functionfs.h>
30
31#include "debug.h"
32#include "transport.h"
33
34#define TRACE_TAG TRACE_USB
35
36#define MAX_PACKET_SIZE_FS 64
37#define MAX_PACKET_SIZE_HS 512
38
39#define cpu_to_le16(x) htole16(x)
40#define cpu_to_le32(x) htole32(x)
41
42#define FASTBOOT_CLASS 0xff
43#define FASTBOOT_SUBCLASS 0x42
44#define FASTBOOT_PROTOCOL 0x3
45
46#define USB_FFS_FASTBOOT_PATH "/dev/usb-ffs/adb/"
47#define USB_FFS_FASTBOOT_EP(x) USB_FFS_FASTBOOT_PATH#x
48
49#define USB_FFS_FASTBOOT_EP0 USB_FFS_FASTBOOT_EP(ep0)
50#define USB_FFS_FASTBOOT_OUT USB_FFS_FASTBOOT_EP(ep1)
51#define USB_FFS_FASTBOOT_IN USB_FFS_FASTBOOT_EP(ep2)
52
53#define READ_BUF_SIZE (16*1024)
54
55#define container_of(ptr, type, member) \
56 ((type*)((char*)(ptr) - offsetof(type, member)))
57
58struct usb_transport {
59 struct transport transport;
60
61 pthread_cond_t notify;
62 pthread_mutex_t lock;
63
64 int control;
65 int bulk_out; /* "out" from the host's perspective => source for fastbootd */
66 int bulk_in; /* "in" from the host's perspective => sink for fastbootd */
67};
68
69struct usb_handle {
70 struct transport_handle handle;
71};
72
73static const struct {
74 struct usb_functionfs_descs_head header;
75 struct {
76 struct usb_interface_descriptor intf;
77 struct usb_endpoint_descriptor_no_audio source;
78 struct usb_endpoint_descriptor_no_audio sink;
79 } __attribute__((packed)) fs_descs, hs_descs;
80} __attribute__((packed)) descriptors = {
81 .header = {
82 .magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC),
83 .length = cpu_to_le32(sizeof(descriptors)),
84 .fs_count = 3,
85 .hs_count = 3,
86 },
87 .fs_descs = {
88 .intf = {
89 .bLength = sizeof(descriptors.fs_descs.intf),
90 .bDescriptorType = USB_DT_INTERFACE,
91 .bInterfaceNumber = 0,
92 .bNumEndpoints = 2,
93 .bInterfaceClass = FASTBOOT_CLASS,
94 .bInterfaceSubClass = FASTBOOT_SUBCLASS,
95 .bInterfaceProtocol = FASTBOOT_PROTOCOL,
96 .iInterface = 1, /* first string from the provided table */
97 },
98 .source = {
99 .bLength = sizeof(descriptors.fs_descs.source),
100 .bDescriptorType = USB_DT_ENDPOINT,
101 .bEndpointAddress = 1 | USB_DIR_OUT,
102 .bmAttributes = USB_ENDPOINT_XFER_BULK,
103 .wMaxPacketSize = MAX_PACKET_SIZE_FS,
104 },
105 .sink = {
106 .bLength = sizeof(descriptors.fs_descs.sink),
107 .bDescriptorType = USB_DT_ENDPOINT,
108 .bEndpointAddress = 2 | USB_DIR_IN,
109 .bmAttributes = USB_ENDPOINT_XFER_BULK,
110 .wMaxPacketSize = MAX_PACKET_SIZE_FS,
111 },
112 },
113 .hs_descs = {
114 .intf = {
115 .bLength = sizeof(descriptors.hs_descs.intf),
116 .bDescriptorType = USB_DT_INTERFACE,
117 .bInterfaceNumber = 0,
118 .bNumEndpoints = 2,
119 .bInterfaceClass = FASTBOOT_CLASS,
120 .bInterfaceSubClass = FASTBOOT_SUBCLASS,
121 .bInterfaceProtocol = FASTBOOT_PROTOCOL,
122 .iInterface = 1, /* first string from the provided table */
123 },
124 .source = {
125 .bLength = sizeof(descriptors.hs_descs.source),
126 .bDescriptorType = USB_DT_ENDPOINT,
127 .bEndpointAddress = 1 | USB_DIR_OUT,
128 .bmAttributes = USB_ENDPOINT_XFER_BULK,
129 .wMaxPacketSize = MAX_PACKET_SIZE_HS,
130 },
131 .sink = {
132 .bLength = sizeof(descriptors.hs_descs.sink),
133 .bDescriptorType = USB_DT_ENDPOINT,
134 .bEndpointAddress = 2 | USB_DIR_IN,
135 .bmAttributes = USB_ENDPOINT_XFER_BULK,
136 .wMaxPacketSize = MAX_PACKET_SIZE_HS,
137 },
138 },
139};
140
141#define STR_INTERFACE_ "Fastboot Interface"
142
143static const struct {
144 struct usb_functionfs_strings_head header;
145 struct {
146 __le16 code;
147 const char str1[sizeof(STR_INTERFACE_)];
148 } __attribute__((packed)) lang0;
149} __attribute__((packed)) strings = {
150 .header = {
151 .magic = cpu_to_le32(FUNCTIONFS_STRINGS_MAGIC),
152 .length = cpu_to_le32(sizeof(strings)),
153 .str_count = cpu_to_le32(1),
154 .lang_count = cpu_to_le32(1),
155 },
156 .lang0 = {
157 cpu_to_le16(0x0409), /* en-us */
158 STR_INTERFACE_,
159 },
160};
161
162static int init_functionfs(struct usb_transport *usb_transport)
163{
164 ssize_t ret;
165
166 D(VERBOSE, "OPENING %s", USB_FFS_FASTBOOT_EP0);
167 usb_transport->control = open(USB_FFS_FASTBOOT_EP0, O_RDWR);
168 if (usb_transport->control < 0) {
169 D(ERR, "[ %s: cannot open control endpoint: errno=%d]", USB_FFS_FASTBOOT_EP0, errno);
170 goto err;
171 }
172
173 ret = write(usb_transport->control, &descriptors, sizeof(descriptors));
174 if (ret < 0) {
175 D(ERR, "[ %s: write descriptors failed: errno=%d ]", USB_FFS_FASTBOOT_EP0, errno);
176 goto err;
177 }
178
179 ret = write(usb_transport->control, &strings, sizeof(strings));
180 if (ret < 0) {
181 D(ERR, "[ %s: writing strings failed: errno=%d]", USB_FFS_FASTBOOT_EP0, errno);
182 goto err;
183 }
184
185 usb_transport->bulk_out = open(USB_FFS_FASTBOOT_OUT, O_RDWR);
186 if (usb_transport->bulk_out < 0) {
187 D(ERR, "[ %s: cannot open bulk-out ep: errno=%d ]", USB_FFS_FASTBOOT_OUT, errno);
188 goto err;
189 }
190
191 usb_transport->bulk_in = open(USB_FFS_FASTBOOT_IN, O_RDWR);
192 if (usb_transport->bulk_in < 0) {
193 D(ERR, "[ %s: cannot open bulk-in ep: errno=%d ]", USB_FFS_FASTBOOT_IN, errno);
194 goto err;
195 }
196
197 return 0;
198
199err:
200 if (usb_transport->bulk_in > 0) {
201 close(usb_transport->bulk_in);
202 usb_transport->bulk_in = -1;
203 }
204 if (usb_transport->bulk_out > 0) {
205 close(usb_transport->bulk_out);
206 usb_transport->bulk_out = -1;
207 }
208 if (usb_transport->control > 0) {
209 close(usb_transport->control);
210 usb_transport->control = -1;
211 }
212 return -1;
213}
214
215static ssize_t bulk_write(int bulk_in, const char *buf, size_t length)
216{
217 size_t count = 0;
218 ssize_t ret;
219
220 do {
221 ret = TEMP_FAILURE_RETRY(write(bulk_in, buf + count, length - count));
222 if (ret < 0) {
223 D(WARN, "[ bulk_read failed fd=%d length=%d errno=%d %s ]",
224 bulk_in, length, errno, strerror(errno));
225 return -1;
226 } else {
227 count += ret;
228 }
229 } while (count < length);
230
231 D(VERBOSE, "[ bulk_write done fd=%d ]", bulk_in);
232 return count;
233}
234
235static ssize_t usb_write(struct transport_handle *thandle, const void *data, size_t len)
236{
237 ssize_t ret;
238 struct transport *t = thandle->transport;
239 struct usb_transport *usb_transport = container_of(t, struct usb_transport, transport);
240
241 D(DEBUG, "about to write (fd=%d, len=%d)", usb_transport->bulk_in, len);
242 ret = bulk_write(usb_transport->bulk_in, data, len);
243 if (ret < 0) {
244 D(ERR, "ERROR: fd = %d, ret = %zd", usb_transport->bulk_in, ret);
245 return -1;
246 }
247 D(DEBUG, "[ usb_write done fd=%d ]", usb_transport->bulk_in);
248 return ret;
249}
250
251static ssize_t bulk_read(int bulk_out, char *buf, size_t length)
252{
253 ssize_t ret;
254 size_t n = 0;
255
256 while (n < length) {
257 size_t to_read = (length - n > READ_BUF_SIZE) ? READ_BUF_SIZE : length - n;
258 ret = TEMP_FAILURE_RETRY(read(bulk_out, buf + n, to_read));
259 if (ret < 0) {
260 D(WARN, "[ bulk_read failed fd=%d length=%d errno=%d %s ]",
261 bulk_out, length, errno, strerror(errno));
262 return ret;
263 }
264 n += ret;
265 if (ret < (ssize_t)to_read) {
266 D(VERBOSE, "bulk_read short read, ret=%zd to_read=%u n=%u length=%u",
267 ret, to_read, n, length);
268 break;
269 }
270 }
271
272 return n;
273}
274
275ssize_t usb_read(struct transport_handle *thandle, void *data, size_t len)
276{
277 ssize_t ret;
278 struct transport *t = thandle->transport;
279 struct usb_transport *usb_transport = container_of(t, struct usb_transport, transport);
280
281 D(DEBUG, "about to read (fd=%d, len=%d)", usb_transport->bulk_out, len);
282 ret = bulk_read(usb_transport->bulk_out, data, len);
283 if (ret < 0) {
284 D(ERR, "ERROR: fd = %d, ret = %zd", usb_transport->bulk_out, ret);
285 return -1;
286 }
287 D(DEBUG, "[ usb_read done fd=%d ret=%zd]", usb_transport->bulk_out, ret);
288 return ret;
289}
290
291void usb_close(struct transport_handle *thandle)
292{
293 int err;
294 struct transport *t = thandle->transport;
295 struct usb_transport *usb_transport = container_of(t, struct usb_transport, transport);
296
297 err = ioctl(usb_transport->bulk_in, FUNCTIONFS_CLEAR_HALT);
298 if (err < 0)
299 D(WARN, "[ kick: source (fd=%d) clear halt failed (%d) ]", usb_transport->bulk_in, errno);
300
301 err = ioctl(usb_transport->bulk_out, FUNCTIONFS_CLEAR_HALT);
302 if (err < 0)
303 D(WARN, "[ kick: sink (fd=%d) clear halt failed (%d) ]", usb_transport->bulk_out, errno);
304
305 pthread_mutex_lock(&usb_transport->lock);
306 close(usb_transport->control);
307 close(usb_transport->bulk_out);
308 close(usb_transport->bulk_in);
309 usb_transport->control = usb_transport->bulk_out = usb_transport->bulk_in = -1;
310
311 pthread_cond_signal(&usb_transport->notify);
312 pthread_mutex_unlock(&usb_transport->lock);
313}
314
315struct transport_handle *usb_connect(struct transport *transport)
316{
317 int ret;
318 struct usb_handle *usb_handle = calloc(sizeof(struct usb_handle), 1);
319 struct usb_transport *usb_transport = container_of(transport, struct usb_transport, transport);
320
321 pthread_mutex_lock(&usb_transport->lock);
322 while (usb_transport->control != -1)
323 pthread_cond_wait(&usb_transport->notify, &usb_transport->lock);
324 pthread_mutex_unlock(&usb_transport->lock);
325
326 ret = init_functionfs(usb_transport);
327 if (ret < 0) {
328 D(ERR, "usb connect: failed to initialize usb transport");
329 return NULL;
330 }
331
332 D(DEBUG, "[ usb_thread - registering device ]");
333 return &usb_handle->handle;
334}
335
336void usb_init()
337{
338 struct usb_transport *usb_transport = calloc(1, sizeof(struct usb_transport));
339
340 usb_transport->transport.connect = usb_connect;
341 usb_transport->transport.close = usb_close;
342 usb_transport->transport.read = usb_read;
343 usb_transport->transport.write = usb_write;
344 usb_transport->control = -1;
345 usb_transport->bulk_out = -1;
346 usb_transport->bulk_out = -1;
347
348 pthread_cond_init(&usb_transport->notify, NULL);
349 pthread_mutex_init(&usb_transport->lock, NULL);
350
351 transport_register(&usb_transport->transport);
352}
353