歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux Input子系統(中)--設備的注冊和打開

Linux Input子系統(中)--設備的注冊和打開

日期:2017/3/1 10:17:51   编辑:Linux編程

這節結合even handler來分析設備的注冊和打開的過程,在設備注冊之前,必須先初始化INPUT子系統,由input_init()函數來完成

相關閱讀:Linux Input子系統(上)--概述 http://www.linuxidc.com/Linux/2012-07/64419.htm

  1. static int __init input_init(void)
  2. {
  3. int err;
  4. input_init_abs_bypass();
  5. err = class_register(&input_class);//注冊input類
  6. if (err) {
  7. printk(KERN_ERR "input: unable to register input_dev class\n");
  8. return err;
  9. }
  10. err = input_proc_init();//創建/proc中的項
  11. if (err)
  12. goto fail1;
  13. /*注冊設備,設備號為INPUT_MAJOR(13),後面注冊的輸入設備都使用該主設備號*/
  14. err = register_chrdev(INPUT_MAJOR, "input", &input_fops);
  15. if (err) {
  16. printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);
  17. goto fail2;
  18. }
  19. return 0;
  20. fail2: input_proc_exit();
  21. fail1: class_unregister(&input_class);
  22. return err;
  23. }

input_fops中只定義了open函數。

  1. static const struct file_operations input_fops = {
  2. .owner = THIS_MODULE,
  3. .open = input_open_file,
  4. };

我們需要在設備驅動層中完成輸入設備的注冊,通過調用input_register_device()函數來完成,該函數的一個重要任務就是完成設備與事件驅動的匹配。

  1. int input_register_device(struct input_dev *dev)
  2. {
  3. static atomic_t input_no = ATOMIC_INIT(0);
  4. struct input_handler *handler;
  5. const char *path;
  6. int error;
  7. __set_bit(EV_SYN, dev->evbit);
  8. /*
  9. * If delay and period are pre-set by the driver, then autorepeating
  10. * is handled by the driver itself and we don't do it in input.c.
  11. */
  12. init_timer(&dev->timer);
  13. if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
  14. dev->timer.data = (long) dev;
  15. dev->timer.function = input_repeat_key;
  16. dev->rep[REP_DELAY] = 250;
  17. dev->rep[REP_PERIOD] = 33;
  18. }
  19. /*沒有定義設備的getkeycode函數,則使用默認的獲取鍵值函數*/
  20. if (!dev->getkeycode)
  21. dev->getkeycode = input_default_getkeycode;
  22. /*沒有定義設備的setkeycode函數,則使用默認的設定鍵值函數*/
  23. if (!dev->setkeycode)
  24. dev->setkeycode = input_default_setkeycode;
  25. /*設定dev的名字*/
  26. dev_set_name(&dev->dev, "input%ld",
  27. (unsigned long) atomic_inc_return(&input_no) - 1);
  28. /*添加設備*/
  29. error = device_add(&dev->dev);
  30. if (error)
  31. return error;
  32. path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
  33. printk(KERN_INFO "input: %s as %s\n",
  34. dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
  35. kfree(path);
  36. error = mutex_lock_interruptible(&input_mutex);
  37. if (error) {
  38. device_del(&dev->dev);
  39. return error;
  40. }
  41. /*將設備添加到input_dev_list設備鏈表*/
  42. list_add_tail(&dev->node, &input_dev_list);
  43. /*遍歷input_handler_list,試圖與每一個handler進行匹配*/
  44. list_for_each_entry(handler, &input_handler_list, node)
  45. input_attach_handler(dev, handler);
  46. input_wakeup_procfs_readers();
  47. mutex_unlock(&input_mutex);
  48. return 0;
  49. }

  1. static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
  2. {
  3. const struct input_device_id *id;
  4. int error;
  5. /*如果定義了handler的黑名單,並且設備和黑名單中的id匹配了,則該設備不能和handler匹配*/
  6. if (handler->blacklist && input_match_device(handler->blacklist, dev))
  7. return -ENODEV;
  8. id = input_match_device(handler->id_table, dev);
  9. if (!id)
  10. return -ENODEV;
  11. /*執行handler的connect,建立handler與設備之間的聯系*/
  12. error = handler->connect(handler, dev, id);
  13. if (error && error != -ENODEV)
  14. printk(KERN_ERR
  15. "input: failed to attach handler %s to device %s, "
  16. "error: %d\n",
  17. handler->name, kobject_name(&dev->dev.kobj), error);
  18. return error;
  19. }
Copyright © Linux教程網 All Rights Reserved