add "adb sideload" and sideload connection state

Recovery will soon support a minimal implementation of adbd which will
do nothing but accept downloads from the "adb sideload" command and
install them.  This is the client side command (mostly resurrected out
of the old circa-2007 "adb recover" command) and the new connection
state.

Change-Id: I4f67b63f1b3b38d28c285d1278d46782679762a2
This commit is contained in:
Doug Zongker 2012-01-09 14:54:53 -08:00
parent 36afde3387
commit 447f061da1
4 changed files with 95 additions and 0 deletions

View File

@ -299,6 +299,13 @@ void parse_banner(char *banner, atransport *t)
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;
}

View File

@ -434,6 +434,7 @@ int connection_state(atransport *t);
#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;

View File

@ -367,6 +367,83 @@ static void format_host_command(char* buffer, size_t buflen, const char* comman
}
}
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 @@ top:
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")

View File

@ -831,6 +831,7 @@ static const char *statename(atransport *t)
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";
}