1.定义的结构体继承input_dev
struct bma150_data { struct i2c_client *bma150_client; struct bma150_platform_data *platform_data; int IRQ; atomic_t delay; unsigned char mode; struct input_dev *input; struct bma150acc value; struct mutex value_mutex; struct mutex mode_mutex; struct delayed_work work; struct work_struct irq_work; };2.给input_dev指定名字和总线类型,对input事件类型可以参考下面代码 EV_MSC 类型参考下面的
set_bit(EV_MSC, dev->evbit);
set_bit(MSC_RAW, dev->mscbit);
EV_ABS类型参考下面的
input->evbit[0] = BIT(EV_ABS);
input->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_Z);
input_set_capability实际调用的也是__set_bit,
input_set_abs_params调用实际上也是set_bit,对于参数(dev,axis,min,max,fuzz,flat) fuzz有滤波作用,min,max代表范围,axis表示了坐标轴,flat暂时不知到用途
3.通过input_register_device(dev)注册input设备
static int bma150_input_init(struct bma150_data *bma150) { struct input_dev *dev; int err; dev = input_allocate_device(); if (!dev) return -ENOMEM; dev->name = SENSOR_NAME; dev->id.bustype = BUS_I2C; input_set_capability(dev, EV_ABS, ABS_MISC); input_set_abs_params(dev, ABS_X, ABSMIN_2G, ABSMAX_2G, 0, 0); input_set_abs_params(dev, ABS_Y, ABSMIN_2G, ABSMAX_2G, 0, 0); input_set_abs_params(dev, ABS_Z, ABSMIN_2G, ABSMAX_2G, 0, 0); input_set_drvdata(dev, bma150); err = input_register_device(dev); if (err < 0) { input_free_device(dev); return err; } bma150->input = dev; return 0; }
据说可以指定input号
dev->phys = "bma150/input0";
dev->id.bustype = BUS_HOST;
4.在中断函数或者工作队列中调用input_event上报事件
static inline void input_report_abs(struct input_dev *dev, unsigned int code, int value)
{
input_event(dev, EV_ABS, code, value);
}
input_event函数说明,input调用input_handle_event
对各种事件类型的处理主要体现在input_handle_event函数上
static void input_handle_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { int disposition = INPUT_IGNORE_EVENT;//忽略事件 switch (type) { case EV_SYN: switch (code) { case SYN_CONFIG: disposition = INPUT_PASS_TO_ALL;//传给设备和handle处理 break; case SYN_REPORT: if (!dev->sync) { dev->sync = true; disposition = INPUT_PASS_TO_HANDLERS;//传给handle处理 同步事件 } break; case SYN_MT_REPORT: dev->sync = false; disposition = INPUT_PASS_TO_HANDLERS;//传给handle处理 多点触摸 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_SW://耳机事件 if (is_event_supported(code, dev->swbit, SW_MAX) && !!test_bit(code, dev->sw) != value) { __change_bit(code, dev->sw); 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);//这里调用的input_handle_abs_event会将上次值和这次值相同的事件过滤掉 break; case EV_REL: if (is_event_supported(code, dev->relbit, REL_MAX) && value) disposition = INPUT_PASS_TO_HANDLERS; break; case EV_MSC: if (is_event_supported(code, dev->mscbit, MSC_MAX)) disposition = INPUT_PASS_TO_ALL; break; case EV_LED: if (is_event_supported(code, dev->ledbit, LED_MAX) && !!test_bit(code, dev->led) != value) { __change_bit(code, dev->led); disposition = INPUT_PASS_TO_ALL; } break; case EV_SND: if (is_event_supported(code, dev->sndbit, SND_MAX)) { if (!!test_bit(code, dev->snd) != !!value) __change_bit(code, dev->snd); disposition = INPUT_PASS_TO_ALL; } break; case EV_REP: if (code <= REP_MAX && value >= 0 && dev->rep[code] != value) { dev->rep[code] = value; disposition = INPUT_PASS_TO_ALL; } break; case EV_FF: if (value >= 0) disposition = INPUT_PASS_TO_ALL; break; case EV_PWR: disposition = INPUT_PASS_TO_ALL; break; } if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN) dev->sync = false; if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event) dev->event(dev, type, code, value); if (disposition & INPUT_PASS_TO_HANDLERS) input_pass_event(dev, type, code, value); } /** * input_event() - report new input event * @dev: device that generated the event * @type: type of the event * @code: event code * @value: value of the event * * This function should be used by drivers implementing various input * devices to report input events. See also input_inject_event(). * * NOTE: input_event() may be safely used right after input device was * allocated with input_allocate_device(), even before it is registered * with input_register_device(), but the event will not reach any of the * input handlers. Such early invocation of input_event() may be used * to 'seed' initial state of a switch or initial position of absolute * axis, etc. */ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { unsigned long flags; if (is_event_supported(type, dev->evbit, EV_MAX)) { spin_lock_irqsave(&dev->event_lock, flags); add_input_randomness(type, code, value); input_handle_event(dev, type, code, value); spin_unlock_irqrestore(&dev->event_lock, flags); } } EXPORT_SYMBOL(input_event);
static int input_handle_abs_event(struct input_dev *dev, unsigned int code, int *pval) { bool is_mt_event; int *pold; if (code == ABS_MT_SLOT) {//多点触摸信号?? /* * "Stage" the event; we'll flush it later, when we * get actual touch data. */ if (*pval >= 0 && *pval < dev->mtsize) dev->slot = *pval; return INPUT_IGNORE_EVENT; } is_mt_event = code >= ABS_MT_FIRST && code <= ABS_MT_LAST;//多点触摸事件值 if (!is_mt_event) {//不是多点触摸值,旧将上次值保存在pold里面 pold = &dev->absinfo[code].value; } else if (dev->mt) { struct input_mt_slot *mtslot = &dev->mt[dev->slot]; pold = &mtslot->abs[code - ABS_MT_FIRST]; } else { /* * Bypass filtering for multi-touch events when * not employing slots. */ pold = NULL; } if (pold) { *pval = input_defuzz_abs_event(*pval, *pold,//fuzz为0时,返回值为pold本身 dev->absinfo[code].fuzz);//这里fuzz是在2中设置类型时传入的参数input_set_abs_params(dev,axis,min,max.fuzz,flat) if (*pold == *pval) return INPUT_IGNORE_EVENT; *pold = *pval; } /* Flush pending "slot" event */ if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_SLOT)) { input_abs_set_val(dev, ABS_MT_SLOT, dev->slot); input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot); } return INPUT_PASS_TO_HANDLERS; }