Chinaunix首页 | 论坛 | 博客
  • 博客访问: 82235
  • 博文数量: 19
  • 博客积分: 325
  • 博客等级: 一等列兵
  • 技术积分: 197
  • 用 户 组: 普通用户
  • 注册时间: 2012-10-29 11:51
文章分类

全部博文(19)

文章存档

2013年(1)

2012年(18)

我的朋友

分类: LINUX

2012-10-29 11:53:58

1、参考文章
       【Andorid】input系统的事件处理

2、源码分析 linux 3.6.3
    1)查看linux-3.6.3/drivers/input下Makefile

点击(此处)折叠或打开

  1. obj-$(CONFIG_INPUT) += input-core.o
  2.     input-core-y := input.o input-compat.o input-mt.o ff-core.o

    2)查看文件input.c

点击(此处)折叠或打开

  1. /* input subsystem entry */
  2. subsys_initcall(input_init);
  3. module_exit(input_exit);

    3)input.c搞啥子

点击(此处)折叠或打开

  1. /* sysfs/procfs/devfs show */
  2.     |-----------|
  3.     |          \/
  4.     | err = class_register(&input_class);
  5.     |
  6.     |-----------|
  7.     |          \/
  8.     | err = input_proc_init();
  9.     |
  10.     |-----------|
  11.     |          \/
  12.     | err = register_chrdev(INPUT_MAJOR, "input", &input_fops);

根据下面的方法,发现手机的tp 对应event1

点击(此处)折叠或打开

  1.     # getevent 
  2.     add device 1: /dev/input/event0
  3.       name: "fluid-keypad"
  4.     add device 2: /dev/input/event3
  5.       name: "7k_handset"
  6.     add device 3: /dev/input/event2
  7.       name: "sensors"
  8.     add device 4: /dev/input/event1
  9.       name: "Synaptics RMI4"
  10.       
  11.     # pwd
  12.     /sys/class/input
  13.     # ls
  14.     event0 event1 event2 event3 input0 input1 input2 input3
  15.       
  16.     # cat /proc/bus/input/devices
  17.     I: Bus=0019 Vendor=0001 Product=0001 Version=0001
  18.     N: Name="fluid-keypad"
  19.     P: Phys=fluid-keypad/input0
  20.     S: Sysfs=/devices/i2c-6/6-0000/pm8058-keypad/input/input0
  21.     U: Uniq=
  22.     H: Handlers=kbd event0
  23.     B: EV=13
  24.     B: KEY=1200000 0 0 c0000 0 0 0
  25.     B: MSC=10
  26.       
  27.     I: Bus=0000 Vendor=0000 Product=0000 Version=0000
  28.     N: Name="Synaptics RMI4"
  29.     P: Phys=Synaptics_rmi
  30.     S: Sysfs=/devices/virtual/input/input1
  31.     U: Uniq=
  32.     H: Handlers=event1
  33.     B: EV=b
  34.     B: KEY=400 0 0 0 2000000 0 40000800 40 0 0 0
  35.     B: ABS=770000 11030003
  36.       
  37.     I: Bus=0018 Vendor=0003 Product=0000 Version=0000
  38.     N: Name="sensors"
  39.     P: Phys=
  40.     S: Sysfs=/devices/virtual/input/input2
  41.     U: Uniq=
  42.     H: Handlers=event2
  43.     B: EV=9
  44.     B: ABS=8000 20304bf
  45.       
  46.     I: Bus=0000 Vendor=0001 Product=0001 Version=0001
  47.     N: Name="7k_handset"
  48.     P: Phys=
  49.     S: Sysfs=/devices/virtual/input/input3
  50.     U: Uniq=
  51.     H: Handlers=kbd event3
  52.     B: EV=23
  53.     B: KEY=4 0 28 0 1c0800 0 0 0
  54.     B: SW=4

    4)touch panel驱动源码

