This is a simple hack that I developed in one afternoon. While reading up about android stuff I ended up finding the getevent command for adb and it inspired me to work on a project to transform my smartphone into a drawing tablet. The result is kinda slow and it's a little bit buggy but works quite well for a quick prototype. See the video:

For this hack you're going to need adb. adb is a command line tool for debugging Android systems, it can be installed from your package manager.

You're going to have your phone connected to your computer via usb and enable the usb debugging mode from it's configuration. If you search the web for it, it's easy to find.

From your computer, running the command adb shell getevent -lp lists the input devices for your phone and provides useful information about variables. More info on getevent.

This is the touchscreen device on my phone:

add device 1: /dev/input/event3
name:     "synaptics_dsx_i2c"
events:
    ABS (0003): ABS_MT_SLOT           : value 0, min 0, max 9, fuzz 0, flat 0, resolution 0
                ABS_MT_TOUCH_MAJOR    : value 0, min 0, max 255, fuzz 0, flat 0, resolution 0
                ABS_MT_POSITION_X     : value 0, min 0, max 720, fuzz 0, flat 0, resolution 0
                ABS_MT_POSITION_Y     : value 0, min 0, max 1280, fuzz 0, flat 0, resolution 0
                ABS_MT_TRACKING_ID    : value 0, min 0, max 65535, fuzz 0, f    lat 0, resolution 0
                ABS_MT_PRESSURE       : value 0, min 0, max 255, fuzz 0, flat 0, resolution 0
input props:
    INPUT_PROP_DIRECT

Running adb shell getevent -l /dev/input/event3, it interactively prints events from this device, like in the example below. The first column is the event type, the second one is the parameter and the third the value. I'm only interested on the latter two.

EV_ABS       ABS_MT_TRACKING_ID   0000190f            
EV_ABS       ABS_MT_POSITION_X    0000022a            
EV_ABS       ABS_MT_POSITION_Y    000002ea            
EV_ABS       ABS_MT_PRESSURE      00000031            
EV_ABS       ABS_MT_TOUCH_MAJOR   00000031            
EV_SYN       SYN_REPORT           00000000            
EV_ABS       ABS_MT_TRACKING_ID   ffffffff            
EV_SYN       SYN_REPORT           00000000

After tapping on my phone and analyzing the output, I found that I could use the variable ABS_MT_TRACKING_ID as a key down / key up event. The value ffffffff seems to be associated with key up, everything else I considered key down. The ABS_MT_POSITION_X and ABS_MT_POSITION_Y parameters are obvious, as they represent the x,y coordinates.

xdotool is a command line tool for simulating input devices on your computer. I used it to move the mouse around my computer. The syntax is as it follows:

# Move mouse to the (x,y) (100,100) coordinates on the screen
xdotool mousemove 100 100;
# Set the mouse button 1 down
xdotool mousedown 1;
# Set the mouse button 1 up
xdotool mouseup 1;

When converting the values from the x,y coordinates, I noticed they are huge. In my device the vertical coordinate seem to vary from 0 to 12360, possibly reflecting the sensitivity of the device. I had to scale these numbers to the resolution of my screem. It is baasic old school math, like so:

scaledCoords = (originalCoords/phone_maxCoords)*computerResolution;

Now all I had to do was to pipe the output of getevent, parse the parameters, scale and convert the x,y coordinates to decimal and use them on xdotool. I made a shell script for it, this is the final version:

#! /bin/bash


x=0;
y=0;
phone_maxY="7080";
phone_maxX="12360";
computer_maxX="1920";
computer_maxY="1080";
scale="0.75";
i=0;
mouse="up";
adb shell getevent -l /dev/input/event3 | while read type param value
do
    if [[ $param == "ABS_MT_TRACKING_ID" ]]
    then
        if [[ ${value:4:4} == "ffff" ]]
        then
            mouse="up"; 
            xdotool mouseup 1;
            echo "up";
        else
            mouse="down";
            echo "down";
        fi
    fi
    if [[ $param == "ABS_MT_POSITION_X" || $param == "ABS_MT_POSITION_Y" ]]
    then
        ((i++));

        [[ $param == "ABS_MT_POSITION_X" ]] && y=$(printf "%d" 0x$value 2>/dev/null);
        [[ $param == "ABS_MT_POSITION_Y" ]] && x=$(printf "%d" 0x$value 2>/dev/null);

        if ((i == 2))
        then
            # scale
            newX=$(lua -e "print($x/$phone_maxX);");
            newY=$(lua -e "print(($phone_maxY-$y)/$phone_maxY);");
            # zoom (centralize)
            newX=$(lua -e "print($newX*$scale+0.5*(1-$scale));");
            newY=$(lua -e "print($newY*$scale+0.5*(1-$scale));");
            # map to screen coordinates
            newX=$(lua -e "print(math.floor($newX*$computer_maxX));");
            newY=$(lua -e "print(math.floor($newY*$computer_maxY));");

            xdotool mousemove $newX $newY mousedown 1;
            echo $mouse $newX $newY;

            i=0;
        fi
    fi
done;

Of course because I did it via a shell script and had to pipe stuff around, the prototype is a little bit slow, but it is just a proof of concept I did in the afternoon. You're free to improve it and make it better.


Download the source code.