Linux input輸入子系統

來源:互聯網
上載者:User

輸入裝置(按鍵、鍵盤、觸控螢幕、滑鼠)是典型的字元裝置,工作機理是底層
在按鍵、觸摸等動作發生時產生一個中斷(或驅動timer定時查詢),然後CPU
通過SPI、I2C或外部儲存空間匯流排讀取索引值,座標等資料。
輸入核心層提供了底層輸入裝置驅動程式所需的API,如分配/釋放一個輸入裝置
struct input_dev *input_allocate_device(void);
void input_free_device(struct input_dev *dev);
input_allocate_device()返回的是1個input_dev的結構體,此結構體用於表徵1個輸入裝置
註冊/登出輸入裝置用的介面
input_register_device(struct input_dev *);
void input_unregister_device(struct input_dev *);
報告輸入事件的介面,指定type, code, value
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);

input通用資料結構
1. input_dev是input裝置基本的裝置結構,每個input驅動程式必須分配初始化這樣一個結構
include/linux/input.h
struct input_dev {
const char *name; //裝置名稱
const char *phys;//裝置在系統的實體路徑
const char *uniq;//統一的ID
struct input_id id;//裝置ID

unsigned long evbit[BITS_TO_LONGS(EV_CNT)];//事件
unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];//按鍵
unsigned long relbit[BITS_TO_LONGS(REL_CNT)];//相對裝置
unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];//絕對裝置
unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];//雜項裝置
unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];//LED
unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];//聲音裝置
unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];//強制反饋裝置
unsigned long swbit[BITS_TO_LONGS(SW_CNT)];//開關裝置

unsigned int keycodemax;//按鍵碼的最大值
unsigned int keycodesize;//按鍵碼的大小
void *keycode;//按鍵碼
int (*setkeycode)(struct input_dev *dev,
 unsigned int scancode, unsigned int keycode);
int (*getkeycode)(struct input_dev *dev,
 unsigned int scancode, unsigned int *keycode);

struct ff_device *ff;

unsigned int repeat_key;
struct timer_list timer;

int sync;

int abs[ABS_CNT];
int rep[REP_MAX + 1];

unsigned long key[BITS_TO_LONGS(KEY_CNT)];
unsigned long led[BITS_TO_LONGS(LED_CNT)];
unsigned long snd[BITS_TO_LONGS(SND_CNT)];
unsigned long sw[BITS_TO_LONGS(SW_CNT)];

int absmax[ABS_CNT];
int absmin[ABS_CNT];
int absfuzz[ABS_CNT];
int absflat[ABS_CNT];
int absres[ABS_CNT];

int (*open)(struct input_dev *dev);
void (*close)(struct input_dev *dev);
int (*flush)(struct input_dev *dev, struct file *file);
int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);

struct input_handle *grab;

spinlock_t event_lock;
struct mutex mutex;

unsigned int users;
bool going_away;

struct device dev;

struct list_headh_list;
struct list_headnode;
};

2. input_event 驅動層向input子系統核心報告事件的函數。
void input_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value);
 
不同裝置內容的報告均是通過input_event函數來完成的,選擇使用了不同參數而已
@type:類型(EV_KEY鍵盤,EV_REL相對,EV_ABS絕對)
@code:編碼(事件代碼,如鍵盤代碼)
@value:值(EV_KEY當按鍵按下時值為1,鬆開時值為0,如果事件為EV_REL,value的正
數值和負數值分別代表兩個不同的方向)

鍵盤keyboard屬於按鍵裝置EV_KEY
軌跡屬於相對裝置EV_REL
觸模屏屬於絕對裝置EV_ABS

3. 分配並初始化input_dev
input_allocate_device()

4. 向核心註冊一個input裝置
input_register_device()

5. input驅動流程
1)定義input裝置結構
struct input_dev *input;
2)分配並初始化input_dev接構
input = input_allocate_device();
input->name = "gpio-keys";
input->phys = "gpio-keys/input0";
input->id.bustype = BUS_HOST;
input->id.vendor  = 0x0001;
input->id.product = 0x0001;
input->id.version = 0x0100;
3) 記錄本裝置對於哪些事件感興趣(對其進行處理)input_set_capability();
定義/drivers/input/input.c
void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code)
input_set_capability(input, EV_KEY, 101);

4)向核心註冊一個input裝置
input_register_device(input);

5)記錄按鍵狀態
int state = (gpio_get_value((S3C64XX_GPN(0)) ? 1 : 0) ^ 1 ;

6)彙報輸入事件
input_event(input, EV_KEY, 101, !!state);

7)等待輸入事件處理完成
input_sync(input);

8)登出一個input裝置
input_unregister_device(input);

/************************input gpio_keys 例子********************/

/***interrupt key kernel 2.6.35.7*/#include <linux/module.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/fs.h>#include <mach/gpio.h>#include <linux/input.h>#include <linux/slab.h>#include <linux/delay.h>#include <linux/timer.h>#define KEY_MAJOR 233#define DEVICE_NAME "gpio_key"struct gpio_button_data {struct input_dev *input;struct timer_list timer;struct work_struct work;} *data;static void gpio_keys_report_event(void){struct input_dev *input = data->input;//記錄按鍵狀態int state = (gpio_get_value(S3C64XX_GPN(0)) ? 1 : 0) ^ 1 ;//彙報輸入事件unsigned int type = EV_KEY;int code = 139;printk("type=%d, code=%d, state=%d\n", type, code, state);/**5. 彙報事件*/input_event(input, type, code, !!state);//等待輸入事件完成input_sync(input);}static void gpio_key_work_func(struct work_struct *work){//struct gpio_button_data *data =//container_of(work, struct gpio_button_data, work);gpio_keys_report_event();}static void gpio_keys_timer(unsigned long _data){schedule_work(&data->work);}static irqreturn_t gpio_key_isr(int irq, void *dev_id){ mod_timer(&data->timer, jiffies+msecs_to_jiffies(0));schedule_work(&data->work);return IRQ_HANDLED;}static int keys_init(void){int ret = 0;int irq;//中斷號unsigned long irqflags;setup_timer(&data->timer, gpio_keys_timer, (unsigned long)data);add_timer(&data->timer);//申請管腳gpio_request(S3C64XX_GPN(0), "HOME");//設定為輸入gpio_direction_input(S3C64XX_GPN(0));irq = gpio_to_irq(S3C64XX_GPN(0));printk("the gpio_key irq is [%d]\n ", irq);irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;ret = request_irq(irq, gpio_key_isr, irqflags, "HOME", NULL);if (ret) {printk("can't get gpio irq\n");return -1;}return 0;}static int gpio_keys_probe(void){int ret = 0;//struct gpio_button_data *data;/**1. 定義input_dev 結構*/struct input_dev *input;/**2. 分配並初始化結構*/input = input_allocate_device();input->name = "gpio-key";input->phys = "gpio-key/input0";input->id.bustype = BUS_HOST;input->id.vendor  = 0x0001;input->id.product = 0x0001;input->id.version = 0x0100;data = kzalloc(sizeof(struct gpio_button_data), GFP_KERNEL);data->input = input;keys_init();/**3. 記錄感興趣的事件*/input_set_capability(input, EV_KEY, 139);/**4. 向核心註冊一個input裝置*/ret = input_register_device(input);if(ret) {printk("unable to register input device\n");return -1;}return 0;}int key_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){return 0;}static const struct file_operations key_ops = {.owner = THIS_MODULE,.ioctl = key_ioctl,};static int __init gpio_keys_init(void){int ret = 0;ret = register_chrdev(KEY_MAJOR, DEVICE_NAME, &key_ops);if (ret < 0) {printk("can't register gpio_keys_number\n");return -1;}gpio_keys_probe();INIT_WORK(&data->work, gpio_key_work_func);printk("gpio_keys init\n");return 0;}static void __exit gpio_keys_exit(void){unregister_chrdev(KEY_MAJOR, DEVICE_NAME);}module_init(gpio_keys_init);module_exit(gpio_keys_exit);MODULE_LICENSE("GPL");

在串口測試

/ # getevent

add device 2: /dev/input/event0
  name:     "gpio-key"
could not get driver version for /dev/input/mice, Not a typewriter
type=1, code=139, state=1
type=1, code=139, state=1
/dev/input/event0: 0001 008b 00000001
/dev/input/event0: 0000 0000 00000000

0001表示EV_KEY,008b是按鍵掃描碼,1按下,0抬起

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.