linux設備驅動歸納總結(八):4.總線熱插拔

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

上一節介紹設備管理中的分層思想和麪向對象思想(名字是我自己瞎編的)。接下來說一下熱插拔的操作。

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


一、熱插拔的實現


我不知道在這裏用熱插拔這樣的名字是否合適,在之前的代碼,需要我自己手動去加載驅動和設備的模塊,但在現實的情況下,一般是當設備一被插入,系統自己會註冊設備,並調用合適的驅動。

所以,接下來我要實現的是,在加載了usb總線和usb鼠標驅動的前提下,當有usb鼠標插入,系統自己進行設備的操作。當然,上面的usb鼠標是我自己想象出來的,當我一按下按鍵(對應中斷E_INT1),就代表有usb鼠標插入。

這樣看來,要實現的代碼就簡單,稍稍修改一下程序就可以了,將之前由devie.ko實現的操作交由中斷處理函數來執行,當我按下按鍵,觸發中斷自動執行


driver.c不用修改,並且把device.c刪掉,將代碼移到bus.c中:

/*8th_devModule_4/1st/bus.c*/

9 struct work_struct my_work;

。。。。。

56 /**************

57 * 設備註冊

58 *************/

59 void usb_dev_release(struct device *dev) //卸載函數沒有幹具體的事情

60 {

61     printk("<kernel> release\n");

62 }

63 /*結構體中不需要指定總線的成員,交由usb_device_register來完成*/

64 struct usb_device mouse_dev = {

65     .dev = {

66         .bus_id = "usb_mouse",

67         .release = usb_dev_release,

68     },

69 };

70

71 irqreturn_t hotplug_handler(int irqno, void *dev_id)

72 {

73     printk("usb mouse device insert\n");

74     schedule_work(&my_work); //調度到中斷下半部執行

75     return IRQ_HANDLED;

76 }

77 void work_func(struct work_struct *work)//中斷下半部處理函數

78 {

79     /*假設從硬件讀取廠商編號和設備編號*/

80     mouse_dev.VendorID = 0x1122;

81     mouse_dev.DeviceID = 0x3344;

82     /*在中斷函數中註冊設備*/

83     usb_device_register(&mouse_dev);

84 }

85

86 static int __init usb_bus_init(void)

87 {

88     int ret;

89     /*初始化中斷下文struct work_struct爲工作隊列類型*/

90     INIT_WORK(&my_work, work_func); 

91     /*設置IRQ_EINT1的中斷*/

92     ret = request_irq(IRQ_EINT1, hotplug_handler, IRQF_TRIGGER_FALLING, "usb irq", NULL);

93     if(ret){

94         printk("irq failed\n");

95         return ret;

96     }

97

98       /*總線註冊,必須檢測返回值*/

99       ret = bus_register(&usb_bus);

100     if(ret){

101         printk("bus register failed!\n");

102         return ret;

103     }

104

105     printk("usb bus init\n");

106     return 0;

107 }

108

109 static void __exit usb_bus_exit(void)

110 {

111     bus_unregister(&usb_bus);

112     free_irq(IRQ_EINT1, NULL); //釋放IRQ_EINT1的中斷源

113     printk("usb bus bye!\n");

114 }

上面的代碼可以看到,函數將原來在device.c中實現的操作放在了中斷函數來執行,一旦usb鼠標被插入(這裏是我假設的,其實就是按下按鍵,觸發E_INT1中斷),就會執行註冊設備的操作。

看效果:

[root: 1st]# insmod bus.ko //先加載總線

usb bus init

[root: 1st]# insmod driver.ko //再加載驅動

usb driver init

[root: 1st]# usb mouse device insert //當我按下按鍵,觸發中斷,假設鼠標被插入

match success //配對成功

init usb mouse //初始化設備

當然,我的函數很多的bug,譬如你再次按下按鍵,那就會出現錯誤。但撇來這些不考慮,基本效果就出來了,當設備一插入,內核自動註冊設備。


xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


二、總結

第八章的設備模型基本上就介紹完了,我在這裏沒有介紹kobject、kset等這一類內核中用於管理設備模型的結構體,有興趣可以自己去看看。

接着就會介紹平臺類總線設備,到時候你會發現,平臺類總線設備其實就是總線的一個封裝。

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章