Friday, February 12, 2010

My simple python driver for my touch screen input

The story begins when I got a laptop (netbook I should say) with a touch screen from a company named "MosArt"

A version of 64-bit windows 7 came pre-installed on it, and the touch screen worked pretty well - it had its moments, but worked.

I installed ubuntu on another partition, and expected the touch screen to work out of the box. But doesn't look like anybody has heard about the company yet (could not find any references to them by regular searches). It was time to write my own driver.

Never written a linux driver before - wanted this to be very simple. First I ran the hardware info command to find the device.

hwinfo > hwinfo.txt

found the following line which led me to the socket that was connected to the device

  hiddev.device = '/dev/usb/hiddev0'
  info.subsystem = 'usb'
  info.product = 'MosArt, Inc. RMTP-MA957'

Now, to really find out if that was the device connected, I ran the command

cat /dev/usb/hiddev0

which printed out a bunch of junk - Now for the moment of truth, I touched the screen, and it printed some more junk. Touch again, and more junk proving that me touching the screen was putting out all the junk confirming that I had the right device.

To make the binary output readable, I wrote a small python program to print the output in hex.

import os

def byte2hex(byteStr):
    return ''.join( [ "%02X" % ord( x ) for x in byteStr ] ).strip()

dev ="/dev/usb/hiddev0", os.O_RDONLY) 

while True:
    bytes =, 10)
    hex = byte2hex(bytes)
    print hex

The output of the above program would print the following on every touch on my screen. My analysis of the output was as follows:

All my assumptions above were just right, except that the x position and y position hex bytes were a bit reversed. For instance D105 (53509) is actually 05D1 which translates to 1485 (more believable number than the other ridiculous number.

Now, all is required is the program which can translate my assumption to mouse moves. I used an external tool called xdotool to simulate mouse moves and clicks.

Here is the program:

#! /usr/bin/python
import os

res_x = 1366; res_y = 768
max_x = 3825; max_y = 3825

def byte2hex(byteStr):
    return ''.join( [ "%02X" % ord( x ) for x in byteStr ] ).strip()

def reverse(h):
    return "%s%s%s%s" % (h[2], h[3], h[0], h[1])

def calibrate_x(n):
    return n * res_x / max_x

def calibrate_y(n):
    return n * res_y / max_y

def mouse_action(pa, px, py):
    cx = calibrate_x(int(px, 16))
    cy = calibrate_y(int(py, 16))
    movemouse(cx, cy)
    if pa == "touch end":
        mouseup(cx, cy)
        mousedown(cx, cy)

def movemouse(x, y):
    os.spawnvp(os.P_WAIT, "/usr/bin/xdotool", ["", "mousemove", "%s"%x, "%s"%y])

def mousedown(x, y):
    os.spawnvp(os.P_WAIT, "/usr/bin/xdotool", ["", "mousedown", "1"])

def mouseup(x, y):
    os.spawnvp(os.P_WAIT, "/usr/bin/xdotool", ["", "mouseup", "1"])

dev ="/dev/usb/hiddev0", os.O_RDONLY)
    pa = None; px = None; py = None
    while True:
        bytes =, 10)
        hex = byte2hex(bytes)
        if hex == "0100090000000000":
            pa = "touch end"
        elif hex == "0100090001000000":
            pa = "touch"
        elif hex == "0200090000000000":
        elif hex[0:8] == "30000100":
            px = reverse(hex[8:12])
        elif hex[0:8] == "31000100":
            py = reverse(hex[8:12])
            mouse_action(pa, px, py)
            print h
except Exception, e:
    print "Stopping"
    raise e


  1. This is a really good idea, and works perfectly on my netbook too. Unfortunately it runs pretty slowly when dragging the mouse. I might build on what you've done in C and see if I can get a speed increase. Thanks!

  2. This comment has been removed by a blog administrator.

  3. I was surfing the Internet for information and came across your blog. I am impressed by the information you have on this blog. It shows how well you understand this subject. monitor