• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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