From 74d7ff8cfd490852d3df1c4b9d8a21beed619caa Mon Sep 17 00:00:00 2001 From: Mike Lockwood Date: Sun, 11 Oct 2009 23:04:18 -0400 Subject: adb: Add "adb disconnect" command for disconnecting TCP/IP devices. Also check that device is not already connected in "adb connect" Change-Id: I5f84b56b63d8c6932f23791cac319fd6bc39d36c Signed-off-by: Mike Lockwood --- adb/adb.c | 33 ++++++++++++++++++++++++++++----- adb/adb.h | 6 ++++++ adb/commandline.c | 5 +++-- adb/jdwp_service.c | 2 +- adb/sysdeps.h | 8 ++++++++ adb/sysdeps_win32.c | 14 ++++++++++++++ adb/transport.c | 32 ++++++++++++++++++++++++++++++++ adb/transport_local.c | 1 + 8 files changed, 93 insertions(+), 8 deletions(-) diff --git a/adb/adb.c b/adb/adb.c index 283ebce..c1646b8 100644 --- a/adb/adb.c +++ b/adb/adb.c @@ -1020,19 +1020,24 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r char* portstr = strchr(host, ':'); if (!portstr) { - snprintf(buffer, sizeof(buffer), "unable to parse %s as :\n", host); + snprintf(buffer, sizeof(buffer), "unable to parse %s as :", host); goto done; } + if (find_transport(host)) { + snprintf(buffer, sizeof(buffer), "Already connected to %s", host); + goto done; + } + // zero terminate host by overwriting the ':' *portstr++ = 0; if (sscanf(portstr, "%d", &port) == 0) { - snprintf(buffer, sizeof(buffer), "bad port number %s\n", portstr); + snprintf(buffer, sizeof(buffer), "bad port number %s", portstr); goto done; } fd = socket_network_client(host, port, SOCK_STREAM); if (fd < 0) { - snprintf(buffer, sizeof(buffer), "unable to connect to %s:%d\n", host, port); + snprintf(buffer, sizeof(buffer), "unable to connect to %s:%d", host, port); goto done; } @@ -1041,10 +1046,28 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r disable_tcp_nagle(fd); snprintf(buf, sizeof buf, "%s:%d", host, port); register_socket_transport(fd, buf, port, 0); - snprintf(buffer, sizeof(buffer), "connected to %s:%d\n", host, port); + snprintf(buffer, sizeof(buffer), "connected to %s:%d", host, port); done: - snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer),buffer); + snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer), buffer); + writex(reply_fd, buf, strlen(buf)); + return 0; + } + + // remove TCP transport + if (!strncmp(service, "disconnect:", 11)) { + char buffer[4096]; + memset(buffer, 0, sizeof(buffer)); + char* serial = service + 11; + atransport *t = find_transport(serial); + + if (t) { + unregister_transport(t); + } else { + snprintf(buffer, sizeof(buffer), "No such device %s", serial); + } + + snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer), buffer); writex(reply_fd, buf, strlen(buf)); return 0; } diff --git a/adb/adb.h b/adb/adb.h index 713666f..b958682 100644 --- a/adb/adb.h +++ b/adb/adb.h @@ -270,11 +270,17 @@ void close_usb_devices(); /* cause new transports to be init'd and added to the list */ void register_socket_transport(int s, const char *serial, int port, int local); + +/* this should only be used for the "adb disconnect" command */ +void unregister_transport(atransport *t); + void register_usb_transport(usb_handle *h, const char *serial, unsigned writeable); /* this should only be used for transports with connection_state == CS_NOPERM */ void unregister_usb_transport(usb_handle *usb); +atransport *find_transport(const char *serial); + int service_to_fd(const char *name); #if ADB_HOST asocket *host_service_to_socket(const char* name, const char *serial); diff --git a/adb/commandline.c b/adb/commandline.c index 411bb82..055aa10 100644 --- a/adb/commandline.c +++ b/adb/commandline.c @@ -106,6 +106,7 @@ void help() " be an absolute path.\n" " devices - list all connected devices\n" " connect : - connect to a device via TCP/IP" + " disconnect : - disconnect from a TCP/IP device" "\n" "device commands:\n" " adb push - copy file/dir to device\n" @@ -853,10 +854,10 @@ top: } } - if(!strcmp(argv[0], "connect")) { + if(!strcmp(argv[0], "connect") || !strcmp(argv[0], "disconnect")) { char *tmp; if (argc != 2) { - fprintf(stderr, "Usage: adb connect :\n"); + fprintf(stderr, "Usage: adb %s :\n", argv[0]); return 1; } snprintf(buf, sizeof buf, "host:%s:%s", argv[0], argv[1]); diff --git a/adb/jdwp_service.c b/adb/jdwp_service.c index ae7f12d..0c26f7b 100644 --- a/adb/jdwp_service.c +++ b/adb/jdwp_service.c @@ -164,7 +164,7 @@ jdwp_process_free( JdwpProcess* proc ) proc->next->prev = proc->prev; if (proc->socket >= 0) { - shutdown(proc->socket, SHUT_RDWR); + adb_shutdown(proc->socket); adb_close(proc->socket); proc->socket = -1; } diff --git a/adb/sysdeps.h b/adb/sysdeps.h index 389fbd2..6372649 100644 --- a/adb/sysdeps.h +++ b/adb/sysdeps.h @@ -113,6 +113,7 @@ extern int adb_creat(const char* path, int mode); extern int adb_read(int fd, void* buf, int len); extern int adb_write(int fd, const void* buf, int len); extern int adb_lseek(int fd, int pos, int where); +extern int adb_shutdown(int fd); extern int adb_close(int fd); static __inline__ int unix_close(int fd) @@ -327,6 +328,13 @@ static __inline__ int adb_open( const char* pathname, int options ) #undef open #define open ___xxx_open +static __inline__ int adb_shutdown(int fd) +{ + return shutdown(fd, SHUT_RDWR); +} +#undef shutdown +#define shutdown ____xxx_shutdown + static __inline__ int adb_close(int fd) { return close(fd); diff --git a/adb/sysdeps_win32.c b/adb/sysdeps_win32.c index a8e3bb9..ced91e8 100644 --- a/adb/sysdeps_win32.c +++ b/adb/sysdeps_win32.c @@ -435,6 +435,20 @@ int adb_lseek(int fd, int pos, int where) } +int adb_shutdown(int fd) +{ + FH f = _fh_from_int(fd); + + if (!f) { + return -1; + } + + D( "adb_shutdown: %s\n", f->name); + shutdown( f->fh_socket, SD_BOTH ); + return 0; +} + + int adb_close(int fd) { FH f = _fh_from_int(fd); diff --git a/adb/transport.c b/adb/transport.c index 617dabf..c2877d2 100644 --- a/adb/transport.c +++ b/adb/transport.c @@ -864,6 +864,38 @@ void register_socket_transport(int s, const char *serial, int port, int local) register_transport(t); } +#if ADB_HOST +atransport *find_transport(const char *serial) +{ + atransport *t; + + adb_mutex_lock(&transport_lock); + for(t = transport_list.next; t != &transport_list; t = t->next) { + if (t->serial && !strcmp(serial, t->serial)) { + break; + } + } + adb_mutex_unlock(&transport_lock); + + if (t != &transport_list) + return t; + else + return 0; +} + +void unregister_transport(atransport *t) +{ + adb_mutex_lock(&transport_lock); + t->next->prev = t->prev; + t->prev->next = t->next; + adb_mutex_unlock(&transport_lock); + + kick_transport(t); + transport_unref(t); +} + +#endif + void register_usb_transport(usb_handle *usb, const char *serial, unsigned writeable) { atransport *t = calloc(1, sizeof(atransport)); diff --git a/adb/transport_local.c b/adb/transport_local.c index c528d1f..81d120e 100644 --- a/adb/transport_local.c +++ b/adb/transport_local.c @@ -204,6 +204,7 @@ static void remote_kick(atransport *t) { int fd = t->sfd; t->sfd = -1; + adb_shutdown(fd); adb_close(fd); #if ADB_HOST -- cgit v1.1