blob: d4846fc8d35bbd6d2beac9368be63f2f0202a414 [file] [log] [blame]
#ifdef CONFIG_SEC_INPUT_BOOSTER
int chk_next_data(struct evdev_client *dev, int idx, int input_type)
{
int ret_val = 0;
int next_type = -1;
int next_code = -1;
int next_idx = (idx+1) & (dev->bufsize - 1);
next_type = dev->buffer[next_idx].type;
next_code = dev->buffer[next_idx].code;
switch (input_type) {
case BTN_TOUCH:
if (next_type == EV_ABS && next_code == ABS_PRESSURE)
ret_val = 1;
break;
case EV_KEY:
ret_val = 1;
break;
default:
break;
}
return ret_val;
}
int chk_boost_on_off(struct evdev_client *dev, int idx, int dev_type)
{
int ret_val = -1;
if (dev_type < 0)
return ret_val;
/* In case of SPEN or HOVER, it must be empty multi event
* Before starting input booster.
*/
if (dev_type == SPEN || dev_type == HOVER) {
if (!evdev_mt_event[dev_type] && dev->buffer[idx].value)
ret_val = 1;
else if (evdev_mt_event[dev_type] && !dev->buffer[idx].value)
ret_val = 0;
} else if (dev_type == TOUCH || dev_type == MULTI_TOUCH) {
if (dev->buffer[idx].value >= 0)
ret_val = 1;
else
ret_val = 0;
} else if (dev->buffer[idx].value > 0)
ret_val = 1;
else if (dev->buffer[idx].value <= 0)
ret_val = 0;
return ret_val;
}
/*
* get_device_type : Define type of device for input_booster.
* dev : Current device that in which input events triggered.
* keyId : Each device get given unique keyid using Type, Code, Slot values
* to identify which booster will be triggered.
* cur_idx : Pointing current handling index from input booster.
* cur_idx will be updated when cur_idx is same as head.
* head : End of events set. Input booster handles from tail event to head events.
* Must check if the event is the last one referring to head.
*/
int get_device_type(struct evdev_client *dev, unsigned int *keyId, int *cur_idx, int head)
{
int i;
int ret_val = -1;
int dev_type = NONE_TYPE_DEVICE;
int uniq_slot = 0;
int next_idx = 0 ;
int target_idx = 0;
if (dev == NULL || dev->ev_cnt > MAX_EVENTS) {
pr_err("evdev client is null and exceed max event number");
return ret_val;
}
/* Initializing device type before finding the proper device type. */
dev->device_type = dev_type;
for (i = *cur_idx; i != head; i = (i+1) & (dev->bufsize - 1)) {
pr_booster("%s Type : %d, Code : %d, Value : %d, Head : %d, idx : %d\n",
"Input Data || ", dev->buffer[i].type,
dev->buffer[i].code, dev->buffer[i].value,
head, i);
if (dev->buffer[i].type == EV_SYN || dev->buffer[i].code == SYN_REPORT) {
break;
}
if (dev->buffer[i].type == EV_KEY) {
target_idx = i;
switch (dev->buffer[i].code) {
case BTN_TOUCH:
if (!chk_next_data(dev, i, BTN_TOUCH))
break;
dev_type = SPEN;
break;
case BTN_TOOL_PEN:
dev_type = HOVER;
break;
case KEY_BACK:
case KEY_HOMEPAGE:
case KEY_RECENT:
dev_type = TOUCH_KEY;
break;
case KEY_VOLUMEUP:
case KEY_VOLUMEDOWN:
case KEY_POWER:
case KEY_WINK:
dev_type = KEY;
break;
default:
break;
}
} else if (dev->buffer[i].type == EV_ABS) {
target_idx = i;
switch (dev->buffer[i].code) {
case ABS_MT_TRACKING_ID:
if (dev->buffer[i].value >= 0) {
evdev_mt_slot++;
} else {
evdev_mt_slot--;
}
if (dev->buffer[i].value >= 0) {
if (evdev_mt_slot == 1) {
dev_type = TOUCH;
uniq_slot = 1;
} else if (evdev_mt_slot == 2) {
dev_type = MULTI_TOUCH;
uniq_slot = 2;
}
} else if (dev->buffer[i].value < 0) {
//ret_val = 0;
if (evdev_mt_slot == 0) {
dev_type = TOUCH;
uniq_slot = 1;
} else if (evdev_mt_slot == 1) {
dev_type = MULTI_TOUCH;
uniq_slot = 2;
}
}
pr_booster("Touch Booster Trigger(%d), Type(%d), Code(%d), Val(%d), head(%d), Tail(%d), uniq_slot(%d), Idx(%d), Cnt(%d)",
evdev_mt_slot, dev->buffer[i].type, dev->buffer[i].code, dev->buffer[i].value, head, dev->tail, uniq_slot, i, dev->ev_cnt);
break;
}
} else if (dev->buffer[i].type == EV_MSC &&
dev->buffer[i].code == MSC_SCAN) {
if (!chk_next_data(dev, i, EV_KEY)) {
break;
}
next_idx = (i+1) & (dev->bufsize - 1);
target_idx = next_idx;
switch (dev->buffer[next_idx].code) {
case BTN_LEFT: /* Checking Touch Button Event */
case BTN_RIGHT:
case BTN_MIDDLE:
dev_type = MOUSE;
//Remain the last of CODE value as a uniq_slot to recognize BTN Type (LEFT, RIGHT, MIDDLE)
uniq_slot = dev->buffer[next_idx].code;
break;
default: /* Checking Keyboard Event */
dev_type = KEYBOARD;
uniq_slot = dev->buffer[next_idx].code;
pr_booster("KBD Booster Trigger(%d), Type(%d), Code(%d), Val(%d), head(%d), Tail(%d), Idx(%d), Cnt(%d)\n",
dev->buffer[next_idx].code, dev->buffer[i].type,
dev->buffer[i].code, dev->buffer[i].value,
head, dev->tail, i, dev->ev_cnt);
break;
}
}
if (dev_type != NONE_TYPE_DEVICE) {
*keyId = create_uniq_id(dev->buffer[i].type, dev->buffer[i].code, uniq_slot);
ret_val = chk_boost_on_off(dev, target_idx, dev_type);
pr_booster("Dev type Find(%d), KeyID(%d), enable(%d), Target(%d)\n",
dev_type, *keyId, ret_val, target_idx);
break;
}
}
// if for loop reach the end, cur_idx is set as head value or pointing next one with plus one.
// Especially, dev->bufsize has to be set as a 2^n.
// In the code that set bufzise, we can see bufsize would be set using roundup_pow_of_two function.
// return roundup_pow_of_two(n_events);
// which means "A power of two is a number of the form 2n where n is an integer"
*cur_idx = (i == head) ? head : ((i+1) & (dev->bufsize - 1));
dev->device_type = dev_type;
return ret_val;
}
// ********** Detect Events ********** //
void input_booster(struct evdev_client *dev, int dev_head)
{
int dev_type = 0;
int keyId = 0;
unsigned int uniqId = 0;
int res_type = 0;
int cnt = 0;
int cur_idx = -1;
int head = 0;
if (dev == NULL) {
pr_err(ITAG"dev is Null");
return;
}
if (!ib_init_succeed || dev->ev_cnt == 0) {
pr_err(ITAG"ev_cnt(%d) dt_infor hasn't mem alloc", dev->ev_cnt);
return;
}
head = dev_head;
cur_idx = (head - dev->ev_cnt) & (dev->bufsize - 1);
while (cur_idx != head) {
keyId = 0;
int enable = get_device_type(dev, &keyId, &cur_idx, head);
if (enable < 0 || keyId == 0) {
continue;
}
dev_type = dev->device_type;
if (dev_type <= NONE_TYPE_DEVICE || dev_type >= MAX_DEVICE_TYPE_NUM) {
continue;
}
if (enable == BOOSTER_ON) {
evdev_mt_event[dev_type]++;
} else {
evdev_mt_event[dev_type]--;
}
if (cnt == 0 && dev->evdev->handle.dev != NULL) {
while (dev->evdev->handle.dev->name[cnt] != '\0') {
ib_trigger[trigger_cnt].dev_name[cnt] = dev->evdev->handle.dev->name[cnt];
cnt++;
}
ib_trigger[trigger_cnt].dev_name[cnt] = '\0';
}
pr_booster("Dev Name : %s(%d), Key Id(%d), IB_Cnt(%d)", ib_trigger[trigger_cnt].dev_name, dev_type, keyId, trigger_cnt);
ib_trigger[trigger_cnt].key_id = keyId;
ib_trigger[trigger_cnt].event_type = enable;
ib_trigger[trigger_cnt].dev_type = dev_type;
queue_work(ev_unbound_wq, &(ib_trigger[trigger_cnt++].ib_trigger_work));
trigger_cnt = (trigger_cnt == MAX_IB_COUNT) ? 0 : trigger_cnt;
}
}
#endif //--CONFIG_SEC_INPUT_BOOSTER