Merge "Add NETLINK_ROUTE processing to the netlink client code, so that Ethernet physical-layer up/down events can be tracked. Upper layers will use these events to enable/disable Ethernet connectivity."
diff --git a/fastboot/fastboot.c b/fastboot/fastboot.c
index 63208bc..973510a 100644
--- a/fastboot/fastboot.c
+++ b/fastboot/fastboot.c
@@ -223,6 +223,7 @@
" boot <kernel> [ <ramdisk> ] download and boot kernel\n"
" flash:raw boot <kernel> [ <ramdisk> ] create bootimage and flash it\n"
" devices list all connected devices\n"
+ " continue continue with autoboot\n"
" reboot reboot device normally\n"
" reboot-bootloader reboot device into bootloader\n"
"\n"
diff --git a/include/usbhost/usbhost.h b/include/usbhost/usbhost.h
index ccc12b1..7ef7ace 100644
--- a/include/usbhost/usbhost.h
+++ b/include/usbhost/usbhost.h
@@ -39,6 +39,17 @@
unsigned char* curr_desc;
};
+struct usb_request
+{
+ struct usb_device *dev;
+ void* buffer;
+ int buffer_length;
+ int actual_length;
+ int max_packet_size;
+ void *private_data; /* struct usbdevfs_urb* */
+ void *client_data; /* free for use by client */
+};
+
/* Callback for notification when new USB devices are attached.
* Return true to exit from usb_host_run.
*/
@@ -81,14 +92,10 @@
/* Releases all resources associated with the USB device */
void usb_device_close(struct usb_device *device);
-/* Creates a usb_device object for already open USB device.
- * This is intended to facilitate sharing USB devices across address spaces.
- */
+/* Creates a usb_device object for already open USB device */
struct usb_device *usb_device_new(const char *dev_name, int fd);
-/* Returns the file descriptor for the usb_device. Used in conjunction with
- * usb_device_new() for sharing USB devices across address spaces.
- */
+/* Returns the file descriptor for the usb_device */
int usb_device_get_fd(struct usb_device *device);
/* Returns the name for the USB device, which is the same as
@@ -96,13 +103,20 @@
*/
const char* usb_device_get_name(struct usb_device *device);
-/* Returns a unique ID for the device. Currently this is generated from the
- * dev_name path.
+/* Returns a unique ID for the device.
+ *Currently this is generated from the dev_name path.
*/
int usb_device_get_unique_id(struct usb_device *device);
+/* Returns a unique ID for the device name.
+ * Currently this is generated from the device path.
+ */
int usb_device_get_unique_id_from_name(const char* name);
+/* Returns the device name for the unique ID.
+ * Call free() to deallocate the returned string */
+char* usb_device_get_name_from_unique_id(int id);
+
/* Returns the USB vendor ID from the device descriptor for the USB device */
uint16_t usb_device_get_vendor_id(struct usb_device *device);
@@ -163,38 +177,23 @@
/* Releases the specified interface of a USB device */
int usb_device_release_interface(struct usb_device *device, unsigned int interface);
+/* Creates a new usb_request. */
+struct usb_request *usb_request_new(struct usb_device *dev,
+ const struct usb_endpoint_descriptor *ep_desc);
-/* Creates a new usb_endpoint for the specified endpoint of a USB device.
- * This can be used to read or write data across the endpoint.
- */
-struct usb_endpoint *usb_endpoint_open(struct usb_device *dev,
- const struct usb_endpoint_descriptor *desc);
+/* Releases all resources associated with the request */
+void usb_request_free(struct usb_request *req);
-/* Releases all resources associated with the endpoint */
-void usb_endpoint_close(struct usb_endpoint *ep);
+/* Submits a read or write request on the specified device */
+int usb_request_queue(struct usb_request *req);
-/* Begins a read or write operation on the specified endpoint */
-int usb_endpoint_queue(struct usb_endpoint *ep, void *data, int len);
-
- /* Waits for the results of a previous usb_endpoint_queue operation on the
- * specified endpoint. Returns number of bytes transferred, or a negative
- * value for error.
+ /* Waits for the results of a previous usb_request_queue operation.
+ * Returns a usb_request, or NULL for error.
*/
-int usb_endpoint_wait(struct usb_device *device, int *out_ep_num);
+struct usb_request *usb_request_wait(struct usb_device *dev);
-/* Cancels a pending usb_endpoint_queue() operation on an endpoint. */
-int usb_endpoint_cancel(struct usb_endpoint *ep);
-
-/* Returns the usb_device for the given endpoint */
-struct usb_device *usb_endpoint_get_device(struct usb_endpoint *ep);
-
-/* Returns the endpoint address for the given endpoint */
-int usb_endpoint_number(struct usb_endpoint *ep);
-
-/* Returns the maximum packet size for the given endpoint.
- * For bulk endpoints this should be 512 for highspeed or 64 for fullspeed.
- */
-int usb_endpoint_max_packet(struct usb_endpoint *ep);
+/* Cancels a pending usb_request_queue() operation. */
+int usb_request_cancel(struct usb_request *req);
#ifdef __cplusplus
}
diff --git a/init/keychords.c b/init/keychords.c
index 892cbdf..aab0819 100644
--- a/init/keychords.c
+++ b/init/keychords.c
@@ -105,14 +105,14 @@
// and on user builds for users that are developers.
debuggable = property_get("ro.debuggable");
adb_enabled = property_get("init.svc.adbd");
+ ret = read(keychord_fd, &id, sizeof(id));
+ if (ret != sizeof(id)) {
+ ERROR("could not read keychord id\n");
+ return;
+ }
+
if ((debuggable && !strcmp(debuggable, "1")) ||
(adb_enabled && !strcmp(adb_enabled, "running"))) {
- ret = read(keychord_fd, &id, sizeof(id));
- if (ret != sizeof(id)) {
- ERROR("could not read keychord id\n");
- return;
- }
-
svc = service_find_by_keychord(id);
if (svc) {
INFO("starting service %s from keychord\n", svc->name);
diff --git a/libusbhost/Android.mk b/libusbhost/Android.mk
index 97c1edc..52b4ead 100644
--- a/libusbhost/Android.mk
+++ b/libusbhost/Android.mk
@@ -30,7 +30,7 @@
endif
-# Static library for target
+# Shared library for target
# ========================================================
include $(CLEAR_VARS)
@@ -40,4 +40,7 @@
LOCAL_CFLAGS := -g -DUSE_LIBLOG
-include $(BUILD_STATIC_LIBRARY)
+# needed for logcat
+LOCAL_SHARED_LIBRARIES := libcutils
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/libusbhost/usbhost.c b/libusbhost/usbhost.c
index dba0b48..d6736d3 100644
--- a/libusbhost/usbhost.c
+++ b/libusbhost/usbhost.c
@@ -45,18 +45,13 @@
#include <pthread.h>
#include <linux/usbdevice_fs.h>
-#include <linux/version.h>
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20)
-#include <linux/usb/ch9.h>
-#else
-#include <linux/usb_ch9.h>
-#endif
#include <asm/byteorder.h>
#include "usbhost/usbhost.h"
#define USB_FS_DIR "/dev/bus/usb"
#define USB_FS_ID_SCANNER "/dev/bus/usb/%d/%d"
+#define USB_FS_ID_FORMAT "/dev/bus/usb/%03d/%03d"
struct usb_host_context {
@@ -71,13 +66,6 @@
int writeable;
};
-struct usb_endpoint
-{
- struct usb_device *dev;
- struct usb_endpoint_descriptor desc;
- struct usbdevfs_urb urb;
-};
-
static inline int badname(const char *name)
{
while(*name) {
@@ -314,6 +302,15 @@
return bus * 1000 + dev;
}
+char* usb_device_get_name_from_unique_id(int id)
+{
+ int bus = id / 1000;
+ int dev = id % 1000;
+ char* result = (char *)calloc(1, strlen(USB_FS_ID_FORMAT));
+ snprintf(result, strlen(USB_FS_ID_FORMAT) - 1, USB_FS_ID_FORMAT, bus, dev);
+ return result;
+}
+
uint16_t usb_device_get_vendor_id(struct usb_device *device)
{
struct usb_device_descriptor* desc = (struct usb_device_descriptor*)device->desc;
@@ -455,83 +452,89 @@
return ioctl(device->fd, USBDEVFS_RELEASEINTERFACE, &interface);
}
-struct usb_endpoint *usb_endpoint_open(struct usb_device *dev,
- const struct usb_endpoint_descriptor *desc)
+struct usb_request *usb_request_new(struct usb_device *dev,
+ const struct usb_endpoint_descriptor *ep_desc)
{
- struct usb_endpoint *ep = calloc(1, sizeof(struct usb_endpoint));
- memcpy(&ep->desc, desc, sizeof(ep->desc));
- ep->dev = dev;
- return ep;
+ struct usbdevfs_urb *urb = calloc(1, sizeof(struct usbdevfs_urb));
+ if (!urb)
+ return NULL;
+
+ if ((ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)
+ urb->type = USBDEVFS_URB_TYPE_BULK;
+ else if ((ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
+ urb->type = USBDEVFS_URB_TYPE_INTERRUPT;
+ else {
+ D("Unsupported endpoint type %d", ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
+ free(urb);
+ return NULL;
+ }
+ urb->endpoint = ep_desc->bEndpointAddress;
+
+ struct usb_request *req = calloc(1, sizeof(struct usb_request));
+ if (!req) {
+ free(urb);
+ return NULL;
+ }
+
+ req->dev = dev;
+ req->max_packet_size = __le16_to_cpu(ep_desc->wMaxPacketSize);
+ req->private_data = urb;
+ urb->usercontext = req;
+
+ return req;
}
-void usb_endpoint_close(struct usb_endpoint *ep)
+void usb_request_free(struct usb_request *req)
{
- // cancel IO here?
- free(ep);
+ free(req->private_data);
+ free(req);
}
-int usb_endpoint_queue(struct usb_endpoint *ep, void *data, int len)
+int usb_request_queue(struct usb_request *req)
{
- struct usbdevfs_urb *urb = &ep->urb;
+ struct usbdevfs_urb *urb = (struct usbdevfs_urb*)req->private_data;
int res;
- D("usb_endpoint_queue\n");
- memset(urb, 0, sizeof(*urb));
- urb->type = USBDEVFS_URB_TYPE_BULK;
- urb->endpoint = ep->desc.bEndpointAddress;
urb->status = -1;
- urb->buffer = data;
- urb->buffer_length = len;
+ urb->buffer = req->buffer;
+ urb->buffer_length = req->buffer_length;
do {
- res = ioctl(ep->dev->fd, USBDEVFS_SUBMITURB, urb);
+ res = ioctl(req->dev->fd, USBDEVFS_SUBMITURB, urb);
} while((res < 0) && (errno == EINTR));
return res;
}
-int usb_endpoint_wait(struct usb_device *dev, int *out_ep_num)
+struct usb_request *usb_request_wait(struct usb_device *dev)
{
- struct usbdevfs_urb *out = NULL;
+ struct usbdevfs_urb *urb = NULL;
+ struct usb_request *req = NULL;
int res;
while (1) {
- res = ioctl(dev->fd, USBDEVFS_REAPURB, &out);
+ int res = ioctl(dev->fd, USBDEVFS_REAPURB, &urb);
D("USBDEVFS_REAPURB returned %d\n", res);
if (res < 0) {
if(errno == EINTR) {
continue;
}
D("[ reap urb - error ]\n");
- *out_ep_num = -1;
+ return NULL;
} else {
D("[ urb @%p status = %d, actual = %d ]\n",
- out, out->status, out->actual_length);
- res = out->actual_length;
- *out_ep_num = out->endpoint;
+ urb, urb->status, urb->actual_length);
+ req = (struct usb_request*)urb->usercontext;
+ req->actual_length = urb->actual_length;
}
break;
}
- return res;
+ return req;
}
-int usb_endpoint_cancel(struct usb_endpoint *ep)
+int usb_request_cancel(struct usb_request *req)
{
- return ioctl(ep->dev->fd, USBDEVFS_DISCARDURB, &ep->urb);
-}
-
-struct usb_device *usb_endpoint_get_device(struct usb_endpoint *ep)
-{
- return ep->dev;
-}
-
-int usb_endpoint_number(struct usb_endpoint *ep)
-{
- return ep->desc.bEndpointAddress;
-}
-
-int usb_endpoint_max_packet(struct usb_endpoint *ep)
-{
- return __le16_to_cpu(ep->desc.wMaxPacketSize);
+ struct usbdevfs_urb *urb = ((struct usbdevfs_urb*)req->private_data);
+ return ioctl(req->dev->fd, USBDEVFS_DISCARDURB, &urb);
}
diff --git a/rootdir/etc/init.goldfish.rc b/rootdir/etc/init.goldfish.rc
index 6f30843..fa70c2e 100644
--- a/rootdir/etc/init.goldfish.rc
+++ b/rootdir/etc/init.goldfish.rc
@@ -22,6 +22,11 @@
stop dund
stop akmd
+# start essential services
+ start qemud
+ start goldfish-logcat
+ start goldfish-setup
+
setprop ro.setupwizard.mode EMULATOR
# enable Google-specific location features,
@@ -42,6 +47,8 @@
# something else.
service goldfish-setup /system/etc/init.goldfish.sh
+ user root
+ group root
oneshot
service qemud /system/bin/qemud
@@ -52,7 +59,7 @@
# program to check wether it runs on the emulator
# if it does, it redirects its output to the device
# named by the androidboot.console kernel option
-# if not, is simply exit immediately
+# if not, is simply exits immediately
service goldfish-logcat /system/bin/logcat -Q
oneshot
diff --git a/rootdir/etc/init.goldfish.sh b/rootdir/etc/init.goldfish.sh
index cfa2c82..c18c032 100755
--- a/rootdir/etc/init.goldfish.sh
+++ b/rootdir/etc/init.goldfish.sh
@@ -18,7 +18,7 @@
;;
esac
-num_dns=`getprop ro.kernel.android.ndns`
+num_dns=`getprop ro.kernel.ndns`
case "$num_dns" in
2) setprop net.eth0.dns2 10.0.2.4
;;
@@ -44,7 +44,7 @@
# this line doesn't really do anything useful. however without it the
# previous setprop doesn't seem to apply for some really odd reason
-setprop ro.qemu.init.completed 1
+#setprop ro.qemu.init.completed 1
# set up the second interface (for inter-emulator connections)
# if required
diff --git a/rootdir/etc/ueventd.goldfish.rc b/rootdir/etc/ueventd.goldfish.rc
index e69de29..b5828e7 100644
--- a/rootdir/etc/ueventd.goldfish.rc
+++ b/rootdir/etc/ueventd.goldfish.rc
@@ -0,0 +1,4 @@
+# These settings are specific to running under the Android emulator
+/dev/qemu_trace 0666 system system
+/dev/ttyS* 0666 system system
+/proc 0666 system system
diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc
index a52bdda..c0540a7 100644
--- a/rootdir/ueventd.rc
+++ b/rootdir/ueventd.rc
@@ -63,7 +63,6 @@
/dev/snd/dsp1 0660 system audio
/dev/snd/mixer 0660 system audio
/dev/smd0 0640 radio radio
-/dev/qemu_trace 0666 system system
/dev/qmi 0640 radio radio
/dev/qmi0 0640 radio radio
/dev/qmi1 0640 radio radio
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c
index de630f5..9dda0ea 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -195,6 +195,7 @@
node->parent = parent;
node->next = parent->child;
parent->child = node;
+ parent->refcount++;
}
struct node *node_create(struct node *parent, const char *name, __u64 nid, __u64 gen)
@@ -217,7 +218,6 @@
add_node_to_parent(node, parent);
memcpy(node->name, name, namelen + 1);
node->namelen = namelen;
- parent->refcount++;
return node;
}
@@ -293,6 +293,15 @@
return 0;
}
+static void dec_refcount(struct node *node) {
+ if (node->refcount > 0) {
+ node->refcount--;
+ TRACE("dec_refcount %p(%s) -> %d\n", node, node->name, node->refcount);
+ } else {
+ ERROR("Zero refcnt %p\n", node);
+ }
+ }
+
static struct node *remove_child(struct node *parent, __u64 nid)
{
struct node *prev = 0;
@@ -307,6 +316,7 @@
}
node->next = 0;
node->parent = 0;
+ dec_refcount(parent);
return node;
}
prev = node;
@@ -348,7 +358,7 @@
void node_release(struct node *node)
{
TRACE("RELEASE %p (%s) rc=%d\n", node, node->name, node->refcount);
- node->refcount--;
+ dec_refcount(node);
if (node->refcount == 0) {
if (node->parent->child == node) {
node->parent->child = node->parent->child->next;
@@ -371,7 +381,7 @@
/* TODO: remove debugging - poison memory */
memset(node->name, 0xef, node->namelen);
free(node->name);
- memset(node, 0xef, sizeof(*node));
+ memset(node, 0xfc, sizeof(*node));
free(node);
}
}
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index 66ebbef..bc8c02f 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -60,10 +60,7 @@
toolbox.c \
$(patsubst %,%.c,$(TOOLS))
-LOCAL_SHARED_LIBRARIES := libcutils libc
-
-# Needed for lsusb. Should optimize out in linker if lsusb is not included
-LOCAL_STATIC_LIBRARIES := libusbhost
+LOCAL_SHARED_LIBRARIES := libcutils libc libusbhost
LOCAL_MODULE:= toolbox
diff --git a/toolbox/uptime.c b/toolbox/uptime.c
index 3d8061c..1c312b0 100644
--- a/toolbox/uptime.c
+++ b/toolbox/uptime.c
@@ -35,6 +35,7 @@
#include <linux/android_alarm.h>
#include <fcntl.h>
#include <stdio.h>
+#include <time.h>
static void format_time(int time, char* buffer) {
@@ -75,19 +76,26 @@
float up_time, idle_time;
char up_string[100], idle_string[100], sleep_string[100];
int elapsed;
+ struct timespec up_timespec;
FILE* file = fopen("/proc/uptime", "r");
if (!file) {
fprintf(stderr, "Could not open /proc/uptime\n");
return -1;
}
- if (fscanf(file, "%f %f", &up_time, &idle_time) != 2) {
+ if (fscanf(file, "%*f %f", &idle_time) != 1) {
fprintf(stderr, "Could not parse /proc/uptime\n");
fclose(file);
return -1;
}
fclose(file);
+ if (clock_gettime(CLOCK_MONOTONIC, &up_timespec) < 0) {
+ fprintf(stderr, "Could not get monotonic time\n");
+ return -1;
+ }
+ up_time = up_timespec.tv_sec + up_timespec.tv_nsec / 1e9;
+
elapsed = elapsedRealtime();
if (elapsed < 0) {
fprintf(stderr, "elapsedRealtime failed\n");