1 /*
2 * Copyright (C) 2008 The Android Open Source Project
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 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <errno.h>
33
34 #include "fastboot.h"
35
36 static char ERROR[128];
37
fb_get_error(void)38 char *fb_get_error(void)
39 {
40 return ERROR;
41 }
42
check_response(usb_handle * usb,unsigned size,unsigned data_okay,char * response)43 static int check_response(usb_handle *usb, unsigned size,
44 unsigned data_okay, char *response)
45 {
46 unsigned char status[65];
47 int r;
48
49 for(;;) {
50 r = usb_read(usb, status, 64);
51 if(r < 0) {
52 sprintf(ERROR, "status read failed (%s)", strerror(errno));
53 usb_close(usb);
54 return -1;
55 }
56 status[r] = 0;
57
58 if(r < 4) {
59 sprintf(ERROR, "status malformed (%d bytes)", r);
60 usb_close(usb);
61 return -1;
62 }
63
64 if(!memcmp(status, "INFO", 4)) {
65 fprintf(stderr,"%s\n", status);
66 continue;
67 }
68
69 if(!memcmp(status, "OKAY", 4)) {
70 if(response) {
71 strcpy(response, (char*) status + 4);
72 }
73 return 0;
74 }
75
76 if(!memcmp(status, "FAIL", 4)) {
77 if(r > 4) {
78 sprintf(ERROR, "remote: %s", status + 4);
79 } else {
80 strcpy(ERROR, "remote failure");
81 }
82 return -1;
83 }
84
85 if(!memcmp(status, "DATA", 4) && data_okay){
86 unsigned dsize = strtoul((char*) status + 4, 0, 16);
87 if(dsize > size) {
88 strcpy(ERROR, "data size too large");
89 usb_close(usb);
90 return -1;
91 }
92 return dsize;
93 }
94
95 strcpy(ERROR,"unknown status code");
96 usb_close(usb);
97 break;
98 }
99
100 return -1;
101 }
102
_command_send(usb_handle * usb,const char * cmd,const void * data,unsigned size,char * response)103 static int _command_send(usb_handle *usb, const char *cmd,
104 const void *data, unsigned size,
105 char *response)
106 {
107 int cmdsize = strlen(cmd);
108 int r;
109
110 if(response) {
111 response[0] = 0;
112 }
113
114 if(cmdsize > 64) {
115 sprintf(ERROR,"command too large");
116 return -1;
117 }
118
119 if(usb_write(usb, cmd, cmdsize) != cmdsize) {
120 sprintf(ERROR,"command write failed (%s)", strerror(errno));
121 usb_close(usb);
122 return -1;
123 }
124
125 if(data == 0) {
126 return check_response(usb, size, 0, response);
127 }
128
129 r = check_response(usb, size, 1, 0);
130 if(r < 0) {
131 return -1;
132 }
133 size = r;
134
135 if(size) {
136 r = usb_write(usb, data, size);
137 if(r < 0) {
138 sprintf(ERROR, "data transfer failure (%s)", strerror(errno));
139 usb_close(usb);
140 return -1;
141 }
142 if(r != ((int) size)) {
143 sprintf(ERROR, "data transfer failure (short transfer)");
144 usb_close(usb);
145 return -1;
146 }
147 }
148
149 r = check_response(usb, 0, 0, 0);
150 if(r < 0) {
151 return -1;
152 } else {
153 return size;
154 }
155 }
156
fb_command(usb_handle * usb,const char * cmd)157 int fb_command(usb_handle *usb, const char *cmd)
158 {
159 return _command_send(usb, cmd, 0, 0, 0);
160 }
161
fb_command_response(usb_handle * usb,const char * cmd,char * response)162 int fb_command_response(usb_handle *usb, const char *cmd, char *response)
163 {
164 return _command_send(usb, cmd, 0, 0, response);
165 }
166
fb_download_data(usb_handle * usb,const void * data,unsigned size)167 int fb_download_data(usb_handle *usb, const void *data, unsigned size)
168 {
169 char cmd[64];
170 int r;
171
172 sprintf(cmd, "download:%08x", size);
173 r = _command_send(usb, cmd, data, size, 0);
174
175 if(r < 0) {
176 return -1;
177 } else {
178 return 0;
179 }
180 }
181
182