linux設(shè)備驅(qū)動(dòng)歸納總結(jié)(八):4.總線熱插拔
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
上一節(jié)介紹設(shè)備管理中的分層思想和面向?qū)ο笏枷耄质俏易约合咕幍模。接下來說一下熱插拔的操作。
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
一、熱插拔的實(shí)現(xiàn)
我不知道在這里用熱插拔這樣的名字是否合適,在之前的代碼,需要我自己手動(dòng)去加載驅(qū)動(dòng)和設(shè)備的模塊,但在現(xiàn)實(shí)的情況下,一般是當(dāng)設(shè)備一被插入,系統(tǒng)自己會(huì)注冊(cè)設(shè)備,并調(diào)用合適的驅(qū)動(dòng)。
所以,接下來我要實(shí)現(xiàn)的是,在加載了usb總線和usb鼠標(biāo)驅(qū)動(dòng)的前提下,當(dāng)有usb鼠標(biāo)插入,系統(tǒng)自己進(jìn)行設(shè)備的操作。當(dāng)然,上面的usb鼠標(biāo)是我自己想象出來的,當(dāng)我一按下按鍵(對(duì)應(yīng)中斷E_INT1),就代表有usb鼠標(biāo)插入。
這樣看來,要實(shí)現(xiàn)的代碼就簡(jiǎn)單,稍稍修改一下程序就可以了,將之前由devie.ko實(shí)現(xiàn)的操作交由中斷處理函數(shù)來執(zhí)行,當(dāng)我按下按鍵,觸發(fā)中斷自動(dòng)執(zhí)行。
driver.c不用修改,并且把device.c刪掉,將代碼移到bus.c中:
/*8th_devModule_4/1st/bus.c*/
9 struct work_struct my_work;
。。。。。
56 /**************
57 * 設(shè)備注冊(cè)
58 *************/
59 void usb_dev_release(struct
device *dev) //卸載函數(shù)沒有干具體的事情
60 {
61 printk("<kernel>
release\n");
62 }
63
/*結(jié)構(gòu)體中不需要指定總線的成員,交由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);
//調(diào)度到中斷下半部執(zhí)行
75 return IRQ_HANDLED;
76 }
77 void work_func(struct
work_struct *work)//中斷下半部處理函數(shù)
78 {
79 /*假設(shè)從硬件讀取廠商編號(hào)和設(shè)備編號(hào)*/
80 mouse_dev.VendorID =
0x1122;
81 mouse_dev.DeviceID =
0x3344;
82 /*在中斷函數(shù)中注冊(cè)設(shè)備*/
83
usb_device_register(&mouse_dev);
84 }
85
86 static int __init
usb_bus_init(void)
87 {
88 int ret;
89 /*初始化中斷下文struct
work_struct為工作隊(duì)列類型*/
90
INIT_WORK(&my_work, work_func);
91 /*設(shè)置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 /*總線注冊(cè),必須檢測(cè)返回值*/
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 }
上面的代碼可以看到,函數(shù)將原來在device.c中實(shí)現(xiàn)的操作放在了中斷函數(shù)來執(zhí)行,一旦usb鼠標(biāo)被插入(這里是我假設(shè)的,其實(shí)就是按下按鍵,觸發(fā)E_INT1中斷),就會(huì)執(zhí)行注冊(cè)設(shè)備的操作。
看效果:
[root: 1st]# insmod bus.ko
//先加載總線
usb bus init
[root: 1st]# insmod driver.ko
//再加載驅(qū)動(dòng)
usb driver init
[root: 1st]# usb mouse device
insert
//當(dāng)我按下按鍵,觸發(fā)中斷,假設(shè)鼠標(biāo)被插入
match success
//配對(duì)成功
init usb mouse
//初始化設(shè)備
當(dāng)然,我的函數(shù)很多的bug,譬如你再次按下按鍵,那就會(huì)出現(xiàn)錯(cuò)誤。但撇來這些不考慮,基本效果就出來了,當(dāng)設(shè)備一插入,內(nèi)核自動(dòng)注冊(cè)設(shè)備。
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
二、總結(jié)
第八章的設(shè)備模型基本上就介紹完了,我在這里沒有介紹kobject、kset等這一類內(nèi)核中用于管理設(shè)備模型的結(jié)構(gòu)體,有興趣可以自己去看看。 接著就會(huì)介紹平臺(tái)類總線設(shè)備,到時(shí)候你會(huì)發(fā)現(xiàn),平臺(tái)類總線設(shè)備其實(shí)就是總線的一個(gè)封裝。
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
源代碼: 8th_devModule_4.rar
|