Home | History | Annotate | Download | only in fastboot
      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 
     38 char *fb_get_error(void)
     39 {
     40     return ERROR;
     41 }
     42 
     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,"(bootloader) %s\n", status + 4);
     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 
    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 
    157 int fb_command(usb_handle *usb, const char *cmd)
    158 {
    159     return _command_send(usb, cmd, 0, 0, 0);
    160 }
    161 
    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 
    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