Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

adb: Add ability to specify device path

For manufacturing and testing, there is a need to talk to
whatever device is connected to a given port on the host.  This
change modifies adb's "-s" option to take either a serial
number or a device path.  The device paths of the connected
devices can be listed using "adb devices -l" whose output
will resemble:

    List of devices attached
    016B75D60A00600D	usb:2-5	device
    3031D0B2E71D00EC	usb:1-4.3	device

The second column lists the device paths.  If the -l option is
not given, the output from "adb devices" will be the same as
it used to be (i.e. the paths will not be printed).

The device path can also be obtained with the get-devpath
command:

    $adb -s 3031D0B2E71D00EC get-devpath
    usb:1-4.3

Note that the format of the device paths are platform dependent.
The example above is from Linux.  On OS-X, the paths will be
"usb:" followed by hex digits.  For other platforms, the device
paths will be printed as "????????????" and the -s option will
not be able to select a device until someone implements the
underlying functionality.

Change-Id: I057d5d9f8c5bb72eddf5b8088aae110763f809d7
Signed-off-by: Scott Anderson <saa@android.com>
  • Loading branch information...
commit e109d266c12c5f537d429ca4b892f2719e02c2da 1 parent 5383476
Scott Anderson authored
7 adb/SERVICES.TXT
@@ -17,8 +17,10 @@ host:kill
17 17 upgrade.
18 18
19 19 host:devices
  20 +host:devices-l
20 21 Ask to return the list of available Android devices and their
21   - state. After the OKAY, this is followed by a 4-byte hex len,
  22 + state. devices-l includes the device paths in the state.
  23 + After the OKAY, this is followed by a 4-byte hex len,
22 24 and a string that will be dumped as-is by the client, then
23 25 the connection is closed
24 26
@@ -88,6 +90,9 @@ host:<request>
88 90 Returns the serial number of the corresponding device/emulator.
89 91 Note that emulator serial numbers are of the form "emulator-5554"
90 92
  93 +<host-prefix>:get-devpath
  94 + Returns the device path of the corresponding device/emulator.
  95 +
91 96 <host-prefix>:get-state
92 97 Returns the state of a given device as a string.
93 98
31 adb/adb.c
@@ -1132,16 +1132,19 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r
1132 1132 }
1133 1133
1134 1134 // return a list of all connected devices
1135   - if (!strcmp(service, "devices")) {
  1135 + if (!strncmp(service, "devices", 7)) {
1136 1136 char buffer[4096];
1137   - memset(buf, 0, sizeof(buf));
1138   - memset(buffer, 0, sizeof(buffer));
1139   - D("Getting device list \n");
1140   - list_transports(buffer, sizeof(buffer));
1141   - snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer),buffer);
1142   - D("Wrote device list \n");
1143   - writex(reply_fd, buf, strlen(buf));
1144   - return 0;
  1137 + int use_long = !strcmp(service+7, "-l");
  1138 + if (use_long || service[7] == 0) {
  1139 + memset(buf, 0, sizeof(buf));
  1140 + memset(buffer, 0, sizeof(buffer));
  1141 + D("Getting device list \n");
  1142 + list_transports(buffer, sizeof(buffer), use_long);
  1143 + snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer),buffer);
  1144 + D("Wrote device list \n");
  1145 + writex(reply_fd, buf, strlen(buf));
  1146 + return 0;
  1147 + }
1145 1148 }
1146 1149
1147 1150 // add a new TCP transport, device or emulator
@@ -1207,6 +1210,16 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r
1207 1210 writex(reply_fd, buf, strlen(buf));
1208 1211 return 0;
1209 1212 }
  1213 + if(!strncmp(service,"get-devpath",strlen("get-devpath"))) {
  1214 + char *out = "unknown";
  1215 + transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
  1216 + if (transport && transport->devpath) {
  1217 + out = transport->devpath;
  1218 + }
  1219 + snprintf(buf, sizeof buf, "OKAY%04x%s",(unsigned)strlen(out),out);
  1220 + writex(reply_fd, buf, strlen(buf));
  1221 + return 0;
  1222 + }
