Skip to content

Instantly share code, notes, and snippets.

@trtg
Created October 20, 2012 10:15
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trtg/3922875 to your computer and use it in GitHub Desktop.
Save trtg/3922875 to your computer and use it in GitHub Desktop.
Visualize multitouch contact points from the magic trackpad using python in linux
#!/usr/bin/python
import pygame
import re
from numpy import int32
import ctypes
import time
w=1280
h=1024
#this is the debugfs entry for the trackpad, you can figure
#this out by watching the system log when you connect the trackpad
fd = open('/sys/kernel/debug/hid/0005:05AC:030E.0008/events','r')
screen = pygame.display.set_mode((w,h))
pygame.font.init()
font1 = pygame.font.match_font('mikachan')
mikaFont = pygame.font.Font(font1,28)
for index in range(20000):
oline=fd.readline();
line=oline.split();
#repaint black background
#if you move this outside the loop, you get
#fingerpainting-like behaviour, i.e. fingers leave tracks
screen.fill((0,0,0))
packets=[]
if((len(line)<4) or (line[0]!= "report")):
continue
#strip out everything but digits
reportsize=re.sub(r'\D',"",line[2])
header=line[5:9]
#handle the double packet message ID
if(int(header[0],16)==0xf7):
firstpktlength=int(header[1],16)
numpackets=2
packets.append(line[7:7+firstpktlength])
packets.append(line[firstpktlength+7:(len(line))])
elif(int(header[0],16)==0x28):
packets.append(line[5:(len(line))])
numpackets=1
if(len(packets)<=0):
continue
for ipkt in range(0,numpackets):
pkt=packets[ipkt]
data=pkt[4:len(pkt)]
numtouches=len(data)/9;
text1 = mikaFont.render(str(numtouches),1,(255,0,0),(0,0,0))
screen.blit(text1,(200,200))
for itouch in range(0,(numtouches)):
color=(0,0,100)
if(itouch%5==0):
color=(0,0,255)
if(itouch%5==1):
color=(0,255,0)
if(itouch%5==2):
color=(255,0,0)
tdata=data[itouch*9:(itouch+1)*9+1]
if(len(tdata)<9):
continue
X=(((int(tdata[1],16)&0x1F)<<27) | (int(int(tdata[0],16)<<19)))
Y=((((int(tdata[3],16)&0x3)<<30) | (int(tdata[2],16)<<22)|(int(tdata[1],16)<<14))>>19)
X=(((X>>19)))
X=ctypes.c_int32(X).value
X=X&0x1FFF
Y=Y&0x1FFF
#handle 2's complement
if(X&0x1000):
X=X-8192
if(Y&0x1000):
Y=Y-8192
#invert Y
Y=-Y
#push coordinates up into positive range
#then rescale to fit inside our pygame window
X=(X+3499)/6
Y=(Y+2856)/6
radius=int(tdata[6],16)&0x3f
orientation=(int(tdata[7],16)>>2)-32
touch_major=int(tdata[4],16)
touch_minor=int(tdata[5],16)
if((radius==0) or (touch_minor==0) or (touch_major==0)):
continue
if (radius>60):
radius=60
#if((int(tdata[8],16)&0xf0)==0x40): #only display fingers in drag state
if(1):
surface=pygame.Surface((touch_minor*2,touch_major*2))
surface.set_colorkey((0,0,0))
pygame.draw.ellipse(surface, color, (0,0,2*touch_minor,2*touch_major))
surface=pygame.transform.rotate(surface,orientation)
screen.blit(surface,(X,Y))
pygame.display.flip()
fd.close
@paven
Copy link

paven commented Jun 10, 2016

does this work?
tdata=data[itouch_9:(itouch+1)_9+1] has wierd intdentation

@Hzzkygcs
Copy link

huh? Invalid argument on line 11

Traceback (most recent call last):
File "C:\NE\Touchpad\main.py", line 11, in
fd = open('/sys/kernel/debug/hid/0005:05AC:030E.0008/events','r')
OSError: [Errno 22] Invalid argument: '/sys/kernel/debug/hid/0005:05AC:030E.0008/events'

@trtg
Copy link
Author

trtg commented Mar 31, 2020

@Hzzkygcs this gist was written specifically for Linux, this absolutely will not work as is with Windows. Even if you were using Linux, this was written 8 years ago, I have no idea if the kernel interface will still be the same now.

@Hzzkygcs
Copy link

@Hzzkygcs this gist was written specifically for Linux, this absolutely will not work as is with Windows. Even if you were using Linux, this was written 8 years ago, I have no idea if the kernel interface will still be the same now.

Uh, sorry for that then... Thank you anyway...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment