Linux/Android——輸入子系統input_event傳遞

來源:互聯網
上載者:User

標籤:input   dev   event   input_dev   touchscreen-abs   

  在前文 Linux/Android——usb觸控螢幕驅動 - usbtouchscreen 中記錄了如何在kernel中添加input device 類型為touchscreen的驅動,

這在整個輸入體系中是最下層的裝置驅動部分,往上一層就是linux核心的管理驅動input系統,kernel中的源碼位置:/kernel/drivers/input/input.c


                                              撰寫不易,轉載需註明出處:http://blog.csdn.net/jscese/article/details/42099381


到目前已經完全調通,可以正常使用了,現在記錄一下這段時間接觸到的Android 輸入input 系統,先看一張網上的層次圖,蠻不錯的:
              

        


上一篇部落格裡面的 usbtouchscreen 就是對應的I2c module的位置,而在kernel中input的核心就是input.c .

input_dev:

 這個結構體表述的是一個輸入裝置的相關資訊,在usbtouchscreen 驅動中的 usbtouch_probe 會初始化input_dev,作為usbtouch裝置的一部分.

會對 input_dev  做一系列的初始化,設定參數之類的,具體可參考之前部落格

input_dev 結構原型如下,/kernel/include/linux/input.h中定義:

/** * struct input_dev - represents an input device * @name: name of the device * @phys: physical path to the device in the system hierarchy * @uniq: unique identification code for the device (if device has it) * @id: id of the device (struct input_id) * @propbit: bitmap of device properties and quirks * @evbit: bitmap of types of events supported by the device (EV_KEY, *EV_REL, etc.) * @keybit: bitmap of keys/buttons this device has * @relbit: bitmap of relative axes for the device * @absbit: bitmap of absolute axes for the device * @mscbit: bitmap of miscellaneous events supported by the device * @ledbit: bitmap of leds present on the device * @sndbit: bitmap of sound effects supported by the device * @ffbit: bitmap of force feedback effects supported by the device * @swbit: bitmap of switches present on the device * @hint_events_per_packet: average number of events generated by the *device in a packet (between EV_SYN/SYN_REPORT events). Used by *event handlers to estimate size of the buffer needed to hold *events. * @keycodemax: size of keycode table * @keycodesize: size of elements in keycode table * @keycode: map of scancodes to keycodes for this device * @getkeycode: optional legacy method to retrieve current keymap. * @setkeycode: optional method to alter current keymap, used to implement *sparse keymaps. If not supplied default mechanism will be used. *The method is being called while holding event_lock and thus must *not sleep * @ff: force feedback structure associated with the device if device *supports force feedback effects * @repeat_key: stores key code of the last key pressed; used to implement *software autorepeat * @timer: timer for software autorepeat * @rep: current values for autorepeat parameters (delay, rate) * @mt: pointer to array of struct input_mt_slot holding current values *of tracked contacts * @mtsize: number of MT slots the device uses * @slot: MT slot currently being transmitted * @trkid: stores MT tracking ID for the current contact * @absinfo: array of &struct input_absinfo elements holding information *about absolute axes (current value, min, max, flat, fuzz, *resolution) * @key: reflects current state of device's keys/buttons * @led: reflects current state of device's LEDs * @snd: reflects current state of sound effects * @sw: reflects current state of device's switches * @open: this method is called when the very first user calls *input_open_device(). The driver must prepare the device *to start generating events (start polling thread, *request an IRQ, submit URB, etc.) * @close: this method is called when the very last user calls *input_close_device(). * @flush: purges the device. Most commonly used to get rid of force *feedback effects loaded into the device when disconnecting *from it * @event: event handler for events sent _to_ the device, like EV_LED *or EV_SND. The device is expected to carry out the requested *action (turn on a LED, play sound, etc.) The call is protected *by @event_lock and must not sleep * @grab: input handle that currently has the device grabbed (via *EVIOCGRAB ioctl). When a handle grabs a device it becomes sole *recipient for all input events coming from the device * @event_lock: this spinlock is is taken when input core receives *and processes a new event for the device (in input_event()). *Code that accesses and/or modifies parameters of a device *(such as keymap or absmin, absmax, absfuzz, etc.) after device *has been registered with input core must take this lock. * @mutex: serializes calls to open(), close() and flush() methods * @users: stores number of users (input handlers) that opened this *device. It is used by input_open_device() and input_close_device() *to make sure that dev->open() is only called when the first *user opens device and dev->close() is called when the very *last user closes the device * @going_away: marks devices that are in a middle of unregistering and *causes input_open_device*() fail with -ENODEV. * @sync: set to %true when there were no new events since last EV_SYN * @dev: driver model's view of this device * @h_list: list of input handles associated with the device. When *accessing the list dev->mutex must be held * @node: used to place the device onto input_dev_list */struct input_dev {const char *name;const char *phys;const char *uniq;struct input_id id;unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];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)];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 hint_events_per_packet;unsigned int keycodemax;unsigned int keycodesize;void *keycode;int (*setkeycode)(struct input_dev *dev,  const struct input_keymap_entry *ke,  unsigned int *old_keycode);int (*getkeycode)(struct input_dev *dev,  struct input_keymap_entry *ke);struct ff_device *ff;unsigned int repeat_key;struct timer_list timer;int rep[REP_CNT];struct input_mt_slot *mt;int mtsize;int slot;int trkid;struct input_absinfo *absinfo;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 (*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 __rcu *grab;spinlock_t event_lock;struct mutex mutex;unsigned int users;bool going_away;bool sync;struct device dev;struct list_headh_list;struct list_headnode;};

我解釋可能還會誤導,源碼上面的注釋是最好的解釋,都是描述一個input 裝置的相關資訊.

每一個input裝置,都需要初始化一個這樣的input_dev結構來描述記錄此裝置的一些特性,然後通過input_register_device 註冊到裝置匯流排上以供後續使用

可以到系統運行目錄的/proc/bus/inputcat devices  查看匯流排上的已經註冊上的input device



input_event:

  裝置驅動部分往上傳遞的就是觸發的event事件了,還以usbtouchscreen的為例,回呼函數為:

/***************************************************************************** * Generic Part */static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,                                 unsigned char *pkt, int len){    struct usbtouch_device_info *type = usbtouch->type;     if (!type->read_data(usbtouch, pkt))            return;    input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch); // 上報觸摸類型 。touch為按下    if (swap_xy) {        input_report_abs(usbtouch->input, ABS_X, usbtouch->y);        input_report_abs(usbtouch->input, ABS_Y, usbtouch->x);    } else {        input_report_abs(usbtouch->input, ABS_X, usbtouch->x);        input_report_abs(usbtouch->input, ABS_Y, usbtouch->y); // 上報絕對座標值    }    if (type->max_press)        input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press);    input_sync(usbtouch->input);   // 同步操作}


可以看到通過 input_report_* 上報事件到input.c中,這也就是上面層次圖中的箭頭 9 ,初始在/kernel/include/linux/input.h:

static inline void input_report_key(struct input_dev *dev, unsigned int code, int value){input_event(dev, EV_KEY, code, !!value);}static inline void input_report_rel(struct input_dev *dev, unsigned int code, int value){input_event(dev, EV_REL, code, value);}static inline void input_report_abs(struct input_dev *dev, unsigned int code, int value){input_event(dev, EV_ABS, code, value);}

可以看到不同的report 都調用進了input_event,只是傳參不同,接下來的事就全交由input.c 來做了!

/** * input_event() - report new input event * @dev: device that generated the event * @type: type of the event * @code: event code * @value: value of the event * * This function should be used by drivers implementing various input * devices to report input events. See also input_inject_event(). * * NOTE: input_event() may be safely used right after input device was * allocated with input_allocate_device(), even before it is registered * with input_register_device(), but the event will not reach any of the * input handlers. Such early invocation of input_event() may be used * to 'seed' initial state of a switch or initial position of absolute * axis, etc. */void input_event(struct input_dev *dev,         unsigned int type, unsigned int code, int value){    unsigned long flags;    if (is_event_supported(type, dev->evbit, EV_MAX)) {  //判斷是否是註冊時的event類型,驅動probe時註冊input_dev時設定了能響應的event類型        spin_lock_irqsave(&dev->event_lock, flags); //自旋鎖枷鎖       add_input_randomness(type, code, value);        input_handle_event(dev, type, code, value);  //進一步處理傳上來的這個 event        spin_unlock_irqrestore(&dev->event_lock, flags);//解鎖    }}

可以看到在這裡首先就是過濾了事件類型,這個也是在usbtouchscreen中的probe中初始化過的!

類型有如下幾種:

/* * Event types */#define EV_SYN0x00#define EV_KEY0x01#define EV_REL0x02#define EV_ABS0x03#define EV_MSC0x04#define EV_SW0x05#define EV_LED0x11#define EV_SND0x12#define EV_REP0x14#define EV_FF0x15#define EV_PWR0x16#define EV_FF_STATUS0x17#define EV_MAX0x1f#define EV_CNT(EV_MAX+1)



input_handle_event:

 由上面的input_event 調入進這個handle處理。這裡會根據type進行分類處理:

static void input_handle_event(struct input_dev *dev,                   unsigned int type, unsigned int code, int value){    int disposition = INPUT_IGNORE_EVENT; //初始為不做處理    switch (type) {    case EV_SYN:        switch (code) {        case SYN_CONFIG:            disposition = INPUT_PASS_TO_ALL;            break;        case SYN_REPORT:            if (!dev->sync) {                dev->sync = true;                disposition = INPUT_PASS_TO_HANDLERS;            }            break;...    case EV_KEY:        if (is_event_supported(code, dev->keybit, KEY_MAX) &&  //按鍵code是否被keybit支援            !!test_bit(code, dev->key) != value) {  //key是鍵盤當前所有鍵狀態,測試code對應鍵狀態,value傳來事件的按鍵狀態。此句表示按鍵狀態應有變化            if (value != 2) {                __change_bit(code, dev->key);  //改變key的值以改變按鍵狀態。                if (value)                    input_start_autorepeat(dev, code);  //如果按索引值為按下,則開始重複按鍵動作。具體會不會重複,input_start_autorepeat還會根據evbit中有沒有置位重複事件等判斷。                else                    input_stop_autorepeat(dev); //如果是鬆開按鍵則應停止重複按鍵相關操作。            }            disposition = INPUT_PASS_TO_HANDLERS;        }        break;...    case EV_ABS:        if (is_event_supported(code, dev->absbit, ABS_MAX))  //同上面一樣看是否支援            disposition = input_handle_abs_event(dev, code, &value);  //這個函數可以跟進去看,是做為篩選的,第一次是不會返回INPUT_IGNORE_EVENT ,後面如果有跟上次相同的ABS座標就會被過濾掉,返回IGNORE//        err("jscese display disposition vlue ==0x%x,code==0x%x, value== 0x%x\n",disposition,code,value);        break;...   }    if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)        dev->sync = false;    if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)        dev->event(dev, type, code, value);     if (disposition & INPUT_PASS_TO_HANDLERS)        input_pass_event(dev, type, code, value);  //更深一步調用 ,最終都是 調用到 event(**)方法}


這裡先記錄整個輸入系統從裝置驅動到上層的關係,以及從kernel中的驅動調用到input系統中的傳遞過程,雖然看到調用了input.c中的一些函數傳遞,但是對input核心還是沒多少概念,

下篇解析記錄一下input這個核心模組~






Linux/Android——輸入子系統input_event傳遞

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.