溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Linux輸入子系統(tǒng)是什么

發(fā)布時(shí)間:2022-01-27 14:26:17 來(lái)源:億速云 閱讀:95 作者:iii 欄目:開發(fā)技術(shù)

這篇“Linux輸入子系統(tǒng)是什么”文章的知識(shí)點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價(jià)值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來(lái)看看這篇“Linux輸入子系統(tǒng)是什么”文章吧。

Linux內(nèi)核為了能夠處理各種不同類型的輸入設(shè)備,比如 觸摸屏 ,鼠標(biāo) , 鍵盤 , 操縱桿 ,設(shè)計(jì)并實(shí)現(xiàn)了為驅(qū)動(dòng)層程序的實(shí)現(xiàn)提供統(tǒng)一接口函數(shù);為上層應(yīng)用提供試圖統(tǒng)一的抽象層 , 即是Linux 輸入子系統(tǒng) 。

Linux輸入子系統(tǒng)是什么

驅(qū)動(dòng)層

將底層的硬件輸入轉(zhuǎn)化為統(tǒng)一事件形式,想輸入核心(Input Core)匯報(bào)。

輸入子系統(tǒng)3核心層

它承上啟下為驅(qū)動(dòng)層提供輸入設(shè)備注冊(cè)與操作接口,如:input_register_device;通知事件處理層對(duì)事件進(jìn)行處理;在/Proc下產(chǎn)生相應(yīng)的設(shè)備信息。

事件處理層

主要是和用戶空間交互(Linux中在用戶空間將所有的設(shè)備都當(dāng)作文件來(lái)處理,由于在一般的驅(qū)動(dòng)程序中都有提供fops接口,以及在/dev下生成相應(yīng)的設(shè)備文件nod,這些操作在輸入子系統(tǒng)中由事件處理層完成)。

設(shè)備描述

input_dev結(jié)構(gòu)是實(shí)現(xiàn)設(shè)備驅(qū)動(dòng)核心工作:向系統(tǒng)報(bào)告按鍵、觸摸屏等輸入事件(event,通過(guò)input_event結(jié)構(gòu)描述),不再需要關(guān)心文件操作接口。驅(qū)動(dòng)報(bào)告事件經(jīng)過(guò)inputCore和Eventhandler到達(dá)用戶空間。

注冊(cè)輸入設(shè)備函數(shù):

int input_register_device(struct input_dev *dev)

注銷輸入設(shè)備函數(shù):

void input_unregister_device(struct input_dev *dev)

驅(qū)動(dòng)實(shí)現(xiàn)——初始化(事件支持)set_bit()告訴input輸入子系統(tǒng)支持哪些事件,哪些按鍵。例如:

set_bit(EV_KEY,button_dev.evbit)  (其中button_dev是struct input_dev類型)

**struct input_dev**中有兩個(gè)成員為: **1)**evbit事件類型(包括EV_RST,EV_REL,EV_MSC,EV_KEY,EV_ABS,EV_REP等)。 **2)**keybit按鍵類型(當(dāng)事件類型為EV_KEY時(shí)包括BTN_LEFT,BTN_0,BTN_1,BTN_MIDDLE等)。

驅(qū)動(dòng)實(shí)現(xiàn)——報(bào)告事件用于報(bào)告EV_KEY,EV_REL,EV_ABS事件的函數(shù)分別為:

void input_report_key(struct input_dev *dev,unsigned int code,int value)
void input_report_rel(struct input_dev *dev,unsigned int code,int value)
void input_report_abs(struct input_dev *dev,unsigned int code,int value)

驅(qū)動(dòng)實(shí)現(xiàn)——報(bào)告結(jié)束input_sync()同步用于告訴input core子系統(tǒng)報(bào)告結(jié)束,觸摸屏設(shè)備驅(qū)動(dòng)中,一次點(diǎn)擊的整個(gè)報(bào)告過(guò)程如下:

input_reprot_abs(input_dev,ABS_X,x);   //x坐標(biāo)
input_reprot_abs(input_dev,ABS_Y,y);   // y坐標(biāo)
input_reprot_abs(input_dev,ABS_PRESSURE,1);
input_sync(input_dev);//同步結(jié)束

實(shí)例分析(按鍵中斷程序):

//按鍵初始化
static int __init button_init(void)
{//申請(qǐng)中斷
   if(request_irq(BUTTON_IRQ,button_interrupt,0,”button”,NUll))
       return –EBUSY;
   set_bit(EV_KEY,button_dev.evbit); //支持EV_KEY事件
   set_bit(BTN_0,button_dev.keybit); //支持設(shè)備兩個(gè)鍵
   set_bit(BTN_1,button_dev.keybit); //
   input_register_device(&button_dev);//注冊(cè)input設(shè)備
}
/*在按鍵中斷中報(bào)告事件*/
Static void button_interrupt(int irq,void *dummy,struct pt_regs *fp)
{
   input_report_key(&button_dev,BTN_0,inb(BUTTON_PORT0));//讀取寄存器BUTTON_PORT0的值
   input_report_key(&button_dev,BTN_1,inb(BUTTON_PORT1));
   input_sync(&button_dev);
}

總結(jié):input子系統(tǒng)仍然是字符設(shè)備驅(qū)動(dòng)程序,但是代碼量減少很多,*input子系統(tǒng)只需要完成兩個(gè)工作:初始化和事件報(bào)告(這里在linux中是通過(guò)中斷來(lái)實(shí)現(xiàn)的)。*

