zoukankan      html  css  js  c++  java
  • Linux设备驱动剖析之Input(四)

    00000076 static void input_pass_event(struct input_dev *dev,
    00000077                  unsigned int type, unsigned int code, int value)
    00000078 {
    00000079     struct input_handler *handler;
    00000080     struct input_handle *handle;
    00000081 
    00000082     rcu_read_lock();
    00000083 
    00000084     handle = rcu_dereference(dev->grab);
    00000085     if (handle)
    00000086         handle->handler->event(handle, type, code, value);
    00000087     else {
    00000088         bool filtered = false;
    00000089 
    00000090         list_for_each_entry_rcu(handle, &dev->h_list, d_node) {
    00000091             if (!handle->open)
    00000092                 continue;
    00000093 
    00000094             handler = handle->handler;
    00000095             if (!handler->filter) {
    00000096                 if (filtered)
    00000097                     break;
    00000098 
    00000099                 handler->event(handle, type, code, value);
    00000100 
    00000101             } else if (handler->filter(handle, type, code, value))
    00000102                 filtered = true;
    00000103         }
    00000104     }
    00000105 
    00000106     rcu_read_unlock();
    00000107 }

    84至86行,如果有为Input设备指定handle,那么就执行该handle的handler的event函数,这里默认是没有指定的,用户程序可以通过ioctl函数来指定。

    90行,遍历Input设备的handle链表,经过一些检查后会执行handler->event函数,即,drivers/input/evdev.c里的evdev_event函数,这时Input消息已经传递到事件驱动程序层了,暂时先不说evdev_event函数,但是要记得Input消息已经来到了这里。我们知道,应用程序使用设备之前要先open它(这里忽略了网络设备),最终会调用驱动程序里的open函数,那么下面看drivers/input/evdev.c里定义的open函数evdev_open。

    00000260 static int evdev_open(struct inode *inode, struct file *file)
    00000261 {
    00000262     struct evdev *evdev;
    00000263     struct evdev_client *client;
    00000264     int i = iminor(inode) - EVDEV_MINOR_BASE;
    00000265     unsigned int bufsize;
    00000266     int error;
    00000267 
    00000268     if (i >= EVDEV_MINORS)
    00000269         return -ENODEV;
    00000270 
    00000271     error = mutex_lock_interruptible(&evdev_table_mutex);
    00000272     if (error)
    00000273         return error;
    00000274     evdev = evdev_table[i];
    00000275     if (evdev)
    00000276         get_device(&evdev->dev);
    00000277     mutex_unlock(&evdev_table_mutex);
    00000278 
    00000279     if (!evdev)
    00000280         return -ENODEV;
    00000281 
    00000282     bufsize = evdev_compute_buffer_size(evdev->handle.dev);
    00000283 
    00000284     client = kzalloc(sizeof(struct evdev_client) +
    00000285                 bufsize * sizeof(struct input_event),
    00000286              GFP_KERNEL);
    00000287     if (!client) {
    00000288         error = -ENOMEM;
    00000289         goto err_put_evdev;
    00000290     }
    00000291 
    00000292     client->bufsize = bufsize;
    00000293     spin_lock_init(&client->buffer_lock);
    00000294     client->evdev = evdev;
    00000295     evdev_attach_client(evdev, client);
    00000296 
    00000297     error = evdev_open_device(evdev);
    00000298     if (error)
    00000299         goto err_free_client;
    00000300 
    00000301     file->private_data = client;
    00000302     nonseekable_open(inode, file);
    00000303 
    00000304     return 0;
    00000305 
    00000306  err_free_client:
    00000307     evdev_detach_client(evdev, client);
    00000308     kfree(client);
    00000309  err_put_evdev:
    00000310     put_device(&evdev->dev);
    00000311     return error;
    00000312 }

    264行,获取次设备号。

    268行,如果次设备号大于EVDEV_MINORS,就不用往下走了,返回出错。

    274行,从evdev_table数组中取出对应的struct evdev实例。

    282行,调用evdev_compute_buffer_size函数计算环形缓冲区的长度。

    00000251 static unsigned int evdev_compute_buffer_size(struct input_dev *dev)
    00000252 {
    00000253     unsigned int n_events =
    00000254         max(dev->hint_events_per_packet * EVDEV_BUF_PACKETS,
    00000255             EVDEV_MIN_BUFFER_SIZE);
    00000256 
    00000257     return roundup_pow_of_two(n_events);
    00000258 }

    254行,EVDEV_BUF_PACKETS的值为8,hint_events_per_packet为0,因此n_events的值就为EVDEV_MIN_BUFFER_SIZE,即64。

    257行,将n_events的值调整到2的幂次方。

          回到evdev_open函数,284至290行,为struct evdev_client实例分配内存,注意所分配内存的大小。

    295行,调用evdev_attach_client函数,定义如下:

    00000168 static void evdev_attach_client(struct evdev *evdev,
    00000169                 struct evdev_client *client)
    00000170 {
    00000171     spin_lock(&evdev->client_lock);
    00000172     list_add_tail_rcu(&client->node, &evdev->client_list);
    00000173     spin_unlock(&evdev->client_lock);
    00000174     synchronize_rcu();
    00000175 }

    172行,就是将client加入到struct evdev实例的链表尾部。

    297行,evdev_open_device函数的定义:

    00000186 static int evdev_open_device(struct evdev *evdev)
    00000187 {
    00000188     int retval;
    00000189 
    00000190     retval = mutex_lock_interruptible(&evdev->mutex);
    00000191     if (retval)
    00000192         return retval;
    00000193 
    00000194     if (!evdev->exist)
    00000195         retval = -ENODEV;
    00000196     else if (!evdev->open++) {
    00000197         retval = input_open_device(&evdev->handle);
    00000198         if (retval)
    00000199             evdev->open--;
    00000200     }
    00000201 
    00000202     mutex_unlock(&evdev->mutex);
    00000203     return retval;
    00000204 }

    194行,exist在evdev_connect函数里已经设置为true。

    196行,open计数加1。

    197行,input_open_device函数在input core里定义:

    00000502 int input_open_device(struct input_handle *handle)
    00000503 {
    00000504     struct input_dev *dev = handle->dev;
    00000505     int retval;
    00000506 
    00000507     retval = mutex_lock_interruptible(&dev->mutex);
    00000508     if (retval)
    00000509         return retval;
    00000510 
    00000511     if (dev->going_away) {
    00000512         retval = -ENODEV;
    00000513         goto out;
    00000514     }
    00000515 
    00000516     handle->open++;
    00000517 
    00000518     if (!dev->users++ && dev->open)
    00000519         retval = dev->open(dev);
    00000520 
    00000521     if (retval) {
    00000522         dev->users--;
    00000523         if (!--handle->open) {
    00000524             /*
    00000525              * Make sure we are not delivering any more events
    00000526              * through this handle
    00000527              */
    00000528             synchronize_rcu();
    00000529         }
    00000530     }
    00000531 
    00000532  out:
    00000533     mutex_unlock(&dev->mutex);
    00000534     return retval;
    00000535 }

    511至514行,如果Input设备还没准备好,那么就返回。

    516行,将handle的open计数加1,表示此handle已经打开。

    519行,调用Input设备里的open函数,对于本文,里面啥事也没做,直接返回0,因此521至530行不用管。

          退回到evdev_open函数,301行,将文件的私有数据指针指向此client。

    302行,nonseekable_open函数不说了,就是设置文件的模式,定义很简单,如下:

    int nonseekable_open(struct inode *inode, struct file *filp)
    {
        filp->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
        return 0;
    }

          下面是一张简单的描述evdev是怎么把client连接起来的图。

    此时用户程序已经open了设备,假设接下来用户程序执行read函数读取Input消息,下面看此驱动里read函数evdev_read的定义:

    00000366 static ssize_t evdev_read(struct file *file, char __user *buffer,
    00000367               size_t count, loff_t *ppos)
    00000368 {
    00000369     struct evdev_client *client = file->private_data;
    00000370     struct evdev *evdev = client->evdev;
    00000371     struct input_event event;
    00000372     int retval;
    00000373 
    00000374     if (count < input_event_size())
    00000375         return -EINVAL;
    00000376 
    00000377     if (client->head == client->tail && evdev->exist &&
    00000378         (file->f_flags & O_NONBLOCK))
    00000379         return -EAGAIN;
    00000380 
    00000381     retval = wait_event_interruptible(evdev->wait,
    00000382         client->head != client->tail || !evdev->exist);
    00000383     if (retval)
    00000384         return retval;
    00000385 
    00000386     if (!evdev->exist)
    00000387         return -ENODEV;
    00000388 
    00000389     while (retval + input_event_size() <= count &&
    00000390            evdev_fetch_next_event(client, &event)) {
    00000391 
    00000392         if (input_event_to_user(buffer + retval, &event))
    00000393             return -EFAULT;
    00000394 
    00000395         retval += input_event_size();
    00000396     }
    00000397 
    00000398     return retval;
    00000399 }

    374行,input_event_size函数的定义有两种,一种是为了考虑兼容性的,这里为了简单起见,只看不需要兼容性那种的定义,在drivers/input/input-compat.h中:

    00000076 static inline size_t input_event_size(void)
    00000077 {
    00000078     return sizeof(struct input_event);
    00000079 }

    很简单,直接返回struct input_event结构体的大小。那么374行的意思就很明显了,就是说用户程序read的数据不能小于struct input_event结构体的大小。

    377至379行,此时,第一和第二个条件都会成立,关键是看第三个条件,这个条件是否成立取决于用户程序是以怎样的方式打开设备文件的,是阻塞还是非阻塞,这里很明显,不能以非阻塞方式打开设备文件,否则返回出错。

    381至384行,等待,有承若才会有等待,这个等待可能是无了期的,现实也是这样,承若不一定都能够实现,算了,说得有点伤感了。

    接下来我们要看这个承若是怎么实现的。前面说过,Input消息已经进入了evdev_event函数,下面就看它的定义:

    00000075 static void evdev_event(struct input_handle *handle,
    00000076             unsigned int type, unsigned int code, int value)
    00000077 {
    00000078     struct evdev *evdev = handle->private;
    00000079     struct evdev_client *client;
    00000080     struct input_event event;
    00000081 
    00000082     do_gettimeofday(&event.time);
    00000083     event.type = type;
    00000084     event.code = code;
    00000085     event.value = value;
    00000086 
    00000087     rcu_read_lock();
    00000088 
    00000089     client = rcu_dereference(evdev->grab);
    00000090     if (client)
    00000091         evdev_pass_event(client, &event);
    00000092     else
    00000093         list_for_each_entry_rcu(client, &evdev->client_list, node)
    00000094             evdev_pass_event(client, &event);
    00000095 
    00000096     rcu_read_unlock();
    00000097 
    00000098     wake_up_interruptible(&evdev->wait);
    00000099 }

    82至85行,填充struct input_event的实例evevt。从这里也看以知道,struct input_event表示消息的内容。

    89至91行,同样可以在用户空间通过ioctl为struct evdev实例指定client,默认是没有指定的。

    93、94行,遍历client_list链表,每找到一个client就调用evdev_pass_event函数,evdev_pass_event函数的定义如下:

    00000053 static void evdev_pass_event(struct evdev_client *client,
    00000054                  struct input_event *event)
    00000055 {
    00000056     /*
    00000057      * Interrupts are disabled, just acquire the lock.
    00000058      * Make sure we don't leave with the client buffer
    00000059      * "empty" by having client->head == client->tail.
    00000060      */
    00000061     spin_lock(&client->buffer_lock);
    00000062     do {
    00000063         client->buffer[client->head++] = *event;
    00000064         client->head &= client->bufsize - 1;
    00000065     } while (client->head == client->tail);
    00000066     spin_unlock(&client->buffer_lock);
    00000067 
    00000068     if (event->type == EV_SYN)
    00000069         kill_fasync(&client->fasync, SIGIO, POLL_IN);
    00000070 }

    63行,将Input消息放入client的环形缓冲区,接着client->head加1。

    64行,client->head的值不能大于client->bufsize – 1,也就是当client->head的值大于client->bufsize – 1时,让client->head的值回到0,从0开始再往上递增,为什么说是环形缓冲区也就是这个原因。

    68行,因为此时event->type的值是EV_KEY,所以条件不成立。

    回到evdev_event函数,98行,唤醒,到这里承若已经实现了,等待是值得的,不应该为暂时的美好而停下脚本,继续往下走吧。回到evdev_read剩下的内容,这里把它贴出来好了,省得再回去看。

    00000381     retval = wait_event_interruptible(evdev->wait,
    00000382         client->head != client->tail || !evdev->exist);
    00000383     if (retval)
    00000384         return retval;
    00000385 
    00000386     if (!evdev->exist)
    00000387         return -ENODEV;
    00000388 
    00000389     while (retval + input_event_size() <= count &&
    00000390            evdev_fetch_next_event(client, &event)) {
    00000391 
    00000392         if (input_event_to_user(buffer + retval, &event))
    00000393             return -EFAULT;
    00000394 
    00000395         retval += input_event_size();
    00000396     }
    00000397 
    00000398     return retval;
    00000399 }

    382行,唤醒的条件是因为client->head != client->tail,顺便提一下,此时client->head=1,client->tail=0。

    390行,evdev_fetch_next_event函数的定义:

    00000348 static int evdev_fetch_next_event(struct evdev_client *client,
    00000349                   struct input_event *event)
    00000350 {
    00000351     int have_event;
    00000352 
    00000353     spin_lock_irq(&client->buffer_lock);
    00000354 
    00000355     have_event = client->head != client->tail;
    00000356     if (have_event) {
    00000357         *event = client->buffer[client->tail++];
    00000358         client->tail &= client->bufsize - 1;
    00000359     }
    00000360 
    00000361     spin_unlock_irq(&client->buffer_lock);
    00000362 
    00000363     return have_event;
    00000364 }

    355行,因为client->head != client->tail,所以have_event的值不为0,356行的if条件成立。

    357行,从环形缓冲区中取出一个Input消息,接着client->tail的值加1。

    358行,同样是为了保证client->tail的值不会大于client->bufsize – 1。

          回到evdev_read函数,此时389行的while条件成立。

    392行,为了保持兼容性,input_event_to_user函数同样有两种定义,看不考虑兼容性那一种,在drivers/input/input-compat.c中。

    00000110 int input_event_to_user(char __user *buffer,
    00000111             const struct input_event *event)
    00000112 {
    00000113     if (copy_to_user(buffer, event, sizeof(struct input_event)))
    00000114         return -EFAULT;
    00000115 
    00000116     return 0;
    00000117 }

    就是对copy_to_user函数的封装,这样Input消息就传递到用户空间了,接下来应用程序想对它干嘛就干嘛。但是别忘了gpio_keys_report_event函数里还有一条语句没有执行,下面把gpio_keys_report_event函数的定义在贴一遍:

    00000320 static void gpio_keys_report_event(struct gpio_button_data *bdata)
    00000321 {
    00000322     struct gpio_keys_button *button = bdata->button;
    00000323     struct input_dev *input = bdata->input;
    00000324     unsigned int type = button->type ?: EV_KEY;
    00000325     int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low;
    00000326 
    00000327     input_event(input, type, button->code, !!state);
    00000328     input_sync(input);
    00000329 }

    上面的内容是从327行的input_event函数一直讲的,下面把最后一个函数的调用过程讲完,看328行的input_sync函数的定义:

    00001423 static inline void input_sync(struct input_dev *dev)
    00001424 {
    00001425     input_event(dev, EV_SYN, SYN_REPORT, 0);
    00001426 }

    其实就是input_event函数的封装,只是参数值不一样而已,这里需要记住它的后三个参数。

    在input_event函数里会调用input_handle_event函数,这里有必要把input_handle_event函数的定义再贴一遍:

    00000215 static void input_handle_event(struct input_dev *dev,
    00000216                    unsigned int type, unsigned int code, int value)
    00000217 {
    00000218     int disposition = INPUT_IGNORE_EVENT;
    00000219 
    00000220     switch (type) {
    00000221 
    00000222     case EV_SYN:
    00000223         switch (code) {
    00000224         case SYN_CONFIG:
    00000225             disposition = INPUT_PASS_TO_ALL;
    00000226             break;
    00000227 
    00000228         case SYN_REPORT:
    00000229             if (!dev->sync) {
    00000230                 dev->sync = true;
    00000231                 disposition = INPUT_PASS_TO_HANDLERS;
    00000232             }
    00000233             break;
    00000234         case SYN_MT_REPORT:
    00000235             dev->sync = false;
    00000236             disposition = INPUT_PASS_TO_HANDLERS;
    00000237             break;
    00000238         }
    00000239         break;
    00000240 
    00000241     case EV_KEY:
    00000242         if (is_event_supported(code, dev->keybit, KEY_MAX) &&
    00000243             !!test_bit(code, dev->key) != value) {
    00000244 
    00000245             if (value != 2) {
    00000246                 __change_bit(code, dev->key);
    00000247                 if (value)
    00000248                     input_start_autorepeat(dev, code);
    00000249                 else
    00000250                     input_stop_autorepeat(dev);
    00000251             }
    00000252 
    00000253             disposition = INPUT_PASS_TO_HANDLERS;
    00000254         }
    00000255         break;
    00000256 
    00000257     case EV_SW:
    00000258         if (is_event_supported(code, dev->swbit, SW_MAX) &&
    00000259             !!test_bit(code, dev->sw) != value) {
    00000260 
    00000261             __change_bit(code, dev->sw);
    00000262             disposition = INPUT_PASS_TO_HANDLERS;
    00000263         }
    00000264         break;
    00000265 
    00000266     case EV_ABS:
    00000267         if (is_event_supported(code, dev->absbit, ABS_MAX))
    00000268             disposition = input_handle_abs_event(dev, code, &value);
    00000269 
    00000270         break;
    00000271 
    00000272     case EV_REL:
    00000273         if (is_event_supported(code, dev->relbit, REL_MAX) && value)
    00000274             disposition = INPUT_PASS_TO_HANDLERS;
    00000275 
    00000276         break;
    00000277 
    00000278     case EV_MSC:
    00000279         if (is_event_supported(code, dev->mscbit, MSC_MAX))
    00000280             disposition = INPUT_PASS_TO_ALL;
    00000281 
    00000282         break;
    00000283 
    00000284     case EV_LED:
    00000285         if (is_event_supported(code, dev->ledbit, LED_MAX) &&
    00000286             !!test_bit(code, dev->led) != value) {
    00000287 
    00000288             __change_bit(code, dev->led);
    00000289             disposition = INPUT_PASS_TO_ALL;
    00000290         }
    00000291         break;
    00000292 
    00000293     case EV_SND:
    00000294         if (is_event_supported(code, dev->sndbit, SND_MAX)) {
    00000295 
    00000296             if (!!test_bit(code, dev->snd) != !!value)
    00000297                 __change_bit(code, dev->snd);
    00000298             disposition = INPUT_PASS_TO_ALL;
    00000299         }
    00000300         break;
    00000301 
    00000302     case EV_REP:
    00000303         if (code <= REP_MAX && value >= 0 && dev->rep[code] != value) {
    00000304             dev->rep[code] = value;
    00000305             disposition = INPUT_PASS_TO_ALL;
    00000306         }
    00000307         break;
    00000308 
    00000309     case EV_FF:
    00000310         if (value >= 0)
    00000311             disposition = INPUT_PASS_TO_ALL;
    00000312         break;
    00000313 
    00000314     case EV_PWR:
    00000315         disposition = INPUT_PASS_TO_ALL;
    00000316         break;
    00000317     }
    00000318 
    00000319     if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
    00000320         dev->sync = false;
    00000321 
    00000322     if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)
    00000323         dev->event(dev, type, code, value);
    00000324 
    00000325     if (disposition & INPUT_PASS_TO_HANDLERS)
    00000326         input_pass_event(dev, type, code, value);
    00000327 }

    这时,进入的是222行的case,接着进入228行的case,229行,dev->sync的值到现在一直没有被设置过,因此if条件成立。

    230行,dev->sync = true。

    231行,disposition = INPUT_PASS_TO_HANDLERS。

    接下来两次break,跳出switch到319行,319和322行的if条件都不成立,因此又是执行326行的input_pass_event函数,这个过程前面已经讲过了,最后也是会到达evdev_event函数,唯一不同的是,在evdev_pass_event函数会执行下面的语句。

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

    这是异步通知机制发送信号到用户空间,如果用户程序有设置使用这种机制,那么用户程序中指定的函数就会被调用。

          到这里,Linux Input子系统的工作过程已经说完了,当然还有其他很多内容没有分析到,不过已经对其工作原理有一个比较深入的了解了,由于本人知识水平和精力有限,没办法做到面面俱到,当中有什么错误,望不吝指出。

    总结

          Linux的SPI、IIC和Input子系统都已经分析过了,马上就要找工作了,如果时间允许的话,接下来我会结合实际硬件写几篇关于它们具体使用方法的文章。

  • 相关阅读:
    黑客技术训练场
    常用安全测试用例
    Burp suite 一款Web渗透测试的集成套件
    soapUI安全测试教程
    黑客视频动画
    Cookie安全测试
    安全测试资源列表【持续收集中】
    软件安全测试系列视频
    软件安全测试辅助工具列表【持续收集中】
    WEB安全问题的层次
  • 原文地址:https://www.cnblogs.com/lknlfy/p/3275875.html
Copyright © 2011-2022 走看看