1210 1223 // indicates a new emulator instance has started
1211 1224 if (!strncmp(service,"emulator:",9)) {
1212 1225 int port = atoi(service+9);
5 adb/adb.h
@@ -185,6 +185,7 @@ struct atransport
185 185 /* used to identify transports for clients */
186 186 char *serial;
187 187 char *product;
  188 + char *devpath;
188 189 int adb_port; // Use for emulators (local transport)
189 190
190 191 /* a list of adisconnect callbacks called when the transport is kicked */
@@ -248,7 +249,7 @@ int adb_main(int is_daemon, int server_port);
248 249 ** get_device_transport does an acquire on your behalf before returning
249 250 */
250 251 void init_transport_registration(void);
251   -int list_transports(char *buf, size_t bufsize);
  252 +int list_transports(char *buf, size_t bufsize, int show_devpath);
252 253 void update_transports(void);
253 254
254 255 asocket* create_device_tracker(void);
@@ -281,7 +282,7 @@ void register_socket_transport(int s, const char *serial, int port, int local);
281 282 void unregister_transport(atransport *t);
282 283 void unregister_all_tcp_transports();
283 284
284   -void register_usb_transport(usb_handle *h, const char *serial, unsigned writeable);
  285 +void register_usb_transport(usb_handle *h, const char *serial, const char *devpath, unsigned writeable);
285 286
286 287 /* this should only be used for transports with connection_state == CS_NOPERM */
287 288 void unregister_usb_transport(usb_handle *usb);
22 adb/commandline.c
@@ -84,8 +84,8 @@ void help()
84 84 " returns an error if more than one USB device is present.\n"
85 85 " -e - directs command to the only running emulator.\n"
86 86 " returns an error if more than one emulator is running.\n"
87   - " -s <serial number> - directs command to the USB device or emulator with\n"
88   - " the given serial number. Overrides ANDROID_SERIAL\n"
  87 + " -s <specific device> - directs command to the device or emulator with the given\n"
  88 + " serial number or device path. Overrides ANDROID_SERIAL\n"
89 89 " environment variable.\n"
90 90 " -p <product name or path> - simple product name like 'sooner', or\n"
91 91 " a relative/absolute path to a product\n"
@@ -93,7 +93,8 @@ void help()
93 93 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
94 94 " environment variable is used, which must\n"
95 95 " be an absolute path.\n"
96   - " devices - list all connected devices\n"
  96 + " devices [-l] - list all connected devices\n"
  97 + " ('-l' means list device paths)\n"
97 98 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
98 99 " Port 5555 is used by default if no port number is specified.\n"
99 100 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
@@ -157,6 +158,7 @@ void help()
157 158 " adb kill-server - kill the server if it is running\n"
158 159 " adb get-state - prints: offline | bootloader | device\n"
159 160 " adb get-serialno - prints: <serial-number>\n"
  161 + " adb get-devpath - prints: <device-path>\n"
160 162 " adb status-window - continuously print device status for a specified device\n"
161 163 " adb remount - remounts the /system partition on the device read-write\n"
162 164 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
@@ -931,7 +933,16 @@ int adb_commandline(int argc, char **argv)
931 933
932 934 if(!strcmp(argv[0], "devices")) {
933 935 char *tmp;
934   - snprintf(buf, sizeof buf, "host:%s", argv[0]);
  936 + char *listopt;
  937 + if (argc < 2)
  938 + listopt = "";
  939 + else if (argc == 2 && !strcmp(argv[1], "-l"))
  940 + listopt = argv[1];
  941 + else {
  942 + fprintf(stderr, "Usage: adb devices [-l]\n");
  943 + return 1;
  944 + }
  945 + snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
935 946 tmp = adb_query(buf);
936 947 if(tmp) {
937 948 printf("List of devices attached \n");
@@ -1204,7 +1215,8 @@ int adb_commandline(int argc, char **argv)
1204 1215 /* passthrough commands */
1205 1216
1206 1217 if(!strcmp(argv[0],"get-state") ||
1207   - !strcmp(argv[0],"get-serialno"))
  1218 + !strcmp(argv[0],"get-serialno") ||
  1219 + !strcmp(argv[0],"get-devpath"))
1208 1220 {
1209 1221 char *tmp;
1210 1222
26 adb/transport.c
@@ -370,7 +370,7 @@ static int list_transports_msg(char* buffer, size_t bufferlen)
370 370 char head[5];
371 371 int len;
372 372
373   - len = list_transports(buffer+4, bufferlen-4);
  373 + len = list_transports(buffer+4, bufferlen-4, 0);
374 374 snprintf(head, sizeof(head), "%04x", len);
375 375 memcpy(buffer, head, 4);
376 376 len += 4;
@@ -601,6 +601,8 @@ static void transport_registration_func(int _fd, unsigned ev, void *data)
601 601 free(t->product);
602 602 if (t->serial)
603 603 free(t->serial);
  604 + if (t->devpath)
  605 + free(t->devpath);
604 606
605 607 memset(t,0xee,sizeof(atransport));
606 608 free(t);
@@ -762,6 +764,10 @@ atransport *acquire_one_transport(int state, transport_type ttype, const char* s
762 764 result = t;
763 765 break;
764 766 }
  767 + if (t->devpath && !strcmp(serial, t->devpath)) {
  768 + result = t;
  769 + break;
  770 + }
765 771 } else {
766 772 if (ttype == kTransportUsb && t->type == kTransportUsb) {
767 773 if (result) {
@@ -836,7 +842,7 @@ static const char *statename(atransport *t)
836 842 }
837 843 }
838 844
839   -int list_transports(char *buf, size_t bufsize)
  845 +int list_transports(char *buf, size_t bufsize, int show_devpath)
840 846 {
841 847 char* p = buf;
842 848 char* end = buf + bufsize;
@@ -849,7 +855,13 @@ int list_transports(char *buf, size_t bufsize)
849 855 const char* serial = t->serial;
850 856 if (!serial || !serial[0])
851 857 serial = "????????????";
852   - len = snprintf(p, end - p, "%s\t%s\n", serial, statename(t));
  858 + if (show_devpath) {
  859 + const char* devpath = t->devpath;
  860 + if (!devpath || !devpath[0])
  861 + devpath = "????????????";
  862 + len = snprintf(p, end - p, "%s\t%s\t%s\n", serial, devpath, statename(t));
  863 + } else
  864 + len = snprintf(p, end - p, "%s\t%s\n", serial, statename(t));
853 865
854 866 if (p + len >= end) {
855 867 /* discard last line if buffer is too short */
@@ -910,6 +922,9 @@ atransport *find_transport(const char *serial)
910 922 if (t->serial && !strcmp(serial, t->serial)) {
911 923 break;
912 924 }
  925 + if (t->devpath && !strcmp(serial, t->devpath)) {
  926 + break;
  927 + }
913 928 }
914 929 adb_mutex_unlock(&transport_lock);
915 930
@@ -955,7 +970,7 @@ void unregister_all_tcp_transports()
955 970
956 971 #endif
957 972
958   -void register_usb_transport(usb_handle *usb, const char *serial, unsigned writeable)
  973 +void register_usb_transport(usb_handle *usb, const char *serial, const char *devpath, unsigned writeable)
959 974 {
960 975 atransport *t = calloc(1, sizeof(atransport));
961 976 D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb,
@@ -964,6 +979,9 @@ void register_usb_transport(usb_handle *usb, const char *serial, unsigned writea
964 979 if(serial) {
965 980 t->serial = strdup(serial);
966 981 }
  982 + if(devpath) {
  983 + t->devpath = strdup(devpath);
  984 + }
967 985 register_transport(t);
968 986 }
969 987
2  adb/usb_libusb.c
@@ -347,7 +347,7 @@ register_device(struct usb_handle *uh, const char *serial)
347 347
348 348 adb_mutex_unlock(&usb_lock);
349 349
350   - register_usb_transport(usb, serial, 1);
  350 + register_usb_transport(usb, serial, NULL, 1);
351 351
352 352 return (1);
353 353 }
35 adb/usb_linux.c
@@ -116,7 +116,8 @@ static void kick_disconnected_devices()
116 116
117 117 }
118 118
119   -static void register_device(const char *dev_name, unsigned char ep_in, unsigned char ep_out,
  119 +static void register_device(const char *dev_name, const char *devpath,
  120 + unsigned char ep_in, unsigned char ep_out,
120 121 int ifc, int serial_index, unsigned zero_mask);
121 122
122 123 static inline int badname(const char *name)
@@ -129,7 +130,7 @@ static inline int badname(const char *name)
129 130
130 131 static void find_usb_device(const char *base,
131 132 void (*register_device_callback)
132   - (const char *, unsigned char, unsigned char, int, int, unsigned))
  133 + (const char *, const char *, unsigned char, unsigned char, int, int, unsigned))
133 134 {
134 135 char busname[32], devname[32];
135 136 unsigned char local_ep_in, local_ep_out;
@@ -227,6 +228,11 @@ static void find_usb_device(const char *base,
227 228 is_adb_interface(vid, pid, interface->bInterfaceClass,
228 229 interface->bInterfaceSubClass, interface->bInterfaceProtocol)) {
229 230
  231 + struct stat st;
  232 + char pathbuf[128];
  233 + char link[256];
  234 + char *devpath = NULL;
  235 +
230 236 DBGX("looking for bulk endpoints\n");
231 237 // looks like ADB...
232 238 ep1 = (struct usb_endpoint_descriptor *)bufptr;
@@ -263,7 +269,26 @@ static void find_usb_device(const char *base,
263 269 local_ep_out = ep1->bEndpointAddress;
264 270 }
265 271
266   - register_device_callback(devname, local_ep_in, local_ep_out,
  272 + // Determine the device path
  273 + if (!fstat(fd, &st) && S_ISCHR(st.st_mode)) {
  274 + char *slash;
  275 + ssize_t link_len;
  276 + snprintf(pathbuf, sizeof(pathbuf), "/sys/dev/char/%d:%d",
  277 + major(st.st_rdev), minor(st.st_rdev));
  278 + link_len = readlink(pathbuf, link, sizeof(link) - 1);
  279 + if (link_len > 0) {
  280 + link[link_len] = '\0';
  281 + slash = strrchr(link, '/');
  282 + if (slash) {
  283 + snprintf(pathbuf, sizeof(pathbuf),
  284 + "usb:%s", slash + 1);
  285 + devpath = pathbuf;
  286 + }
  287 + }
  288 + }
  289 +
  290 + register_device_callback(devname, devpath,
  291 + local_ep_in, local_ep_out,
267 292 interface->bInterfaceNumber, device->iSerialNumber, zero_mask);
268 293 break;
269 294 }
@@ -532,7 +557,7 @@ int usb_close(usb_handle *h)
532 557 return 0;
533 558 }
534 559
535   -static void register_device(const char *dev_name,
  560 +static void register_device(const char *dev_name, const char *devpath,
536 561 unsigned char ep_in, unsigned char ep_out,
537 562 int interface, int serial_index, unsigned zero_mask)
538 563 {
@@ -644,7 +669,7 @@ static void register_device(const char *dev_name,
644 669 usb->next->prev = usb;
645 670 adb_mutex_unlock(&usb_lock);
646 671
647   - register_usb_transport(usb, serial, usb->writeable);
  672 + register_usb_transport(usb, serial, devpath, usb->writeable);
648 673 return;
649 674
650 675 fail:
2  adb/usb_linux_client.c
@@ -72,7 +72,7 @@ static void *usb_open_thread(void *x)
72 72 usb->fd = fd;
73 73
74 74 D("[ usb_thread - registering device ]\n");
75   - register_usb_transport(usb, 0, 1);
  75 + register_usb_transport(usb, 0, 0, 1);
76 76 }
77 77
78 78 // never gets here
10 adb/usb_osx.c
@@ -125,10 +125,13 @@ AndroidInterfaceAdded(void *refCon, io_iterator_t iterator)
125 125 IOUSBDeviceInterface197 **dev = NULL;
126 126 HRESULT result;
127 127 SInt32 score;
  128 + UInt32 locationId;
128 129 UInt16 vendor;
129 130 UInt16 product;
130 131 UInt8 serialIndex;
131 132 char serial[256];
  133 + char devpathBuf[64];
  134 + char *devpath = NULL;
132 135
133 136 while ((usbInterface = IOIteratorNext(iterator))) {
134 137 //* Create an intermediate interface plugin
@@ -192,6 +195,11 @@ AndroidInterfaceAdded(void *refCon, io_iterator_t iterator)
192 195
193 196 kr = (*dev)->GetDeviceVendor(dev, &vendor);
194 197 kr = (*dev)->GetDeviceProduct(dev, &product);
  198 + kr = (*dev)->GetLocationID(dev, &locationId);
  199 + if (kr == 0) {
  200 + snprintf(devpathBuf, sizeof(devpathBuf), "usb:%lX", locationId);
  201 + devpath = devpathBuf;
  202 + }
195 203 kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex);
196 204
197 205 if (serialIndex > 0) {
@@ -256,7 +264,7 @@ AndroidInterfaceAdded(void *refCon, io_iterator_t iterator)
256 264 }
257 265
258 266 DBG("AndroidDeviceAdded calling register_usb_transport\n");
259   - register_usb_transport(handle, (serial[0] ? serial : NULL), 1);
  267 + register_usb_transport(handle, (serial[0] ? serial : NULL), devpath, 1);
260 268
261 269 // Register for an interest notification of this device being removed.
262 270 // Pass the reference to our private data as the refCon for the
2  adb/usb_windows.c
@@ -490,7 +490,7 @@ void find_devices() {
490 490 true)) {
491 491 // Lets make sure that we don't duplicate this device
492 492 if (register_new_device(handle)) {
493   - register_usb_transport(handle, serial_number, 1);
  493 + register_usb_transport(handle, serial_number, NULL, 1);
494 494 } else {
495 495 D("register_new_device failed for %s\n", interf_name);
496 496 usb_cleanup_handle(handle);

0 comments on commit e109d26

Please sign in to comment.
Something went wrong with that request. Please try again.