Permalink
Browse files

am 2ca3e6b: adb: Generalizing -s to take qualifiers.

* commit '2ca3e6b35f79136418ebc32fef57580698dbd045':
  adb: Generalizing -s to take qualifiers.
  • Loading branch information...
2 parents 3fef581 + 2ca3e6b commit 0e9e13eb46d8ffbb456f937db4a8fb0da02dd5d2 Scott Anderson committed with Android Git Automerger Jun 5, 2012
Showing with 126 additions and 27 deletions.
  1. +3 −4 adb/adb.c
  2. +1 −1 adb/adb.h
  3. +2 −2 adb/commandline.c
  4. +16 −2 adb/sockets.c
  5. +104 −18 adb/transport.c
View
@@ -341,9 +341,7 @@ static char *connection_state_name(atransport *t)
/* qual_overwrite is used to overwrite a qualifier string. dst is a
* pointer to a char pointer. It is assumed that if *dst is non-NULL, it
- * was malloc'ed and needs to freed. A char buffer will be malloc'ed and
- * filled with src and *dst will be set to
- * point to the buffer.
+ * was malloc'ed and needs to freed. *dst will be set to a dup of src.
*/
static void qual_overwrite(char **dst, const char *src)
{
@@ -363,7 +361,8 @@ void parse_banner(char *banner, atransport *t)
{
static const char *prop_seps = ";";
static const char key_val_sep = '=';
- char *cp, *type;
+ char *cp;
+ char *type;
D("parse_banner: %s\n", banner);
type = banner;
View
@@ -256,7 +256,7 @@ int adb_main(int is_daemon, int server_port);
** get_device_transport does an acquire on your behalf before returning
*/
void init_transport_registration(void);
-int list_transports(char *buf, size_t bufsize, int show_devpath);
+int list_transports(char *buf, size_t bufsize, int long_listing);
void update_transports(void);
asocket* create_device_tracker(void);
View
@@ -85,7 +85,7 @@ void help()
" -e - directs command to the only running emulator.\n"
" returns an error if more than one emulator is running.\n"
" -s <specific device> - directs command to the device or emulator with the given\n"
- " serial number or device path. Overrides ANDROID_SERIAL\n"
+ " serial number or qualifier. Overrides ANDROID_SERIAL\n"
" environment variable.\n"
" -p <product name or path> - simple product name like 'sooner', or\n"
" a relative/absolute path to a product\n"
@@ -94,7 +94,7 @@ void help()
" environment variable is used, which must\n"
" be an absolute path.\n"
" devices [-l] - list all connected devices\n"
- " ('-l' means list device paths)\n"
+ " ('-l' will also list device qualifiers)\n"
" connect <host>[:<port>] - connect to a device via TCP/IP\n"
" Port 5555 is used by default if no port number is specified.\n"
" disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
View
@@ -608,15 +608,29 @@ unsigned unhex(unsigned char *s, int len)
return n;
}
+#define PREFIX(str) { str, sizeof(str) - 1 }
+static const struct prefix_struct {
+ const char *str;
+ const size_t len;
+} prefixes[] = {
+ PREFIX("usb:"),
+ PREFIX("product:"),
+ PREFIX("model:"),
+ PREFIX("device:"),
+};
+static const int num_prefixes = (sizeof(prefixes) / sizeof(prefixes[0]));
+
/* skip_host_serial return the position in a string
skipping over the 'serial' parameter in the ADB protocol,
where parameter string may be a host:port string containing
the protocol delimiter (colon). */
char *skip_host_serial(char *service) {
char *first_colon, *serial_end;
+ int i;
- if (!strncmp(service, "usb:", 4)) {
- return strchr(service + 4, ':');
+ for (i = 0; i < num_prefixes; i++) {
+ if (!strncmp(service, prefixes[i].str, prefixes[i].len))
+ return strchr(service + prefixes[i].len, ':');
}
first_colon = strchr(service, ':');
View
@@ -743,6 +743,45 @@ void remove_transport_disconnect(atransport* t, adisconnect* dis)
dis->next = dis->prev = dis;
}
+static int qual_char_is_invalid(char ch)
+{
+ if ('A' <= ch && ch <= 'Z')
+ return 0;
+ if ('a' <= ch && ch <= 'z')
+ return 0;
+ if ('0' <= ch && ch <= '9')
+ return 0;
+ return 1;
+}
+
+static int qual_match(const char *to_test,
+ const char *prefix, const char *qual, int sanitize_qual)
+{
+ if (!to_test || !*to_test)
+ /* Return true if both the qual and to_test are null strings. */
+ return !qual || !*qual;
+
+ if (!qual)
+ return 0;
+
+ if (prefix) {
+ while (*prefix) {
+ if (*prefix++ != *to_test++)
+ return 0;
+ }
+ }
+
+ while (*qual) {
+ char ch = *qual++;
+ if (sanitize_qual && qual_char_is_invalid(ch))
+ ch = '_';
+ if (ch != *to_test++)
+ return 0;
+ }
+
+ /* Everything matched so far. Return true if *to_test is a NUL. */
+ return !*to_test;
+}
atransport *acquire_one_transport(int state, transport_type ttype, const char* serial, char** error_out)
{
@@ -764,13 +803,19 @@ atransport *acquire_one_transport(int state, transport_type ttype, const char* s
/* check for matching serial number */
if (serial) {
- if (t->serial && !strcmp(serial, t->serial)) {
- result = t;
- break;
- }
- if (t->devpath && !strcmp(serial, t->devpath)) {
+ if ((t->serial && !strcmp(serial, t->serial)) ||
+ (t->devpath && !strcmp(serial, t->devpath)) ||
+ qual_match(serial, "product:", t->product, 0) ||
+ qual_match(serial, "model:", t->model, 1) ||
+ qual_match(serial, "device:", t->device, 0)) {
+ if (result) {
+ if (error_out)
+ *error_out = "more than one device";
+ ambiguous = 1;
+ result = NULL;
+ break;
+ }
result = t;
- break;
}
} else {
if (ttype == kTransportUsb && t->type == kTransportUsb) {
@@ -847,7 +892,58 @@ static const char *statename(atransport *t)
}
}
-int list_transports(char *buf, size_t bufsize, int show_devpath)
+static void add_qual(char **buf, size_t *buf_size,
+ const char *prefix, const char *qual, int sanitize_qual)
+{
+ size_t len;
+ int prefix_len;
+
+ if (!buf || !*buf || !buf_size || !*buf_size || !qual || !*qual)
+ return;
+
+ len = snprintf(*buf, *buf_size, "%s%n%s", prefix, &prefix_len, qual);
+
+ if (sanitize_qual) {
+ char *cp;
+ for (cp = *buf + prefix_len; cp < *buf + len; cp++) {
+ if (qual_char_is_invalid(*cp))
+ *cp = '_';
+ }
+ }
+
+ *buf_size -= len;
+ *buf += len;
+}
+
+static size_t format_transport(atransport *t, char *buf, size_t bufsize,
+ int long_listing)
+{
+ const char* serial = t->serial;
+ if (!serial || !serial[0])
+ serial = "????????????";
+
+ if (!long_listing) {
+ return snprintf(buf, bufsize, "%s\t%s\n", serial, statename(t));
+ } else {
+ size_t len, remaining = bufsize;
+
+ len = snprintf(buf, remaining, "%-22s %s", serial, statename(t));
+ remaining -= len;
+ buf += len;
+
+ add_qual(&buf, &remaining, " ", t->devpath, 0);
+ add_qual(&buf, &remaining, " product:", t->product, 0);
+ add_qual(&buf, &remaining, " model:", t->model, 1);
+ add_qual(&buf, &remaining, " device:", t->device, 0);
+
+ len = snprintf(buf, remaining, "\n");
+ remaining -= len;
+
+ return bufsize - remaining;
+ }
+}
+
+int list_transports(char *buf, size_t bufsize, int long_listing)
{
char* p = buf;
char* end = buf + bufsize;
@@ -857,17 +953,7 @@ int list_transports(char *buf, size_t bufsize, int show_devpath)
/* XXX OVERRUN PROBLEMS XXX */
adb_mutex_lock(&transport_lock);
for(t = transport_list.next; t != &transport_list; t = t->next) {
- const char* serial = t->serial;
- if (!serial || !serial[0])
- serial = "????????????";
- if (show_devpath) {
- const char* devpath = t->devpath;
- if (!devpath || !devpath[0])
- devpath = "????????????";
- len = snprintf(p, end - p, "%s\t%s\t%s\n", serial, devpath, statename(t));
- } else
- len = snprintf(p, end - p, "%s\t%s\n", serial, statename(t));
-
+ len = format_transport(t, p, end - p, long_listing);
if (p + len >= end) {
/* discard last line if buffer is too short */
break;

0 comments on commit 0e9e13e

Please sign in to comment.