protocol.c revision 4f6e8d7a00cbeda1e70cc15be9c4af1018bdad53
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
36static char ERROR[128];
37
38char *fb_get_error(void)
39{
40    return ERROR;
41}
42
43static 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
103static 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
157int fb_command(usb_handle *usb, const char *cmd)
158{
159    return _command_send(usb, cmd, 0, 0, 0);
160}
161
162int fb_command_response(usb_handle *usb, const char *cmd, char *response)
163{
164    return _command_send(usb, cmd, 0, 0, response);
165}
166
167int 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