[Android Software/Hacking General [Developers Only]] corphish:
Disclaimer

First off all, thanks to showp1984 for his original sweep2wake, based on which, this has been made.

I am a newbie in linux kernel programming, I did spend considerable amount of time, working with others to know about how touch input works. In many places, code will be useless, or there may be better way of implementation. Based on my understanding, I coded this.

This was originally made for a specific device, so I will try to explain wherever possible, so that it becomes easier for someone to implement in case they are interested.

This post does not show how to add hooks in touch panel driver and display driver.

Gestures Available

Swipe Left

Swipe Right

Swipe Up

Swipe Down

Swipe Forward Diagonally

Swipe Backward Diagonally

Draw 'L'

Draw 'V'

Commits

Initial Commit - https://github.com/corphish/android_kernel_sony_msm8930_lp/commit/dae03796da1f8ce97ed41c1b150b18741ac75f24 (Please read the extended description, as I have explained there what I have done)

Fixes - https://github.com/corphish/android_kernel_sony_msm8930_lp/commit/73562680a73956af105bffc0f2d1e7815a375677

Walkthrough

First off all I modified detect_sweep2wake function.

static bool detect_sweep2wake(int x, int y, int id)
{
key = KEY_POWER;
if (id == 255 && s2w_touch_count > 10) {
int x = s2w_coord_nature();
if(x) {
if(x == 1) {
if(s2w_right) {
s2w_coord_reset();
doubletap2wake_reset();
return true;
}
}
if(x == 2) {
if(s2w_left){
s2w_coord_reset();
doubletap2wake_reset();
return true;
}
}
if(x == 3) {
if(s2w_up){
s2w_coord_reset();
doubletap2wake_reset();
return true;
}
}
if(x == 4) {
if(s2w_down){
s2w_coord_reset();
doubletap2wake_reset();
return true;
}
}
if(x == 5) {
if(s2w_fwd_diag){
s2w_coord_reset();
doubletap2wake_reset();
return true;
}
}
if(x == 6) {
if(s2w_bck_diag){
s2w_coord_reset();
doubletap2wake_reset();
return true;
}
}
if(x == 7) {
if(s2w_l){
s2w_coord_reset();
doubletap2wake_reset();
return true;
}
}
if(x == 8) {
if(s2w_v){
s2w_coord_reset();
doubletap2wake_reset();
return true;
}
}
//pr_info("%s returned true\n",__func__);

}
} else {
//doubletap2wake_reset();
s2w_coord_dump(x, y);
direction_vector_calc();
new_touch(x, y);
}
if (ktime_to_ms(ktime_get())-tap_time_pre > D2W_TIME){
s2w_coord_reset();
doubletap2wake_reset();
}
//pr_info("%s returned false\n",__func__);
return false;
}

It now takes id as parameters as well.

id here is the touch id which is returned when we lift off contact from touch.

Do note that for this device, the id returned when we lift off contact from touch is 255, it will be different for different devices.

What this new detect_sweep2wake fn does is, it tests whether the id returned is that id (touch id which is returned when we lift off contact from touch) and the touch count is greater than a specific number or not.

The specific touch count is used to detect continuous touches (swipes).

If true, it calls for gesture detection function, if true, returns true, if false returns false.

If false, it dumps co-ordinates. Co-ordinates are dumped to 2 variables (x,y) and previous data is stored in (x_prev,y_prev). The first values of touch (the touch co-ordinates on first touch) is stored separately as well.

Then direction_vector_calc is called, which tests the nature of co-ordinates with respect to the previous one.

void direction_vector_calc(void) {
int tot = 0;
if(s2w_coord_count > 1) {
if(x > x_pre) {
dir[0]++; //right
tot++;
} else if (x < x_pre) {
dir[1]++; //left
tot++;
}
if(y < y_pre) {
dir[2]++; //up
tot++;
} else if (y > y_pre) {
dir[3]++; //down
tot++;
}
//To determine whether both x and y co-ordinates have changed from previous input or not and act accordingly.
if(tot > 1)
multiple_dir++;
//To determine max deviation in x coord.
if(x > max_x)
max_x = x;
//To determine min deviation in x coord.
if(x < min_x)
min_x = x;
//To determine max deviation in y coord.
if(y > max_y)
max_y = y;
//To determine min deviation in y coord.
if(y < min_y)
min_y = y;
} else {
min_y = y;
min_x = x;
max_x = x;
max_y = y;
}
}

At times, there maybe cases that a co-ordinate differs from its previous co-ordinate by 2 directions. This functions take care of that too.

The readings are stored in an array an then tested by gesture detection logic.

The working of gesture_detection is explained in the extended description of this commit.

int s2w_coord_nature(void)
{
int i = 0;
pr_info("%s:Recieved count - %d\n",__func__,s2w_touch_count);
pr_info("%s:max_x-%d\n",__func__,max_x);
pr_info("%s:max_y-%d\n",__func__,max_y);
pr_info("%s:min_x-%d\n",__func__,min_x);
pr_info("%s:min_y-%d\n",__func__,min_y);
/*This function detects the nature of sweep input, and on the basis of following, it returns -
1 - sweep right
2 - sweep left
3 - sweep up
4 - sweep down*/
pr_info("%s:multiple_dir - %d\n",__func__,multiple_dir);
for(i = 0; i < 4; i++ )
pr_info("%s:dir[%d] - %d\n",__func__,i,dir[i]);
if (abs(x - x_first) > 150 && abs(y - y_first) < 50 && abs(max_y - y) < 50) {
if(dir[0] > s2w_touch_count/2) {
pr_info("%s:Sweep right\n",__func__);
return 1;
}
else if(dir[1] > s2w_touch_count/2) {
pr_info("%s:Sweep left\n",__func__);
return 2;
}
}
if (abs(y - y_first) > 150 && abs(x - x_first) < 50 && abs(max_x - x) < 50) {
if(dir[2] > s2w_touch_count/2) {
pr_info("%s:Sweep up\n",__func__);
return 3;
}
else if(dir[3] > s2w_touch_count/2) {
pr_info("%s:Sweep down\n",__func__);
return 4;
}
}
if(abs(x - x_first) > 100 && abs(y - y_first) > 100 && (multiple_dir == s2w_touch_count - 1)) {
if(x > x_first) {
pr_info("%s:Forward diagonal swipe!!\n",__func__);
return 5;
}//forward diagonal swipe!!
else if(x < x_first) {
pr_info("%s:Backward diagonal swipe!!\n",__func__);
return 6;
}//backward diagonal swipe!!
}
if(abs(x - x_first) > 100 && abs(y - y_first) > 100 && (multiple_dir < s2w_touch_count - 1) && dir[0] > s2w_touch_count/3 && dir[3] > s2w_touch_count/3) {
pr_info("%s:Draw 'L'\n",__func__);
return 7;
}
if(abs(x - x_first) > 80 && abs(y - y_first) < 50 && dir[2] > s2w_touch_count/3 && dir[3] > s2w_touch_count/3 && (multiple_dir < s2w_touch_count - 1)) {
pr_info("%s:Draw 'V'\n",__func__);
return 8;
}

s2w_coord_reset();
return 0;

}

If swipe matches any gesture, it returns corresponding value, else returns 0.

About toggling, I created separate files for each gesture. Also, to simplify things, I had added a master switch for these gestures.

I also made an app for this to control these toggles - Gesture Control 1.4

Credits

showp1984 - Without his works, this is just nothing.

thewisenerd - It is for this guy, I know what I know about touch panels.