多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > 綜合技術 > input子系統――架構、驅動、應用程序

input子系統――架構、驅動、應用程序

來源:程序員人生   發布時間:2015-01-17 09:41:02 閱讀次數:2682次

1、input子系統架構

input子系統由驅動層drivers,輸入子系統核心層input core,事件處理層event handler組成。

1個輸入事件,通過輸入裝備發給系統如鼠標移動,鍵盤按鍵按下等通過device driver->input core(handler->event函數)->event handler->user space的順序到達用戶空間傳給利用程序。

1個輸失事件,通過系統發給輸入裝備,通過user space->event handler->input core(dev->event函數)->device driver

1、驅動功能層:負責和底層的硬件裝備打交道,將底層硬件裝備對用戶輸入的響應轉換為標準的輸入事件以后再向上發送給輸入系統核心層

2、Input系統核心層:由driver/input/input.c及相干頭文件實現,他對下提供了裝備驅動層的接口,對上提供了事件處理層的變成接口。

3、事件處理層將硬件裝備上報的事件分發到用戶空間和內核。


結構圖以下:



2、編寫input驅動需要的函數

1)包括頭文件<linux/input.h>,他是input子系統的接口,提供了必要的定義消息

2)Input_allocate_device()

分配了1個Input device的結構,設置他的bit field來告知input子系統他能產生或接收甚么事件。

3)input_register_device(struct input_dev *dev)

dev結構體添加到input_dev_list全局鏈表中去

通過input_attach_handler(struct input_dev *dev, struct input_handler *handler)來查找對應的handler

input_attach_handler里面實際調用了input_match_device(const struct input_device_id *id,struct input_dev *dev)

1旦input_attach_handler找到了對應的handler,就履行handler->connect

4)input_report_key(struct input_dev *dev, unsigned int code, int value)

5)input_sync(struct input_dev *dev)

告知事件的接收者,到此為止為1次完全的消息。比如我們在touch screen上取得了xy的值,要使作為1次事件,那末將input_sync加在report xy值得后面。

6)其他的事件type,輸失事件處理

其他的事件有:

EV_LED:用作鍵盤的LED

EV_SND:用作鍵盤的蜂鳴器

他和鍵盤事件很相似,只不過鍵盤事件是INPUT_PASS_TO_DEVICE,而輸失事件是INPUT_PASS_TO_HANDLERS,從系統到輸入裝備的驅動程序,如果你的驅動程序要處理這些事件,必須設置evbit中相應位,而且要實現1個回調函數。

struct input_dev *button_dev;

button_dev->event = button_event;這個便是處理輸失事件的回調函數



3、普通按鍵實現input驅動例子

/* drivers->input core->event handler function: this file is button driver date: 20150101 author: lei_wang */ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/irq.h> #include <asm/irq.h> #include <asm/io.h> #include <mach/regs-gpio.h> #include <mach/hardware.h> #include <linux/interrupt.h> #include <linux/gpio.h> #include <linux/input.h> static struct input_dev *button_dev; static irqreturn_t button_intr(int irq, void *dev_id) { int val; val = s3c2410_gpio_getpin(S3C2410_GPG(0)); // printk(KERN_INFO "key value is %d ", val); input_report_key(button_dev, BTN_0, val); input_sync(button_dev); return IRQ_RETVAL(IRQ_HANDLED); } static int __init button_init(void) { int ret; ret = request_irq(IRQ_EINT8, button_intr, IRQ_TYPE_EDGE_BOTH, "button0", NULL); if (ret) { printk(KERN_ERR "%s request failed ", __func__); return -ENODEV; } button_dev = input_allocate_device(); if (!button_dev) { printk(KERN_ERR "button.c: Not enough memory "); free_irq(IRQ_EINT8, NULL); return -ENOMEM; } button_dev->name = "button0"; button_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY); button_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0); ret = input_register_device(button_dev); if (ret) { printk(KERN_ERR "button.c: Failed to register device "); input_free_device(button_dev); free_irq(IRQ_EINT8, NULL); return -ENODEV; } printk(KERN_INFO "button init ok! "); return 0; } static void __exit button_exit(void) { input_unregister_device(button_dev); input_free_device(button_dev); free_irq(IRQ_EINT8, NULL); printk(KERN_INFO "button exit ok! "); } module_init(button_init); module_exit(button_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Realsil Luckywang");


