1. 程式人生 > >USB裝置插拔檢測

USB裝置插拔檢測

1)hub初始化時

hub_wq = alloc_workqueue(“usb_hub_wq”, WQ_FREEZABLE, 0);
INIT_WORK(&hub->events, hub_event)
queue_work(hub_wq, &hub->events)

–alloc_workqueue(“usb_hub_wq”, WQ_FREEZABLE, 0)
此函式在usb_hub_init中分配佇列,替代了以前的thrread_run的功能


```int usb_hub_init(void)
{
        if (usb_register(&hub_driver) < 0) {
...
        }
/*  The workqueue needs to be freezable to avoid interfering with USB-PERSIST port handover. 
Otherwise it might see that a full-speed device was gone before the EHCI controller had handed 
its port over to the companion full-speed controller.
*/
        hub_wq = alloc_workqueue("usb_hub_wq", WQ_FREEZABLE, 0);
...
        usb_deregister(&hub_driver);
}

–queue_work(hub_wq, &hub->events)
函式在kick_hub_wq中呼叫,以便hub_wq函式的呼叫

static void kick_hub_wq(struct usb_hub *hub)
{
        struct usb_interface *intf;

printk("%s function enter\n", __func__);
        if (hub->disconnected || work_pending(&hub->events))
                return;

        /*
         * Suppress autosuspend until the event is proceed.
         *
         * Be careful and make sure that the symmetric operation is
         * always called. We are here only when there is no pending
         * work for this hub. Therefore put the interface either when
         * the new work is called or when it is canceled.
         */
        intf = to_usb_interface(hub->intfdev);
        usb_autopm_get_interface_no_resume(intf);
        kref_get(&hub->kref);

        if (queue_work(hub_wq, &hub->events))
                return;

        /* the work has already been scheduled */
        usb_autopm_put_interface_async(intf);
        kref_put(&hub->kref, hub_release);
}