I am doing an edit to a driver file that uses Multi-Touch protocol. My goal is to bind a swipe gesture from (x1,y1) to (x2,y2) that follows a line.
To do this i execute this function inside the key pressure detection function:
static void do_swipe(struct kp *kp, long xstart, long ystart, long xend, long yend,
int id) {
printk("SWIPE! X1 %d Y1 %d X2 %d Y2 %d ID %d \n",xstart,ystart,xend,yend,id);
int sx, sy;
int dx = abs(xend - xstart);
int dy = abs(yend - ystart);
if (xstart < xend)
sx = 1;
else
sx = -1;
if (ystart < yend)
sy = 1;
else
sy = -1;
int err = dx - dy;
long tempx = xstart;
long tempy = ystart;
while (1) {
key_report(kp, tempx, tempy, id);
//Touch is now detected with input_sync
input_sync(kp->input);
if(tempx == xend && tempy == yend) break;
int e2 = 2 * err;
if (e2 > (-1)*dy) {
err = err - dy;
tempx = tempx + sx;
} else if (e2 < dx) {
err = err + dx;
tempy = tempy + sy;
}
}
printk("END! X %d Y %d \n",tempx, tempy);
}
This function is an edited Bresenham's line algorhitm that instead of drawing a line calls key_report to simulate a touch at the given coordinates.
static void key_report(struct kp *kp, long x, long y, int id) {
if (x == 0 && y == 0) {
//printk("---------- zero point --------------\n");
;
} else {
input_report_key(kp->input, BTN_TOUCH, 1);
input_report_abs(kp->input, ABS_MT_TRACKING_ID, id);
input_report_abs(kp->input, ABS_MT_TOUCH_MAJOR, 20);
input_report_abs(kp->input, ABS_MT_WIDTH_MAJOR, 20);
input_report_abs(kp->input, ABS_MT_POSITION_X, x);
input_report_abs(kp->input, ABS_MT_POSITION_Y, y);
input_mt_sync(kp->input);
}
release = 1;
}
Where kp-> input is so defined
struct input_dev *input;
Edit: I updated the code and I'm also attaching the generic code of a key pressure, because I'd like the driver to perform a swipe only once for each key pressure, to avoid swipe looping.
static void kp_work(struct kp *kp) {
int i, code, value;
kp_search_key(kp);
if (key_param[0] == 3) {
if (kp->key_valid[4] == 1) {
value = kp->key_value[4];
kp->flagchan4 = 0;
if (value >= 0 && value <= (9 + 40)) {
if (key_param[99] == 1 ) {
do_swipe(kp, key_param[25], key_param[26], key_param[97],
key_param[98], 12);
} else
key_report(kp, key_param[25], key_param[26], 12);
} else if (value >= 392 - 40 && value <= (392 + 40)) {
if (key_param[102] == 1) {
do_swipe(kp, key_param[23], key_param[24], key_param[100],
key_param[101], 12);
} else
key_report(kp, key_param[23], key_param[24], 12);
}
kp->flagchan4 = 0;
} else {
kp->flagchan4 = 1;
}
}
input_sync(kp->input);
}
Maybe i could set a check on kp->flagchan4... Edit: Setting a check on flagchan4 did the trick.