summaryrefslogtreecommitdiffstats
path: root/adb/usb_linux.c
diff options
context:
space:
mode:
Diffstat (limited to 'adb/usb_linux.c')
-rw-r--r--adb/usb_linux.c181
1 files changed, 95 insertions, 86 deletions
diff --git a/adb/usb_linux.c b/adb/usb_linux.c
index 537122d..cf78d80 100644
--- a/adb/usb_linux.c
+++ b/adb/usb_linux.c
@@ -57,6 +57,7 @@ struct usb_handle
unsigned char ep_out;
unsigned zero_mask;
+ unsigned writeable;
struct usbdevfs_urb urb_in;
struct usbdevfs_urb urb_out;
@@ -115,7 +116,7 @@ static void kick_disconnected_devices()
}
static void register_device(const char *dev_name, unsigned char ep_in, unsigned char ep_out,
- int ifc, const char *serial, unsigned zero_mask);
+ int ifc, int serial_index, unsigned zero_mask);
static inline int badname(const char *name)
{
@@ -125,19 +126,18 @@ static inline int badname(const char *name)
return 0;
}
-static int find_usb_device(const char *base,
- void (*register_device_callback) (const char *, unsigned char, unsigned char, int, const char *, unsigned))
+static void find_usb_device(const char *base,
+ void (*register_device_callback)
+ (const char *, unsigned char, unsigned char, int, int, unsigned))
{
char busname[32], devname[32];
unsigned char local_ep_in, local_ep_out;
DIR *busdir , *devdir ;
struct dirent *de;
int fd ;
- int found_device = 0;
- char serial[256];
busdir = opendir(base);
- if(busdir == 0) return 0;
+ if(busdir == 0) return;
while((de = readdir(busdir)) != 0) {
if(badname(de->d_name)) continue;
@@ -168,7 +168,7 @@ static int find_usb_device(const char *base,
}
// DBGX("[ scanning %s ]\n", devname);
- if((fd = unix_open(devname, O_RDWR)) < 0) {
+ if((fd = unix_open(devname, O_RDONLY)) < 0) {
continue;
}
@@ -263,59 +263,9 @@ static int find_usb_device(const char *base,
local_ep_out = ep1->bEndpointAddress;
}
- // read the device's serial number
- serial[0] = 0;
- memset(serial, 0, sizeof(serial));
- if (device->iSerialNumber) {
- struct usbdevfs_ctrltransfer ctrl;
- __u16 buffer[128];
- __u16 languages[128];
- int i, result;
- int languageCount = 0;
-
- memset(languages, 0, sizeof(languages));
- memset(&ctrl, 0, sizeof(ctrl));
-
- // read list of supported languages
- ctrl.bRequestType = USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE;
- ctrl.bRequest = USB_REQ_GET_DESCRIPTOR;
- ctrl.wValue = (USB_DT_STRING << 8) | 0;
- ctrl.wIndex = 0;
- ctrl.wLength = sizeof(languages);
- ctrl.data = languages;
-
- result = ioctl(fd, USBDEVFS_CONTROL, &ctrl);
- if (result > 0)
- languageCount = (result - 2) / 2;
-
- for (i = 1; i <= languageCount; i++) {
- memset(buffer, 0, sizeof(buffer));
- memset(&ctrl, 0, sizeof(ctrl));
-
- ctrl.bRequestType = USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE;
- ctrl.bRequest = USB_REQ_GET_DESCRIPTOR;
- ctrl.wValue = (USB_DT_STRING << 8) | device->iSerialNumber;
- ctrl.wIndex = languages[i];
- ctrl.wLength = sizeof(buffer);
- ctrl.data = buffer;
-
- result = ioctl(fd, USBDEVFS_CONTROL, &ctrl);
- if (result > 0) {
- int i;
- // skip first word, and copy the rest to the serial string, changing shorts to bytes.
- result /= 2;
- for (i = 1; i < result; i++)
- serial[i - 1] = buffer[i];
- serial[i - 1] = 0;
- break;
- }
- }
- }
-
register_device_callback(devname, local_ep_in, local_ep_out,
- interface->bInterfaceNumber, serial, zero_mask);
+ interface->bInterfaceNumber, device->iSerialNumber, zero_mask);
- found_device = 1;
break;
} else {
// seek next interface descriptor
@@ -332,8 +282,6 @@ static int find_usb_device(const char *base,
closedir(devdir);
} //end of busdir while
closedir(busdir);
-
- return found_device;
}
void usb_cleanup()
@@ -537,26 +485,30 @@ void usb_kick(usb_handle *h)
if(h->dead == 0) {
h->dead = 1;
- /* HACK ALERT!
- ** Sometimes we get stuck in ioctl(USBDEVFS_REAPURB).
- ** This is a workaround for that problem.
- */
- if (h->reaper_thread) {
- pthread_kill(h->reaper_thread, SIGALRM);
- }
+ if (h->writeable) {
+ /* HACK ALERT!
+ ** Sometimes we get stuck in ioctl(USBDEVFS_REAPURB).
+ ** This is a workaround for that problem.
+ */
+ if (h->reaper_thread) {
+ pthread_kill(h->reaper_thread, SIGALRM);
+ }
- /* cancel any pending transactions
- ** these will quietly fail if the txns are not active,
- ** but this ensures that a reader blocked on REAPURB
- ** will get unblocked
- */
- ioctl(h->desc, USBDEVFS_DISCARDURB, &h->urb_in);
- ioctl(h->desc, USBDEVFS_DISCARDURB, &h->urb_out);
- h->urb_in.status = -ENODEV;
- h->urb_out.status = -ENODEV;
- h->urb_in_busy = 0;
- h->urb_out_busy = 0;
- adb_cond_broadcast(&h->notify);
+ /* cancel any pending transactions
+ ** these will quietly fail if the txns are not active,
+ ** but this ensures that a reader blocked on REAPURB
+ ** will get unblocked
+ */
+ ioctl(h->desc, USBDEVFS_DISCARDURB, &h->urb_in);
+ ioctl(h->desc, USBDEVFS_DISCARDURB, &h->urb_out);
+ h->urb_in.status = -ENODEV;
+ h->urb_out.status = -ENODEV;
+ h->urb_in_busy = 0;
+ h->urb_out_busy = 0;
+ adb_cond_broadcast(&h->notify);
+ } else {
+ unregister_usb_transport(h);
+ }
}
adb_mutex_unlock(&h->lock);
}
@@ -580,11 +532,11 @@ int usb_close(usb_handle *h)
static void register_device(const char *dev_name,
unsigned char ep_in, unsigned char ep_out,
- int interface,
- const char *serial, unsigned zero_mask)
+ int interface, int serial_index, unsigned zero_mask)
{
usb_handle* usb = 0;
int n = 0;
+ char serial[256];
/* Since Linux will not reassign the device ID (and dev_name)
** as long as the device is open, we can add to the list here
@@ -610,6 +562,7 @@ static void register_device(const char *dev_name,
usb->ep_in = ep_in;
usb->ep_out = ep_out;
usb->zero_mask = zero_mask;
+ usb->writeable = 1;
adb_cond_init(&usb->notify, 0);
adb_mutex_init(&usb->lock, 0);
@@ -618,10 +571,66 @@ static void register_device(const char *dev_name,
usb->reaper_thread = 0;
usb->desc = unix_open(usb->fname, O_RDWR);
- if(usb->desc < 0) goto fail;
- D("[ usb open %s fd = %d]\n", usb->fname, usb->desc);
- n = ioctl(usb->desc, USBDEVFS_CLAIMINTERFACE, &interface);
- if(n != 0) goto fail;
+ if(usb->desc < 0) {
+ /* if we fail, see if have read-only access */
+ usb->desc = unix_open(usb->fname, O_RDONLY);
+ if(usb->desc < 0) goto fail;
+ usb->writeable = 0;
+ D("[ usb open read-only %s fd = %d]\n", usb->fname, usb->desc);
+ } else {
+ D("[ usb open %s fd = %d]\n", usb->fname, usb->desc);
+ n = ioctl(usb->desc, USBDEVFS_CLAIMINTERFACE, &interface);
+ if(n != 0) goto fail;
+ }
+
+ /* read the device's serial number */
+ serial[0] = 0;
+ memset(serial, 0, sizeof(serial));
+ if (serial_index) {
+ struct usbdevfs_ctrltransfer ctrl;
+ __u16 buffer[128];
+ __u16 languages[128];
+ int i, result;
+ int languageCount = 0;
+
+ memset(languages, 0, sizeof(languages));
+ memset(&ctrl, 0, sizeof(ctrl));
+
+ // read list of supported languages
+ ctrl.bRequestType = USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE;
+ ctrl.bRequest = USB_REQ_GET_DESCRIPTOR;
+ ctrl.wValue = (USB_DT_STRING << 8) | 0;
+ ctrl.wIndex = 0;
+ ctrl.wLength = sizeof(languages);
+ ctrl.data = languages;
+
+ result = ioctl(usb->desc, USBDEVFS_CONTROL, &ctrl);
+ if (result > 0)
+ languageCount = (result - 2) / 2;
+
+ for (i = 1; i <= languageCount; i++) {
+ memset(buffer, 0, sizeof(buffer));
+ memset(&ctrl, 0, sizeof(ctrl));
+
+ ctrl.bRequestType = USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE;
+ ctrl.bRequest = USB_REQ_GET_DESCRIPTOR;
+ ctrl.wValue = (USB_DT_STRING << 8) | serial_index;
+ ctrl.wIndex = languages[i];
+ ctrl.wLength = sizeof(buffer);
+ ctrl.data = buffer;
+
+ result = ioctl(usb->desc, USBDEVFS_CONTROL, &ctrl);
+ if (result > 0) {
+ int i;
+ // skip first word, and copy the rest to the serial string, changing shorts to bytes.
+ result /= 2;
+ for (i = 1; i < result; i++)
+ serial[i - 1] = buffer[i];
+ serial[i - 1] = 0;
+ break;
+ }
+ }
+ }
/* add to the end of the active handles */
adb_mutex_lock(&usb_lock);
@@ -631,7 +640,7 @@ static void register_device(const char *dev_name,
usb->next->prev = usb;
adb_mutex_unlock(&usb_lock);
- register_usb_transport(usb, serial);
+ register_usb_transport(usb, serial, usb->writeable);
return;
fail: