• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
fastboot_register(const char * prefix,void (* phandle)(struct protocol_handle * phandle,const char * arg))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 
fastboot_publish(const char * name,const char * value)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 
fastboot_getvar(const char * name)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 
protocol_handle_download(struct protocol_handle * phandle,size_t len)102 int protocol_handle_download(struct protocol_handle *phandle, size_t len)
103 {
104     return transport_handle_download(phandle->transport_handle, len);
105 }
106 
protocol_handle_write(struct protocol_handle * phandle,char * buffer,size_t len)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 
fastboot_ack(struct protocol_handle * phandle,const char * code,const char * reason)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 
fastboot_fail(struct protocol_handle * phandle,const char * reason)130 void fastboot_fail(struct protocol_handle *phandle, const char *reason)
131 {
132     fastboot_ack(phandle, "FAIL", reason);
133 }
134 
fastboot_okay(struct protocol_handle * phandle,const char * info)135 void fastboot_okay(struct protocol_handle *phandle, const char *info)
136 {
137     fastboot_ack(phandle, "OKAY", info);
138 }
139 
fastboot_data(struct protocol_handle * phandle,size_t len)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 
protocol_handle_command(struct protocol_handle * phandle,char * buffer)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 
create_protocol_handle(struct transport_handle * thandle)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 
protocol_get_download(struct protocol_handle * phandle)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