#!/usr/bin/env python

#  ccw: ??01004f1000
#   cw: ??ff004f1000
# down: 01??004f1000
#   up: 00??004f1000

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

outport:
	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.

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

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

def daemonize():
	import os
	pid = os.fork()
	if pid != 0:
		print pid
		return True
	else:
		os.setsid()

	return False

def main():
	import os
	from sys import argv, stdin, stdout, stderr
	args = dict(enumerate(argv))

	default_debug = False

	if 1 in args:
		if args[1] == "-h":
			usage()
			return

		outport_path = args[1]
	else:
		outport_path = None
		default_debug = True

	if 2 in args:
		inport = open(args[2], "rb")
	else:
		inport = open("/dev/uhid0", "rb")

	if 3 in args:
		debug = bool(args[3])
	else:
		debug = default_debug

	if not debug:
		if daemonize():
			return

	if outport_path is None:
		outport = stdout
	else:
		try:
			os.mkfifo(args[1], 0600)
		except OSError:
			pass
		outport = open(outport_path, "ab")

	separate = False

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

			pressed = ord(event[0]) > 0
			if pressed:
				delta *= 32
				if delta < -128:
					delta = -128
				elif delta > 127:
					delta = 127

			amount = abs(delta)
			if amount == 0:
				amount = 1

			if separate:
				if delta == 0:
					b6 = None
				elif delta > 0:
					b6 = 0x01
				elif delta < 0:
					b6 = 0x7f

				if b6 is not None:
					for i in range(amount):
						outport.write("\x87\x00\x00\x00\x00%s\x00\x7f" % (chr(b6)))
						outport.flush()	
			else:
				if delta == 0:
					b6 = 0
					b7 = 0
				elif delta > 0:
					if delta < 0x40:
						b6 = delta
						b7 = 0
					else:
						b6 = 0x3f
						b7 = delta - 0x3f
				elif delta < 0:
					if delta < -0x40:
						b6 = -0x40
						b7 = delta + 0x40
					else:
						b6 = delta
						b7 = 0
						
				if b6 != 0 or b7 != 0:
					if b6 < 0:
						b6 += 0x80
					if b7 < 0:
						b7 += 0x80
					outport.write("\x87\x00\x00\x00\x00%s%s\x7f" % (chr(b6), chr(b7)))
					outport.flush()	
				
				
			if debug:
				if delta < 0:
					direction = "ccw"
				elif delta > 0:
					direction = "cw"
				else:
					direction = "none"

				button = "down" if pressed else "up"

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

if __name__ == '__main__':
	main()
