分类:
2012-03-14 15:35:32
原文地址:LINUX设备驱动之输入子系统(二) 作者:eric_fang
Eric Fang 2010-02-03
--------------------------------------------------------------
本站分析linux内核源码,版本号为2.6.32.3
转载请注明出处:http://ericfang.cublog.cn/
--------------------------------------------------------------
接上一篇文章继续分析。
二.Input handler的注册
在Input device的注册中存在下列疑问:
1, 匹配dev和handler时,input_handler_list上的handler是什么时候挂上去的呢?
2, 匹配成功后会调用相应handler的connect函数,此函数做了什么事?
带着这两个疑问,我们以键盘为例进行分析。
在系统启动初始化vty(vty_init函数,tty、vty部分内容将在以后分析)时会调用kbd_init()进行键盘初始化,kbd_init函数定义于drivers/char/keyboard.c:
1403 int __init kbd_init(void)
1404 {
1405 int i;
1406 int error;
1407
1408 for (i = 0; i < MAX_NR_CONSOLES; i++) {
1409 kbd_table[i].ledflagstate = KBD_DEFLEDS;
1410 kbd_table[i].default_ledflagstate = KBD_DEFLEDS;
1411 kbd_table[i].ledmode = LED_SHOW_FLAGS;
1412 kbd_table[i].lockstate = KBD_DEFLOCK;
1413 kbd_table[i].slockstate = 0;
1414 kbd_table[i].modeflags = KBD_DEFMODE;
1415 kbd_table[i].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
1416 }
1417
1418 error = input_register_handler(&kbd_handler);
1419 if (error)
1420 return error;
1421
1422 tasklet_enable(&keyboard_tasklet);
1423 tasklet_schedule(&keyboard_tasklet);
1424
1425 return 0;
1426 }
第1408~1416行初始化kbd_table数组,这部分与tty内容相关,以后再分析。
1418行,这里我们终于看到调用input_register_handler函数注册kbd_handler,kbd_handler定义如下:
1394 static struct input_handler kbd_handler = {
1395 .event = kbd_event,
1396 .connect = kbd_connect,
1397 .disconnect = kbd_disconnect,
1398 .start = kbd_start,
1399 .name = "kbd",
1400 .id_table = kbd_ids,
1401 };
我们看到id_table指向kbd_ids数组,kbd_ids定义如下:
1378 static const struct input_device_id kbd_ids[] = {
1379 {
1380 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
1381 .evbit = { BIT_MASK(EV_KEY) },
1382 },
1383
1384 {
1385 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
1386 .evbit = { BIT_MASK(EV_SND) },
1387 },
1388
1389 { }, /* Terminating entry */
1390 };
从这个id_table看到,只要input_dev设置了其evbit字段支持EV_KEY或EV_SND都会匹配到hnadler,回想一下在键盘驱动中创建input_dev后调用的atkbd_set_device_attrs设置input_dev的函数中有下列语句:
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |
BIT_MASK(EV_MSC);
说明at键盘的input_dev会匹配到这个hnadler。
我们接着看input_register_handler函数:
1600 int input_register_handler(struct input_handler *handler)
1601 {
1602 struct input_dev *dev;
1603 int retval;
1604
1605 retval = mutex_lock_interruptible(&input_mutex);
1606 if (retval)
1607 return retval;
1608
1609 INIT_LIST_HEAD(&handler->h_list);
1610
1611 if (handler->fops != NULL) {
1612 if (input_table[handler->minor >> 5]) {
1613 retval = -EBUSY;
1614 goto out;
1615 }
1616 input_table[handler->minor >> 5] = handler;
1617 }
1618
1619 list_add_tail(&handler->node, &input_handler_list);
1620
1621 list_for_each_entry(dev, &input_dev_list, node)
1622 input_attach_handler(dev, handler);
1623
1624 input_wakeup_procfs_readers();
1625
1626 out:
1627 mutex_unlock(&input_mutex);
1628 return retval;
1629 }
第1605行获得互斥信号量,1609行初始化handler 的h_list字段,这个h_list指向的链表用于存放input_handle。
第1611~1617行,我们的kbd_handler没有定义fops函数,所以这段代码不会执行,不过我们还是看一下,这里的input_table数组是一个struct input_handler结构数组,根据设备的次设备号除以32的值为下标的元素为input_handler为什么是32?输入子系统最多支持256个设备,而input_handler结构的数组最多处理8类事件,所以分给每一类的次设备号段分配32个。
第1619行把handler链接到input_handler_list尾部。
第1621~1622用handler去匹配input_dev_list上的input_dev,input_attach_handler函数在上面已经分析过,再最后如果匹配成功会调用handler的connect函数,对于这个kbd_handler相应的函数为kbd_connect,看一下这个函数:
1314 static int kbd_connect(struct input_handler *handler, struct input_dev *dev,
1315 const struct input_device_id *id)
1316 {
1317 struct input_handle *handle;
1318 int error;
1319 int i;
1320
1321 for (i = KEY_RESERVED; i < BTN_MISC; i++)
1322 if (test_bit(i, dev->keybit))
1323 break;
1324
1325 if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit))
1326 return -ENODEV;
1327
1328 handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
1329 if (!handle)
1330 return -ENOMEM;
1331
1332 handle->dev = dev;
1333 handle->handler = handler;
1334 handle->name = "kbd";
1335
1336 error = input_register_handle(handle);
1337 if (error)
1338 goto err_free_handle;
1339
1340 error = input_open_device(handle);
1341 if (error)
1342 goto err_unregister_handle;
1343
1344 return 0;
1345
1346 err_unregister_handle:
1347 input_unregister_handle(handle);
1348 err_free_handle:
1349 kfree(handle);
1350 return error;
1351 }
第1321~1326行判断dev->keybit,如果属于例外的情况,则不再往下走,返回-ENODEV。
第1328行,为handle分配内存空间,1332~1334行初始化handle的部分字段。
第1336行调用input_register_handle注册handle,看一下这个函数:
1671 int input_register_handle(struct input_handle *handle)
1672 {
1673 struct input_handler *handler = handle->handler;
1674 struct input_dev *dev = handle->dev;
1675 int error;
1676
1677 /*
1678 * We take dev->mutex here to prevent race with
1679 * input_release_device().
1680 */
1681 error = mutex_lock_interruptible(&dev->mutex);
1682 if (error)
1683 return error;
1684 list_add_tail_rcu(&handle->d_node, &dev->h_list);
1685 mutex_unlock(&dev->mutex);
1686
1687 /*
1688 * Since we are supposed to be called from ->connect()
1689 * which is mutually exclusive with ->disconnect()
1690 * we can't be racing with input_unregister_handle()
1691 * and so separate lock is not needed here.
1692 */
1693 list_add_tail(&handle->h_node, &handler->h_list);
1694
1695 if (handler->start)
1696 handler->start(handle);
1697
1698 return 0;
1699 }
第1684、1693将handle分别链接到dev->h_list和handler->h_list。
第1695~1696行,如果handler的start函数存在,则调用它。对于这个kbd_handler相应的函数为kbd_start,看一下这个函数:
1364 static void kbd_start(struct input_handle *handle)
1365 {
1366 unsigned char leds = ledstate;
1367
1368 tasklet_disable(&keyboard_tasklet);
1369 if (leds != 0xff) {
1370 input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
1371 input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
1372 input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
1373 input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
1374 }
1375 tasklet_enable(&keyboard_tasklet);
1376 }
禁止keyboard_tasklet,初始化键盘的三个led灯及SYN_REPORT,然后启用keyboard_tasklet,这个keyboard_tasklet也是对led灯进行操作的,函数如下
1032 DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
1014 static void kbd_bh(unsigned long dummy)
1015 {
1016 struct list_head *node;
1017 unsigned char leds = getleds();
1018
1019 if (leds != ledstate) {
1020 list_for_each(node, &kbd_handler.h_list) {
1021 struct input_handle *handle = to_handle_h(node);
1022 input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
1023 input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
1024 input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
1025 input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
1026 }
1027 }
1028
1029 ledstate = leds;
1030 }
input_register_handle函数返回后,第1340行调用input_open_device函数,这个函数执行后相应的handle就能接受设备上报的事件。函数如下:
0421 int input_open_device(struct input_handle *handle)
0422 {
0423 struct input_dev *dev = handle->dev;
0424 int retval;
0425
0426 retval = mutex_lock_interruptible(&dev->mutex);
0427 if (retval)
0428 return retval;
0429
0430 if (dev->going_away) {
0431 retval = -ENODEV;
0432 goto out;
0433 }
0434
0435 handle->open++;
0436
0437 if (!dev->users++ && dev->open)
0438 retval = dev->open(dev);
0439
0440 if (retval) {
0441 dev->users--;
0442 if (!--handle->open) {
0443 /*
0444 * Make sure we are not delivering any more events
0445 * through this handle
0446 */
0447 synchronize_rcu();
0448 }
0449 }
0450
0451 out:
0452 mutex_unlock(&dev->mutex);
0453 return retval;
0454 }
增加handle的open计数,如果handle->dev->users不为0,则自增1,如果为0并且handle->dev的open函数存在则会调用它,对于前面分析的atkbd,相应的handle->dev的open函数不存在。
至此,input handler和input handler的注册都分析完了,接着将分析事件处理部分内容。
接下一篇文章。