import code from https://code.google.com/archive/p/pybuddy-dx/
This commit is contained in:
52
dx/manual.txt
Normal file
52
dx/manual.txt
Normal 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
15
dx/pybuddy.cfg
Normal 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
250
dx/pybuddyDX.py
Normal 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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user