Iput子系统模型探究--2(handler-->以evdev_handler为例)



3. 关于input_handler
//Evdev--> Event char devices, giving access to raw input device events.
接下来以evdev(Input driver event char devices)为例,探究基本的handler;

3.1 input_handler数据结构
struct input_handler {

 void *private;  /*私有数据*/

 /*@event: event handler. This method is being called by input core with
  * interrupts disabled and dev->event_lock spinlock held and so
  * it may not sleep
  */
 void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
 /*
 * @filter: similar to @event; separates normal event handlers from
  *"filters".*/
 bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
 
 /** @match: called after comparing device's id with handler's id_table
 * to perform fine-grained matching between device and handler
  */
 bool (*match)(struct input_handler *handler, struct input_dev *dev);
 
 /* * @connect: called when attaching a handler to an input device*/
 int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
 
 /* * @disconnect: disconnects a handler from input device*/
 void (*disconnect)(struct input_handle *handle);
 /*
  * @start: starts handler for given handle. This function is called by
  * input core right after connect() method and also when a process
  * that "grabbed" a device releases it*/
 void (*start)(struct input_handle *handle);

 /* @fops: file operations this driver implements*/
 const struct file_operations *fops;
 
 /** @minor: beginning of range of 32 minors for devices this driver
  **can provide*/
 int minor;
 
 /*@name: name of the handler, to be shown in /proc/bus/input/handlers*/
 const char *name;
 
 /* * @id_table: pointer to a table of input_device_ids this driver can
 * handle,匹配的时候用*/
 const struct input_device_id *id_table;
 
 /** @h_list: list of input handles associated with the handler*/
 struct list_head h_list;
 
 /*@node: for placing the driver onto input_handler_list*/
 struct list_head node;
};


3.2 初始化evdev
static int __init evdev_init(void)
{
 return input_register_handler(&evdev_handler);
}

直接看--input_register_handler
/**
 * input_register_handler - register a new input handler
 * @handler: handler to be registered
 *
 * This function registers a new input handler (interface) for input
 * devices in the system
 
 **and attaches it to all input devices that are compatible with the handler.
 */
 
int input_register_handler(struct input_handler *handler)
{
 struct input_dev *dev;
 int retval;

 retval = mutex_lock_interruptible(&input_mutex); //互斥访问--防止并发(链表也相当于资源)
 if (retval)
  return retval;

 INIT_LIST_HEAD(&handler->h_list);  //初始化h_list, 用于handle

 if (handler->fops != NULL) {
  if (input_table[handler->minor >> 5]) {
   retval = -EBUSY;
   goto out;
  }
  input_table[handler->minor >> 5] = handler; //将handler填入全局变量input_table中
 }

 list_add_tail(&handler->node, &input_handler_list); //将handler添加到input_handler_list全局handler链表中

 /**input_attach_handler这个函数在注册input_dev设备时调用到,在注册input_handler驱动时也调用到*/
 
 list_for_each_entry(dev, &input_dev_list, node) //遍历input_dev_list设备链表,匹配handler和input_device
  input_attach_handler(dev, handler); 

 input_wakeup_procfs_readers();

 out:
 mutex_unlock(&input_mutex);   //解锁
 return retval;
}


/******************接下来分析****handler->connect**************************/
在evdev中handler->connect=evdev_connect;

static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
    const struct input_device_id *id)
{
 struct evdev *evdev;
 int minor;
 int error;

 /*查找全局evdev_table中可用的号码*/
 for (minor = 0; minor < EVDEV_MINORS; minor++)   //minor < 32
  if (!evdev_table[minor])
   break;

 if (minor == EVDEV_MINORS) {
  pr_err("no more free evdev devices\n");
  return -ENFILE;
 }

 /*分配evdev*/
 evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);

 INIT_LIST_HEAD(&evdev->client_list);  //初始化client_list-->用来连接客户端client
 spin_lock_init(&evdev->client_lock);  //初始化链表锁-->互斥访问client_list,防止并发
 mutex_init(&evdev->mutex);     //初始化evdev防止并发访问    
 init_waitqueue_head(&evdev->wait);   //初始化等待队列

 dev_set_name(&evdev->dev, "event%d", minor);   //设置evdev->dev的名字-->event%d
 evdev->exist = true;      //设置evdev存在标志
 evdev->minor = minor;      //设置evdev次设备号

 /*将handler驱动 和 input_dev设备用handle连接起来*/
 evdev->handle.dev = input_get_device(dev);   
 evdev->handle.name = dev_name(&evdev->dev); 
 evdev->handle.handler = handler;     
 evdev->handle.private = evdev;    //设置handle.private数据    

 evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor); //设置evdev->dev的设备号--主设备号13,用于创建设备文件
 evdev->dev.class = &input_class;   //设置设备类-->属于input_class类
 evdev->dev.parent = &dev->dev;    
 evdev->dev.release = evdev_free;
 
 /********前面Linux驱动模型探究--3(device)*************/
 
 device_initialize(&evdev->dev);      //初始化设备

  /*input_register_handle - register a new input handle
   *handle: handle to register*/
 error = input_register_handle(&evdev->handle);  //注册handle,和input_dev和handler建立连接 


 error = evdev_install_chrdev(evdev);   

 error = device_add(&evdev->dev);    //注册evdev , 生成设备文件(event%d)
 return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值