Merge "add "adb sideload" and sideload connection state"
diff --git a/adb/adb.c b/adb/adb.c
index e35c334..6dbd562 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -299,6 +299,13 @@
return;
}
+ if(!strcmp(type, "sideload")) {
+ D("setting connection_state to CS_SIDELOAD\n");
+ t->connection_state = CS_SIDELOAD;
+ update_transports();
+ return;
+ }
+
t->connection_state = CS_HOST;
}
diff --git a/adb/adb.h b/adb/adb.h
index ac31f11..f7667c2 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -434,6 +434,7 @@
#define CS_HOST 3
#define CS_RECOVERY 4
#define CS_NOPERM 5 /* Insufficient permissions to communicate with the device */
+#define CS_SIDELOAD 6
extern int HOST;
extern int SHELL_EXIT_NOTIFY_FD;
diff --git a/adb/commandline.c b/adb/commandline.c
index ffce883..5b2aa88 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -367,6 +367,83 @@
}
}
+int adb_download_buffer(const char *service, const void* data, int sz,
+ unsigned progress)
+{
+ char buf[4096];
+ unsigned total;
+ int fd;
+ const unsigned char *ptr;
+
+ sprintf(buf,"%s:%d", service, sz);
+ fd = adb_connect(buf);
+ if(fd < 0) {
+ fprintf(stderr,"error: %s\n", adb_error());
+ return -1;
+ }
+
+ int opt = CHUNK_SIZE;
+ opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
+
+ total = sz;
+ ptr = data;
+
+ if(progress) {
+ char *x = strrchr(service, ':');
+ if(x) service = x + 1;
+ }
+
+ while(sz > 0) {
+ unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
+ if(writex(fd, ptr, xfer)) {
+ adb_status(fd);
+ fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
+ return -1;
+ }
+ sz -= xfer;
+ ptr += xfer;
+ if(progress) {
+ printf("sending: '%s' %4d%% \r", service, (int)(100LL - ((100LL * sz) / (total))));
+ fflush(stdout);
+ }
+ }
+ if(progress) {
+ printf("\n");
+ }
+
+ if(readx(fd, buf, 4)){
+ fprintf(stderr,"* error reading response *\n");
+ adb_close(fd);
+ return -1;
+ }
+ if(memcmp(buf, "OKAY", 4)) {
+ buf[4] = 0;
+ fprintf(stderr,"* error response '%s' *\n", buf);
+ adb_close(fd);
+ return -1;
+ }
+
+ adb_close(fd);
+ return 0;
+}
+
+
+int adb_download(const char *service, const char *fn, unsigned progress)
+{
+ void *data;
+ unsigned sz;
+
+ data = load_file(fn, &sz);
+ if(data == 0) {
+ fprintf(stderr,"* cannot read '%s' *\n", service);
+ return -1;
+ }
+
+ int status = adb_download_buffer(service, data, sz, progress);
+ free(data);
+ return status;
+}
+
static void status_window(transport_type ttype, const char* serial)
{
char command[4096];
@@ -1063,6 +1140,15 @@
return 0;
}
+ if(!strcmp(argv[0], "sideload")) {
+ if(argc != 2) return usage();
+ if(adb_download("sideload", argv[1], 1)) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
|| !strcmp(argv[0], "reboot-bootloader")
|| !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
diff --git a/adb/transport.c b/adb/transport.c
index 83a349a..2f7bd27 100644
--- a/adb/transport.c
+++ b/adb/transport.c
@@ -831,6 +831,7 @@
case CS_DEVICE: return "device";
case CS_HOST: return "host";
case CS_RECOVERY: return "recovery";
+ case CS_SIDELOAD: return "sideload";
case CS_NOPERM: return "no permissions";
default: return "unknown";
}