点击(此处)折叠或打开

  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/slab.h>
  4. #include <linux/platform_device.h>
  5. #include <linux/i2c.h>
  6. #include <linux/input.h>
  7.   
  8. #include "gsl1680.h"
  9.   
  10. #define gsl_pr(fmt, arg...) \
  11.     printk(KERN_ERR "[GSL]%s: \033[32m" fmt "\033[0m\n", __FUNCTION__, ##arg)
  12.   
  13. #define GSL_ADAPTER_INDEX 0
  14. #define GSL1680D0_ID 0
  15. #define GSL_DEV_NAME "gsl"
  16.   
  17. /**
  18.  * Description : global var
  19.  */
  20. static struct gsl_ts_data *ddata = NULL;
  21. static const struct i2c_device_id gsl_id[] = {
  22.     {GSL_DEV_NAME, GSL1680D0_ID},
  23.     {},
  24. };
  25. MODULE_DEVICE_TABLE(silead, gsl_id);
  26.   
  27. static struct i2c_board_info gsl_i2c_info = {
  28.     .type = GSL_DEV_NAME,
  29.     .addr = 0x40,
  30. };
  31.   
  32. /**
  33.  * Description : gsl soc operation
  34.  */
  35. static int gsl_hw_init(void)
  36. {
  37.     return 0;
  38. }
  39.   
  40. static int gsl_sw_init(void)
  41. {
  42.     return 0;
  43. }
  44.   
  45. /**
  46.  * Description : touch panel driver
  47.  */
  48. static void gsl_report_work(struct work_struct *work)
  49. {
  50. }
  51.   
  52. static int gsl_request_input(void)
  53. {
  54.     int ret = 0;
  55.   
  56.     ddata->idev = input_allocate_device();
  57.     if (!ddata->idev) {
  58.         dev_err(&ddata->idev->dev, "could not allocate device\n");
  59.         return -ENODEV;
  60.     }
  61.   
  62.     ddata->idev->name = GSL_DEV_NAME;
  63.     ddata->idev->id.bustype = BUS_I2C;
  64.     ddata->idev->dev.parent = &ddata->client->dev;
  65.     input_set_drvdata(ddata->idev, ddata);
  66.   
  67.     __set_bit(EV_ABS, ddata->idev->evbit);
  68.   
  69.     input_set_abs_params(ddata->idev, ABS_MT_POSITION_X,
  70.         DIS_MIN_X, DIS_MAX_X, 0, 0);
  71.     input_set_abs_params(ddata->idev, ABS_MT_POSITION_Y,
  72.         DIS_MIN_Y, DIS_MAX_Y, 0, 0);
  73.     input_set_abs_params(ddata->idev, ABS_MT_TOUCH_MAJOR,
  74.         MIN_TOUCH, MAX_TOUCH, 0, 0);
  75.     input_set_abs_params(ddata->idev, ABS_MT_WIDTH_MAJOR,
  76.         MIN_WIDTH, MAX_WIDTH, 0, 0);
  77.     input_set_abs_params(ddata->idev, ABS_MT_TRACKING_ID,
  78.         MIN_TRCKID, MAX_TRCKID, 0, 0);
  79.   
  80.     INIT_WORK(&ddata->work, gsl_report_work);
  81.   
  82.     ddata->wq = create_singlethread_workqueue(GSL_DEV_NAME);
  83.     if (!ddata->wq) {
  84.         dev_err(&ddata->idev->dev, "could not create workqueue\n");
  85.         ret = -ENOMEM;
  86.         goto error_wq_create;
  87.     }
  88. #if 0
  89.     ddata->pm.suspend = gsl_suspend;
  90.     ddata->pm.resume = gsl_resume;
  91.     register_early_suspend(&ddata->pm);
  92. #endif
  93.     ret = input_register_device(ddata->idev);
  94.     if (ret) {
  95.         dev_err(&ddata->idev->dev, "ret = %d : could not register input device\n", ret);
  96.         goto error_unreg_device;
  97.     }
  98.     return 0;
  99.   
  100. error_unreg_device:
  101.     destroy_workqueue(ddata->wq);
  102. error_wq_create:
  103.     input_free_device(ddata->idev);
  104.     return ret;
  105. }
  106.   
  107. static __devinit int gsl_probe(struct i2c_client *client,
  108.         const struct i2c_device_id *id)
  109. {
  110.     int ret = 0;
  111.   
  112.     gsl_pr();
  113.   
  114.     ddata->ti = kzalloc(sizeof(union gsl_touch_info), GFP_KERNEL);
  115.     if (!ddata->ti) {
  116.         dev_err(&client->dev, "failed to alloc ddata->ti memory!\n");
  117.         ret = -ENOMEM;
  118.         goto error_alloc_mem;
  119.     }
  120.   
  121.     /* regist a input dev */
  122.     ret = gsl_request_input();
  123.     if (ret) {
  124.         dev_err(&client->dev, "failed to regist input dev!\n");
  125.         goto error_regist_input;
  126.     }
  127.   
  128.     /* setup the gpio -- irq & rst */
  129.     ret = gsl_hw_init();
  130.     if (ret) {
  131.         dev_err(&client->dev, "failed to init hw!\n");
  132.         goto error_init_hw;
  133.     }
  134.   
  135.     /* setup client data & download fw */
  136.     ret = gsl_sw_init();
  137.     if (ret) {
  138.         dev_err(&client->dev, "failed to init sw!\n");
  139.         goto error_init_sw;
  140.     }
  141.   
  142.     return 0;
  143.   
  144. error_init_sw:
  145. error_init_hw:
  146.     destroy_workqueue(ddata->wq);
  147.     input_free_device(ddata->idev);
  148. error_regist_input:
  149.     kfree(ddata->ti);
  150.     input_unregister_device(ddata->idev);
  151.     destroy_workqueue(ddata->wq);
  152.     input_free_device(ddata->idev);
  153. error_alloc_mem:
  154.     kfree(ddata);
  155.     return ret;
  156. }
  157.   
  158. static __devexit int gsl_remove(struct i2c_client *client)
  159. {
  160.     return 0;
  161. }
  162.   
  163. static struct i2c_driver gsl_driver = {
  164.     .driver = {
  165.         .name = GSL_DEV_NAME,
  166.         .owner = THIS_MODULE,
  167.     },
  168.     .probe = gsl_probe,
  169.     .remove = gsl_remove,
  170.     .id_table = gsl_id,
  171. };
  172.   
  173. /**
  174.  * Description : module operation
  175.  */
  176. static __init int gsl_init(void)
  177. {
  178.     int ret = 0;
  179.     struct i2c_adapter *adapter;
  180.   
  181.     gsl_pr();
  182.   
  183.     ddata = kzalloc(sizeof(struct gsl_ts_data), GFP_KERNEL);
  184.     if (!ddata) {
  185.         gsl_pr("alloc mem error");
  186.         goto err_mem;
  187.     }
  188.   
  189.     /* tips : try_module_get */
  190.     adapter = i2c_get_adapter(GSL_ADAPTER_INDEX);
  191.     if (!(adapter)) {
  192.         gsl_pr("get %d adapter failed", GSL_ADAPTER_INDEX);
  193.         ret = -ENODEV;
  194.         goto err_adap;
  195.     }
  196.   
  197.     ddata->client = i2c_new_device(adapter, &gsl_i2c_info);
  198.     if (!(ddata->client)) {
  199.         gsl_pr("get i2c device error");
  200.         ret = -ENODEV;
  201.         goto err_dev;
  202.     }
  203.   
  204.     /* release the module */
  205.     i2c_put_adapter(adapter);
  206.   
  207.     ret = i2c_add_driver(&gsl_driver);
  208.     if (ret) {
  209.         gsl_pr("i2c add driver failed");
  210.         goto err_driver;
  211.     }
  212.   
  213.     return 0;
  214.   
  215. err_driver:
  216.     i2c_unregister_device(ddata->client);
  217.     i2c_put_adapter(adapter);
  218. err_dev:
  219. err_adap:
  220.     kfree(ddata);
  221. err_mem:
  222.     return ret;
  223. }
  224.   
  225. static __exit void gsl_exit(void)
  226. {
  227.     gsl_pr();
  228.   
  229.     /* reverse effect of i2c_new_device() */
  230.     i2c_del_driver(&gsl_driver);
  231.     i2c_unregister_device(ddata->client);
  232.     kfree(ddata);
  233.   
  234.     return;
  235. }
  236.   
  237. module_init(gsl_init);
  238. module_exit(gsl_exit);
  239.   
  240. MODULE_LICENSE("GPL");
  241. MODULE_AUTHOR("mark");

点击(此处)折叠或打开

  1. //touch coordinate range
  2. #define TP_WIDTH 480
  3. #define TP_LENTH 800
  4.       
  5. //coordinate direction
  6. #define TP_DIREC 1 // if 1 is (1,1), then 2(1,-1), 3(-1,-1), 4(-1,1)
  7.       
  8. //touch threshold
  9. #define MAI_TRSD 200
  10. #define SUB_TRSD 40
  11. #define SUM_TRSD (MAI_TRSD + SUB_TRSD + 20)
  12.       
  13. //touch tigger condition
  14. #define TRIG_MOD 1 // 1 is edge, 0 is level
  15. #define VOLT_LEV 0 // if trig mode is edge,
  16.                             // 0 is IRQF_TRIGGER_RISING, 1 is IRQF_TRIGGER_FALLING
  17.                             // if trig mode is level,
  18.                             // 0 is IRQF_TRIGGER_HIGH, 1 is IRQF_TRIGGER_LOW
  19.       
  20. //touch sensitivity
  21. #define TP_DACG 0x00100010 //9f/30
  22. #define DAC_STEP 0x8e //if TP_DACG=0x00180018,TP_DAC_STEP=0x61
  23.                                     //if TP_DACG=0x00100010,TP_DAC_STEP=0x8e
  24.                                     //if TP_DACG=0x000c000c,TP_DAC_STEP=0xbb
  25.                                     //if TP_DACG=0x000a000a,TP_DAC_STEP=0xdf
  26.                                     //if TP_DACG=0x00080008,TP_DAC_STEP=0x114
  27.                                     //if TP_DACG=0x00060006,TP_DAC_STEP=0x16e
  28. #define CHANGE_CONDITION 0x0 //0--use average,1--use max
  29.       
  30. #define GSL_PAGE_REG 0xf0
  31. #define GSL_CLOCK_REG 0xe4
  32. #define GSL_START_REG 0xe0
  33. #define GSL_CLOCK_REG 0xe4
  34. #define POWE_FAIL_REG 0xbc
  35. #define TOUCH_INFO_REG 0x80
  36.       
  37. #define DIS_MIN_X 0
  38. #define DIS_MAX_X TP_WIDTH
  39. #define DIS_MIN_Y 0
  40. #define DIS_MAX_Y TP_LENTH
  41.       
  42. #define MIN_TOUCH 0
  43. #define MAX_TOUCH 1
  44. #define MIN_WIDTH 0
  45. #define MAX_WIDTH 1
  46. #define MIN_TRCKID 1
  47. #define MAX_TRCKID 5
  48.       
  49. /* the data format of one point */
  50. union gsl_point_data {
  51.     struct {
  52.         u16 y;
  53.         u16 x : 12;
  54.         u16 id : 4;
  55.     };
  56.     u8 all[4];
  57. };
  58.       
  59. /* the 24-byte data of read once */
  60. union gsl_touch_info {
  61.     struct {
  62.         u32 finger_num : 8;
  63.         u32 : 0;
  64.         union gsl_point_data point[5];
  65.     };
  66.     u8 all[24];
  67. };
  68.       
  69. struct gsl_ts_data {
  70.     union gsl_touch_info *ti;
  71.     struct i2c_client *client;
  72.     struct input_dev *idev;
  73.     struct workqueue_struct *wq;
  74.     struct work_struct work;
  75.     unsigned int irq;
  76. };
  77.       
  78. /* Fixme mem Alig */
  79. struct fw_data {
  80.     u32 offset : 8;
  81.     u32 : 0;
  82.     u32 val;
  83. };
  84.       
  85. static const struct fw_data GSL1680_D0_FW[] = {
  86.     /* void */
  87.     { },
  88. };

    5)input_report_abs上报流程

