一.等待
static struct usb_driver hub_driver = ;
int usb_hub_init(void)
khubd_task = kthread_run(hub_thread, null, "khubd");
if (!is_err(khubd_task))
return 0;
/* fall through if kernel_thread failed */
usb_deregister(&hub_driver);
printk(kern_err "%s: can't start khubd\n", usbcore_name);
return -1;
}static int hub_thread(void *__unused)
while (!kthread_should_stop() || !list_empty(&hub_event_list));
pr_debug("%s: khubd exiting\n", usbcore_name);
return 0;
}在hub_thread執行時,會進入hub_events,但是這時候hub_event_list隊列為空,於是hub_events退出並wait
二.喚醒
當主控制器初始化時,會初始化root hub,之後呼叫:
static int hub_probe(struct usb_inte***ce *intf, const struct usb_device_id *id)
hub_probe()所做的工作:
1.為此root hub申請struct usb_hub結構體並初始化它
2.填充並提交中斷in端點(由hub_activate完成)
usb_fill_int_urb(hub->urb, hdev, pipe, *hub->buffer, maxp, hub_irq,
hub, endpoint->binterval);
usb_submit_urb(hub->urb, gfp_noio);
3.呼叫kick_khubd(hub)
static void kick_khubd(struct usb_hub *hub)
spin_unlock_irqrestore(&hub_event_lock, flags);
}由於這個時候root hub已經成功初始化了,所以kick_khubd會將root hub的event_list,新增到
hub_event_list,表示root hub已經被識別了,同時wake_up(&khubd_wait)會喚醒上面的等待,
於是hub_events()又一次執行了,但是這次,它是有備而來,因為hub_event_list不為空
三.hub_events
hub_events函式所做的工作:
對每個埠號(共計bnbrports個埠,bnbrports這個值從hub描述符裡邊得到,因為此值描述了hub所用用的埠的情況),假如滿足下列條件則呼叫hub_port_connect_change()
1.連線有變化
2.埠本身重新使能,即所謂的enable,這種情況通常就是為了對付電磁干擾的,正如我們前面的判斷中所說的那樣
3.在復位乙個裝置的時候發現其描述符變了,這通常對應的是硬體本身有了公升級.很顯然,第一種情況是真正的物理變化,後兩者就算是邏輯變化
**模型如下:
for (i = 1; i <= hub->descriptor->bnbrports; i++) {
...if (connect_change)
//對root hub上活躍的port呼叫hub_port_connect_change
hub_port_connect_change(hub, i,
portstatus, portchange);
...
}hub_port_connect_change()所做的工作:
1.udev = usb_alloc_dev(hdev, hdev_bus, port1);
原型:struct usb_device *usb_alloc_dev(struct usb_device *parent,
struct usb_bus *bus, unsigned port1)
為探測到的usb裝置(包括普通hub,u盤等)分配並初始化udev;
2.status = hub_port_init(hub, udev, port1, i);
先進行兩次新的策略(i=0和=1時),如果不行就再進行兩次舊的策略(i=2和i=3時).所有這一切只有乙個目的,就是為了獲得裝置的描述符,設定了udev->tt、udev->ttport和udev->ep0.desc.wmaxpacketsize,設定udev->status=
usb_state_address
3.usb_new_device(udev);
(1)usb_configure_device(udev)->
usb_get_configuration(udev);
a.usb_get_descriptor()
//得到裝置的描述符(包括裝置描述符、配置描述符、介面描述符等)
b.usb_parse_configuration()
//分析以上描述符資訊,提取出配置、介面等,並賦值給udev結構裡相應的字段
(2)device_add(&udev->dev);
將usb裝置註冊到系統裡,這個動作將觸發驅動的匹配,由於這是個usb裝置,所以萬能usb驅動usb_generic_driver會匹配上,
從而generic_probe會得到執行.關於 generic_probe所做的工作,請參考:
從上面可以看出來,這一次hub_events()呼叫是由於主控制器初始化呼叫了hub_probe,從而引發hub_events呼叫。那root hub初始化完成以後hub_events會如何觸發呢?
答案是通過中斷!而這個中斷的服務函式就是hub_irq,也即是說,凡是真正的有埠變化事件發生,hub_irq就會被呼叫,而hub_irq()最終會呼叫kick_khubd(),觸發hub的event_list,於是再次呼叫hub_events().
那hub_irq是什麼時候註冊的呢?
前面我們講到:
hub_probe()所做的第二項工作是:填充並提交中斷in端點(由hub_activate完成)
usb_fill_int_urb(hub->urb, hdev, pipe, *hub->buffer, maxp, hub_irq,
hub, endpoint->binterval);
usb_submit_urb(hub->urb, gfp_noio);
hub_irq作為引數傳給了usb_fill_int_urb,這樣設定以後,只要root hub的埠有變化,hub_irq就會執行到 0
給主人留下些什麼吧!~~
MFC檢測USB熱插拔
在網上找了很久,發現這個方法還是可以實現的,但是必須要知道usb裝置的guid,我準備寫下來留作以便以後查詢 bool cxxdlg ondevicechange uint neventtype,dword dwdata break case dbt devicearrival break defa...
linux下實現USB口的熱插拔
目前要做乙個在嵌入式平台上的usb口的熱插拔事件。經過我現在的分析總結目前有如下方法 1,定時檢查 proc scsi scsi檔案 此方法只能在pc上,但在嵌入式平台上不可用。2,netlink方式 使用netlink.include include include include include...
JAVA SPI機制 實現功能的熱插拔
開發中經常遇到的乙個需求是,處理不同種類的資料,但是完成的功能是相似的,功能隨著傳入型別的不同而變化 1 定義介面 定義乙個介面,編寫不同的實現類 1 使用場景 完成功能相同,引數也類似,只是內部的實現邏輯不同,可以編寫介面實現的配置類,使用時動態獲取實現類 2 缺點 資料的型別必須確定 3 舉例 ...