Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d372c5c3 authored by Kenny Root's avatar Kenny Root Committed by Gerrit Code Review
Browse files

Merge changes I11e84a7b,I5adaedd8

* changes:
  adb: fix 64-bit build
  add sideload-host mode to adb
parents 23aeeff5 52e0b619
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -36,7 +36,7 @@
#define ADB_VERSION_MAJOR 1         // Used for help/version information
#define ADB_VERSION_MAJOR 1         // Used for help/version information
#define ADB_VERSION_MINOR 0         // Used for help/version information
#define ADB_VERSION_MINOR 0         // Used for help/version information


#define ADB_SERVER_VERSION    31    // Increment this when we want to force users to start a new adb server
#define ADB_SERVER_VERSION    32    // Increment this when we want to force users to start a new adb server


typedef struct amessage amessage;
typedef struct amessage amessage;
typedef struct apacket apacket;
typedef struct apacket apacket;
+2 −1
Original line number Original line Diff line number Diff line
@@ -279,7 +279,7 @@ int adb_connect(const char *service)


    fd = _adb_connect(service);
    fd = _adb_connect(service);
    if(fd == -1) {
    if(fd == -1) {
        fprintf(stderr,"error: %s\n", __adb_error);
        D("_adb_connect error: %s\n", __adb_error);
    } else if(fd == -2) {
    } else if(fd == -2) {
        fprintf(stderr,"** daemon still not running\n");
        fprintf(stderr,"** daemon still not running\n");
    }
    }
@@ -296,6 +296,7 @@ int adb_command(const char *service)
{
{
    int fd = adb_connect(service);
    int fd = adb_connect(service);
    if(fd < 0) {
    if(fd < 0) {
        fprintf(stderr, "error: %s\n", adb_error());
        return -1;
        return -1;
    }
    }


+110 −1
Original line number Original line Diff line number Diff line
@@ -500,6 +500,115 @@ int adb_download(const char *service, const char *fn, unsigned progress)
    return status;
    return status;
}
}


#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)

/*
 * The sideload-host protocol serves the data in a file (given on the
 * command line) to the client, using a simple protocol:
 *
 * - The connect message includes the total number of bytes in the
 *   file and a block size chosen by us.
 *
 * - The other side sends the desired block number as eight decimal
 *   digits (eg "00000023" for block 23).  Blocks are numbered from
 *   zero.
 *
 * - We send back the data of the requested block.  The last block is
 *   likely to be partial; when the last block is requested we only
 *   send the part of the block that exists, it's not padded up to the
 *   block size.
 *
 * - When the other side sends "DONEDONE" instead of a block number,
 *   we hang up.
 */
int adb_sideload_host(const char* fn) {
    uint8_t* data;
    unsigned sz;
    size_t xfer = 0;
    int status;

    printf("loading: '%s'", fn);
    fflush(stdout);
    data = load_file(fn, &sz);
    if (data == 0) {
        printf("\n");
        fprintf(stderr, "* cannot read '%s' *\n", fn);
        return -1;
    }

    char buf[100];
    sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
    int fd = adb_connect(buf);
    if (fd < 0) {
        // Try falling back to the older sideload method.  Maybe this
        // is an older device that doesn't support sideload-host.
        printf("\n");
        status = adb_download_buffer("sideload", fn, data, sz, 1);
        goto done;
    }

    int opt = SIDELOAD_HOST_BLOCK_SIZE;
    opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));

    int last_percent = -1;
    while (true) {
        if (readx(fd, buf, 8)) {
            fprintf(stderr, "* failed to read command: %s\n", adb_error());
            status = -1;
            goto done;
        }

        if (strncmp("DONEDONE", buf, 8) == 0) {
            status = 0;
            break;
        }

        buf[8] = '\0';
        int block = strtol(buf, NULL, 10);

        size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
        if (offset >= sz) {
            fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
            status = -1;
            goto done;
        }
        uint8_t* start = data + offset;
        size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
        size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
        if (offset_end > sz) {
            to_write = sz - offset;
        }

        if(writex(fd, start, to_write)) {
            adb_status(fd);
            fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
            status = -1;
            goto done;
        }
        xfer += to_write;

        // For normal OTA packages, we expect to transfer every byte
        // twice, plus a bit of overhead (one read during
        // verification, one read of each byte for installation, plus
        // extra access to things like the zip central directory).
        // This estimate of the completion becomes 100% when we've
        // transferred ~2.13 (=100/47) times the package size.
        int percent = (int)(xfer * 47LL / (sz ? sz : 1));
        if (percent != last_percent) {
            printf("\rserving: '%s'  (~%d%%)    ", fn, percent);
            fflush(stdout);
            last_percent = percent;
        }
    }

    printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");

  done:
    if (fd >= 0) adb_close(fd);
    free(data);
    return status;
}

static void status_window(transport_type ttype, const char* serial)
static void status_window(transport_type ttype, const char* serial)
{
{
    char command[4096];
    char command[4096];
@@ -1290,7 +1399,7 @@ top:


    if(!strcmp(argv[0], "sideload")) {
    if(!strcmp(argv[0], "sideload")) {
        if(argc != 2) return usage();
        if(argc != 2) return usage();
        if(adb_download("sideload", argv[1], 1)) {
        if (adb_sideload_host(argv[1])) {
            return 1;
            return 1;
        } else {
        } else {
            return 0;
            return 0;