点击(此处)折叠或打开

  1. /* 观察linux-3.6.3/drivers/input/Kconfig, 对应/dev/input/eventX */
  2.     config INPUT_EVDEV
  3.         tristate "Event interface"
  4.         help
  5.           Say Y here if you want your input device events be accessible
  6.           under char device 13:64+ - /dev/input/eventX in a generic way.
  7.       
  8.           To compile this driver as a module, choose M here: the
  9.           module will be called evdev.
android 4.0 一般报点序列:

点击(此处)折叠或打开

  1. input_mt_slot(ts->input, id);
  2. input_report_abs(ts->input, ABS_MT_TRACKING_ID, id);
  3. input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, 1);
  4. input_report_abs(ts->input, ABS_MT_POSITION_X, x);
  5. input_report_abs(ts->input, ABS_MT_POSITION_Y, y);
  6. input_report_abs(ts->input, ABS_MT_WIDTH_MAJOR, 1);
  7. input_mt_sync(ts->input);

点击(此处)折叠或打开

  1. input_sync(ts->input);

input_handle_event(dev, type, code, value)上报流程:

点击(此处)折叠或打开

  1. ...
  2. switch (type) {
  3.   
  4. case EV_SYN:
  5.     switch (code) {
  6.        ...
  7.     case SYN_REPORT:
  8.         if (!dev->sync) {
  9.             dev->sync = true;
  10.             disposition = INPUT_PASS_TO_HANDLERS;
  11.         }
  12.         break;
  13.     case SYN_MT_REPORT:
  14.         dev->sync = false;
  15.         disposition = INPUT_PASS_TO_HANDLERS;
  16.         break;
  17.     }
  18.     break;
  19.   
  20. case EV_KEY:
  21.     if (is_event_supported(code, dev->keybit, KEY_MAX) &&
  22.         !!test_bit(code, dev->key) != value) {
  23.   
  24.         if (value != 2) {
  25.             __change_bit(code, dev->key);
  26.             if (value)
  27.                 input_start_autorepeat(dev, code);
  28.             else
  29.                 input_stop_autorepeat(dev);
  30.         }
  31.   
  32.         disposition = INPUT_PASS_TO_HANDLERS;
  33.     }
  34.     break;
  35.    ...
  36. case EV_ABS:
  37.     if (is_event_supported(code, dev->absbit, ABS_MAX))
  38.         disposition = input_handle_abs_event(dev, code, &value);
  39.   
  40.     break;
  41.    ...
  42. }
  43.   
  44.    ...
  45. if (disposition & INPUT_PASS_TO_HANDLERS)
  46.     input_pass_event(dev, type, code, value);

 

