This commit is contained in:
2016-07-11 09:08:14 +01:00
parent 9a5b9bbd8d
commit 440005d7a1
3 changed files with 317 additions and 0 deletions

52
dx/manual.txt Normal file
View File

@@ -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

15
dx/pybuddy.cfg Normal file
View File

@@ -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

250
dx/pybuddyDX.py Normal file
View File

@@ -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