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