点击(此处)折叠或打开

  1. static void input_pass_event(struct input_dev *dev,
  2.                      unsigned int type, unsigned int code, int value)
  3. {
  4.      struct input_handler *handler;
  5.      struct input_handle *handle;
  6.       
  7.      rcu_read_lock();
  8.       
  9.      /* 获得一个被RCU保护的指针 */
  10.      handle = rcu_dereference(dev->grab);
  11.      /* (1) 如果是设备专有handle, 仅将事件传给该handler. */
  12.      if (handle)
  13.          handle->handler->event(handle, type, code, value);
  14.      else {
  15.          bool filtered = false;
  16.       
  17.          /* (2)遍历与此设备连接的每一个handle. */
  18.          list_for_each_entry_rcu(handle, &dev->h_list, d_node) {
  19.             /* (3)如果hnadle已经被打开. */
  20.             if (!handle->open)
  21.                 continue;
  22.       
  23.             handler = handle->handler;
  24.             if (!handler->filter) {
  25.                  if (filtered)
  26.                      break;
  27.                  /* (4)将事件分发给handler的事件处理函数. */
  28.                  handler->event(handle, type, code, value);
  29.       
  30.             } else if (handler->filter(handle, type, code, value))
  31.                filtered = true;
  32.          }
  33.    }
  34.       
  35.    rcu_read_unlock(); 
  36. }

附上android 4.0上报方式(linux必须2.6.38以上)

点击(此处)折叠或打开

  1. #include <linux/input/mt.h>


点击(此处)折叠或打开

  1. //down
  2.     input_mt_slot(ts->input_dev, id);
  3.     //input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, id);
  4.     input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, true);
  5.     input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w);
  6.     input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
  7.     input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);


点击(此处)折叠或打开

  1. //up
  2.     input_mt_slot(ts->input_dev, id);
  3.     //input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1);
  4.     input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);


点击(此处)折叠或打开

  1. //init
  2.     //__set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
  3.     input_mt_init_slots(ts->input_dev, 255);



阅读(10806) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:vim技巧

给主人留下些什么吧!~~