1/* 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#include "utils.h" 34 35#define TRACE_TAG TRACE_USB 36 37#define MAX_PACKET_SIZE_FS 64 38#define MAX_PACKET_SIZE_HS 512 39 40#define cpu_to_le16(x) htole16(x) 41#define cpu_to_le32(x) htole32(x) 42 43#define FASTBOOT_CLASS 0xff 44#define FASTBOOT_SUBCLASS 0x42 45#define FASTBOOT_PROTOCOL 0x3 46 47#define USB_FFS_FASTBOOT_PATH "/dev/usb-ffs/adb/" 48#define USB_FFS_FASTBOOT_EP(x) USB_FFS_FASTBOOT_PATH#x 49 50#define USB_FFS_FASTBOOT_EP0 USB_FFS_FASTBOOT_EP(ep0) 51#define USB_FFS_FASTBOOT_OUT USB_FFS_FASTBOOT_EP(ep1) 52#define USB_FFS_FASTBOOT_IN USB_FFS_FASTBOOT_EP(ep2) 53 54#define container_of(ptr, type, member) \ 55 ((type*)((char*)(ptr) - offsetof(type, member))) 56 57struct usb_transport { 58 struct transport transport; 59 60 pthread_cond_t notify; 61 pthread_mutex_t lock; 62 63 int control; 64 int bulk_out; /* "out" from the host's perspective => source for fastbootd */ 65 int bulk_in; /* "in" from the host's perspective => sink for fastbootd */ 66}; 67 68struct usb_handle { 69 struct transport_handle handle; 70}; 71 72static const struct { 73 struct usb_functionfs_descs_head header; 74 struct { 75 struct usb_interface_descriptor intf; 76 struct usb_endpoint_descriptor_no_audio source; 77 struct usb_endpoint_descriptor_no_audio sink; 78 } __attribute__((packed)) fs_descs, hs_descs; 79} __attribute__((packed)) descriptors = { 80 .header = { 81 .magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC), 82 .length = cpu_to_le32(sizeof(descriptors)), 83 .fs_count = 3, 84 .hs_count = 3, 85 }, 86 .fs_descs = { 87 .intf = { 88 .bLength = sizeof(descriptors.fs_descs.intf), 89 .bDescriptorType = USB_DT_INTERFACE, 90 .bInterfaceNumber = 0, 91 .bNumEndpoints = 2, 92 .bInterfaceClass = FASTBOOT_CLASS, 93 .bInterfaceSubClass = FASTBOOT_SUBCLASS, 94 .bInterfaceProtocol = FASTBOOT_PROTOCOL, 95 .iInterface = 1, /* first string from the provided table */ 96 }, 97 .source = { 98 .bLength = sizeof(descriptors.fs_descs.source), 99 .bDescriptorType = USB_DT_ENDPOINT, 100 .bEndpointAddress = 1 | USB_DIR_OUT, 101 .bmAttributes = USB_ENDPOINT_XFER_BULK, 102 .wMaxPacketSize = MAX_PACKET_SIZE_FS, 103 }, 104 .sink = { 105 .bLength = sizeof(descriptors.fs_descs.sink), 106 .bDescriptorType = USB_DT_ENDPOINT, 107 .bEndpointAddress = 2 | USB_DIR_IN, 108 .bmAttributes = USB_ENDPOINT_XFER_BULK, 109 .wMaxPacketSize = MAX_PACKET_SIZE_FS, 110 }, 111 }, 112 .hs_descs = { 113 .intf = { 114 .bLength = sizeof(descriptors.hs_descs.intf), 115 .bDescriptorType = USB_DT_INTERFACE, 116 .bInterfaceNumber = 0, 117 .bNumEndpoints = 2, 118 .bInterfaceClass = FASTBOOT_CLASS, 119 .bInterfaceSubClass = FASTBOOT_SUBCLASS, 120 .bInterfaceProtocol = FASTBOOT_PROTOCOL, 121 .iInterface = 1, /* first string from the provided table */ 122 }, 123 .source = { 124 .bLength = sizeof(descriptors.hs_descs.source), 125 .bDescriptorType = USB_DT_ENDPOINT, 126 .bEndpointAddress = 1 | USB_DIR_OUT, 127 .bmAttributes = USB_ENDPOINT_XFER_BULK, 128 .wMaxPacketSize = MAX_PACKET_SIZE_HS, 129 }, 130 .sink = { 131 .bLength = sizeof(descriptors.hs_descs.sink), 132 .bDescriptorType = USB_DT_ENDPOINT, 133 .bEndpointAddress = 2 | USB_DIR_IN, 134 .bmAttributes = USB_ENDPOINT_XFER_BULK, 135 .wMaxPacketSize = MAX_PACKET_SIZE_HS, 136 }, 137 }, 138}; 139 140#define STR_INTERFACE_ "Fastboot Interface" 141 142static const struct { 143 struct usb_functionfs_strings_head header; 144 struct { 145 __le16 code; 146 const char str1[sizeof(STR_INTERFACE_)]; 147 } __attribute__((packed)) lang0; 148} __attribute__((packed)) strings = { 149 .header = { 150 .magic = cpu_to_le32(FUNCTIONFS_STRINGS_MAGIC), 151 .length = cpu_to_le32(sizeof(strings)), 152 .str_count = cpu_to_le32(1), 153 .lang_count = cpu_to_le32(1), 154 }, 155 .lang0 = { 156 cpu_to_le16(0x0409), /* en-us */ 157 STR_INTERFACE_, 158 }, 159}; 160 161static int init_functionfs(struct usb_transport *usb_transport) 162{ 163 ssize_t ret; 164 165 D(VERBOSE, "OPENING %s", USB_FFS_FASTBOOT_EP0); 166 usb_transport->control = open(USB_FFS_FASTBOOT_EP0, O_RDWR); 167 if (usb_transport->control < 0) { 168 D(ERR, "[ %s: cannot open control endpoint: errno=%d]", USB_FFS_FASTBOOT_EP0, errno); 169 goto err; 170 } 171 172 ret = write(usb_transport->control, &descriptors, sizeof(descriptors)); 173 if (ret < 0) { 174 D(ERR, "[ %s: write descriptors failed: errno=%d ]", USB_FFS_FASTBOOT_EP0, errno); 175 goto err; 176 } 177 178 ret = write(usb_transport->control, &strings, sizeof(strings)); 179 if (ret < 0) { 180 D(ERR, "[ %s: writing strings failed: errno=%d]", USB_FFS_FASTBOOT_EP0, errno); 181 goto err; 182 } 183 184 usb_transport->bulk_out = open(USB_FFS_FASTBOOT_OUT, O_RDWR); 185 if (usb_transport->bulk_out < 0) { 186 D(ERR, "[ %s: cannot open bulk-out ep: errno=%d ]", USB_FFS_FASTBOOT_OUT, errno); 187 goto err; 188 } 189 190 usb_transport->bulk_in = open(USB_FFS_FASTBOOT_IN, O_RDWR); 191 if (usb_transport->bulk_in < 0) { 192 D(ERR, "[ %s: cannot open bulk-in ep: errno=%d ]", USB_FFS_FASTBOOT_IN, errno); 193 goto err; 194 } 195 196 return 0; 197 198err: 199 if (usb_transport->bulk_in > 0) { 200 close(usb_transport->bulk_in); 201 usb_transport->bulk_in = -1; 202 } 203 if (usb_transport->bulk_out > 0) { 204 close(usb_transport->bulk_out); 205 usb_transport->bulk_out = -1; 206 } 207 if (usb_transport->control > 0) { 208 close(usb_transport->control); 209 usb_transport->control = -1; 210 } 211 return -1; 212} 213 214static ssize_t usb_write(struct transport_handle *thandle, const void *data, size_t len) 215{ 216 ssize_t ret; 217 struct transport *t = thandle->transport; 218 struct usb_transport *usb_transport = container_of(t, struct usb_transport, transport); 219 220 D(DEBUG, "about to write (fd=%d, len=%zu)", usb_transport->bulk_in, len); 221 ret = bulk_write(usb_transport->bulk_in, data, len); 222 if (ret < 0) { 223 D(ERR, "ERROR: fd = %d, ret = %zd", usb_transport->bulk_in, ret); 224 return -1; 225 } 226 D(DEBUG, "[ usb_write done fd=%d ]", usb_transport->bulk_in); 227 return ret; 228} 229 230ssize_t usb_read(struct transport_handle *thandle, void *data, size_t len) 231{ 232 ssize_t ret; 233 struct transport *t = thandle->transport; 234 struct usb_transport *usb_transport = container_of(t, struct usb_transport, transport); 235 236 D(DEBUG, "about to read (fd=%d, len=%zu)", usb_transport->bulk_out, len); 237 ret = bulk_read(usb_transport->bulk_out, data, len); 238 if (ret < 0) { 239 D(ERR, "ERROR: fd = %d, ret = %zd", usb_transport->bulk_out, ret); 240 return -1; 241 } 242 D(DEBUG, "[ usb_read done fd=%d ret=%zd]", usb_transport->bulk_out, ret); 243 return ret; 244} 245 246void usb_close(struct transport_handle *thandle) 247{ 248 int err; 249 struct transport *t = thandle->transport; 250 struct usb_transport *usb_transport = container_of(t, struct usb_transport, transport); 251 252 err = ioctl(usb_transport->bulk_in, FUNCTIONFS_CLEAR_HALT); 253 if (err < 0) 254 D(WARN, "[ kick: source (fd=%d) clear halt failed (%d) ]", usb_transport->bulk_in, errno); 255 256 err = ioctl(usb_transport->bulk_out, FUNCTIONFS_CLEAR_HALT); 257 if (err < 0) 258 D(WARN, "[ kick: sink (fd=%d) clear halt failed (%d) ]", usb_transport->bulk_out, errno); 259 260 pthread_mutex_lock(&usb_transport->lock); 261 close(usb_transport->control); 262 close(usb_transport->bulk_out); 263 close(usb_transport->bulk_in); 264 usb_transport->control = usb_transport->bulk_out = usb_transport->bulk_in = -1; 265 266 pthread_cond_signal(&usb_transport->notify); 267 pthread_mutex_unlock(&usb_transport->lock); 268} 269 270struct transport_handle *usb_connect(struct transport *transport) 271{ 272 int ret; 273 struct usb_handle *usb_handle = calloc(sizeof(struct usb_handle), 1); 274 struct usb_transport *usb_transport = container_of(transport, struct usb_transport, transport); 275 276 pthread_mutex_lock(&usb_transport->lock); 277 while (usb_transport->control != -1) 278 pthread_cond_wait(&usb_transport->notify, &usb_transport->lock); 279 pthread_mutex_unlock(&usb_transport->lock); 280 281 ret = init_functionfs(usb_transport); 282 if (ret < 0) { 283 D(ERR, "usb connect: failed to initialize usb transport"); 284 return NULL; 285 } 286 287 D(DEBUG, "[ usb_thread - registering device ]"); 288 return &usb_handle->handle; 289} 290 291void usb_init() 292{ 293 struct usb_transport *usb_transport = calloc(1, sizeof(struct usb_transport)); 294 295 usb_transport->transport.connect = usb_connect; 296 usb_transport->transport.close = usb_close; 297 usb_transport->transport.read = usb_read; 298 usb_transport->transport.write = usb_write; 299 usb_transport->control = -1; 300 usb_transport->bulk_out = -1; 301 usb_transport->bulk_out = -1; 302 303 pthread_cond_init(&usb_transport->notify, NULL); 304 pthread_mutex_init(&usb_transport->lock, NULL); 305 306 transport_register(&usb_transport->transport); 307} 308 309