Project

General

Profile

Submit #2921 » scrollwheel.py

example that maps a volume knob USB HID device to scrolling mouse events - tautolog, 06/10/2016 02:31 PM

 
1
#!/usr/bin/env python
2

    
3
#  ccw: ??01004f1000
4
#   cw: ??ff004f1000
5
# down: 01??004f1000
6
#   up: 00??004f1000
7

    
8
def usage():
9
	from sys import argv
10
	print "%s [outport] [inport] [debug]" % argv[0]
11
	print """
12
Generates sysmouse mouse-wheel events from USB HID Multimedia Controllers (USB volume knobs)
13

    
14
outport:
15
	Named pipe for `moused -p $outport -t sysmouse`. Defaults to stdout for `moused -f -p /dev/stdin -t sysmouse -d -d` and enables debug mode.
16

    
17
inport:
18
	The USB HID device node. Defaults to "/dev/uhid0".
19

    
20
debug:
21
	If non-empty, this doesn't background the process, and prints CSV events to stderr.
22
	If empty or non-existent, then the process will background and print the daemon PID to stdout and exit.
23
""" 
24

    
25
def daemonize():
26
	import os
27
	pid = os.fork()
28
	if pid != 0:
29
		print pid
30
		return True
31
	else:
32
		os.setsid()
33

    
34
	return False
35

    
36
def main():
37
	import os
38
	from sys import argv, stdin, stdout, stderr
39
	args = dict(enumerate(argv))
40

    
41
	default_debug = False
42

    
43
	if 1 in args:
44
		if args[1] == "-h":
45
			usage()
46
			return
47

    
48
		outport_path = args[1]
49
	else:
50
		outport_path = None
51
		default_debug = True
52

    
53
	if 2 in args:
54
		inport = open(args[2], "rb")
55
	else:
56
		inport = open("/dev/uhid0", "rb")
57

    
58
	if 3 in args:
59
		debug = bool(args[3])
60
	else:
61
		debug = default_debug
62

    
63
	if not debug:
64
		if daemonize():
65
			return
66

    
67
	if outport_path is None:
68
		outport = stdout
69
	else:
70
		try:
71
			os.mkfifo(args[1], 0600)
72
		except OSError:
73
			pass
74
		outport = open(outport_path, "ab")
75

    
76
	separate = False
77

    
78
	while True:
79
		event = inport.read(6)
80
		if event.endswith("\x00\x4f\x10\x00"):
81
			delta = ((ord(event[1]) + 128) % 256) - 128
82

    
83
			pressed = ord(event[0]) > 0
84
			if pressed:
85
				delta *= 32
86
				if delta < -128:
87
					delta = -128
88
				elif delta > 127:
89
					delta = 127
90

    
91
			amount = abs(delta)
92
			if amount == 0:
93
				amount = 1
94

    
95
			if separate:
96
				if delta == 0:
97
					b6 = None
98
				elif delta > 0:
99
					b6 = 0x01
100
				elif delta < 0:
101
					b6 = 0x7f
102

    
103
				if b6 is not None:
104
					for i in range(amount):
105
						outport.write("\x87\x00\x00\x00\x00%s\x00\x7f" % (chr(b6)))
106
						outport.flush()	
107
			else:
108
				if delta == 0:
109
					b6 = 0
110
					b7 = 0
111
				elif delta > 0:
112
					if delta < 0x40:
113
						b6 = delta
114
						b7 = 0
115
					else:
116
						b6 = 0x3f
117
						b7 = delta - 0x3f
118
				elif delta < 0:
119
					if delta < -0x40:
120
						b6 = -0x40
121
						b7 = delta + 0x40
122
					else:
123
						b6 = delta
124
						b7 = 0
125
						
126
				if b6 != 0 or b7 != 0:
127
					if b6 < 0:
128
						b6 += 0x80
129
					if b7 < 0:
130
						b7 += 0x80
131
					outport.write("\x87\x00\x00\x00\x00%s%s\x7f" % (chr(b6), chr(b7)))
132
					outport.flush()	
133
				
134
				
135
			if debug:
136
				if delta < 0:
137
					direction = "ccw"
138
				elif delta > 0:
139
					direction = "cw"
140
				else:
141
					direction = "none"
142

    
143
				button = "down" if pressed else "up"
144

    
145
				for i in range(amount):
146
					stderr.write("%s,%s\r\n" % (direction, button))
147
					stderr.flush()
148

    
149
if __name__ == '__main__':
150
	main()
(2-2/2)