⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 u132-hcd.c

📁 host usb 主设备程序 支持sd卡 mouse keyboard 的最单单的驱动程序 gcc编译
💻 C
📖 第 1 页 / 共 5 页
字号:
static void u132_ring_queue_work(struct u132 *u132, struct u132_ring *ring,        unsigned int delta){        kref_get(&u132->kref);        u132_ring_requeue_work(u132, ring, delta);        return;}static void u132_ring_cancel_work(struct u132 *u132, struct u132_ring *ring){        if (cancel_delayed_work(&ring->scheduler)) {                kref_put(&u132->kref, u132_hcd_delete);        }}static void u132_endp_delete(struct kref *kref){        struct u132_endp *endp = kref_to_u132_endp(kref);        struct u132 *u132 = endp->u132;        u8 usb_addr = endp->usb_addr;        u8 usb_endp = endp->usb_endp;        u8 address = u132->addr[usb_addr].address;        struct u132_udev *udev = &u132->udev[address];        u8 endp_number = endp->endp_number;        struct usb_host_endpoint *hep = endp->hep;        struct u132_ring *ring = endp->ring;        struct list_head *head = &endp->endp_ring;        ring->length -= 1;        if (endp == ring->curr_endp) {                if (list_empty(head)) {                        ring->curr_endp = NULL;                        list_del(head);                } else {                        struct u132_endp *next_endp = list_entry(head->next,                                struct u132_endp, endp_ring);                        ring->curr_endp = next_endp;                        list_del(head);        }} else                list_del(head);        if (endp->input) {                udev->endp_number_in[usb_endp] = 0;                u132_udev_put_kref(u132, udev);        }        if (endp->output) {                udev->endp_number_out[usb_endp] = 0;                u132_udev_put_kref(u132, udev);        }        u132->endp[endp_number - 1] = NULL;        hep->hcpriv = NULL;        kfree(endp);        u132_u132_put_kref(u132);}static inline void u132_endp_put_kref(struct u132 *u132, struct u132_endp *endp){        kref_put(&endp->kref, u132_endp_delete);}static inline void u132_endp_get_kref(struct u132 *u132, struct u132_endp *endp){        kref_get(&endp->kref);}static inline void u132_endp_init_kref(struct u132 *u132,        struct u132_endp *endp){        kref_init(&endp->kref);        kref_get(&u132->kref);}static void u132_endp_queue_work(struct u132 *u132, struct u132_endp *endp,        unsigned int delta){	if (queue_delayed_work(workqueue, &endp->scheduler, delta))		kref_get(&endp->kref);}static void u132_endp_cancel_work(struct u132 *u132, struct u132_endp *endp){        if (cancel_delayed_work(&endp->scheduler))                kref_put(&endp->kref, u132_endp_delete);}static inline void u132_monitor_put_kref(struct u132 *u132){        kref_put(&u132->kref, u132_hcd_delete);}static void u132_monitor_queue_work(struct u132 *u132, unsigned int delta){	if (queue_delayed_work(workqueue, &u132->monitor, delta))		kref_get(&u132->kref);}static void u132_monitor_requeue_work(struct u132 *u132, unsigned int delta){	if (!queue_delayed_work(workqueue, &u132->monitor, delta))		kref_put(&u132->kref, u132_hcd_delete);}static void u132_monitor_cancel_work(struct u132 *u132){        if (cancel_delayed_work(&u132->monitor))                kref_put(&u132->kref, u132_hcd_delete);}static int read_roothub_info(struct u132 *u132){        u32 revision;        int retval;        retval = u132_read_pcimem(u132, revision, &revision);        if (retval) {                dev_err(&u132->platform_dev->dev, "error %d accessing device co"                        "ntrol\n", retval);                return retval;        } else if ((revision & 0xFF) == 0x10) {        } else if ((revision & 0xFF) == 0x11) {        } else {                dev_err(&u132->platform_dev->dev, "device revision is not valid"                        " %08X\n", revision);                return -ENODEV;        }        retval = u132_read_pcimem(u132, control, &u132->hc_control);        if (retval) {                dev_err(&u132->platform_dev->dev, "error %d accessing device co"                        "ntrol\n", retval);                return retval;        }        retval = u132_read_pcimem(u132, roothub.status,                &u132->hc_roothub_status);        if (retval) {                dev_err(&u132->platform_dev->dev, "error %d accessing device re"                        "g roothub.status\n", retval);                return retval;        }        retval = u132_read_pcimem(u132, roothub.a, &u132->hc_roothub_a);        if (retval) {                dev_err(&u132->platform_dev->dev, "error %d accessing device re"                        "g roothub.a\n", retval);                return retval;        }        {                int I = u132->num_ports;                int i = 0;                while (I-- > 0) {                        retval = u132_read_pcimem(u132, roothub.portstatus[i],                                &u132->hc_roothub_portstatus[i]);                        if (retval) {                                dev_err(&u132->platform_dev->dev, "error %d acc"                                        "essing device roothub.portstatus[%d]\n"                                        , retval, i);                                return retval;                        } else                                i += 1;                }        }        return 0;}static void u132_hcd_monitor_work(struct work_struct *work){        struct u132 *u132 = container_of(work, struct u132, monitor.work);        if (u132->going > 1) {                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"                        , u132->going);                u132_monitor_put_kref(u132);                return;        } else if (u132->going > 0) {                dev_err(&u132->platform_dev->dev, "device is being removed\n");                u132_monitor_put_kref(u132);                return;        } else {                int retval;                down(&u132->sw_lock);                retval = read_roothub_info(u132);                if (retval) {                        struct usb_hcd *hcd = u132_to_hcd(u132);                        u132_disable(u132);                        u132->going = 1;                        up(&u132->sw_lock);                        usb_hc_died(hcd);                        ftdi_elan_gone_away(u132->platform_dev);                        u132_monitor_put_kref(u132);                        return;                } else {                        u132_monitor_requeue_work(u132, 500);                        up(&u132->sw_lock);                        return;                }        }}static void u132_hcd_giveback_urb(struct u132 *u132, struct u132_endp *endp,        struct urb *urb, int status){        struct u132_ring *ring;        unsigned long irqs;        struct usb_hcd *hcd = u132_to_hcd(u132);        urb->error_count = 0;        urb->status = status;        urb->hcpriv = NULL;        spin_lock_irqsave(&endp->queue_lock.slock, irqs);        endp->queue_next += 1;        if (ENDP_QUEUE_SIZE > --endp->queue_size) {                endp->active = 0;                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);        } else {                struct list_head *next = endp->urb_more.next;                struct u132_urbq *urbq = list_entry(next, struct u132_urbq,                        urb_more);                list_del(next);                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =                        urbq->urb;                endp->active = 0;                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);                kfree(urbq);        } down(&u132->scheduler_lock);        ring = endp->ring;        ring->in_use = 0;        u132_ring_cancel_work(u132, ring);        u132_ring_queue_work(u132, ring, 0);        up(&u132->scheduler_lock);        u132_endp_put_kref(u132, endp);        usb_hcd_giveback_urb(hcd, urb);        return;}static void u132_hcd_forget_urb(struct u132 *u132, struct u132_endp *endp,        struct urb *urb, int status){        u132_endp_put_kref(u132, endp);}static void u132_hcd_abandon_urb(struct u132 *u132, struct u132_endp *endp,        struct urb *urb, int status){        unsigned long irqs;        struct usb_hcd *hcd = u132_to_hcd(u132);        urb->error_count = 0;        urb->status = status;        urb->hcpriv = NULL;        spin_lock_irqsave(&endp->queue_lock.slock, irqs);        endp->queue_next += 1;        if (ENDP_QUEUE_SIZE > --endp->queue_size) {                endp->active = 0;                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);        } else {                struct list_head *next = endp->urb_more.next;                struct u132_urbq *urbq = list_entry(next, struct u132_urbq,                        urb_more);                list_del(next);                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =                        urbq->urb;                endp->active = 0;                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);                kfree(urbq);        } usb_hcd_giveback_urb(hcd, urb);        return;}static inline int edset_input(struct u132 *u132, struct u132_ring *ring,        struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,        int toggle_bits, int error_count, int condition_code, int repeat_number,         int halted, int skipped, int actual, int non_null)){        return usb_ftdi_elan_edset_input(u132->platform_dev, ring->number, endp,                 urb, address, endp->usb_endp, toggle_bits, callback);}static inline int edset_setup(struct u132 *u132, struct u132_ring *ring,        struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,        int toggle_bits, int error_count, int condition_code, int repeat_number,         int halted, int skipped, int actual, int non_null)){        return usb_ftdi_elan_edset_setup(u132->platform_dev, ring->number, endp,                 urb, address, endp->usb_endp, toggle_bits, callback);}static inline int edset_single(struct u132 *u132, struct u132_ring *ring,        struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,        int toggle_bits, int error_count, int condition_code, int repeat_number,         int halted, int skipped, int actual, int non_null)){        return usb_ftdi_elan_edset_single(u132->platform_dev, ring->number,                endp, urb, address, endp->usb_endp, toggle_bits, callback);}static inline int edset_output(struct u132 *u132, struct u132_ring *ring,        struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,        int toggle_bits, int error_count, int condition_code, int repeat_number,         int halted, int skipped, int actual, int non_null)){        return usb_ftdi_elan_edset_output(u132->platform_dev, ring->number,                endp, urb, address, endp->usb_endp, toggle_bits, callback);}/** must not LOCK sw_lock**/static void u132_hcd_interrupt_recv(void *data, struct urb *urb, u8 *buf,        int len, int toggle_bits, int error_count, int condition_code,        int repeat_number, int halted, int skipped, int actual, int non_null){        struct u132_endp *endp = data;        struct u132 *u132 = endp->u132;        u8 address = u132->addr[endp->usb_addr].address;        struct u132_udev *udev = &u132->udev[address];        down(&u132->scheduler_lock);        if (u132->going > 1) {                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"                        , u132->going);                up(&u132->scheduler_lock);

⌨️ 快捷键说明

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