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_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);
阅读(10806) | 评论(0) | 转发(0) |