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設備。