From: <bla...@us...> - 2009-07-27 09:16:23
|
Revision: 19709 http://personalrobots.svn.sourceforge.net/personalrobots/?rev=19709&view=rev Author: blaisegassend Date: 2009-07-27 09:16:09 +0000 (Mon, 27 Jul 2009) Log Message: ----------- Robustified and simplified the driver. Removed dependence on swiged kernel headers. Modified Paths: -------------- pkg/trunk/stacks/joystick_drivers/ps3joy/ps3joy.py Removed Paths: ------------- pkg/trunk/stacks/joystick_drivers/ps3joy/uinput.i Modified: pkg/trunk/stacks/joystick_drivers/ps3joy/ps3joy.py =================================================================== --- pkg/trunk/stacks/joystick_drivers/ps3joy/ps3joy.py 2009-07-27 08:27:45 UTC (rev 19708) +++ pkg/trunk/stacks/joystick_drivers/ps3joy/ps3joy.py 2009-07-27 09:16:09 UTC (rev 19709) @@ -1,14 +1,22 @@ #!/usr/bin/python from bluetooth import * import select -import uinput import fcntl import os import time +import sys +import traceback L2CAP_PSM_HIDP_CTRL = 17 L2CAP_PSM_HIDP_INTR = 19 +class uinput: + EV_KEY = 1 + EV_REL = 2 + EV_ABS = 3 + BUS_USB = 3 + ABS_MAX = 0x3f + class uinputjoy: def __init__(self, buttons, axes): self.file = None @@ -72,95 +80,76 @@ class decoder: def __init__(self): - buttons=[uinput.BTN_SELECT, uinput.BTN_THUMBL, uinput.BTN_THUMBR, uinput.BTN_START, - uinput.BTN_FORWARD, uinput.BTN_RIGHT, uinput.BTN_BACK, uinput.BTN_LEFT, - uinput.BTN_TL, uinput.BTN_TR, uinput.BTN_TL2, uinput.BTN_TR2, - uinput.BTN_X, uinput.BTN_A, uinput.BTN_B, uinput.BTN_Y, - uinput.BTN_MODE] - axes=[uinput.ABS_X, uinput.ABS_Y, uinput.ABS_Z, uinput.ABS_RX, - uinput.ABS_RX, uinput.ABS_RY, uinput.ABS_PRESSURE, uinput.ABS_DISTANCE, - uinput.ABS_THROTTLE, uinput.ABS_RUDDER, uinput.ABS_WHEEL, uinput.ABS_GAS, - uinput.ABS_HAT0Y, uinput.ABS_HAT1Y, uinput.ABS_HAT2Y, uinput.ABS_HAT3Y, - uinput.ABS_TILT_X, uinput.ABS_TILT_Y, uinput.ABS_MISC, uinput.ABS_RZ, - ] + #buttons=[uinput.BTN_SELECT, uinput.BTN_THUMBL, uinput.BTN_THUMBR, uinput.BTN_START, + # uinput.BTN_FORWARD, uinput.BTN_RIGHT, uinput.BTN_BACK, uinput.BTN_LEFT, + # uinput.BTN_TL, uinput.BTN_TR, uinput.BTN_TL2, uinput.BTN_TR2, + # uinput.BTN_X, uinput.BTN_A, uinput.BTN_B, uinput.BTN_Y, + # uinput.BTN_MODE] + #axes=[uinput.ABS_X, uinput.ABS_Y, uinput.ABS_Z, uinput.ABS_RX, + # uinput.ABS_RX, uinput.ABS_RY, uinput.ABS_PRESSURE, uinput.ABS_DISTANCE, + # uinput.ABS_THROTTLE, uinput.ABS_RUDDER, uinput.ABS_WHEEL, uinput.ABS_GAS, + # uinput.ABS_HAT0Y, uinput.ABS_HAT1Y, uinput.ABS_HAT2Y, uinput.ABS_HAT3Y, + # uinput.ABS_TILT_X, uinput.ABS_TILT_Y, uinput.ABS_MISC, uinput.ABS_RZ, + # ] + buttons = range(0x100,0x111) + axes = range(0, 20) self.joy = uinputjoy(buttons, axes) + self.outlen = len(buttons) + len(axes) - def step(self, sock): - joy_coding = "!3x3B1x4B4x12B15x4H" - data = struct.unpack(joy_coding, sock.recv(128)) - #print data, - out = [0] * (17 + 20) - i = 0 + def step(self, sock): # Returns true if the packet was legal + joy_coding = "!1B2x3B1x4B4x12B15x4H" + rawdata = sock.recv(128) + if len(rawdata) != 50: + print "Unexpected packet length:", len(data) + return False + data = list(struct.unpack(joy_coding, rawdata)) + prefix = data.pop(0) + if prefix != 161: + print "Unexpected prefix:", prefix + return False + out = [] for j in range(0,2): + curbyte = data.pop(0) for k in range(0,8): - out[i] = int((data[j] & (1 << k)) != 0) - i = i + 1 - out[i] =data[2] - i = i + 1 + out.append(int((curbyte & (1 << k)) != 0)) + out.append(data.pop(0)) for j in range(3,7): - out[i] = data[j] - 0x80 - i = i + 1 + out.append(data.pop(0) - 0x80) for j in range(7,19): - out[i] = data[j] - i = i + 1 + out.append(data.pop(0)) for j in range(19,23): - out[i] = data[j] - 0x200 - i = i + 1 + out.append(data.pop(0) - 0x200) #print out self.joy.update(out) + return True + def fullstop(self): + self.joy.update([0] * self.outlen) + def run(self, intr, ctrl): - start = time.time() - frames = 0 - while True: - (rd, wr, err) = select.select([intr], [], [], 0.1) - if len(rd) + len(wr) + len(err) == 0: # Timeout - print "Activating connection." - ctrl.send("\x53\xf4\x42\x03\x00\x00") # Try activating the stream. - else: # Got a frame. - frames = frames + 1 + try: + lastvalidtime = 0 + while True: + (rd, wr, err) = select.select([intr], [], [], 0.1) curtime = time.time() - print "Got a frame at ", curtime, frames / (curtime - start) - self.step(intr) + if len(rd) + len(wr) + len(err) == 0: # Timeout + print "Activating connection." + ctrl.send("\x53\xf4\x42\x03\x00\x00") # Try activating the stream. + if lastvalidtime - curtime >= 0.1: # Zero all outputs if we don't hear a valid frame for 0.1 to 0.2 seconds + self.fullstop() + if lastvalidtime - curtime >= 5: # Disconnect if we don't hear a valid frame for 5 seconds + return + else: # Got a frame. + print "Got a frame at ", curtime, 1 / (curtime - lastvalidtime) + if self.step(intr): + lastvalidtime = curtime + finally: + self.fullstop() class connection_manager: def __init__(self, decoder): - self.devicesockets = {} # Stores dev to socket pair mapping - self.intrdev = {} # Stores socket to dev mapping - self.ctrldev = {} # Stores socket to dev mapping - self.socknames = [ "intr", "ctrl" ] - self.sockdev = [ self.intrdev, self.ctrldev ] self.decoder = decoder - def acceptsock(self, index, servsock): - (sock, (dev, port)) = servsock.accept() - print "Adding", self.socknames[index], "from", dev - try: - devsock = self.devicesockets[dev] - except KeyError: - devsock = [None, None] - if devsock[index] != None: - print "addintr: Already had an", self.socknames[index], "socket for ", dev - devsock[index] = sock - self.devicesockets[dev] = devsock - self.sockdev[index][sock] = dev - print devsock - print self.devicesockets - if devsock[0] != None and devsock[1] != None: - print "Both connections are open" - try: - self.decoder.run(devsock[0], devsock[1]) - except: # Normal exit point upon disconnect. - print "Joystick disconnected or errored out." - devsock[0].close() - devsock[1].close() - - def acceptintr(self, sock): - self.acceptsock(0, sock) - - def acceptctrl(self, sock): - self.acceptsock(1, sock) - def prepare_socket(self, port): sock = BluetoothSocket(L2CAP) sock.bind(("", port)) @@ -172,15 +161,18 @@ ctrl_sock = self.prepare_socket(L2CAP_PSM_HIDP_CTRL) while True: - (rd, wr, err) = select.select([intr_sock, ctrl_sock], [], [], 60) - for s in rd: - #print "Socket ", s, "is in read list." - if s == intr_sock: - cm.acceptintr(s) - elif s == ctrl_sock: - cm.acceptctrl(s) - else: - print "Unexpected socket after select" + (intr, (idev, iport)) = intr_sock.accept(); + (ctrl, (cdev, cport)) = ctrl_sock.accept(); + if idev == cdev: + try: + self.decoder.run(intr, ctrl) + except: + print "Connection broken or error." + traceback.print_exc() + else: + print "Simultaneous connection from two different devices. Ignoring both." + ctrl.close() + intr.close() if __name__ == "__main__": cm = connection_manager(decoder()) Deleted: pkg/trunk/stacks/joystick_drivers/ps3joy/uinput.i =================================================================== --- pkg/trunk/stacks/joystick_drivers/ps3joy/uinput.i 2009-07-27 08:27:45 UTC (rev 19708) +++ pkg/trunk/stacks/joystick_drivers/ps3joy/uinput.i 2009-07-27 09:16:09 UTC (rev 19709) @@ -1,8 +0,0 @@ -%module uinput -%{ -#include "linux/uinput.h" -#include "linux/input.h" -%} - -%include "linux/uinput.h" -%include "linux/input.h" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bla...@us...> - 2009-08-06 18:18:32
|
Revision: 20914 http://personalrobots.svn.sourceforge.net/personalrobots/?rev=20914&view=rev Author: blaisegassend Date: 2009-08-06 18:18:14 +0000 (Thu, 06 Aug 2009) Log Message: ----------- Added pairing tools and instructions Modified Paths: -------------- pkg/trunk/stacks/joystick_drivers/ps3joy/CMakeLists.txt Added Paths: ----------- pkg/trunk/stacks/joystick_drivers/ps3joy/README pkg/trunk/stacks/joystick_drivers/ps3joy/sixpair.c Modified: pkg/trunk/stacks/joystick_drivers/ps3joy/CMakeLists.txt =================================================================== --- pkg/trunk/stacks/joystick_drivers/ps3joy/CMakeLists.txt 2009-08-06 18:16:23 UTC (rev 20913) +++ pkg/trunk/stacks/joystick_drivers/ps3joy/CMakeLists.txt 2009-08-06 18:18:14 UTC (rev 20914) @@ -21,10 +21,12 @@ #uncomment if you have defined services #gensrv() +rospack_add_executable(sixpair sixpair.c) +target_link_libraries(sixpair -lusb) + #common commands for building c++ executables and libraries #rospack_add_library(${PROJECT_NAME} src/example.cpp) #target_link_libraries(${PROJECT_NAME} another_library) #rospack_add_boost_directories() #rospack_link_boost(${PROJECT_NAME} thread) #rospack_add_executable(example examples/example.cpp) -#target_link_libraries(example ${PROJECT_NAME}) Added: pkg/trunk/stacks/joystick_drivers/ps3joy/README =================================================================== --- pkg/trunk/stacks/joystick_drivers/ps3joy/README (rev 0) +++ pkg/trunk/stacks/joystick_drivers/ps3joy/README 2009-08-06 18:18:14 UTC (rev 20914) @@ -0,0 +1,46 @@ +Packages that need to be installed +---------------------------------- +joystick +libusb-dev + +Pairing instructions +-------------------- + +1) If you can connect the joystick and the bluetooth dongle into the same +computer. + +Connect the joystick to the computer using a USB cable. + +Load the bluetooth dongle's MAC address into the ps3 joystick using: + +sudo bash +rosrun ps3joy sixpair + +2) If you cannot connect the joystick to the same computer as the dongle. + +Find out the bluetooth dongle's MAC address by running (on the computer +that has the bluetooth dongle): + +hciconfig + +If this does not work, you may need to do +sudo hciconfig hci0 up +and retry +hciconfig + +Plug the PS3 joystick into some other computer using a USB cable. + +Replace the joystick's mac address in the following command: +sudo rosrun ps3joy sixpair 01:23:45:67:89:ab + +Starting the PS3 joystick +------------------------- + +rosrun ps3joy ps3joy.py + +This should make a joystick appear at /dev/input/js? + +You can check that it is working with +jstest /dev/input/js? +(replace ? with the name of your joystick) + Added: pkg/trunk/stacks/joystick_drivers/ps3joy/sixpair.c =================================================================== --- pkg/trunk/stacks/joystick_drivers/ps3joy/sixpair.c (rev 0) +++ pkg/trunk/stacks/joystick_drivers/ps3joy/sixpair.c 2009-08-06 18:18:14 UTC (rev 20914) @@ -0,0 +1,122 @@ +/* + * sixpair.c version 2007-04-18 + * Compile with: gcc -o sixpair sixpair.c -lusb + */ + +#include <string.h> +#include <unistd.h> +#include <stdio.h> +#include <usb.h> + +#define VENDOR 0x054c +#define PRODUCT 0x0268 + +#define USB_DIR_IN 0x80 +#define USB_DIR_OUT 0 + +void fatal(char *msg) { perror(msg); exit(1); } + +void show_master(usb_dev_handle *devh, int itfnum) { + printf("Current Bluetooth master: "); + unsigned char msg[8]; + int res = usb_control_msg + (devh, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + 0x01, 0x03f5, itfnum, (void*)msg, sizeof(msg), 5000); + if ( res < 0 ) { perror("USB_REQ_GET_CONFIGURATION"); return; } + printf("%02x:%02x:%02x:%02x:%02x:%02x\n", + msg[2], msg[3], msg[4], msg[5], msg[6], msg[7]); +} + +void set_master(usb_dev_handle *devh, int itfnum, int mac[6]) { + printf("Setting master bd_addr to %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + char msg[8]= { 0x01, 0x00, mac[0],mac[1],mac[2],mac[3],mac[4],mac[5] }; + int res = usb_control_msg + (devh, + USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + 0x09, + 0x03f5, itfnum, msg, sizeof(msg), + 5000); + if ( res < 0 ) fatal("USB_REQ_SET_CONFIGURATION"); +} + +void process_device(int argc, char **argv, struct usb_device *dev, + struct usb_config_descriptor *cfg, int itfnum) { + int mac[6], have_mac=0; + + usb_dev_handle *devh = usb_open(dev); + if ( ! devh ) fatal("usb_open"); + + usb_detach_kernel_driver_np(devh, itfnum); + + int res = usb_claim_interface(devh, itfnum); + if ( res < 0 ) fatal("usb_claim_interface"); + + show_master(devh, itfnum); + + if ( argc >= 2 ) { + if ( sscanf(argv[1], "%x:%x:%x:%x:%x:%x", + &mac[0],&mac[1],&mac[2],&mac[3],&mac[4],&mac[5]) != 6 ) { + + printf("usage: %s [<bd_addr of master>]\n", argv[0]); + exit(1); + } + } else { + FILE *f = popen("hcitool dev", "r"); + if ( !f || + fscanf(f, "%*s\n%*s %x:%x:%x:%x:%x:%x", + &mac[0],&mac[1],&mac[2],&mac[3],&mac[4],&mac[5]) != 6 ) { + printf("Unable to retrieve local bd_addr from `hcitool dev`.\n"); + printf("Please enable Bluetooth or specify an address manually.\n"); + exit(1); + } + pclose(f); + } + + set_master(devh, itfnum, mac); + + usb_close(devh); +} + +int main(int argc, char *argv[]) { + + usb_init(); + if ( usb_find_busses() < 0 ) fatal("usb_find_busses"); + if ( usb_find_devices() < 0 ) fatal("usb_find_devices"); + struct usb_bus *busses = usb_get_busses(); + if ( ! busses ) fatal("usb_get_busses"); + + int found = 0; + + struct usb_bus *bus; + for ( bus=busses; bus; bus=bus->next ) { + struct usb_device *dev; + for ( dev=bus->devices; dev; dev=dev->next) { + struct usb_config_descriptor *cfg; + for ( cfg = dev->config; + cfg < dev->config + dev->descriptor.bNumConfigurations; + ++cfg ) { + int itfnum; + for ( itfnum=0; itfnum<cfg->bNumInterfaces; ++itfnum ) { + struct usb_interface *itf = &cfg->interface[itfnum]; + struct usb_interface_descriptor *alt; + for ( alt = itf->altsetting; + alt < itf->altsetting + itf->num_altsetting; + ++alt ) { + if ( dev->descriptor.idVendor == VENDOR && + dev->descriptor.idProduct == PRODUCT && + alt->bInterfaceClass == 3 ) { + process_device(argc, argv, dev, cfg, itfnum); + ++found; + } + } + } + } + } + } + + if ( ! found ) printf("No controller found on USB busses.\n"); + return 0; + +} + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bla...@us...> - 2009-08-12 05:29:00
|
Revision: 21636 http://personalrobots.svn.sourceforge.net/personalrobots/?rev=21636&view=rev Author: blaisegassend Date: 2009-08-12 05:28:51 +0000 (Wed, 12 Aug 2009) Log Message: ----------- Finished updating driver based on useability test. Modified Paths: -------------- pkg/trunk/stacks/joystick_drivers/ps3joy/ps3joy.py pkg/trunk/stacks/joystick_drivers/ps3joy/sixpair.c Modified: pkg/trunk/stacks/joystick_drivers/ps3joy/ps3joy.py =================================================================== --- pkg/trunk/stacks/joystick_drivers/ps3joy/ps3joy.py 2009-08-12 05:12:47 UTC (rev 21635) +++ pkg/trunk/stacks/joystick_drivers/ps3joy/ps3joy.py 2009-08-12 05:28:51 UTC (rev 21636) @@ -24,8 +24,8 @@ try: self.file = os.open(name, os.O_WRONLY) break - except: - print "Error opening uinput. Are you root?" + except Exception, e: + print >> sys.stderr, "Error opening uinput: %s"%str(e) raise if self.file == None: raise IOError @@ -70,7 +70,7 @@ th = int(t) tl = int((t - th) * 1000000) if len(value) != len(self.value): - print "Unexpected length for value in update" + print >> sys.stderr, "Unexpected length for value in update. This is a bug." for i in range(0, len(value)): if value[i] != self.value[i]: os.write(self.file, struct.pack(input_event, th, tl, self.type[i], self.code[i], value[i])) @@ -98,12 +98,12 @@ joy_coding = "!1B2x3B1x4B4x12B15x4H" rawdata = sock.recv(128) if len(rawdata) != 50: - print "Unexpected packet length:", len(data) + print >> sys.stderr, "Unexpected packet length (%i). Is this a PS3 Dual Axis or Six Axis?"%len(data) return False data = list(struct.unpack(joy_coding, rawdata)) prefix = data.pop(0) if prefix != 161: - print "Unexpected prefix:", prefix + print >> sys.stderr, "Unexpected prefix (%i). Is this a PS3 Dual Axis or Six Axis?"%prefix return False out = [] for j in range(0,2): @@ -117,7 +117,6 @@ out.append(data.pop(0)) for j in range(19,23): out.append(data.pop(0) - 0x200) - #print out self.joy.update(out) return True @@ -153,7 +152,7 @@ try: sock.bind(("", port)) except: - print "Error binding to bluetooth socket. Are you root?" + print >> sys.stderr, "Error binding to bluetooth socket." exit (-1) sock.listen(1) return sock @@ -163,13 +162,13 @@ ctrl_sock = self.prepare_socket(L2CAP_PSM_HIDP_CTRL) while True: - print "Waiting for connection" + print "Waiting for connection. Disconnect your PS3 joystick from USB and press the pairing button." try: (intr, (idev, iport)) = intr_sock.accept(); try: (rd, wr, err) = select.select([ctrl_sock], [], [], 1) if len(rd) == 0: - print "Got interrupt connection without control connection. Giving up on it." + print >> sys.stderr, "Got interrupt connection without control connection. Giving up on it." intr.close() continue (ctrl, (cdev, cport)) = ctrl_sock.accept(); @@ -178,10 +177,10 @@ try: self.decoder.run(intr, ctrl) except: - print "Connection broken or error." + print >> sys.stderr, "Connection broken or error." traceback.print_exc() else: - print "Simultaneous connection from two different devices. Ignoring both." + print >> sys.stderr, "Simultaneous connection from two different devices. Ignoring both." finally: ctrl.close() finally: @@ -190,13 +189,15 @@ print "CTRL+C detected. Exiting." exit(0) except Exception, e: - print "Caught exception: %s"%str(e) + print >> sys.stderr, "Caught exception: %s"%str(e) if __name__ == "__main__": try: + if os.getuid() != 0: + print >> sys.stderr, "ps3joy.py must be run as root." os.system("/etc/init.d/bluetooth stop > /dev/null 2>&1") while os.system("hciconfig hci0 > /dev/null 2>&1") != 0: - print "No bluetooth device found. Will retry in 5 seconds." + print >> sys.stderr, "No bluetooth device found. Will retry in 5 seconds." time.sleep(5) os.system("hciconfig hci0 up > /dev/null 2>&1") os.system("hciconfig hci0 pscan > /dev/null 2>&1") @@ -205,4 +206,4 @@ cm = connection_manager(decoder()) cm.listen() except KeyboardInterrupt: - pass + print "CTRL+C detected. Exiting." Modified: pkg/trunk/stacks/joystick_drivers/ps3joy/sixpair.c =================================================================== --- pkg/trunk/stacks/joystick_drivers/ps3joy/sixpair.c 2009-08-12 05:12:47 UTC (rev 21635) +++ pkg/trunk/stacks/joystick_drivers/ps3joy/sixpair.c 2009-08-12 05:28:51 UTC (rev 21636) @@ -115,7 +115,7 @@ } } - if ( ! found ) printf("No controller found on USB busses.\n"); + if ( ! found ) printf("No controller found on USB busses. Please connect your joystick via USB.\n"); return 0; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bla...@us...> - 2009-09-04 19:56:51
|
Revision: 23857 http://personalrobots.svn.sourceforge.net/personalrobots/?rev=23857&view=rev Author: blaisegassend Date: 2009-09-04 19:56:44 +0000 (Fri, 04 Sep 2009) Log Message: ----------- Added bluez as sysdep and made error message clearer. Modified Paths: -------------- pkg/trunk/stacks/joystick_drivers/ps3joy/manifest.xml pkg/trunk/stacks/joystick_drivers/ps3joy/ps3joy.py Modified: pkg/trunk/stacks/joystick_drivers/ps3joy/manifest.xml =================================================================== --- pkg/trunk/stacks/joystick_drivers/ps3joy/manifest.xml 2009-09-04 19:54:50 UTC (rev 23856) +++ pkg/trunk/stacks/joystick_drivers/ps3joy/manifest.xml 2009-09-04 19:56:44 UTC (rev 23857) @@ -15,6 +15,7 @@ <url>http://www.ros.org/wiki/ps3joy</url> <rosdep name="libusb"/> <rosdep name="joystick"/> + <rosdep name="bluez"/> <rosdep name="python-bluez"/> </package> Modified: pkg/trunk/stacks/joystick_drivers/ps3joy/ps3joy.py =================================================================== --- pkg/trunk/stacks/joystick_drivers/ps3joy/ps3joy.py 2009-09-04 19:54:50 UTC (rev 23856) +++ pkg/trunk/stacks/joystick_drivers/ps3joy/ps3joy.py 2009-09-04 19:56:44 UTC (rev 23857) @@ -199,7 +199,7 @@ quit(1) os.system("/etc/init.d/bluetooth stop > /dev/null 2>&1") while os.system("hciconfig hci0 > /dev/null 2>&1") != 0: - print >> sys.stderr, "No bluetooth device found. Will retry in 5 seconds." + print >> sys.stderr, "No bluetooth dongle found. Will retry in 5 seconds." time.sleep(5) os.system("hciconfig hci0 up > /dev/null 2>&1") os.system("hciconfig hci0 pscan > /dev/null 2>&1") This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |