17.1.2 註冊函數input_register_device()(1)
button_init()函數中的28行調用了input_register_device()函數註冊輸入裝置結構體。input_register_device()函數是輸入子系統核心(input core)提供的函數。該函數將input_dev結構體註冊到輸入子系統核心中,input_dev結構體必須由前面講的input_allocate_device()函數來分配。input_register_device()函數如果註冊失敗,必須調用input_free_device()函數釋放分配的空間。如果該函數註冊成功,在卸載函數中應該調用input_unregister_device()函數來登出輸入裝置結構體。
1.input_register_device()函數
input_register_device()函數的代碼如下:
/** * input_register_device - register device with input core * @dev: device to be registered * * This function registers device with input core. The device must be * allocated with input_allocate_device() and all it's capabilities * set up before registering. * If function fails the device must be freed with input_free_device(). * Once device has been successfully registered it can be unregistered * with input_unregister_device(); input_free_device() should not be * called in this case. */int input_register_device(struct input_dev *dev){static atomic_t input_no = ATOMIC_INIT(0);struct input_handler *handler;const char *path;int error;/* Every input device generates EV_SYN/SYN_REPORT events. */__set_bit(EV_SYN, dev->evbit);/* KEY_RESERVED is not supposed to be transmitted to userspace. */__clear_bit(KEY_RESERVED, dev->keybit);/* Make sure that bitmasks not mentioned in dev->evbit are clean. */input_cleanse_bitmasks(dev);/* * If delay and period are pre-set by the driver, then autorepeating * is handled by the driver itself and we don't do it in input.c. */init_timer(&dev->timer);if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {dev->timer.data = (long) dev;dev->timer.function = input_repeat_key;dev->rep[REP_DELAY] = 250;dev->rep[REP_PERIOD] = 33;}if (!dev->getkeycode)dev->getkeycode = input_default_getkeycode;if (!dev->setkeycode)dev->setkeycode = input_default_setkeycode;dev_set_name(&dev->dev, "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);error = device_add(&dev->dev);if (error)return error;path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);printk(KERN_INFO "input: %s as %s\n",dev->name ? dev->name : "Unspecified device", path ? path : "N/A");kfree(path);error = mutex_lock_interruptible(&input_mutex);if (error) {device_del(&dev->dev);return error;}list_add_tail(&dev->node, &input_dev_list);list_for_each_entry(handler, &input_handler_list, node)input_attach_handler(dev, handler);input_wakeup_procfs_readers();mutex_unlock(&input_mutex);return 0;}
下面對該函數的主要代碼進行分析。
第03~06行,定義了一些函數中將要用到的局部變數。
第07行,調用__set_bit()函數設定input_dev所支援的事件類型。事件類型由input_dev的evbit成員來表示,在這裡將其EV_SYN置位,表示裝置支援所有的事件。注意,一個裝置可以支援一種或者多種事件類型。常用的事件類型如下:
- #define EV_SYN 0x00 /*表示裝置支援所有的事件*/
- #define EV_KEY 0x01 /*鍵盤或者按鍵,表示一個鍵碼*/
- #define EV_REL 0x02 /*滑鼠裝置,表示一個相對的游標位置結果*/
- #define EV_ABS 0x03 /*手寫板產生的值,其是一個絕對整數值*/
- #define EV_MSC 0x04 /*其他類型*/
- #define EV_LED 0x11 /*LED燈裝置*/
- #define EV_SND 0x12 /*蜂鳴器,輸入聲音*/
- #define EV_REP 0x14 /*允許重複按鍵類型*/
- #define EV_PWR 0x16 /*電源管理事件*/
dev_set_name設定input_dev中的device的名字,名字以input0、input1、input2、input3、input4等的形式出現在sysfs檔案系統中。
使用device_add()函數將input_dev包含的device結構註冊到Linux裝置模型中,並可以在sysfs檔案系統中表現出來。
列印裝置的路徑,輸出調試資訊。
調用list_add_tail()函數將input_dev加入input_dev_list鏈表中,input_dev_list鏈表中包含了系統中所有的input_dev裝置。