實(shí)例

#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct input_dev *button_dev;
struct button_irq_desc {
   int irq;
   int pin;
   int pin_setting;
   int number;
   char *name;
};

/*定義一個(gè)結(jié)構(gòu)體數(shù)組*/
static struct button_irq_desc button_irqs [] = {
   {IRQ_EINT8 , S3C2410_GPG0 , S3C2410_GPG0_EINT8 , 0, "KEY0"},
   {IRQ_EINT11, S3C2410_GPG3 , S3C2410_GPG3_EINT11 , 1, "KEY1"},
   {IRQ_EINT13, S3C2410_GPG5 , S3C2410_GPG5_EINT13 , 2, "KEY2"},
   {IRQ_EINT14, S3C2410_GPG6 , S3C2410_GPG6_EINT14 , 3, "KEY3"},
   {IRQ_EINT15, S3C2410_GPG7 , S3C2410_GPG7_EINT15 , 4, "KEY4"},
   {IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG11_EINT19, 5, "KEY5"},
};

static int key_values = 0;
static irqreturn_t buttons_interrupt(int irq, void *dev_id)
{
   struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;
   int down;
   udelay(0);
/*獲取按鍵值*/
down = !s3c2410_gpio_getpin(button_irqs->pin); //down: 1(按下),0(彈起)if (!down) {
   /*報(bào)告事件*/
   key_values = button_irqs->number;
   //printk("====>rising key_values=%d\n",key_values);
   if(key_values==0)
       input_report_key(button_dev, KEY_1, 0);
   if(key_values==1)
       input_report_key(button_dev, KEY_2, 0);
   if(key_values==2)
       input_report_key(button_dev, KEY_3, 0);
   if(key_values==3)
       input_report_key(button_dev, KEY_4, 0);
   if(key_values==4)
       input_report_key(button_dev, KEY_5, 0);
   if(key_values==5)
       input_report_key(button_dev, KEY_6, 0);
   /*報(bào)告結(jié)束*/
   input_sync(button_dev);
   }else {
   key_values = button_irqs->number;
   //printk("====>falling key_values=%d\n",key_values);
   if(key_values==0)
       input_report_key(button_dev, KEY_1, 1);
   if(key_values==1)
       input_report_key(button_dev, KEY_2, 1);
   if(key_values==2)
       input_report_key(button_dev, KEY_3, 1);
   if(key_values==3)
       input_report_key(button_dev, KEY_4, 1);
   if(key_values==4)
       input_report_key(button_dev, KEY_5, 1);
   if(key_values==5)
       input_report_key(button_dev, KEY_6, 1);
   input_sync(button_dev);
   }
   return IRQ_RETVAL(IRQ_HANDLED);
}
static int s3c24xx_request_irq(void)
{
   int i;
   int err = 0;
   for (i = 0; i if (button_irqs[i].irq continue;
       }
       /* IRQ_TYPE_EDGE_FALLING,IRQ_TYPE_EDGE_RISING,IRQ_TYPE_EDGE_BOTH */
       err = request_irq(button_irqs[i].irq, buttons_interrupt, IRQ_TYPE_EDGE_BOTH,
       button_irqs[i].name, (void *)&button_irqs[i]);
       if (err)
           break;
   }
   /*錯(cuò)誤處理*/
   if (err) {
       i--;
       for (; i >= 0; i--) {
           if (button_irqs[i].irq continue;
           }
           disable_irq(button_irqs[i].irq);
         free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);
       }
       return -EBUSY;
   }
   return 0;
}
static int __init dev_init(void)
{
   /*request irq*/
   s3c24xx_request_irq();
   /* Initialise input stuff */
   button_dev = input_allocate_device();
   if (!button_dev) {
       printk(KERN_ERR "Unable to allocate the input device !!\n");
       return -ENOMEM;
   }
   button_dev->name = "s3c2440_button";
   button_dev->id.bustype = BUS_RS232;
   button_dev->id.vendor = 0xDEAD;
   button_dev->id.product = 0xBEEF;
   button_dev->id.version = 0x0100;

   button_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT(EV_SYN);
   //set_bit(EV_KEY, button_dev->evbit)//支持EV_KEY事件
   /*設(shè)置支持哪些按鍵*/
   set_bit(KEY_1, button_dev->keybit);
   set_bit(KEY_2, button_dev->keybit);
   set_bit(KEY_3, button_dev->keybit);
   set_bit(KEY_4, button_dev->keybit);
   set_bit(KEY_5, button_dev->keybit);
   set_bit(KEY_6, button_dev->keybit);
   //printk("KEY_RESERVED=%d ,KEY_1=%d",KEY_RESERVED,KEY_1);
   input_register_device(button_dev); //注冊(cè)input設(shè)備

   printk ("initialized\n");

   return 0;
}

static void __exit dev_exit(void)
{
   int i;

   for (i = 0; i if (button_irqs[i].irq continue;
       }
       free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);
   }

   input_unregister_device(button_dev);
}

module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Xie");

以上就是關(guān)于“Linux輸入子系統(tǒng)是什么”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對(duì)大家有幫助,若想了解更多相關(guān)的知識(shí)內(nèi)容,請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI