usb_linux.c

来自「Android 一些工具」· C语言 代码 · 共 654 行 · 第 1/2 页

C
654
字号
    urb->buffer_length = len;    D("++ write ++\n");    adb_mutex_lock(&h->lock);    if(h->dead) {        res = -1;        goto fail;    }    do {        res = ioctl(h->desc, USBDEVFS_SUBMITURB, urb);    } while((res < 0) && (errno == EINTR));    if(res < 0) {        goto fail;    }    res = -1;    h->urb_out_busy = 1;    for(;;) {        adb_cond_wait(&h->notify, &h->lock);        if(h->dead) {            break;        }        if(h->urb_out_busy == 0) {            if(urb->status == 0) {                res = urb->actual_length;            }            break;        }    }fail:    adb_mutex_unlock(&h->lock);    D("-- write --\n");    return res;}static int usb_bulk_read(usb_handle *h, void *data, int len){    struct usbdevfs_urb *urb = &h->urb_in;    struct usbdevfs_urb *out = NULL;    int res;    memset(urb, 0, sizeof(*urb));    urb->type = USBDEVFS_URB_TYPE_BULK;    urb->endpoint = h->ep_in;    urb->status = -1;    urb->buffer = data;    urb->buffer_length = len;    adb_mutex_lock(&h->lock);    if(h->dead) {        res = -1;        goto fail;    }    do {        res = ioctl(h->desc, USBDEVFS_SUBMITURB, urb);    } while((res < 0) && (errno == EINTR));    if(res < 0) {        goto fail;    }    h->urb_in_busy = 1;    for(;;) {        D("[ reap urb - wait ]\n");        h->reaper_thread = pthread_self();        adb_mutex_unlock(&h->lock);        res = ioctl(h->desc, USBDEVFS_REAPURB, &out);        adb_mutex_lock(&h->lock);        h->reaper_thread = 0;        if(h->dead) {            res = -1;            break;        }        if(res < 0) {            if(errno == EINTR) {                continue;            }            D("[ reap urb - error ]\n");            break;        }        D("[ urb @%p status = %d, actual = %d ]\n",            out, out->status, out->actual_length);        if(out == &h->urb_in) {            D("[ reap urb - IN complete ]\n");            h->urb_in_busy = 0;            if(urb->status == 0) {                res = urb->actual_length;            } else {                res = -1;            }            break;        }        if(out == &h->urb_out) {            D("[ reap urb - OUT compelete ]\n");            h->urb_out_busy = 0;            adb_cond_broadcast(&h->notify);        }    }fail:    adb_mutex_unlock(&h->lock);    return res;}int usb_write(usb_handle *h, const void *_data, int len){    unsigned char *data = (unsigned char*) _data;    int n;    int need_zero = 0;    if(h->zero_mask) {            /* if we need 0-markers and our transfer            ** is an even multiple of the packet size,            ** we make note of it            */        if(!(len & h->zero_mask)) {            need_zero = 1;        }    }    while(len > 0) {        int xfer = (len > 4096) ? 4096 : len;        n = usb_bulk_write(h, data, xfer);        if(n != xfer) {            D("ERROR: n = %d, errno = %d (%s)\n",                n, errno, strerror(errno));            return -1;        }        len -= xfer;        data += xfer;    }    if(need_zero){        n = usb_bulk_write(h, _data, 0);        return n;    }    return 0;}int usb_read(usb_handle *h, void *_data, int len){    unsigned char *data = (unsigned char*) _data;    int n;    D("++ usb_read ++\n");    while(len > 0) {        int xfer = (len > 4096) ? 4096 : len;        D("[ usb read %d fd = %d], fname=%s\n", xfer, h->desc, h->fname);        n = usb_bulk_read(h, data, xfer);        D("[ usb read %d ] = %d, fname=%s\n", xfer, n, h->fname);        if(n != xfer) {            if((errno == ETIMEDOUT) && (h->desc != -1)) {                D("[ timeout ]\n");                if(n > 0){                    data += n;                    len -= n;                }                continue;            }            D("ERROR: n = %d, errno = %d (%s)\n",                n, errno, strerror(errno));            return -1;        }        len -= xfer;        data += xfer;    }    D("-- usb_read --\n");    return 0;}void usb_kick(usb_handle *h){    D("[ kicking %p (fd = %d) ]\n", h, h->desc);    adb_mutex_lock(&h->lock);    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);        }        /* 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);    }    adb_mutex_unlock(&h->lock);}int usb_close(usb_handle *h){    D("[ usb close ... ]\n");    adb_mutex_lock(&usb_lock);    h->next->prev = h->prev;    h->prev->next = h->next;    h->prev = 0;    h->next = 0;    adb_close(h->desc);    D("[ usb closed %p (fd = %d) ]\n", h, h->desc);    adb_mutex_unlock(&usb_lock);    free(h);    return 0;}static void register_device(const char *dev_name,                            unsigned char ep_in, unsigned char ep_out,                            int interface,                            const char *serial, unsigned zero_mask){    usb_handle* usb = 0;    int n = 0;        /* 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        ** once we open it and remove from the list when we're finally        ** closed and everything will work out fine.        **        ** If we have a usb_handle on the list 'o handles with a matching        ** name, we have no further work to do.        */    adb_mutex_lock(&usb_lock);    for(usb = handle_list.next; usb != &handle_list; usb = usb->next){        if(!strcmp(usb->fname, dev_name)) {            adb_mutex_unlock(&usb_lock);            return;        }    }    adb_mutex_unlock(&usb_lock);    D("[ usb located new device %s (%d/%d/%d) ]\n",        dev_name, ep_in, ep_out, interface);    usb = calloc(1, sizeof(usb_handle));    strcpy(usb->fname, dev_name);    usb->ep_in = ep_in;    usb->ep_out = ep_out;    usb->zero_mask = zero_mask;    adb_cond_init(&usb->notify, 0);    adb_mutex_init(&usb->lock, 0);    /* initialize mark to 1 so we don't get garbage collected after the device scan */    usb->mark = 1;    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;        /* add to the end of the active handles */    adb_mutex_lock(&usb_lock);    usb->next = &handle_list;    usb->prev = handle_list.prev;    usb->prev->next = usb;    usb->next->prev = usb;    adb_mutex_unlock(&usb_lock);    register_usb_transport(usb, serial);    return;fail:    D("[ usb open %s error=%d, err_str = %s]\n",        usb->fname,  errno, strerror(errno));    if(usb->desc >= 0) {        adb_close(usb->desc);    }    free(usb);}void* device_poll_thread(void* unused){    D("Created device thread\n");    for(;;) {            /* XXX use inotify */        find_usb_device("/dev/bus/usb", register_device);        kick_disconnected_devices();        sleep(1);    }    return NULL;}static void sigalrm_handler(int signo){    // don't need to do anything here}void usb_init(){    adb_thread_t tid;    struct sigaction    actions;    memset(&actions, 0, sizeof(actions));    sigemptyset(&actions.sa_mask);    actions.sa_flags = 0;    actions.sa_handler = sigalrm_handler;    sigaction(SIGALRM,& actions, NULL);    if(adb_thread_create(&tid, device_poll_thread, NULL)){        fatal_errno("cannot create input thread");    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?