am 295afb36: am 6bdc0ca8: Merge "Use O_CLOEXEC when opening cgroup fds." into jb-dev
* commit '295afb36b5c2551243c73c607e245e30525a6942':
Use O_CLOEXEC when opening cgroup fds.
diff --git a/adb/SERVICES.TXT b/adb/SERVICES.TXT
index be4d50b..d9aa09c 100644
--- a/adb/SERVICES.TXT
+++ b/adb/SERVICES.TXT
@@ -17,8 +17,10 @@
upgrade.
host:devices
+host:devices-l
Ask to return the list of available Android devices and their
- state. After the OKAY, this is followed by a 4-byte hex len,
+ state. devices-l includes the device paths in the state.
+ After the OKAY, this is followed by a 4-byte hex len,
and a string that will be dumped as-is by the client, then
the connection is closed
@@ -88,6 +90,9 @@
Returns the serial number of the corresponding device/emulator.
Note that emulator serial numbers are of the form "emulator-5554"
+<host-prefix>:get-devpath
+ Returns the device path of the corresponding device/emulator.
+
<host-prefix>:get-state
Returns the state of a given device as a string.
diff --git a/adb/adb.c b/adb/adb.c
index f4ee448..44eaebb 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -1201,16 +1201,19 @@
}
// return a list of all connected devices
- if (!strcmp(service, "devices")) {
+ if (!strncmp(service, "devices", 7)) {
char buffer[4096];
- memset(buf, 0, sizeof(buf));
- memset(buffer, 0, sizeof(buffer));
- D("Getting device list \n");
- list_transports(buffer, sizeof(buffer));
- snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer),buffer);
- D("Wrote device list \n");
- writex(reply_fd, buf, strlen(buf));
- return 0;
+ int use_long = !strcmp(service+7, "-l");
+ if (use_long || service[7] == 0) {
+ memset(buf, 0, sizeof(buf));
+ memset(buffer, 0, sizeof(buffer));
+ D("Getting device list \n");
+ list_transports(buffer, sizeof(buffer), use_long);
+ snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer),buffer);
+ D("Wrote device list \n");
+ writex(reply_fd, buf, strlen(buf));
+ return 0;
+ }
}
// add a new TCP transport, device or emulator
@@ -1276,6 +1279,16 @@
writex(reply_fd, buf, strlen(buf));
return 0;
}
+ if(!strncmp(service,"get-devpath",strlen("get-devpath"))) {
+ char *out = "unknown";
+ transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
+ if (transport && transport->devpath) {
+ out = transport->devpath;
+ }
+ snprintf(buf, sizeof buf, "OKAY%04x%s",(unsigned)strlen(out),out);
+ writex(reply_fd, buf, strlen(buf));
+ return 0;
+ }
// indicates a new emulator instance has started
if (!strncmp(service,"emulator:",9)) {
int port = atoi(service+9);
diff --git a/adb/adb.h b/adb/adb.h
index 03a7393..4a9b53c 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -190,6 +190,7 @@
/* used to identify transports for clients */
char *serial;
char *product;
+ char *devpath;
int adb_port; // Use for emulators (local transport)
/* a list of adisconnect callbacks called when the transport is kicked */
@@ -253,7 +254,7 @@
** 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 list_transports(char *buf, size_t bufsize, int show_devpath);
void update_transports(void);
asocket* create_device_tracker(void);
@@ -286,7 +287,7 @@
void unregister_transport(atransport *t);
void unregister_all_tcp_transports();
-void register_usb_transport(usb_handle *h, const char *serial, unsigned writeable);
+void register_usb_transport(usb_handle *h, const char *serial, const char *devpath, unsigned writeable);
/* this should only be used for transports with connection_state == CS_NOPERM */
void unregister_usb_transport(usb_handle *usb);
diff --git a/adb/commandline.c b/adb/commandline.c
index 47c9bec..a6f1ce2 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -84,8 +84,8 @@
" returns an error if more than one USB device is present.\n"
" -e - directs command to the only running emulator.\n"
" returns an error if more than one emulator is running.\n"
- " -s <serial number> - directs command to the USB device or emulator with\n"
- " the given serial number. Overrides ANDROID_SERIAL\n"
+ " -s <specific device> - directs command to the device or emulator with the given\n"
+ " serial number or device path. 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"
@@ -93,7 +93,8 @@
" If -p is not specified, the ANDROID_PRODUCT_OUT\n"
" environment variable is used, which must\n"
" be an absolute path.\n"
- " devices - list all connected devices\n"
+ " devices [-l] - list all connected devices\n"
+ " ('-l' means list device paths)\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"
@@ -159,6 +160,7 @@
" adb kill-server - kill the server if it is running\n"
" adb get-state - prints: offline | bootloader | device\n"
" adb get-serialno - prints: <serial-number>\n"
+ " adb get-devpath - prints: <device-path>\n"
" adb status-window - continuously print device status for a specified device\n"
" adb remount - remounts the /system partition on the device read-write\n"
" adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
@@ -1016,7 +1018,16 @@
if(!strcmp(argv[0], "devices")) {
char *tmp;
- snprintf(buf, sizeof buf, "host:%s", argv[0]);
+ char *listopt;
+ if (argc < 2)
+ listopt = "";
+ else if (argc == 2 && !strcmp(argv[1], "-l"))
+ listopt = argv[1];
+ else {
+ fprintf(stderr, "Usage: adb devices [-l]\n");
+ return 1;
+ }
+ snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
tmp = adb_query(buf);
if(tmp) {
printf("List of devices attached \n");
@@ -1298,7 +1309,8 @@
/* passthrough commands */
if(!strcmp(argv[0],"get-state") ||
- !strcmp(argv[0],"get-serialno"))
+ !strcmp(argv[0],"get-serialno") ||
+ !strcmp(argv[0],"get-devpath"))
{
char *tmp;
diff --git a/adb/transport.c b/adb/transport.c
index 2f7bd27..29cb582 100644
--- a/adb/transport.c
+++ b/adb/transport.c
@@ -370,7 +370,7 @@
char head[5];
int len;
- len = list_transports(buffer+4, bufferlen-4);
+ len = list_transports(buffer+4, bufferlen-4, 0);
snprintf(head, sizeof(head), "%04x", len);
memcpy(buffer, head, 4);
len += 4;
@@ -601,6 +601,8 @@
free(t->product);
if (t->serial)
free(t->serial);
+ if (t->devpath)
+ free(t->devpath);
memset(t,0xee,sizeof(atransport));
free(t);
@@ -762,6 +764,10 @@
result = t;
break;
}
+ if (t->devpath && !strcmp(serial, t->devpath)) {
+ result = t;
+ break;
+ }
} else {
if (ttype == kTransportUsb && t->type == kTransportUsb) {
if (result) {
@@ -837,7 +843,7 @@
}
}
-int list_transports(char *buf, size_t bufsize)
+int list_transports(char *buf, size_t bufsize, int show_devpath)
{
char* p = buf;
char* end = buf + bufsize;
@@ -850,7 +856,13 @@
const char* serial = t->serial;
if (!serial || !serial[0])
serial = "????????????";
- len = snprintf(p, end - p, "%s\t%s\n", serial, statename(t));
+ 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));
if (p + len >= end) {
/* discard last line if buffer is too short */
@@ -911,6 +923,9 @@
if (t->serial && !strcmp(serial, t->serial)) {
break;
}
+ if (t->devpath && !strcmp(serial, t->devpath)) {
+ break;
+ }
}
adb_mutex_unlock(&transport_lock);
@@ -956,7 +971,7 @@
#endif
-void register_usb_transport(usb_handle *usb, const char *serial, unsigned writeable)
+void register_usb_transport(usb_handle *usb, const char *serial, const char *devpath, unsigned writeable)
{
atransport *t = calloc(1, sizeof(atransport));
D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb,
@@ -965,6 +980,9 @@
if(serial) {
t->serial = strdup(serial);
}
+ if(devpath) {
+ t->devpath = strdup(devpath);
+ }
register_transport(t);
}
diff --git a/adb/usb_libusb.c b/adb/usb_libusb.c
index 8c75266..06ff5dc 100644
--- a/adb/usb_libusb.c
+++ b/adb/usb_libusb.c
@@ -347,7 +347,7 @@
adb_mutex_unlock(&usb_lock);
- register_usb_transport(usb, serial, 1);
+ register_usb_transport(usb, serial, NULL, 1);
return (1);
}
diff --git a/adb/usb_linux.c b/adb/usb_linux.c
index 4d55b74..7bf2057 100644
--- a/adb/usb_linux.c
+++ b/adb/usb_linux.c
@@ -116,7 +116,8 @@
}
-static void register_device(const char *dev_name, unsigned char ep_in, unsigned char ep_out,
+static void register_device(const char *dev_name, const char *devpath,
+ unsigned char ep_in, unsigned char ep_out,
int ifc, int serial_index, unsigned zero_mask);
static inline int badname(const char *name)
@@ -129,7 +130,7 @@
static void find_usb_device(const char *base,
void (*register_device_callback)
- (const char *, unsigned char, unsigned char, int, int, unsigned))
+ (const char *, const char *, unsigned char, unsigned char, int, int, unsigned))
{
char busname[32], devname[32];
unsigned char local_ep_in, local_ep_out;
@@ -227,6 +228,11 @@
is_adb_interface(vid, pid, interface->bInterfaceClass,
interface->bInterfaceSubClass, interface->bInterfaceProtocol)) {
+ struct stat st;
+ char pathbuf[128];
+ char link[256];
+ char *devpath = NULL;
+
DBGX("looking for bulk endpoints\n");
// looks like ADB...
ep1 = (struct usb_endpoint_descriptor *)bufptr;
@@ -263,7 +269,26 @@
local_ep_out = ep1->bEndpointAddress;
}
- register_device_callback(devname, local_ep_in, local_ep_out,
+ // Determine the device path
+ if (!fstat(fd, &st) && S_ISCHR(st.st_mode)) {
+ char *slash;
+ ssize_t link_len;
+ snprintf(pathbuf, sizeof(pathbuf), "/sys/dev/char/%d:%d",
+ major(st.st_rdev), minor(st.st_rdev));
+ link_len = readlink(pathbuf, link, sizeof(link) - 1);
+ if (link_len > 0) {
+ link[link_len] = '\0';
+ slash = strrchr(link, '/');
+ if (slash) {
+ snprintf(pathbuf, sizeof(pathbuf),
+ "usb:%s", slash + 1);
+ devpath = pathbuf;
+ }
+ }
+ }
+
+ register_device_callback(devname, devpath,
+ local_ep_in, local_ep_out,
interface->bInterfaceNumber, device->iSerialNumber, zero_mask);
break;
}
@@ -532,7 +557,7 @@
return 0;
}
-static void register_device(const char *dev_name,
+static void register_device(const char *dev_name, const char *devpath,
unsigned char ep_in, unsigned char ep_out,
int interface, int serial_index, unsigned zero_mask)
{
@@ -644,7 +669,7 @@
usb->next->prev = usb;
adb_mutex_unlock(&usb_lock);
- register_usb_transport(usb, serial, usb->writeable);
+ register_usb_transport(usb, serial, devpath, usb->writeable);
return;
fail:
diff --git a/adb/usb_linux_client.c b/adb/usb_linux_client.c
index 635fa4b..b110ed8 100644
--- a/adb/usb_linux_client.c
+++ b/adb/usb_linux_client.c
@@ -72,7 +72,7 @@
usb->fd = fd;
D("[ usb_thread - registering device ]\n");
- register_usb_transport(usb, 0, 1);
+ register_usb_transport(usb, 0, 0, 1);
}
// never gets here
diff --git a/adb/usb_osx.c b/adb/usb_osx.c
index 00d02da..45ce444 100644
--- a/adb/usb_osx.c
+++ b/adb/usb_osx.c
@@ -125,10 +125,13 @@
IOUSBDeviceInterface197 **dev = NULL;
HRESULT result;
SInt32 score;
+ UInt32 locationId;
UInt16 vendor;
UInt16 product;
UInt8 serialIndex;
char serial[256];
+ char devpathBuf[64];
+ char *devpath = NULL;
while ((usbInterface = IOIteratorNext(iterator))) {
//* Create an intermediate interface plugin
@@ -192,6 +195,11 @@
kr = (*dev)->GetDeviceVendor(dev, &vendor);
kr = (*dev)->GetDeviceProduct(dev, &product);
+ kr = (*dev)->GetLocationID(dev, &locationId);
+ if (kr == 0) {
+ snprintf(devpathBuf, sizeof(devpathBuf), "usb:%lX", locationId);
+ devpath = devpathBuf;
+ }
kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex);
if (serialIndex > 0) {
@@ -256,7 +264,7 @@
}
DBG("AndroidDeviceAdded calling register_usb_transport\n");
- register_usb_transport(handle, (serial[0] ? serial : NULL), 1);
+ register_usb_transport(handle, (serial[0] ? serial : NULL), devpath, 1);
// Register for an interest notification of this device being removed.
// Pass the reference to our private data as the refCon for the
diff --git a/adb/usb_windows.c b/adb/usb_windows.c
index b216999..a2fbb79 100644
--- a/adb/usb_windows.c
+++ b/adb/usb_windows.c
@@ -490,7 +490,7 @@
true)) {
// Lets make sure that we don't duplicate this device
if (register_new_device(handle)) {
- register_usb_transport(handle, serial_number, 1);
+ register_usb_transport(handle, serial_number, NULL, 1);
} else {
D("register_new_device failed for %s\n", interf_name);
usb_cleanup_handle(handle);
diff --git a/fastboot/engine.c b/fastboot/engine.c
index 994eeae..a1b6539 100644
--- a/fastboot/engine.c
+++ b/fastboot/engine.c
@@ -520,6 +520,8 @@
int status = 0;
a = action_list;
+ if (!a)
+ return status;
resp[FB_RESPONSE_SZ] = 0;
double start = -1;
@@ -556,3 +558,8 @@
fprintf(stderr,"finished. total time: %.3fs\n", (now() - start));
return status;
}
+
+int fb_queue_is_empty(void)
+{
+ return (action_list == NULL);
+}
diff --git a/fastboot/fastboot.c b/fastboot/fastboot.c
index af61f88..b96d93b 100644
--- a/fastboot/fastboot.c
+++ b/fastboot/fastboot.c
@@ -58,6 +58,7 @@
static const char *cmdline = 0;
static int wipe_data = 0;
static unsigned short vendor_id = 0;
+static int long_listing = 0;
static unsigned base_addr = 0x10000000;
@@ -167,9 +168,10 @@
if(info->ifc_class != 0xff) return -1;
if(info->ifc_subclass != 0x42) return -1;
if(info->ifc_protocol != 0x03) return -1;
- // require matching serial number if a serial number is specified
+ // require matching serial number or device path if requested
// at the command line with the -s option.
- if (serial && strcmp(serial, info->serial_number) != 0) return -1;
+ if (serial && (strcmp(serial, info->serial_number) != 0 &&
+ strcmp(serial, info->device_path) != 0)) return -1;
return 0;
}
@@ -183,8 +185,16 @@
if (!serial[0]) {
serial = "????????????";
}
- // output compatible with "adb devices"
- printf("%s\tfastboot\n", serial);
+ if (!long_listing) {
+ // output compatible with "adb devices"
+ printf("%s\tfastboot\n", serial);
+ } else {
+ char* device_path = info->device_path;
+ if (!device_path[0]) {
+ device_path = "????????????";
+ }
+ printf("%s\t%s\tfastboot\n", serial, device_path);
+ }
}
return -1;
@@ -238,7 +248,9 @@
"\n"
"options:\n"
" -w erase userdata and cache\n"
- " -s <serial number> specify device serial number\n"
+ " -s <specific device> specify device serial number\n"
+ " or path to device port\n"
+ " -l with \"devices\", lists device paths\n"
" -p <product> specify product name\n"
" -c <cmdline> override kernel commandline\n"
" -i <vendor id> specify a custom USB vendor id\n"
@@ -571,6 +583,7 @@
int wants_wipe = 0;
int wants_reboot = 0;
int wants_reboot_bootloader = 0;
+ int wants_device_list = 0;
void *data;
unsigned sz;
unsigned page_size = 2048;
@@ -582,11 +595,6 @@
return 1;
}
- if (!strcmp(*argv, "devices")) {
- list_devices();
- return 0;
- }
-
if (!strcmp(*argv, "help")) {
usage();
return 0;
@@ -612,6 +620,9 @@
require(2);
serial = argv[1];
skip(2);
+ } else if(!strcmp(*argv, "-l")) {
+ long_listing = 1;
+ skip(1);
} else if(!strcmp(*argv, "-p")) {
require(2);
product = argv[1];
@@ -630,6 +641,9 @@
die("invalid vendor id '%s'", argv[1]);
vendor_id = (unsigned short)val;
skip(2);
+ } else if (!strcmp(*argv, "devices")) {
+ skip(1);
+ wants_device_list = 1;
} else if(!strcmp(*argv, "getvar")) {
require(2);
fb_queue_display(argv[1], argv[1]);
@@ -725,6 +739,9 @@
}
}
+ if (wants_device_list)
+ list_devices();
+
if (wants_wipe) {
fb_queue_erase("userdata");
fb_queue_erase("cache");
@@ -735,6 +752,9 @@
fb_queue_command("reboot-bootloader", "rebooting into bootloader");
}
+ if (fb_queue_is_empty())
+ return 0;
+
usb = open_device();
status = fb_execute_queue(usb);
diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h
index 7d56ecb..c249a8f 100644
--- a/fastboot/fastboot.h
+++ b/fastboot/fastboot.h
@@ -53,6 +53,7 @@
void fb_queue_download(const char *name, void *data, unsigned size);
void fb_queue_notice(const char *notice);
int fb_execute_queue(usb_handle *usb);
+int fb_queue_is_empty(void);
/* util stuff */
void die(const char *fmt, ...);
diff --git a/fastboot/usb.h b/fastboot/usb.h
index df9efde..d504ee2 100644
--- a/fastboot/usb.h
+++ b/fastboot/usb.h
@@ -53,6 +53,7 @@
unsigned char writable;
char serial_number[256];
+ char device_path[256];
};
typedef int (*ifc_match_func)(usb_ifc_info *ifc);
diff --git a/fastboot/usb_linux.c b/fastboot/usb_linux.c
index 83c6de9..b7a9ca3 100644
--- a/fastboot/usb_linux.c
+++ b/fastboot/usb_linux.c
@@ -32,6 +32,7 @@
#include <string.h>
#include <sys/ioctl.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
@@ -107,6 +108,9 @@
int in, out;
unsigned i;
unsigned e;
+
+ struct stat st;
+ int result;
if(check(ptr, len, USB_DT_DEVICE, USB_DT_DEVICE_SIZE))
return -1;
@@ -134,7 +138,6 @@
// Keep it short enough because some bootloaders are borked if the URB len is > 255
// 128 is too big by 1.
__u16 buffer[127];
- int result;
memset(buffer, 0, sizeof(buffer));
@@ -158,6 +161,42 @@
}
}
+ /* We need to get a path that represents a particular port on a particular
+ * hub. We are passed an fd that was obtained by opening an entry under
+ * /dev/bus/usb. Unfortunately, the names of those entries change each
+ * time devices are plugged and unplugged. So how to get a repeatable
+ * path? udevadm provided the inspiration. We can get the major and
+ * minor of the device file, read the symlink that can be found here:
+ * /sys/dev/char/<major>:<minor>
+ * and then use the last element of that path. As a concrete example, I
+ * have an Android device at /dev/bus/usb/001/027 so working with bash:
+ * $ ls -l /dev/bus/usb/001/027
+ * crw-rw-r-- 1 root plugdev 189, 26 Apr 9 11:03 /dev/bus/usb/001/027
+ * $ ls -l /sys/dev/char/189:26
+ * lrwxrwxrwx 1 root root 0 Apr 9 11:03 /sys/dev/char/189:26 ->
+ * ../../devices/pci0000:00/0000:00:1a.7/usb1/1-4/1-4.2/1-4.2.3
+ * So our device_path would be 1-4.2.3 which says my device is connected
+ * to port 3 of a hub on port 2 of a hub on port 4 of bus 1 (per
+ * http://www.linux-usb.org/FAQ.html).
+ */
+ info.device_path[0] = '\0';
+ result = fstat(fd, &st);
+ if (!result && S_ISCHR(st.st_mode)) {
+ char cdev[128];
+ char link[256];
+ char *slash;
+ ssize_t link_len;
+ snprintf(cdev, sizeof(cdev), "/sys/dev/char/%d:%d",
+ major(st.st_rdev), minor(st.st_rdev));
+ link_len = readlink(cdev, link, sizeof(link) - 1);
+ if (link_len > 0) {
+ link[link_len] = '\0';
+ slash = strrchr(link, '/');
+ if (slash)
+ snprintf(info.device_path, sizeof(info.device_path), "usb:%s", slash+1);
+ }
+ }
+
for(i = 0; i < cfg->bNumInterfaces; i++) {
if(check(ptr, len, USB_DT_INTERFACE, USB_DT_INTERFACE_SIZE))
return -1;
diff --git a/fastboot/usb_osx.c b/fastboot/usb_osx.c
index cbce9bd..1548ba8 100644
--- a/fastboot/usb_osx.c
+++ b/fastboot/usb_osx.c
@@ -264,6 +264,7 @@
SInt32 score;
HRESULT result;
UInt8 serialIndex;
+ UInt32 locationId;
// Create an intermediate plugin.
kr = IOCreatePlugInInterfaceForService(device,
@@ -322,6 +323,13 @@
goto error;
}
+ kr = (*dev)->GetLocationID(dev, &locationId);
+ if (kr != 0) {
+ ERR("GetLocationId");
+ goto error;
+ }
+ snprintf(handle->info.device_path, sizeof(handle->info.device_path), "usb:%lX", locationId);
+
kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex);
if (serialIndex > 0) {
diff --git a/fastboot/usb_windows.c b/fastboot/usb_windows.c
index 99027cc..7aa36b2 100644
--- a/fastboot/usb_windows.c
+++ b/fastboot/usb_windows.c
@@ -311,6 +311,8 @@
info.serial_number[0] = 0;
}
+ info.device_path[0] = 0;
+
if (callback(&info) == 0) {
return 1;
}