Iput設備使用分析--1(驅動層面)



4. 使用input_device分析
/****************怎樣使用input系統--簡單的分析********************/

static int __init inputdev_init(void)
{
  
 struct input_dev* inputdev = input_allocate_device(); /*1分配input_dev設備*/
 
 set_bit(EV_KEY, inputdev->evbit);  /*設置事件類型--按鍵類型*/
 
 /*設置按鍵--->linux系統中已經分配好了按鍵值--例如
 #define KEY_1   2
 #define KEY_2   3
 #define KEY_3   4
 #define KEY_4   5
 */
 set_bit(KEY_1, inputdev->evbit); 
 set_bit(KEY_2, inputdev->evbit);
 set_bit(KEY_3, inputdev->evbit);
 set_bit(KEY_4, inputdev->evbit); 
  
 /*然後註冊設備 */
 input_register_device(inputdev);
 
}


/*當按鍵值發生變化,要將按鍵值往上報告----比如在中斷處理函數中報告*/

/**dev-->哪個input_dev設備;code-->按鍵編號KEY_1/2/3/4; value-->鍵值*/
用函數--input_report_key(struct input_dev *dev, unsigned int code, int value)
{
   input_report_key(button_dev,KEY_4,1);
  
   input_report_key(button_dev,KEY_3,1);
  
   input_sync(inputdev);-->input_event(dev, EV_SYN, SYN_REPORT, 0);
}

/************再來分析input_report_key()****************/
執行線路:input_report_key()-->input_event-->input_handle_event-->input_pass_event ;

static void input_pass_event(struct input_dev *dev,
        unsigned int type, unsigned int code, int value)
{
 struct input_handler *handler;
 struct input_handle *handle;

 rcu_read_lock();

 handle = rcu_dereference(dev->grab);
 if (handle)
  handle->handler->event(handle, type, code, value);
 else {
  bool filtered = false;
  
 /*在dev->h_list中(handle註冊中->input_register_handle建立的關係)取得handle*/
  list_for_each_entry_rcu(handle, &dev->h_list, d_node) {  
  
   if (!handle->open)
    continue;

   handler = handle->handler;
   if (!handler->filter) {
    if (filtered)
     break;

    handler->event(handle, type, code, value);  /*接下來調用handler->event處理函數-->evdev_event*/

   } else if (handler->filter(handle, type, code, value))
    filtered = true;
  }
 }
}

/*********************接着分析evdev_event()************************/
/*
 * Pass incoming event to all connected clients.
 */
static void evdev_event(struct input_handle *handle,
   unsigned int type, unsigned int code, int value)
{
 struct evdev *evdev = handle->private;
 
 struct evdev_client *client;  /*事件客戶端---evdev_client主要是用來接受事件--event*/
 struct input_event event;

 /*給事件賦值*/
 do_gettimeofday(&event.time);
 event.type = type;
 event.code = code;
 event.value = value;

 rcu_read_lock();

 client = rcu_dereference(evdev->grab);
 if (client)
  evdev_pass_event(client, &event);
 else
 /*遍歷evdev中的鏈表,接着調用evdev_pass_event,提交客戶端client*/
  list_for_each_entry_rcu(client, &evdev->client_list, node)
   evdev_pass_event(client, &event);          

 rcu_read_unlock();

 wake_up_interruptible(&evdev->wait);
}

static void evdev_pass_event(struct evdev_client *client,
        struct input_event *event)
{
 /*
  * Interrupts are disabled, just acquire the lock.
  * Make sure we don't leave with the client buffer
  * "empty" by having client->head == client->tail.
  */
 spin_lock(&client->buffer_lock);
 do {
  client->buffer[client->head++] = *event;   //將事件寫入client->buffer中,等待應用程序來處理
  client->head &= client->bufsize - 1;
 } while (client->head == client->tail);
 spin_unlock(&client->buffer_lock);

 if (event->type == EV_SYN)
  kill_fasync(&client->fasync, SIGIO, POLL_IN);
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章