Multi-Touch プロトコルを使用するドライバー ファイルを編集しています。私の目標は、(x1,y1) から (x2,y2) へのスワイプ ジェスチャを線に沿ってバインドすることです。
これを行うには、キー圧力検出関数内でこの関数を実行します。
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);
}
この関数は編集された Bresenham の線アルゴリズムであり、線を描画する代わりに key_report を呼び出して、指定された座標でのタッチをシミュレートします。
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;
}
kp-> input はそのように定義されています
struct input_dev *input;
編集:コードを更新し、キー圧力の汎用コードも添付しています。これは、スワイプのループを避けるために、ドライバーがキー圧力ごとに1回だけスワイプを実行するようにするためです。
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);
}
たぶん、kp->flagchan4にチェックを設定できます... 編集: flagchan4にチェックを設定するとうまくいきました。