转自:http://blog.chinaunix.net/uid-28320320-id-3389196.html
1、参考文章 【Andorid】input系统的事件处理 2、源码分析 linux 3.6.3 1)查看linux-3.6.3/drivers/input下Makefile 点击(此处)折叠或打开 obj-$(CONFIG_INPUT) += input-core.o input-core-y := input.o input-compat.o input-mt.o ff-core.o 2)查看文件input.c 点击(此处)折叠或打开 /* input subsystem entry */ subsys_initcall(input_init); module_exit(input_exit); 3)input.c搞啥子 点击(此处)折叠或打开 /* sysfs/procfs/devfs show */ |-----------| | \/ | err = class_register(&input_class); | |-----------| | \/ | err = input_proc_init(); | |-----------| | \/ | err = register_chrdev(INPUT_MAJOR, "input", &input_fops); 根据下面的方法,发现手机的tp 对应event1 点击(此处)折叠或打开 # getevent add device 1: /dev/input/event0 name: "fluid-keypad" add device 2: /dev/input/event3 name: "7k_handset" add device 3: /dev/input/event2 name: "sensors" add device 4: /dev/input/event1 name: "Synaptics RMI4" # pwd /sys/class/input # ls event0 event1 event2 event3 input0 input1 input2 input3 # cat /proc/bus/input/devices I: Bus=0019 Vendor=0001 Product=0001 Version=0001 N: Name="fluid-keypad" P: Phys=fluid-keypad/input0 S: Sysfs=/devices/i2c-6/6-0000/pm8058-keypad/input/input0 U: Uniq= H: Handlers=kbd event0 B: EV=13 B: KEY=1200000 0 0 c0000 0 0 0 B: MSC=10 I: Bus=0000 Vendor=0000 Product=0000 Version=0000 N: Name="Synaptics RMI4" P: Phys=Synaptics_rmi S: Sysfs=/devices/virtual/input/input1 U: Uniq= H: Handlers=event1 B: EV=b B: KEY=400 0 0 0 2000000 0 40000800 40 0 0 0 B: ABS=770000 11030003 I: Bus=0018 Vendor=0003 Product=0000 Version=0000 N: Name="sensors" P: Phys= S: Sysfs=/devices/virtual/input/input2 U: Uniq= H: Handlers=event2 B: EV=9 B: ABS=8000 20304bf I: Bus=0000 Vendor=0001 Product=0001 Version=0001 N: Name="7k_handset" P: Phys= S: Sysfs=/devices/virtual/input/input3 U: Uniq= H: Handlers=kbd event3 B: EV=23 B: KEY=4 0 28 0 1c0800 0 0 0 B: SW=4 4)touch panel驱动源码 点击(此处)折叠或打开 #include <linux/module.h> #include <linux/kernel.h> #include <linux/slab.h> #include <linux/platform_device.h> #include <linux/i2c.h> #include <linux/input.h> #include "gsl1680.h" #define gsl_pr(fmt, arg...) \ printk(KERN_ERR "[GSL]%s: \033[32m" fmt "\033[0m\n", __FUNCTION__, ##arg) #define GSL_ADAPTER_INDEX 0 #define GSL1680D0_ID 0 #define GSL_DEV_NAME "gsl" /** * Description : global var */ static struct gsl_ts_data *ddata = NULL; static const struct i2c_device_id gsl_id[] = { {GSL_DEV_NAME, GSL1680D0_ID}, {}, }; MODULE_DEVICE_TABLE(silead, gsl_id); static struct i2c_board_info gsl_i2c_info = { .type = GSL_DEV_NAME, .addr = 0x40, }; /** * Description : gsl soc operation */ static int gsl_hw_init(void) { return 0; } static int gsl_sw_init(void) { return 0; } /** * Description : touch panel driver */ static void gsl_report_work(struct work_struct *work) { } static int gsl_request_input(void) { int ret = 0; ddata->idev = input_allocate_device(); if (!ddata->idev) { dev_err(&ddata->idev->dev, "could not allocate device\n"); return -ENODEV; } ddata->idev->name = GSL_DEV_NAME; ddata->idev->id.bustype = BUS_I2C; ddata->idev->dev.parent = &ddata->client->dev; input_set_drvdata(ddata->idev, ddata); __set_bit(EV_ABS, ddata->idev->evbit); input_set_abs_params(ddata->idev, ABS_MT_POSITION_X, DIS_MIN_X, DIS_MAX_X, 0, 0); input_set_abs_params(ddata->idev, ABS_MT_POSITION_Y, DIS_MIN_Y, DIS_MAX_Y, 0, 0); input_set_abs_params(ddata->idev, ABS_MT_TOUCH_MAJOR, MIN_TOUCH, MAX_TOUCH, 0, 0); input_set_abs_params(ddata->idev, ABS_MT_WIDTH_MAJOR, MIN_WIDTH, MAX_WIDTH, 0, 0); input_set_abs_params(ddata->idev, ABS_MT_TRACKING_ID, MIN_TRCKID, MAX_TRCKID, 0, 0); INIT_WORK(&ddata->work, gsl_report_work); ddata->wq = create_singlethread_workqueue(GSL_DEV_NAME); if (!ddata->wq) { dev_err(&ddata->idev->dev, "could not create workqueue\n"); ret = -ENOMEM; goto error_wq_create; } #if 0 ddata->pm.suspend = gsl_suspend; ddata->pm.resume = gsl_resume; register_early_suspend(&ddata->pm); #endif ret = input_register_device(ddata->idev); if (ret) { dev_err(&ddata->idev->dev, "ret = %d : could not register input device\n", ret); goto error_unreg_device; } return 0; error_unreg_device: destroy_workqueue(ddata->wq); error_wq_create: input_free_device(ddata->idev); return ret; } static __devinit int gsl_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret = 0; gsl_pr(); ddata->ti = kzalloc(sizeof(union gsl_touch_info), GFP_KERNEL); if (!ddata->ti) { dev_err(&client->dev, "failed to alloc ddata->ti memory!\n"); ret = -ENOMEM; goto error_alloc_mem; } /* regist a input dev */ ret = gsl_request_input(); if (ret) { dev_err(&client->dev, "failed to regist input dev!\n"); goto error_regist_input; } /* setup the gpio -- irq & rst */ ret = gsl_hw_init(); if (ret) { dev_err(&client->dev, "failed to init hw!\n"); goto error_init_hw; } /* setup client data & download fw */ ret = gsl_sw_init(); if (ret) { dev_err(&client->dev, "failed to init sw!\n"); goto error_init_sw; } return 0; error_init_sw: error_init_hw: destroy_workqueue(ddata->wq); input_free_device(ddata->idev); error_regist_input: kfree(ddata->ti); input_unregister_device(ddata->idev); destroy_workqueue(ddata->wq); input_free_device(ddata->idev); error_alloc_mem: kfree(ddata); return ret; } static __devexit int gsl_remove(struct i2c_client *client) { return 0; } static struct i2c_driver gsl_driver = { .driver = { .name = GSL_DEV_NAME, .owner = THIS_MODULE, }, .probe = gsl_probe, .remove = gsl_remove, .id_table = gsl_id, }; /** * Description : module operation */ static __init int gsl_init(void) { int ret = 0; struct i2c_adapter *adapter; gsl_pr(); ddata = kzalloc(sizeof(struct gsl_ts_data), GFP_KERNEL); if (!ddata) { gsl_pr("alloc mem error"); goto err_mem; } /* tips : try_module_get */ adapter = i2c_get_adapter(GSL_ADAPTER_INDEX); if (!(adapter)) { gsl_pr("get %d adapter failed", GSL_ADAPTER_INDEX); ret = -ENODEV; goto err_adap; } ddata->client = i2c_new_device(adapter, &gsl_i2c_info); if (!(ddata->client)) { gsl_pr("get i2c device error"); ret = -ENODEV; goto err_dev; } /* release the module */ i2c_put_adapter(adapter); ret = i2c_add_driver(&gsl_driver); if (ret) { gsl_pr("i2c add driver failed"); goto err_driver; } return 0; err_driver: i2c_unregister_device(ddata->client); i2c_put_adapter(adapter); err_dev: err_adap: kfree(ddata); err_mem: return ret; } static __exit void gsl_exit(void) { gsl_pr(); /* reverse effect of i2c_new_device() */ i2c_del_driver(&gsl_driver); i2c_unregister_device(ddata->client); kfree(ddata); return; } module_init(gsl_init); module_exit(gsl_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("mark"); 点击(此处)折叠或打开 //touch coordinate range #define TP_WIDTH 480 #define TP_LENTH 800 //coordinate direction #define TP_DIREC 1 // if 1 is (1,1), then 2(1,-1), 3(-1,-1), 4(-1,1) //touch threshold #define MAI_TRSD 200 #define SUB_TRSD 40 #define SUM_TRSD (MAI_TRSD + SUB_TRSD + 20) //touch tigger condition #define TRIG_MOD 1 // 1 is edge, 0 is level #define VOLT_LEV 0 // if trig mode is edge, // 0 is IRQF_TRIGGER_RISING, 1 is IRQF_TRIGGER_FALLING // if trig mode is level, // 0 is IRQF_TRIGGER_HIGH, 1 is IRQF_TRIGGER_LOW //touch sensitivity #define TP_DACG 0x00100010 //9f/30 #define DAC_STEP 0x8e //if TP_DACG=0x00180018,TP_DAC_STEP=0x61 //if TP_DACG=0x00100010,TP_DAC_STEP=0x8e //if TP_DACG=0x000c000c,TP_DAC_STEP=0xbb //if TP_DACG=0x000a000a,TP_DAC_STEP=0xdf //if TP_DACG=0x00080008,TP_DAC_STEP=0x114 //if TP_DACG=0x00060006,TP_DAC_STEP=0x16e #define CHANGE_CONDITION 0x0 //0--use average,1--use max #define GSL_PAGE_REG 0xf0 #define GSL_CLOCK_REG 0xe4 #define GSL_START_REG 0xe0 #define GSL_CLOCK_REG 0xe4 #define POWE_FAIL_REG 0xbc #define TOUCH_INFO_REG 0x80 #define DIS_MIN_X 0 #define DIS_MAX_X TP_WIDTH #define DIS_MIN_Y 0 #define DIS_MAX_Y TP_LENTH #define MIN_TOUCH 0 #define MAX_TOUCH 1 #define MIN_WIDTH 0 #define MAX_WIDTH 1 #define MIN_TRCKID 1 #define MAX_TRCKID 5 /* the data format of one point */ union gsl_point_data { struct { u16 y; u16 x : 12; u16 id : 4; }; u8 all[4]; }; /* the 24-byte data of read once */ union gsl_touch_info { struct { u32 finger_num : 8; u32 : 0; union gsl_point_data point[5]; }; u8 all[24]; }; struct gsl_ts_data { union gsl_touch_info *ti; struct i2c_client *client; struct input_dev *idev; struct workqueue_struct *wq; struct work_struct work; unsigned int irq; }; /* Fixme mem Alig */ struct fw_data { u32 offset : 8; u32 : 0; u32 val; }; static const struct fw_data GSL1680_D0_FW[] = { /* void */ { }, }; 5)input_report_abs上报流程 点击(此处)折叠或打开 /* 观察linux-3.6.3/drivers/input/Kconfig, 对应/dev/input/eventX */ config INPUT_EVDEV tristate "Event interface" help Say Y here if you want your input device events be accessible under char device 13:64+ - /dev/input/eventX in a generic way. To compile this driver as a module, choose M here: the module will be called evdev. android 4.0 一般报点序列: 点击(此处)折叠或打开 input_mt_slot(ts->input, id); input_report_abs(ts->input, ABS_MT_TRACKING_ID, id); input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, 1); input_report_abs(ts->input, ABS_MT_POSITION_X, x); input_report_abs(ts->input, ABS_MT_POSITION_Y, y); input_report_abs(ts->input, ABS_MT_WIDTH_MAJOR, 1); input_mt_sync(ts->input); 点击(此处)折叠或打开 input_sync(ts->input); input_handle_event(dev, type, code, value)上报流程: 点击(此处)折叠或打开 ... switch (type) { case EV_SYN: switch (code) { ... case SYN_REPORT: if (!dev->sync) { dev->sync = true; disposition = INPUT_PASS_TO_HANDLERS; } break; case SYN_MT_REPORT: dev->sync = false; disposition = INPUT_PASS_TO_HANDLERS; break; } break; case EV_KEY: if (is_event_supported(code, dev->keybit, KEY_MAX) && !!test_bit(code, dev->key) != value) { if (value != 2) { __change_bit(code, dev->key); if (value) input_start_autorepeat(dev, code); else input_stop_autorepeat(dev); } disposition = INPUT_PASS_TO_HANDLERS; } break; ... case EV_ABS: if (is_event_supported(code, dev->absbit, ABS_MAX)) disposition = input_handle_abs_event(dev, code, &value); break; ... } ... if (disposition & INPUT_PASS_TO_HANDLERS) input_pass_event(dev, type, code, value); 点击(此处)折叠或打开 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(); /* 获得一个被RCU保护的指针 */ handle = rcu_dereference(dev->grab); /* (1) 如果是设备专有handle, 仅将事件传给该handler. */ if (handle) handle->handler->event(handle, type, code, value); else { bool filtered = false; /* (2)遍历与此设备连接的每一个handle. */ list_for_each_entry_rcu(handle, &dev->h_list, d_node) { /* (3)如果hnadle已经被打开. */ if (!handle->open) continue; handler = handle->handler; if (!handler->filter) { if (filtered) break; /* (4)将事件分发给handler的事件处理函数. */ handler->event(handle, type, code, value); } else if (handler->filter(handle, type, code, value)) filtered = true; } } rcu_read_unlock(); } 附上android 4.0上报方式(linux必须2.6.38以上) 点击(此处)折叠或打开 #include <linux/input/mt.h> 点击(此处)折叠或打开 //down input_mt_slot(ts->input_dev, id); //input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, id); input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, true); input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w); input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x); input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y); 点击(此处)折叠或打开 //up input_mt_slot(ts->input_dev, id); //input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1); input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false); 点击(此处)折叠或打开 //init //__set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit); input_mt_init_slots(ts->input_dev, 255);
时间: 2024-09-27 03:37:03