protocol.c revision f838788e6a4d57634a53eb597ee76a597feffcb5
1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * All rights reserved.
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Redistribution and use in source and binary forms, with or without
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * modification, are permitted provided that the following conditions
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * are met:
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *  * Redistributions of source code must retain the above copyright
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *  * Redistributions in binary form must reproduce the above copyright
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    notice, this list of conditions and the following disclaimer in
125ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau *    the documentation and/or other materials provided with the
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    distribution.
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
225ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * SUCH DAMAGE.
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
29f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross#define min(a, b) \
30f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    ({ typeof(a) _a = (a); typeof(b) _b = (b); (_a < _b) ? _a : _b; })
31f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross#define round_down(a, b) \
32f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    ({ typeof(a) _a = (a); typeof(b) _b = (b); _a - (_a % _b); })
33f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
39f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross#include <sparse/sparse.h>
40f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "fastboot.h"
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic char ERROR[128];
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectchar *fb_get_error(void)
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return ERROR;
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
50f838788e6a4d57634a53eb597ee76a597feffcb5Colin Crossstatic int check_response(usb_handle *usb, unsigned int size, char *response)
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned char status[65];
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int r;
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(;;) {
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        r = usb_read(usb, status, 64);
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(r < 0) {
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            sprintf(ERROR, "status read failed (%s)", strerror(errno));
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            usb_close(usb);
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        status[r] = 0;
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(r < 4) {
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            sprintf(ERROR, "status malformed (%d bytes)", r);
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            usb_close(usb);
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(!memcmp(status, "INFO", 4)) {
7163e5205cd2f693bbfa54411f2dd20354bd30ffd8Brian Swetland            fprintf(stderr,"(bootloader) %s\n", status + 4);
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            continue;
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(!memcmp(status, "OKAY", 4)) {
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(response) {
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                strcpy(response, (char*) status + 4);
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return 0;
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(!memcmp(status, "FAIL", 4)) {
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(r > 4) {
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                sprintf(ERROR, "remote: %s", status + 4);
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else {
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                strcpy(ERROR, "remote failure");
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
91f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        if(!memcmp(status, "DATA", 4) && size > 0){
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            unsigned dsize = strtoul((char*) status + 4, 0, 16);
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(dsize > size) {
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                strcpy(ERROR, "data size too large");
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                usb_close(usb);
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return -1;
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return dsize;
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        strcpy(ERROR,"unknown status code");
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        usb_close(usb);
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
109f838788e6a4d57634a53eb597ee76a597feffcb5Colin Crossstatic int _command_start(usb_handle *usb, const char *cmd, unsigned size,
110f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross                          char *response)
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int cmdsize = strlen(cmd);
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int r;
1145ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(response) {
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        response[0] = 0;
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(cmdsize > 64) {
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        sprintf(ERROR,"command too large");
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(usb_write(usb, cmd, cmdsize) != cmdsize) {
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        sprintf(ERROR,"command write failed (%s)", strerror(errno));
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        usb_close(usb);
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
130f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    return check_response(usb, size, response);
131f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
132f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
133f838788e6a4d57634a53eb597ee76a597feffcb5Colin Crossstatic int _command_data(usb_handle *usb, const void *data, unsigned size)
134f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross{
135f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    int r;
136f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
137f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    r = usb_write(usb, data, size);
138f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if(r < 0) {
139f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        sprintf(ERROR, "data transfer failure (%s)", strerror(errno));
140f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        usb_close(usb);
141f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        return -1;
142f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
143f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if(r != ((int) size)) {
144f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        sprintf(ERROR, "data transfer failure (short transfer)");
145f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        usb_close(usb);
146f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        return -1;
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
149f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    return r;
150f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
151f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
152f838788e6a4d57634a53eb597ee76a597feffcb5Colin Crossstatic int _command_end(usb_handle *usb)
153f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross{
154f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    int r;
155f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    r = check_response(usb, 0, 0);
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(r < 0) {
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
159f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    return 0;
160f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
162f838788e6a4d57634a53eb597ee76a597feffcb5Colin Crossstatic int _command_send(usb_handle *usb, const char *cmd,
163f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross                         const void *data, unsigned size,
164f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross                         char *response)
165f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross{
166f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    int r;
167f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (size == 0) {
168f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        return -1;
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1705ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau
171f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    r = _command_start(usb, cmd, size, response);
172f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (r < 0) {
173f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        return -1;
174f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
175f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
176f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    r = _command_data(usb, data, size);
177f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (r < 0) {
178f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        return -1;
179f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
180f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
181f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    r = _command_end(usb);
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(r < 0) {
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
185f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
186f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    return size;
187f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
188f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
189f838788e6a4d57634a53eb597ee76a597feffcb5Colin Crossstatic int _command_send_no_data(usb_handle *usb, const char *cmd,
190f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross                                 char *response)
191f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross{
192f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    int r;
193f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
194f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    return _command_start(usb, cmd, 0, response);
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint fb_command(usb_handle *usb, const char *cmd)
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
199f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    return _command_send_no_data(usb, cmd, 0);
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint fb_command_response(usb_handle *usb, const char *cmd, char *response)
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
204f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    return _command_send_no_data(usb, cmd, response);
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint fb_download_data(usb_handle *usb, const void *data, unsigned size)
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char cmd[64];
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int r;
2115ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sprintf(cmd, "download:%08x", size);
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    r = _command_send(usb, cmd, data, size, 0);
2145ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(r < 0) {
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
222f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross#define USB_BUF_SIZE 512
223f838788e6a4d57634a53eb597ee76a597feffcb5Colin Crossstatic char usb_buf[USB_BUF_SIZE];
224f838788e6a4d57634a53eb597ee76a597feffcb5Colin Crossstatic int usb_buf_len;
225f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
226f838788e6a4d57634a53eb597ee76a597feffcb5Colin Crossstatic int fb_download_data_sparse_write(void *priv, const void *data, int len)
227f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross{
228f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    int r;
229f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    usb_handle *usb = priv;
230f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    int to_write;
231f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    const char *ptr = data;
232f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
233f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (usb_buf_len) {
234f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        to_write = min(USB_BUF_SIZE - usb_buf_len, len);
235f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
236f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        memcpy(usb_buf + usb_buf_len, ptr, to_write);
237f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        usb_buf_len += to_write;
238f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        ptr += to_write;
239f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        len -= to_write;
240f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
241f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
242f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (usb_buf_len == USB_BUF_SIZE) {
243f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        r = _command_data(usb, usb_buf, USB_BUF_SIZE);
244f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        if (r != USB_BUF_SIZE) {
245f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            return -1;
246f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        }
247f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        usb_buf_len = 0;
248f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
249f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
250f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (len > USB_BUF_SIZE) {
251f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        if (usb_buf_len > 0) {
252f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            sprintf(ERROR, "internal error: usb_buf not empty\n");
253f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            return -1;
254f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        }
255f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        to_write = round_down(len, USB_BUF_SIZE);
256f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        r = _command_data(usb, ptr, to_write);
257f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        if (r != to_write) {
258f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            return -1;
259f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        }
260f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        ptr += to_write;
261f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        len -= to_write;
262f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
263f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
264f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (len > 0) {
265f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        if (len > USB_BUF_SIZE) {
266f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            sprintf(ERROR, "internal error: too much left for usb_buf\n");
267f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            return -1;
268f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        }
269f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        memcpy(usb_buf, ptr, len);
270f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        usb_buf_len = len;
271f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
272f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
273f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    return 0;
274f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
275f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
276f838788e6a4d57634a53eb597ee76a597feffcb5Colin Crossstatic int fb_download_data_sparse_flush(usb_handle *usb)
277f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross{
278f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    int r;
279f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
280f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (usb_buf_len > 0) {
281f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        r = _command_data(usb, usb_buf, usb_buf_len);
282f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        if (r != usb_buf_len) {
283f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            return -1;
284f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        }
285f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        usb_buf_len = 0;
286f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
287f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
288f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    return 0;
289f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
290f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
291f838788e6a4d57634a53eb597ee76a597feffcb5Colin Crossint fb_download_data_sparse(usb_handle *usb, struct sparse_file *s)
292f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross{
293f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    char cmd[64];
294f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    int r;
295f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    int size = sparse_file_len(s, true, false);
296f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (size <= 0) {
297f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        return -1;
298f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
299f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
300f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    sprintf(cmd, "download:%08x", size);
301f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    r = _command_start(usb, cmd, size, 0);
302f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (r < 0) {
303f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        return -1;
304f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
305f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
306f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    r = sparse_file_callback(s, true, false, fb_download_data_sparse_write, usb);
307f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (r < 0) {
308f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        return -1;
309f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
310f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
311f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    fb_download_data_sparse_flush(usb);
312f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
313f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    return _command_end(usb);
314f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
315