# Copyright (c) 2009, Joshua Wright # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * The name of the contributors may not be used to endorse or promote # products derived from this software without specific prior written # permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER # OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Special thanks to Scott Weston and the pymissle project # http://code.google.com/p/pymissile/ import usb class DeviceDescriptor(object) : def __init__(self, vendor_id, product_id, interface_id) : self.vendor_id = vendor_id self.product_id = product_id self.interface_id = interface_id def getDevice(self) : """ Return the device corresponding to the device descriptor if it is available on a USB bus. Otherwise, return None. Note that the returned device has yet to be claimed or opened. """ buses = usb.busses() for bus in buses : for device in bus.devices : if device.idVendor == self.vendor_id : if device.idProduct == self.product_id : return device return None class PlugUSBDevice(object) : PLUG_VENDOR_ID = 0x04d8 PLUG_PRODUCT_ID = 0x000e PLUG_INTERFACE_ID = 0 PLUG_BULK_EP_PACKETS = 0x81 PLUG_BULK_EP_CONTROL = 0x01 PLUG_BULK_IN_EP = 0x81 PLUG_BULK_OUT_EP = 1 PLUG_TIMEOUT = 200 # 1st byte offset is the channel number, 11-26 SET_CHAN = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] def __init__(self) : self.device_descriptor = DeviceDescriptor(PlugUSBDevice.PLUG_VENDOR_ID, PlugUSBDevice.PLUG_PRODUCT_ID, PlugUSBDevice.PLUG_INTERFACE_ID) self.device = self.device_descriptor.getDevice() self.handle = None def open(self) : self.device = self.device_descriptor.getDevice() self.handle = self.device.open() self.handle.claimInterface(self.device_descriptor.interface_id) def close(self) : self.handle.releaseInterface() def setChannel(self, channel) : # Set the channel number if (channel > 26 or channel < 11): raise Exception, "Invalid channel " + str(channel) PlugUSBDevice.SET_CHAN[1] = channel self.handle.interruptWrite(PlugUSBDevice.PLUG_BULK_EP_CONTROL, PlugUSBDevice.SET_CHAN, len(PlugUSBDevice.SET_CHAN)) def getDataPacket(self, bytesToGet) : #print "DEBUG: Sending bulkRead" try: return self.handle.interruptRead( PlugUSBDevice.PLUG_BULK_EP_PACKETS, bytesToGet) except usb.USBError, e: if e.args != ('No error',): # http://bugs.debian.org/476796 raise e plug = PlugUSBDevice() plug.open() plug.setChannel(26) for i in range(1,10): packet = plug.getDataPacket(64) if packet: for j in range(0,len(packet)-1): print hex(packet[j]), print plug.close()