From 440005d7a198bddf28f487aae5a697e3669f608b Mon Sep 17 00:00:00 2001 From: Rik Veenboer Date: Mon, 11 Jul 2016 09:08:14 +0100 Subject: [PATCH] import code from https://code.google.com/archive/p/pybuddy-dx/ --- dx/manual.txt | 52 ++++++++++ dx/pybuddy.cfg | 15 +++ dx/pybuddyDX.py | 250 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 317 insertions(+) create mode 100644 dx/manual.txt create mode 100644 dx/pybuddy.cfg create mode 100644 dx/pybuddyDX.py diff --git a/dx/manual.txt b/dx/manual.txt new file mode 100644 index 0000000..6dea9d7 --- /dev/null +++ b/dx/manual.txt @@ -0,0 +1,52 @@ +pybuddyDX by Peter D'Hoye +http://code.google.com/p/pybuddy-dx/ + +Follow these steps to get pybuddyDX up and running: + + +1) Install dependencies: python v2.3 or higher, python-usb: +2) Edit the pybuddy.cfg if required (change at least the username) + + +=> To launch the daemon: + + $ sudo ./pybuddyDX.py + 2010-01-16 01:58:00,216 INFO Searching e-buddy... + 2010-01-16 01:58:00,668 INFO DX e-buddy found! + 2010-01-16 01:58:01,282 INFO Starting daemon... + +=> To test: + + $ echo 00 | nc -q0 -u localhost 8888 + +Where you can replace the 00 with any number between 00 and 25. 17 turns all effects off. +Effects 18 to 25 last until turned off again, the others stop themselves. + +Here's a quick list of the commands, a more complete description will follow later + +GLADNESS = 00 +FEAR = 01 +FIZZ = 02 +PLEASANTSURPRISE = 03 +GRIEF = 04 +FURY = 05 +QUELL = 06 +REDHEAD = 07 +GREENHEAD = 08 +BLUEHEAD = 09 +YELLOWHEAD = 10 +BLAME = 11 +BLUEGREENHEAD = 12 +WHITEHEAD = 13 +HEART = 14 +WINGS = 15 +BODY = 16 +NOEFFECT = 17 +ONLINE = 18 +BUSY = 19 +DAZE = 20 +BACKSOON = 21 +AWAY = 22 +PHONE = 23 +LUNCH = 24 +OFFLINE = 25 diff --git a/dx/pybuddy.cfg b/dx/pybuddy.cfg new file mode 100644 index 0000000..4a48e18 --- /dev/null +++ b/dx/pybuddy.cfg @@ -0,0 +1,15 @@ +[network] +# 127.0.0.1 is the default +# change it to 0.0.0.0 to bind to all interfaces +address: 127.0.0.1 +port: 8888 + +[system] +# user to setuid to after daemon is started +user: usernamehere + +# logging +# loglevel: info/debug +loglevel: info +# logfile: console for console logging, set to filename to log to file +logfile: console diff --git a/dx/pybuddyDX.py b/dx/pybuddyDX.py new file mode 100644 index 0000000..d0021b1 --- /dev/null +++ b/dx/pybuddyDX.py @@ -0,0 +1,250 @@ +#!/usr/bin/python +# +# pybuddyDX +# python e-buddy (ibuddy alike sold on DX) daemon +# http://code.google.com/p/pybuddyDX +# +# protocol reverse engineered and implemented by +# peter.dhoye@gmail.com +# +# borrows code from http://code.google.com/p/pybuddy +# by Jose.Carlos.Luna@gmail.com and luis.peralta@gmail.com +# who got most of the code from http://cuntography.com/blog/?p=17 +# Which is based on http://scott.weston.id.au/software/pymissile/ + +import usb +import time +import sys +import socket +import os +import pwd +import logging +from ConfigParser import RawConfigParser + +################ +#Commands +################ +# GLADNESS = 00 +# FEAR = 01 +# FIZZ = 02 +# PLEASANTSURPRISE =03 +# GRIEF = 04 +# FURY = 05 +# QUELL = 06 +# REDHEAD = 07 +# GREENHEAD = 08 +# BLUEHEAD = 09 +# YELLOWHEAD = 10 +# BLAME = 11 +# BLUEGREENHEAD = 12 +# WHITEHEAD = 13 +# HEART = 14 +# WINGS = 15 +# BODY = 16 +# NOEFFECT = 17 +# ONLINE = 18 +# BUSY = 19 +# DAZE = 20 +# BACKSOON = 21 +# AWAY = 22 +# PHONE = 23 +# LUNCH = 24 +# OFFLINE = 25 + +################ +#Configuration +################ +tsleep = 0.1 + + +################ +# IBUDDY class +################ + +class BuddyDevice: + SETUP = (0x21, 0x09, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00) + MESS = (0x43, 0x4D) + + OFF1 = 0x31 + OFF2 = 0x37 + + code1 = OFF1 + code2 = OFF2 + + def __init__(self): + try: + self.dev=UsbDevice(0x0c45, 0x11) + self.dev.open() + self.dev.handle.reset() + self.resetMessage() + except NoBuddyException, e: + raise NoBuddyException() + + def resetMessage(self): + self.code1 = self.OFF1 + self.code1 = self.OFF1 + self.send() + + def send(self): + try: + self.dev.handle.controlMsg(0x21, 0x09, self.SETUP, 0x0200, 0x00) + self.dev.handle.controlMsg(0x21, 0x09, self.MESS+(self.code1,self.code2), 0x0200, 0x00) + except usb.USBError: + log.info("Error sending USB command") + raise NoBuddyException() + +##################### +# USB class +###################### + +class UsbDevice: + def __init__(self, vendor_id, product_id): + busses = usb.busses() + self.handle = None + for bus in busses: + devices = bus.devices + for dev in devices: + if dev.idVendor==vendor_id and dev.idProduct==product_id: + log.info("DX e-buddy found!") +# log.info("vend %s prod %s",dev.idVendor, dev.idProduct) + self.dev = dev + self.conf = self.dev.configurations[0] + self.intf = self.conf.interfaces[0][0] + self.endpoints = [] +# log.info("interface = %x, class = %s, protocol = %s", self.intf.interfaceNumber, self.intf.interfaceClass, self.intf.interfaceProtocol) + for endpoint in self.intf.endpoints: + self.endpoints.append(endpoint) +# log.info("endpoint number = %x, type = %s", endpoint.address, endpoint.type) + return + raise NoBuddyException() + + def open(self): + if self.handle: + self.handle = None + self.handle = self.dev.open() + +# if self.handle: +# log.info("Handle OK") + + #We need to detach HID interface + try: + self.handle.detachKernelDriver(0) + self.handle.detachKernelDriver(1) + except: + pass + + try: + self.handle.setConfiguration(self.conf) + self.handle.claimInterface(0) + self.handle.setAltInterface(0) + except: + log.info("Configuration failed") + raise NoBuddyException() + +# log.info("Device opened OK") + +class NoBuddyException(Exception): pass + + +######################################### +# Decoding macros +########################################## + + +def decode_buddy (buddy,msg): +# log.info("Received message: %s",msg) + buddy.code1 = int(msg)/10 + 0x30 + buddy.code2 = int(msg) - (int(msg)/10)*10 + 0x30 +# log.info("Codes: %x %x",buddy.code1,buddy.code2) + +####################################### +# MAIN program +####################################### + +log = logging.getLogger('pybuddy') + +#Default config +config = RawConfigParser( + { 'port': 8888, + 'address': '127.0.0.1', + 'user': 'nobody', + 'loglevel': 'info', + 'logfile': 'console', + } +) + +config._sections = {'network':{}, 'system':{}} + +config_files = [ "~/.pybuddy.cfg", + "/etc/pybuddy/pybuddy.cfg", + "/usr/local/etc/pybuddy.cfg" +] + +#Parse config +if len(sys.argv) > 1: + config_files.append(sys.argv[1]) + +config_read = config.read(config_files) + +if config.get("system", "logfile") != "console": + logging.basicConfig( + filename=config.get("system", "logfile"), + format='%(asctime)s %(levelname)-8s %(message)s', + ) +else: + logging.basicConfig( + stream=sys.stderr, + format='%(asctime)s %(levelname)-8s %(message)s', + ) + + +if config.get("system", "loglevel") == "debug": + log.setLevel(logging.DEBUG) +elif config.get("system", "loglevel") == "info": + log.setLevel(logging.INFO) + + +if config_read: + log.info("Read config file: %s", config_read[0]) + +#Initialize device +log.info("Searching e-buddy...") +try: + buddy=BuddyDevice() +except NoBuddyException, e: + log.error("Not found or ERROR!") + sys.exit(1) + + +#Daemonize +log.info("Starting daemon...") +if os.fork()==0: + os.setsid() +else: + sys.exit(0) + +#Create server socket +s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +s.bind((config.get("network", "address"), int(config.get("network", "port")))) + +#Drop privileges +try: + uid = pwd.getpwnam(config.get("system", "user"))[2] +except KeyError: + log.error("Username %s not found, exiting...", config.get("system", "user")) + sys.exit(1) +os.setuid(uid) + + +#Main message loop +while 1: + try: + message, address = s.recvfrom(8192) +# log.debug("Got data from %s", address) + decode_buddy(buddy, message) + buddy.send() + except (KeyboardInterrupt, SystemExit): + raise + +