Home | History | Annotate | Download | only in fastbootd
      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 
     57 struct 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 
     68 struct usb_handle {
     69     struct transport_handle handle;
     70 };
     71 
     72 static 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 
    142 static 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 
    161 static 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 
    198 err:
    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 
    214 static 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 
    230 ssize_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 
    246 void 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 
    270 struct 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 
    291 void 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