Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 95b837d3 authored by Mike Lockwood's avatar Mike Lockwood
Browse files

adb: On Linux, detect USB devices for which adb does not have permissions to communicate with.



adb devices will now list devices without adequate file system permissions in /dev/bus/usb as:

List of devices attached
????????????	no permissions

Signed-off-by: default avatarMike Lockwood <lockwood@android.com>
parent e64004d3
Loading
Loading
Loading
Loading
+7 −4
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@
#define ADB_VERSION_MAJOR 1         // Used for help/version information
#define ADB_VERSION_MINOR 0         // Used for help/version information

#define ADB_SERVER_VERSION    22    // Increment this when we want to force users to start a new adb server
#define ADB_SERVER_VERSION    23    // Increment this when we want to force users to start a new adb server

typedef struct amessage amessage;
typedef struct apacket apacket;
@@ -263,14 +263,17 @@ void kick_transport( atransport* t );

/* initialize a transport object's func pointers and state */
int  init_socket_transport(atransport *t, int s, int port);
void init_usb_transport(atransport *t, usb_handle *usb);
void init_usb_transport(atransport *t, usb_handle *usb, int state);

/* for MacOS X cleanup */
void close_usb_devices();

/* cause new transports to be init'd and added to the list */
void register_socket_transport(int s, const char *serial, int  port);
void register_usb_transport(usb_handle *h, const char *serial);
void register_usb_transport(usb_handle *h, const char *serial, unsigned writeable);

/* this should only be used for transports with connection_state == CS_NOPERM */
void unregister_usb_transport(usb_handle *usb);

int service_to_fd(const char *name);
#if ADB_HOST
@@ -384,7 +387,7 @@ int connection_state(atransport *t);
#define CS_DEVICE     2
#define CS_HOST       3
#define CS_RECOVERY   4
#define CS_ERROR      5
#define CS_NOPERM     5 /* Insufficient permissions to communicate with the device */

extern int HOST;

+54 −28
Original line number Diff line number Diff line
@@ -584,6 +584,8 @@ static void transport_registration_func(int _fd, unsigned ev, void *data)
        return;
    }

    /* don't create transport threads for inaccessible devices */
    if (t->connection_state != CS_NOPERM) {
        /* initial references are the two threads */
        t->ref_count = 2;

@@ -596,14 +598,6 @@ static void transport_registration_func(int _fd, unsigned ev, void *data)
        t->transport_socket = s[0];
        t->fd = s[1];

        /* put us on the master device list */
    adb_mutex_lock(&transport_lock);
    t->next = &transport_list;
    t->prev = transport_list.prev;
    t->next->prev = t;
    t->prev->next = t;
    adb_mutex_unlock(&transport_lock);

        D("transport: %p install %d\n", t, t->transport_socket );
        fdevent_install(&(t->transport_fde),
                        t->transport_socket,
@@ -619,6 +613,15 @@ static void transport_registration_func(int _fd, unsigned ev, void *data)
        if(adb_thread_create(&output_thread_ptr, output_thread, t)){
            fatal_errno("cannot create output thread");
        }
    }

        /* put us on the master device list */
    adb_mutex_lock(&transport_lock);
    t->next = &transport_list;
    t->prev = transport_list.prev;
    t->next->prev = t;
    t->prev->next = t;
    adb_mutex_unlock(&transport_lock);

    t->disconnects.next = t->disconnects.prev = &t->disconnects;

@@ -717,6 +720,8 @@ retry:

    adb_mutex_lock(&transport_lock);
    for (t = transport_list.next; t != &transport_list; t = t->next) {
        if (t->connection_state == CS_NOPERM) continue;

        /* check for matching serial number */
        if (serial) {
            if (t->serial && !strcmp(serial, t->serial)) {
@@ -763,6 +768,11 @@ retry:
                *error_out = "device offline";
            result = NULL;
        }
        if (result && result->connection_state == CS_NOPERM) {
            if (error_out)
                *error_out = "no permissions for device";
            result = NULL;
        }

         /* check for required connection state */
        if (result && state != CS_ANY && result->connection_state != state) {
@@ -793,6 +803,7 @@ static const char *statename(atransport *t)
    case CS_DEVICE: return "device";
    case CS_HOST: return "host";
    case CS_RECOVERY: return "recovery";
    case CS_NOPERM: return "no permissions";
    default: return "unknown";
    }
}
@@ -807,9 +818,10 @@ int list_transports(char *buf, size_t bufsize)
        /* XXX OVERRUN PROBLEMS XXX */
    adb_mutex_lock(&transport_lock);
    for(t = transport_list.next; t != &transport_list; t = t->next) {
        len = snprintf(p, end - p, "%s\t%s\n",
                t->serial ? t->serial : "",
                statename(t));
        const char* serial = t->serial;
        if (!serial || !serial[0])
            serial = "????????????";
        len = snprintf(p, end - p, "%s\t%s\n", serial, statename(t));

        if (p + len >= end) {
            /* discard last line if buffer is too short */
@@ -854,18 +866,32 @@ void register_socket_transport(int s, const char *serial, int port)
    register_transport(t);
}

void register_usb_transport(usb_handle *usb, const char *serial)
void register_usb_transport(usb_handle *usb, const char *serial, unsigned writeable)
{
    atransport *t = calloc(1, sizeof(atransport));
    D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb,
      serial ? serial : "");
    init_usb_transport(t, usb);
    init_usb_transport(t, usb, (writeable ? CS_OFFLINE : CS_NOPERM));
    if(serial) {
        t->serial = strdup(serial);
    }
    register_transport(t);
}

/* this should only be used for transports with connection_state == CS_NOPERM */
void unregister_usb_transport(usb_handle *usb)
{
    atransport *t;
    adb_mutex_lock(&transport_lock);
    for(t = transport_list.next; t != &transport_list; t = t->next) {
        if (t->usb == usb && t->connection_state == CS_NOPERM) {
            t->next->prev = t->prev;
            t->prev->next = t->next;
            break;
        }
     }
    adb_mutex_unlock(&transport_lock);
}

#undef TRACE_TAG
#define TRACE_TAG  TRACE_RWX
+2 −2
Original line number Diff line number Diff line
@@ -110,7 +110,7 @@ static void remote_kick(atransport *t)
    usb_kick(t->usb);
}

void init_usb_transport(atransport *t, usb_handle *h)
void init_usb_transport(atransport *t, usb_handle *h, int state)
{
    D("transport: usb\n");
    t->close = remote_close;
@@ -118,7 +118,7 @@ void init_usb_transport(atransport *t, usb_handle *h)
    t->read_from_remote = remote_read;
    t->write_to_remote = remote_write;
    t->sync_token = 1;
    t->connection_state = CS_OFFLINE;
    t->connection_state = state;
    t->type = kTransportUsb;
    t->usb = h;

+95 −86
Original line number Diff line number Diff line
@@ -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,6 +485,7 @@ void usb_kick(usb_handle *h)
    if(h->dead == 0) {
        h->dead = 1;

        if (h->writeable) {
            /* HACK ALERT!
            ** Sometimes we get stuck in ioctl(USBDEVFS_REAPURB).
            ** This is a workaround for that problem.
@@ -557,6 +506,9 @@ void usb_kick(usb_handle *h)
            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) {
        /* 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:
+1 −1
Original line number Diff line number Diff line
@@ -72,7 +72,7 @@ static void *usb_open_thread(void *x)
        usb->fd = fd;

        D("[ usb_thread - registering device ]\n");
        register_usb_transport(usb, 0);
        register_usb_transport(usb, 0, 1);
    }

    // never gets here