Home | History | Annotate | Download | only in fastbootd
      1 /*
      2  * Copyright (c) 2009-2013, Google Inc.
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *  * Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *  * Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in
     12  *    the documentation and/or other materials provided with the
     13  *    distribution.
     14  *  * Neither the name of Google, Inc. nor the names of its contributors
     15  *    may be used to endorse or promote products derived from this
     16  *    software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     22  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     24  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
     25  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     26  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     27  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     28  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  * SUCH DAMAGE.
     30  */
     31 
     32 #include <stddef.h>
     33 #include <stdio.h>
     34 #include <stdlib.h>
     35 #include <string.h>
     36 
     37 #include "debug.h"
     38 #include "protocol.h"
     39 #include "transport.h"
     40 
     41 #define STATE_OFFLINE   0
     42 #define STATE_COMMAND   1
     43 #define STATE_COMPLETE  2
     44 #define STATE_ERROR     3
     45 
     46 struct fastboot_cmd {
     47     struct fastboot_cmd *next;
     48     const char *prefix;
     49     unsigned prefix_len;
     50     void (*execute)(struct protocol_handle *phandle, const char *arg);
     51 };
     52 
     53 struct fastboot_var {
     54     struct fastboot_var *next;
     55     const char *name;
     56     const char *value;
     57 };
     58 
     59 static struct fastboot_cmd *cmdlist;
     60 
     61 void fastboot_register(const char *prefix,
     62         void (*phandle)(struct protocol_handle *phandle, const char *arg))
     63 {
     64     struct fastboot_cmd *cmd;
     65     cmd = malloc(sizeof(*cmd));
     66     if (cmd) {
     67         cmd->prefix = prefix;
     68         cmd->prefix_len = strlen(prefix);
     69         cmd->execute = phandle;
     70         cmd->next = cmdlist;
     71         cmdlist = cmd;
     72     }
     73 }
     74 
     75 static struct fastboot_var *varlist;
     76 
     77 void fastboot_publish(const char *name, const char *value)
     78 {
     79     struct fastboot_var *var;
     80     var = malloc(sizeof(*var));
     81     if (var) {
     82         var->name = name;
     83         var->value = value;
     84         var->next = varlist;
     85         varlist = var;
     86     }
     87 }
     88 
     89 const char *fastboot_getvar(const char *name)
     90 {
     91     struct fastboot_var *var;
     92 
     93     for (var = varlist; var; var = var->next) {
     94         if (!strcmp(var->name, name)) {
     95             return var->value;
     96         }
     97     }
     98 
     99     return "";
    100 }
    101 
    102 int protocol_handle_download(struct protocol_handle *phandle, size_t len)
    103 {
    104     return transport_handle_download(phandle->transport_handle, len);
    105 }
    106 
    107 static ssize_t protocol_handle_write(struct protocol_handle *phandle,
    108         char *buffer, size_t len)
    109 {
    110     return transport_handle_write(phandle->transport_handle, buffer, len);
    111 }
    112 
    113 static void fastboot_ack(struct protocol_handle *phandle, const char *code,
    114         const char *reason)
    115 {
    116     char response[64];
    117 
    118     if (phandle->state != STATE_COMMAND)
    119         return;
    120 
    121     if (reason == 0)
    122         reason = "";
    123 
    124     snprintf(response, 64, "%s%s", code, reason);
    125     phandle->state = STATE_COMPLETE;
    126 
    127     protocol_handle_write(phandle, response, strlen(response));
    128 }
    129 
    130 void fastboot_fail(struct protocol_handle *phandle, const char *reason)
    131 {
    132     fastboot_ack(phandle, "FAIL", reason);
    133 }
    134 
    135 void fastboot_okay(struct protocol_handle *phandle, const char *info)
    136 {
    137     fastboot_ack(phandle, "OKAY", info);
    138 }
    139 
    140 void fastboot_data(struct protocol_handle *phandle, size_t len)
    141 {
    142     char response[64];
    143     ssize_t ret;
    144 
    145     snprintf(response, 64, "DATA%08zx", len);
    146     ret = protocol_handle_write(phandle, response, strlen(response));
    147     if (ret < 0)
    148         return;
    149 }
    150 
    151 void protocol_handle_command(struct protocol_handle *phandle, char *buffer)
    152 {
    153     D(INFO,"fastboot: %s\n", buffer);
    154 
    155     struct fastboot_cmd *cmd;
    156 
    157     for (cmd = cmdlist; cmd; cmd = cmd->next) {
    158         if (memcmp(buffer, cmd->prefix, cmd->prefix_len))
    159             continue;
    160         phandle->state = STATE_COMMAND;
    161         cmd->execute(phandle, buffer + cmd->prefix_len);
    162         if (phandle->state == STATE_COMMAND)
    163             fastboot_fail(phandle, "unknown reason");
    164         return;
    165     }
    166 
    167     fastboot_fail(phandle, "unknown command");
    168 }
    169 
    170 struct protocol_handle *create_protocol_handle(struct transport_handle *thandle)
    171 {
    172     struct protocol_handle *phandle;
    173 
    174     phandle = calloc(sizeof(struct protocol_handle), 1);
    175 
    176     phandle->transport_handle = thandle;
    177     phandle->state = STATE_OFFLINE;
    178     phandle->download_fd = -1;
    179 
    180     pthread_mutex_init(&phandle->lock, NULL);
    181 
    182     return phandle;
    183 }
    184 
    185 int protocol_get_download(struct protocol_handle *phandle)
    186 {
    187     int fd;
    188 
    189     pthread_mutex_lock(&phandle->lock);
    190     fd = phandle->download_fd;
    191     phandle->download_fd = -1;
    192     pthread_mutex_unlock(&phandle->lock);
    193 
    194     return fd;
    195 }
    196