天天看點

觸摸屏驅動設計----輸入子系統模型

輸入子系統模型 介紹

對于鍵盤、滑鼠、觸摸屏等輸入裝置的驅動程式來說,使用者程式所調用的操作函數集基本上相同,這些驅動的主要差別在于各自的中斷處理函數對硬體的通路不同,是以為了簡化程式的設計,将所有輸入裝置的驅動簡化,提出一些共性的東西形成輸入子系統,讓不同的驅動程式實作不同的硬體處理程式即可。

輸入子系統如下圖所示:

觸摸屏驅動設計----輸入子系統模型

輸入子系統由裝置驅動層(input device driver),核心層(input core)和事件驅動層(event driver)三部份組成。任何一次輸入事件,如滑鼠移動,按鍵按下,都需要通過:

InputDeviceDriver->InputCore->EventDrive

才能到達使用者空間的應用程式。

裝置驅動層:

将底層的硬體輸入轉化為統一事件型式,向輸入核心(InputCore)彙報。

輸入核心層:

為裝置驅動層提供輸入裝置注冊與操作接口,如:input_ register_ device;通知事件處理層對事件進行處理;

事件驅動層:

主要作用是和使用者空間互動,如提供read,open等裝置方法,建立裝置檔案等。

事件類型:

EV_ RST:Reset

EV_KEY:按鍵

EV_ REL:相對坐标

EV_ABS:絕對坐标

EV_ MSC:其它

EV_LED :LED

EV_ SND: 聲音

EV_ REP: Repeat

EV_ FF :力回報

當事件類型為EV_KEY時,還需指明按鍵類型:

BTN_ LEFT:滑鼠左鍵

BTN_ RIGHT:滑鼠右鍵

BTN_0:數字0鍵

BTN_1:數字1鍵

輸入型驅動模型圖:

觸摸屏驅動設計----輸入子系統模型

代碼舉例:

按鍵輸入驅動設計(将前面的按鍵驅動進行改造):

驅動程式代碼舉例:

//初始化入口函數
static int button_init()
{
    int ret;

    /*配置設定輸入型裝置結構*/
    button_dev = input_allocate_device();

    /*申明所支援的事件類型*/
    set_bit(EV_KEY,button_dev->evbit);

    /*申明可能上報的鍵編号*/
    set_bit(KEY_3,button_dev->keybit);
    set_bit(KEY_4,button_dev->keybit);

    /*注冊輸入型裝置*/
    input_register_device(button_dev);

    //注冊中斷處理程式
    request_irq(IRQ_EINT0,key_int,IRQF_TRIGGER_FALLING,"key",(void *));
    request_irq(IRQ_EINT2,key_int,IRQF_TRIGGER_FALLING,"key",(void *));

    //按鍵初始化
    key_hw_init();

    //建立工作
    work1 = kmalloc(sizeof(struct work_struct),GFP_KERNEL);
    INIT_WORK(work1, work1_func);

    /* 初始化定時器 */  
    init_timer(&buttons_timer);   
    buttons_timer.function  = buttons_timer_function;  

    /* 向核心注冊一個定時器 */  
    add_timer(&buttons_timer);  

    /*初始化等待隊列*/
    init_waitqueue_head(&key_q);

    return ;  
}

//定時器中斷函數
void buttons_timer_function(unsigned long data)  
{
    unsigned int key_val;

    key_val = readw(gpio_data)&; 
    if (key_val == )
    {
       key_num = ;
       //上報事件
       input_report_key(button_dev,KEY_4,);
    }

    key_val = readw(gpio_data)&;
    if (key_val == )
    {
        key_num = ;
        //上報事件
        input_report_key(button_dev,KEY_3,);
    }

    //告訴核心上報結束
    input_sync(button_dev);
} 
           

應用程式代碼舉例:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>
#include <linux/input.h>
int main(void)
{
    int buttons_fd;
    int key_value,i=,count;

    //對應的輸入裝置結構體
    struct input_event ev_key;

    buttons_fd = open("/dev/event1", O_RDWR);
    if (buttons_fd < ) {
        perror("open device buttons");
        exit();
    }

    for (;;) {
        //特别注意:這裡的讀取函數的參數格式是固定的,必須這麼寫
        count = read(buttons_fd,&ev_key,sizeof(struct input_event));

        for(i=; i<(int)count/sizeof(struct input_event); i++)
            if(EV_KEY==ev_key.type)
                printf("type:%d,code:%d,value:%d\n", ev_key.type,ev_key.code-,ev_key.value);
            if(EV_SYN==ev_key.type)
                printf("syn event\n\n");
    }

    close(buttons_fd);
    return ;
}
           

觸摸屏驅動設計

初始化:

1、使能ADC時鐘

2、将實體位址轉化為虛拟位址

3、讓觸摸屏進入到等待中斷的模式

4、配置設定輸入裝置結構

5、設定可能上報的事件類型和按鍵類型

6、為TC和ADC中斷注冊處理函數

7、注冊輸入型裝置

按下處理:

1、判斷觸摸屏按下還是彈起,按下後進入TC中斷處理程式

2、啟動X與Y坐标的AD轉換,觸發ADC中斷

3、進行4次ADC轉換,擷取4次X與Y的值,考慮精度要求

4、計算4次坐标的平均值,并上報核心

源代碼位置:

linux-tq2440\drivers\input\touchscreen\tq2440_ts.c

繼續閱讀