Makefile以下:

obj-m = button.o KERNELDIR ?=/home/lei/linux⑵.6.32.2 modules: $(MAKE) -C $(KERNELDIR) M=$(shell pwd) modules clean: rm -rf *.o *.mod.c *.order *.symvers


Include/linux/bitops.h中定義了

#define BIT(nr) (1UL << (nr))

#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))

#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)

#define BTN_0 0x100

button_dev->evbit[0] = BIT_MASK(EV_KEY);

button_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);

說明:

1)上面的0x100表示BTN_0這個bit在所有的bit中是0x100(bit 256)位,那末

BIT_WORD(BTN_0)代表bit 256keybit這個數組的第幾個數組(第8個)

BIT_MASK(BTN_0)代表bit 256keybit這個數組的第幾個數組里面的值(第8個數組的bit0)

2)事件類型type――編碼code――值value

evbit是事件數組,evbit這個事件數組里面可以放很多事件類型,比如keyabs

事件key里面又有很多具體編碼BTN_0BTN_TOUCH

事件abs里面也有很多具體編碼ABS_XABS_Y

不同編碼有不同的值


另外http://blog.csdn.net/ylyuanlu/article/details/6704744 這篇博客對以下說的挺詳細的

1)input子系統的struct input_dev、struct handler的注冊

2)struct input_dev與struct input_handler怎樣相互匹配(類似于device和driver匹配)

3)事件處理進程



4、例子對應的利用程序

/* 20150101 just a simple input test code lei_wang */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <linux/input.h> int main() { int fd; int version; int ret; struct input_event ev; fd = open("/dev/input/event1", O_RDONLY); if (fd < 0) { printf("open file failed "); exit(1); } ioctl(fd, EVIOCGVERSION, &version); printf("evdev driver version is 0x%x: %d.%d.%d ", version, version>>16, (version>>8) & 0xff, version & 0xff); while (1) { ret = read(fd, &ev, sizeof(struct input_event)); if (ret < 0) { printf("read event error! "); exit(1); } if (ev.type == EV_KEY) printf("type %d,code %d, value %d ", ev.type, ev.code, ev.value); } return 0; }

以上只是1個簡單的利用程序測試。當你按下K1的時候,串口終端會有顯示的input dev上報的按鍵的消息。

編寫利用程序的時候如何肯定是哪一個eventX呢,cat /proc/bus/input/devices,輸出打印消息以下:


這里插入了鼠標,通過比較VID、PID來找到對應的usb mouse裝備,然后找到對應的mouse0、event1


另外還有很多里面ioctl調用的內容沒有實驗,具體可以參考這篇博客http://www.cnblogs.com/leaven/archive/2011/02/12/1952793.html,對ioctl的每一個case和read調用都試1遍,找到自己的體會。


生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 国产日本韩国 | 亚洲一区二区三区高清不卡 | 一区二区三区国产精品 | 亚洲国产精品久久久久久网站 | 国产成人免费a在线资源 | 中文字幕第5页 | 国产午夜精品久久久久 | 亚洲精品国产一区二区三区四区 | 欧美xxxx做受欧美人妖 | 可以看黄的网址 | 操人网站 | 国产精品成人网 | 国产免费一区二区三区最新 | jizz自拍| 亚洲欧美一区二区三区国产精品 | 久久福利资源站免费观看i 久久高清一级毛片 | 第一福利视频网 | 色老头福影院韩国激情影院 | 操你网站| 亚洲天堂在线观看视频 | 亚洲精品高清国产麻豆专区 | 全部无卡免费的毛片在线看 | 欧美大片毛片aaa免费看 | 精品一区二区三区中文字幕 | 成 黄 色 激 情视频网站 | 羞羞视频免费网站入口 | 三级小视频在线观看 | 视频免费观看在线播放高清 | 亚洲国产一区视频 | 日本自己的私人影院 | 日韩精品一 | 又大又硬又黄又刺激的免费视频 | 91综合精品网站久久 | 国产成人综合久久精品红 | 日本xxxx18护士 | 另类综合图片 | 日韩亚洲国产综合久久久 | 亚洲国产精品免费在线观看 | 日韩免费福利视频 | 亚洲精品高清在线 | 国产国产人精品视频69 |