日本a√视频在线,久久青青亚洲国产,亚洲一区欧美二区,免费g片在线观看网站

        <style id="k3y6c"><u id="k3y6c"></u></style>
        <s id="k3y6c"></s>
        <mark id="k3y6c"></mark>
          
          

          <mark id="k3y6c"></mark>

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 一個(gè)相當(dāng)詳細(xì)的MINI2440按鍵驅(qū)動(dòng)詳解

          一個(gè)相當(dāng)詳細(xì)的MINI2440按鍵驅(qū)動(dòng)詳解

          作者: 時(shí)間:2016-11-11 來(lái)源:網(wǎng)絡(luò) 收藏
          /*mini2440_buttons_my.c*/

          /*后面加了_my*/

          本文引用地址:http://yuyingmama.com.cn/article/201611/316663.htm

          /*按鍵驅(qū)動(dòng)程序*/

          /*mini2440所用到的按鍵資源*/
          /**************************************************/
          /* 按鍵 對(duì)應(yīng)的IO寄存器 對(duì)應(yīng)的中斷引腳*/
          /* K1 GPG0 EINT8 */
          /* K2 GPG3 EINT11 */
          /* K3 GPG5 EINT13 */
          /* K4 GPG6 EINT14 */
          /* K5 GPG7 EINT15 */
          /* K6 GPG11 EINT19 */
          /**************************************************/

          /*要搞清楚誰(shuí)是輸入*/
          /*在這里,按鍵控制對(duì)應(yīng)的中斷引腳,從而控制對(duì)應(yīng)的IO寄存器*/
          /*相當(dāng)于信息從外面輸入*/
          /*我們要做的是根據(jù)對(duì)應(yīng)的輸入信息,來(lái)采取相應(yīng)的響應(yīng)動(dòng)作*/
          /*這就達(dá)到了中斷響應(yīng)的目的*/
          /*其核心就是要檢測(cè)*/
          /*那么,該如何去檢測(cè)呢?*/
          /*通過(guò)什么來(lái)檢測(cè)呢?*/

          /*如何得知一個(gè)設(shè)備究竟用到哪些資源呢?*/
          /*這是個(gè)非常重要的問(wèn)題*/
          /*我想應(yīng)該看具體的電路原理圖*/
          /*只有看圖,才能了解具體的電路連接情況*/
          /*從而得知設(shè)備所需的硬件資源*/
          /*廠商的原理圖通常給的都比較詳細(xì)*/

          /*引用的頭文件*/

          #include /*模塊有關(guān)的*/

          #include /*內(nèi)核有關(guān)的*/

          #include /*文件系統(tǒng)有關(guān)的*/

          #include /*init*/

          #include /*delay*/

          #include /*poll*/

          #include /*中斷*/

          #include interrupt.h> /*linux中斷*/

          #include /*uaccess*/

          #include /*寄存器設(shè)置*/

          #include /*hardware*/

          /*定義宏*/

          #define BUTTON_MAJOR 221 /*主設(shè)備號(hào),本來(lái)是232,我改為221*/

          #define DEVICE_NAME "buttons_my" /*設(shè)備名,本來(lái)是buttons,我加上了_my*/

          /*定義按鈕中斷的描述結(jié)構(gòu)體*/
          /*由它把按鈕中斷的信息綜合起來(lái)*/
          /*各個(gè)成員表示什么意思?*/

          struct button_irq_desc
          {
          int irq; /*中斷號(hào)*/
          /*中斷號(hào)唯一表示一個(gè)中斷*/

          int pin; /*中斷控制的寄存器*/
          /*該寄存器的值由中斷引腳設(shè)置*/
          /*我們希望從該寄存器讀出控制信息*/

          int pin_setting; /*中斷的引腳*/
          /*該引腳的電平由按鍵來(lái)控制*/
          /*從而最終我們由按鍵控制了寄存器的值*/

          int number; /*編號(hào)*/
          char *name; /*名稱*/
          };

          /*指定6個(gè)按鍵的信息*/

          static struct button_irq_desc button_irqs [] =
          {
          {IRQ_EINT8,S3C2410_GPG0,S3C2410_GPG0_EINT8,0,"KEY1"}, /*K1*/
          {IRQ_EINT11,S3C2410_GPG3,S3C2410_GPG3_EINT11,1,"KEY2"}, /*K2*/
          {IRQ_EINT13,S3C2410_GPG5,S3C2410_GPG5_EINT13,2,"KEY3"}, /*K3*/
          {IRQ_EINT14,S3C2410_GPG6,S3C2410_GPG6_EINT14,3,"KEY4"}, /*K4*/
          {IRQ_EINT15,S3C2410_GPG7,S3C2410_GPG7_EINT15,4,"KEY5"}, /*K5*/
          {IRQ_EINT19,S3C2410_GPG11,S3C2410_GPG11_EINT19,5,"KEY6"}, /*K6*/
          }

          /*這樣,資源就組織起來(lái)了*/
          /*事實(shí)上,在這里我們不僅組織起了硬件資源*/
          /*我們也把一定的軟件資源也糅合進(jìn)去了*/
          /*像中斷號(hào)*/


          /*key_values數(shù)組*/
          /*存放各個(gè)按鍵在發(fā)生中斷情況下的值*/
          /*volatile是什么意思呢?*/
          /*這個(gè)數(shù)組是我們存放按鍵操作結(jié)果的,因此非常重要*/

          static volatile int key_values [] = {0,0,0,0,0,0};


          /*宏DECLARE_WAIT_QUEUE_HEAD(),是干什么的呢?*/
          /*該宏應(yīng)該是創(chuàng)建了一個(gè)等待隊(duì)列*/
          /*等待隊(duì)列,是進(jìn)程調(diào)度的一種重要方法*/
          /*等待隊(duì)列也很有意思,button_waitq,表示按鍵等待的隊(duì)列*/
          /*就是說(shuō),按鍵一按下,就會(huì)激活其等待隊(duì)列里的進(jìn)程,來(lái)做相應(yīng)的處理*/
          /*因此,按鍵的等待隊(duì)列,或者說(shuō)中斷所設(shè)置的等待隊(duì)列,*/
          /*是中斷處理中非常重要的資源,它大大擴(kuò)展了中斷處理的能力*/


          static DECLARE_WAIT_QUEUE_HEAD(button_waitq); /*button_waitq是什么呢?*/
          /*應(yīng)該是等待隊(duì)列的名稱*/


          /*key_values數(shù)組中是否有數(shù)據(jù)的標(biāo)志,0表示無(wú)數(shù)據(jù)可讀,1表示有數(shù)據(jù)可讀*/

          static volatile int ev_press = 0; /*初始為0*/

          /*中斷服務(wù)程序buttons_interrupt()的申明*/
          /*即當(dāng)檢測(cè)到有中斷時(shí),就會(huì)執(zhí)行該中斷服務(wù)程序*/
          /*那么如何檢測(cè)到有中斷發(fā)生呢?*/
          /*并且中斷發(fā)生了,知道發(fā)生了什么樣的中斷呢?*/
          /*中斷有很多種,該中斷服務(wù)程序究竟該服務(wù)于哪一個(gè)中斷呢?*/
          /*顯然,要把中斷號(hào)與中斷服務(wù)程序聯(lián)結(jié)起來(lái),構(gòu)成一個(gè)整體*/
          /*這個(gè)工作可以在open函數(shù)里做*/

          /*參數(shù)irq---中斷號(hào)*/
          /*中斷服務(wù)程序應(yīng)該是與中斷號(hào)一一對(duì)應(yīng)的*/
          /*對(duì)應(yīng)于某個(gè)中斷號(hào)的中斷一發(fā)生,就會(huì)調(diào)用該中斷號(hào)對(duì)應(yīng)的服務(wù)程序*/
          /*那么,檢測(cè)中斷的發(fā)生,就成了先決條件*/
          /*參數(shù)dev_id ---具體是哪一個(gè)按鈕*/

          static irqreturn_t buttons_interrupt(int irq,void *dev_id);

          /*mini2440_buttons_open()函數(shù)申明*/
          /*驅(qū)動(dòng)函數(shù)open調(diào)用的具體函數(shù)*/
          /*由open函數(shù)具體實(shí)現(xiàn)硬件的初始化工作*/
          /*以及軟件的初始化工作*/
          /*為我們的鍵盤(pán)設(shè)備的運(yùn)行創(chuàng)造好環(huán)境*/

          static int mini2440_buttons_open(struct inode *inode,struct file *file);

          /*mini2440_buttons_close()函數(shù)的申明*/
          /*release調(diào)用的具體函數(shù)*/
          /*設(shè)備軟件環(huán)境的拆卸*/
          /*具體就是中斷的釋放工作*/
          /*因?yàn)橹袛噘Y源,也是系統(tǒng)寶貴的資源,所以不用的時(shí)候,要釋放*/

          static int mini2440_buttons_close(struct inode *inode,struct file *file);

          /*mini2440_buttons_read()函數(shù)的申明*/
          /*read調(diào)用的具體函數(shù)*/
          /*由它讀取鍵盤(pán)輸入的結(jié)果*/
          /*實(shí)質(zhì)上就是讀取key_values數(shù)組的值*/
          /*它完成了鍵盤(pán)作為輸入設(shè)備的核心功能*/
          /*數(shù)組是否可讀,要根據(jù)標(biāo)志位ev_press來(lái)判斷*/
          /*如果數(shù)組可讀,則讀取數(shù)據(jù)到用戶buffer中*/
          /*如果數(shù)組不可讀,則進(jìn)程進(jìn)入等待隊(duì)列,等待到數(shù)組可讀為止*/
          /*等待隊(duì)列機(jī)制,是中斷管理中常用到的機(jī)制*/
          /*因?yàn)橛行┻M(jìn)程經(jīng)常需要等待某一事件的發(fā)生*/

          static int mini2440_buttons_read(struct file *filp,char __user *buff,size_t count,loff_t *offp);
          /*注意__user,指的是用戶空間*/
          /*即要把鍵盤(pán)的輸入結(jié)果讀取到用戶空間去*/

          /*mini2440_buttons_poll()函數(shù)的申明*/
          /*poll調(diào)用的具體函數(shù)*/
          /*poll實(shí)質(zhì)上是select的調(diào)用函數(shù)*/
          /*如果有按鍵數(shù)據(jù),則select會(huì)立刻返回*/
          /*如果沒(méi)有按鍵數(shù)據(jù),則等待*/
          /*實(shí)質(zhì)上這是鍵盤(pán)等待輸入的機(jī)制*/

          static unsigned int mini2440_buttons_poll(struct file *file,struct poll_table_struct *wait);


          /*file_operations結(jié)構(gòu)體*/
          /*驅(qū)動(dòng)函數(shù)的設(shè)置*/
          /*分別將前面的驅(qū)動(dòng)函數(shù)設(shè)置進(jìn)來(lái)*/

          static struct file_operations mini2440_buttons_fops =
          {
          .owner = THIS_MODULE,

          .open = mini2440_buttons_open, /*open()*/

          .release = mini2440_buttons_close, /*release()*/

          .read = mini2440_buttons_read, /*read()*/

          .poll = mini2440_buttons_poll /*poll()*/
          };

          /*mini2440_buttons_init()函數(shù)的申明*/
          /*module_init調(diào)用的具體函數(shù)*/
          /*模塊創(chuàng)建時(shí)的初始化函數(shù)*/
          /*主要做的工作是注冊(cè)設(shè)備和創(chuàng)建設(shè)備*/
          /*而具體的硬件初始化工作,它可以不做*/
          /*而把它留給fops里的函數(shù)來(lái)做*/

          static int __init mini2440_buttons_init(void);

          /*mini2440_buttons_exit()函數(shù)的申明*/
          /*模塊卸載時(shí)的掃尾工作*/
          /*主要是設(shè)備的卸載工作*/

          static void __exit mini2440_buttons_exit(void);

          /*模塊創(chuàng)建時(shí)的入口點(diǎn)*/

          module_init(mini2440_buttons_init);


          /*模塊卸載時(shí)的入口點(diǎn)*/

          module_exit(mini2440_buttons_exit);

          /*驅(qū)動(dòng)程序的一些信息*/

          MODULE_AUTHOR("http://www.arm9.net"); /*驅(qū)動(dòng)程序的作者*/

          MODULE_DESCRIPTION("S3C2410/S3C2440 BUTTON Driver"); /*描述信息*/

          MODULE_LICENSE("GPL"); /*遵循的協(xié)議*/

          /********************************************************************/
          /*********************下面是前面申明函數(shù)的實(shí)現(xiàn)***********************/
          /********************************************************************/


          /**********************mini2440_buttons_init()***********************/

          static int __init mini2440_buttons_init(void)
          {
          int ret; /*設(shè)備注冊(cè)的返回值*/

          /*注冊(cè)設(shè)備驅(qū)動(dòng)程序*/
          /*設(shè)備號(hào),設(shè)備名,和驅(qū)動(dòng)函數(shù)*/

          ret = register_chrdev(BUTTON_MAJOR,DEVICE_NAME,&mini2440_buttons_fops);

          /*對(duì)注冊(cè)失敗的處理*/

          if(ret < 0)
          {
          printk(DEVICE_NAME " cant register major numbern");
          return ret;
          }

          /*創(chuàng)建設(shè)備*/
          /*devfs_mk_cdev()函數(shù)是內(nèi)核態(tài)的設(shè)備創(chuàng)建函數(shù)*/
          /*而mknod是用戶態(tài)的設(shè)備創(chuàng)建函數(shù)*/

          devfs_mk_cdev(MKDEV(BUTTON_MAJOR,0),S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,DEVICE_NAME);

          printk(DEVICE_NAME " initializedn");

          return 0;
          }


          /******************mini2440_buttons_exit()****************************/

          static void __exit mini2440_buttons_exit(void)
          {
          /*移除設(shè)備*/

          devfs_remove(DEVICE_NAME);

          /*注消設(shè)備驅(qū)動(dòng)*/

          unregister_chrdev(BUTTON_MAJOR,DEVICE_NAME);
          }


          /*****************mini2440_buttons_open()******************************/

          static int mini2440_buttons_open(struct inode *inode,struct file *file)
          {
          int i; /*循環(huán)變量,因?yàn)橛?個(gè)按鈕*/

          int err; /*中斷注冊(cè)函數(shù)的返回值*/

          /*對(duì)每個(gè)按鈕分別處理,用for循環(huán)來(lái)做*/
          /*具體地是要聯(lián)結(jié)寄存器和相應(yīng)的引腳*/
          /*聯(lián)結(jié)中斷號(hào)和相應(yīng)的中斷服務(wù)程序*/
          /*這一步類似于前面所說(shuō)的驅(qū)動(dòng)的注冊(cè)*/
          /*我們可以成功稱作中斷的注冊(cè)*/

          for(i = 0;i < sizeof(button_irqs)/sizeof(button_irqs[0]);i++)
          {
          /*寄存器與中斷引腳的聯(lián)結(jié)*/

          s3c2410_gpio_cfgpin(button_irqs[i].pin,button_irqs[i].pin_setting);

          /*中斷的注冊(cè)*/
          /*request_irq()函數(shù)*/
          /*要注意其輸入?yún)?shù)*/
          /*&button_irqs[i]是該中斷享有的資源*/
          /*會(huì)被傳入buttons_interrupt,進(jìn)行處理*/

          err = request_irq(button_irqs[i].irq,buttons_interrupt,NULL,button_irqs[i].name,(void *)&button_irqs[i]);

          /*中斷類型的設(shè)置*/
          /*set_irq_type()函數(shù)*/
          /*IRQT_BOTHEDGE的中斷類型代表什么樣的中斷呢?*/

          /*有幾個(gè)非常重要的問(wèn)題*/
          /*中斷注冊(cè)后,并設(shè)置好其中斷類型之后,當(dāng)有中斷發(fā)生時(shí),*/
          /*即按下某個(gè)按鈕時(shí),系統(tǒng)能夠自動(dòng)檢測(cè)到有中斷發(fā)生嗎?*/
          /*檢測(cè)到有中斷發(fā)生,它能夠自動(dòng)辨別是幾號(hào)中斷嗎?*/
          /*知道了是幾號(hào)中斷,那么它能自動(dòng)調(diào)用其中斷服務(wù)程序嗎?*/
          /*對(duì)這幾個(gè)問(wèn)題的解答,夠成了linux系統(tǒng)中斷處理機(jī)制的核心*/

          set_irq_type(button_irqs[i].irq,IRQT_BOTHEDGE);

          /*注冊(cè)失敗的處理*/

          if(err)
          break; /*跳出循環(huán)*/
          }

          /*若有一個(gè)按鈕中斷注冊(cè)失敗*/
          /*則還需把前面注冊(cè)成功的中斷給拆了*/

          if(err)
          {
          i--; /*回到前面一個(gè)按鈕的處理*/

          for(;i >=0; i--) /*依此拆除*/
          {
          /*使中斷不起作用*/

          disable_irq(button_irqs[i].irq);

          /*釋放中斷資源*/

          free_irq(button_irqs[i].irq,(void *)&button_irqs[i]);
          }

          return -EBUSY; /*中斷注冊(cè)沒(méi)成功的最終的返回值*/
          }

          return 0; /*正常返回*/
          }


          /**************************buttons_interrupt()*****************************/
          /*此中斷服務(wù)程序,在每中斷一次,就要對(duì)key_values數(shù)組設(shè)一下值*/
          /*并對(duì)數(shù)組可讀標(biāo)志位ev_press設(shè)一下值*/
          /*并喚醒在等待隊(duì)列里的進(jìn)程*/
          /*這是中斷處理經(jīng)常要做的事情*/
          /*在這里,等待隊(duì)列button_waitq里經(jīng)常等待的進(jìn)程是數(shù)組的讀取進(jìn)程*/
          /*就是說(shuō),讀取進(jìn)程在沒(méi)有讀到數(shù)據(jù)的時(shí)候就一直在等待,等待按鍵的輸入*/
          /*讀取進(jìn)程在等待,并不代表所有進(jìn)程在等待,其它進(jìn)程該干啥干啥去*/

          static irqreturn_t buttons_interrupt(int irq,void *dev_id)
          {
          /*button_irq_desc結(jié)構(gòu)體變量*/
          /*對(duì)傳入的資源進(jìn)行處理*/

          struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;

          /*獲取寄存器的值*/
          /*這一步至關(guān)重要*/
          /*s3c2410_gpio_getpin()函數(shù)直接獲取寄存器的值*/

          /*要注意,按一下按鈕,會(huì)發(fā)生兩次中斷*/

          /*即按下是一次中斷,放開(kāi)又是一次中斷*/

          int up = s3c2410_gpio_getpin(button_irqs->pin);

          /*通過(guò)電路原理圖,可以知道沒(méi)按下的時(shí)候,中斷引腳應(yīng)該是高電平*/
          /*從而寄存器的值應(yīng)該是1*/
          /*變量取up也是有意義的,表示默認(rèn)狀態(tài)是彈起的狀態(tài)*/
          /*當(dāng)按下按鈕的狀態(tài)下,寄存器的值就應(yīng)該是0*/

          /*下面對(duì)up的值進(jìn)行處理*/
          /*即是要把數(shù)據(jù)經(jīng)過(guò)一定的變換存入key_values數(shù)組中*/

          if(up) /*如果是彈起的狀態(tài)*/
          /*那么就要在key_values數(shù)組的相應(yīng)位存入很大的一個(gè)值*/
          /*同時(shí)又要能從值里辨別出是哪個(gè)按鍵*/

          key_values[button_irqs->number] = (button_irqs->number + 1) + 0x80;
          /*比如K1鍵開(kāi)啟的狀態(tài)下,key_values[0]被置為(0+1)+0x80,即為129*/

          else /*如果按鍵是閉合的狀態(tài)*/
          /*那么就要在key_values數(shù)組的相應(yīng)位存入一個(gè)很小的數(shù)*/
          /*同時(shí)又要能從值中辨別出是哪個(gè)鍵*/

          key_values[button_irqs->number] = (button_irqs->number + 1);
          /*比如K1鍵閉合,則key_values[0]被置為(0+1),即為1*/

          /*對(duì)數(shù)組可讀標(biāo)志位進(jìn)行設(shè)置*/

          ev_press = 1; /*表示數(shù)組已經(jīng)可讀了*/

          /*喚醒休眠的進(jìn)程?*/
          /*button_waitq隊(duì)列里存放有相應(yīng)的處理進(jìn)程*/
          /*如讀取數(shù)組的值的進(jìn)程*/
          /*要注意wake_up_interruptible()這些函數(shù)的用法*/

          wake_up_interruptible(&button_waitq);

          /*返回*/

          return IRQ_RETVAL(IRQ_HANDLED); /*?*/
          }

          /**********************mini2440_buttons_close()*****************************/

          static int mini2440_buttons_close(struct inode *inode,struct file *file)
          {
          int i; /*循環(huán)變量,要操作好幾個(gè)按鍵*/

          /*for循環(huán),對(duì)各個(gè)按鍵依此釋放中斷*/

          for(i = 0;i < sizeof(button_irqs)/sizeof(button_irqs[0]);i++)
          {
          /*使中斷失效*/

          disable_irq(button_irqs[i].irq);

          /*釋放資源*/

          free_irq(button_irqs[i].irq,(void *)&button_irqs[i]);
          }

          /*返回*/

          return 0;
          }


          /**********************mini2440_buttons_read()***************************/

          /*要注意,該read函數(shù),只讀取一次中斷的值,而不是連續(xù)地讀入*/
          /*要做到連續(xù)地讀入,則需要做一個(gè)循環(huán),不斷地調(diào)用該read函數(shù),但那不是驅(qū)動(dòng)程序里該做的事情*/

          static int mini2440_buttons_read(struct file *filp,char __user *buff,size_t count,loff_t *offp)
          {
          unsigned long err; /*copy_to_user()函數(shù)的返回值*/

          /*如果key_values 數(shù)組里沒(méi)有值,則會(huì)此進(jìn)程會(huì)休眠*/
          /*一直到中斷來(lái)臨之后,中斷服務(wù)程序會(huì)喚醒此休眠進(jìn)程從而繼續(xù)讀取值*/
          /*key_values數(shù)組里有沒(méi)有值,是靠ev_press標(biāo)志位來(lái)判斷的*/
          /*有值,就是1,無(wú)值,就是0*/

          /*進(jìn)程等待隊(duì)列的機(jī)制,是進(jìn)程調(diào)度的一種方法*/

          if(!ev_press) /*標(biāo)志位為0,即無(wú)數(shù)據(jù)時(shí)*/
          {
          if(filp->f_flags & O_NONBLOCK) /*??*/
          return -EAGAIN;
          else /*進(jìn)程休眠,放進(jìn)button_waitq等待隊(duì)列*/
          /*這里,把ev_press標(biāo)志位設(shè)成了休眠進(jìn)程的標(biāo)志位了?*/
          /*這是為了便于利用poll_wait函數(shù)*/
          /*也就是利于select函數(shù)*/
          wait_event_interruptible(button_waitq,ev_press);
          /*在中斷處理函數(shù)中,此進(jìn)程會(huì)被喚醒*/
          /*喚醒前,ev_press 已被置1了*/
          /*喚醒后的執(zhí)行點(diǎn)從這里開(kāi)始*/
          }

          /*下面就是標(biāo)志位為1,即有數(shù)據(jù)可讀的的處理情況*/

          /*那就開(kāi)始往用戶空間讀數(shù)據(jù)唄*/

          err = copy_to_user(buff,(const void *)key_values,min(sizeof(key_values),count));
          /*copy_to_user()函數(shù)的使用*/

          /*對(duì)key_values數(shù)組清零*/

          memset((void *)key_values,0,sizeof(key_values));

          /*對(duì)標(biāo)志位置0*/
          /*表示讀取過(guò)了*/

          ev_press = 0;

          /*對(duì)err的處理*/

          if(err) /*讀取錯(cuò)誤*/
          return -EFAULT;
          else /*讀取正確*/
          /*則返回讀取到的字節(jié)數(shù)*/
          return min(sizeof(key_values),count);
          }

          /************************mini2440_buttons_poll()***********************/

          static unsigned int mini2440_buttons_poll(struct file *file,struct poll_table_struct *wait)
          {
          unsigned int mask = 0; /* */

          /*poll_wait()函數(shù)*/
          /*會(huì)監(jiān)測(cè)進(jìn)程隊(duì)列button_waitq里的進(jìn)程*/
          /*例如,如果mini2440_button_read所在的進(jìn)程的標(biāo)志位ev_press置為1了*/
          /*那么就不會(huì)再等待了*/
          /*這實(shí)質(zhì)上就是select函數(shù)的運(yùn)行機(jī)制*/

          poll_wait(file,&button_waitq,wait);

          if(ev_press)
          mask |= POLLIN | POLLRDNORM; /*??*/

          return mask;
          }

          ==================================================================================
          下面是測(cè)試代碼:

          /*按鍵測(cè)試程序*/

          #include /*標(biāo)準(zhǔn)輸入輸出頭文件*/

          #include /*標(biāo)準(zhǔn)庫(kù)*/

          #include /*一些宏的定義在這里*/

          #include /*設(shè)備的控制*/

          #include /*定義了一些類型*/

          #include /*狀態(tài)*/

          #include /*文件控制*/

          #include /*選擇?*/

          #include /*時(shí)間方面的函數(shù)*/

          #include /*有關(guān)錯(cuò)誤方面的宏*/

          /*主函數(shù)入口*/

          int main(void)
          {
          int i; /*鍵盤(pán)輸出時(shí)用到的循環(huán)變量*/

          int buttons_fd; /*buttons設(shè)備號(hào)*/

          int key_value[4]; /*四個(gè)按鍵的取值*/

          /*打開(kāi)鍵盤(pán)設(shè)備文件*/

          buttons_fd = open("/dev/buttons",0); /*以0方式打開(kāi)*/

          /*打開(kāi)出錯(cuò)處理*/

          if(buttons_fd < 0) /*打開(kāi)出錯(cuò)就會(huì)返回一個(gè)負(fù)值*/
          {
          perror("open device buttons"); /*perror函數(shù)?*/

          exit(1); /*返回1*/
          }

          /*for無(wú)限循環(huán),等待用戶輸入*/
          /*這是很典型的程序執(zhí)行方式*/

          for(;;)
          {
          fd_set rds; /*fd_set是types.h中定義的類型,實(shí)質(zhì)上是int型*/
          /*rds用來(lái)存儲(chǔ)設(shè)備號(hào)*/

          int ret; /*for循環(huán)內(nèi)定義的局部變量ret*/

          FD_ZERO(&rds); /*rds初始化*/
          /*FD_ZERO是哪里定義的呢?*/

          FD_SET(buttons_fd,&rds); /*將buttons設(shè)備號(hào)賦給rds*/
          /*FD_SET是哪里定義的呢?*/

          /*使用系統(tǒng)調(diào)用select檢查是否能夠從/dev/buttons設(shè)備讀取數(shù)據(jù)*/
          /*select函數(shù)是干什么的呢?*/

          ret = select(buttons_fd + 1,&rds,NULL,NULL,NULL);
          /*返回值ret*/
          /*返回值的具體意義是什么呢?*/

          /*對(duì)ret的處理*/

          if(ret < 0) /*當(dāng)ret小于0*/
          {
          perror("select");
          exit(1);
          }

          if(ret == 0) /*當(dāng)ret等于0*/
          {
          printf("Timeout.n");
          }
          else /*能夠讀到數(shù)據(jù)*/
          if(FD_ISSET(buttons_fd,&rds)) /*??*/
          {
          /*讀取鍵盤(pán)驅(qū)動(dòng)發(fā)出的數(shù)據(jù)*/
          /*key_value和鍵盤(pán)驅(qū)動(dòng)中定義一致*/

          int ret = read(buttons_fd,key_value,sizeof(key_value)); /*注意此處的ret和前面的ret有何不同*/
          /*注意鍵盤(pán)設(shè)備讀取的特點(diǎn)*/

          /*對(duì)ret的處理*/
          if(ret != sizeof(key_value)) /*沒(méi)有接收夠*/
          {
          if(errno != EAGAIN) /*???*/
          perror("read buttonsn");
          continue;
          }
          else /*正確接收,則打印到標(biāo)準(zhǔn)終端*/
          {
          for(i = 0;i < 4;i++) /*最開(kāi)始定義的循環(huán)變量i*/
          printf("K%d %s, key value = 0x%02xn",i,(key_value[i] & 0x80) ? "released" : key_value[i] ? "pressed down" : "",key_value[i]);
          /*這一連串的輸出,要注意格式*/
          }
          }
          }

          /*關(guān)閉設(shè)備*/

          close(buttons_fd);

          return 0; /*主函數(shù)返回*/

          END!!



          關(guān)鍵詞: MINI2440按鍵驅(qū)

          評(píng)論


          技術(shù)專區(qū)

          關(guān)閉