You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

152 lines
5.5 KiB

import array
import binascii
import usb.core
import usb.util
import time
class USBMIDIConfiguration:
def __init__(self, cfg, ifno, ifalt):
self.cfg = cfg
self.ifno = ifno
self.ifalt = ifalt
def __str__(self):
return "cfg=%d ifno=%d ifalt=%d" % (self.cfg, self.ifno, self.ifalt)
def __repr__(self):
return "USBMIDIConfiguration(%d,%d,%d)" % (self.cfg, self.ifno, self.ifalt)
class USBMIDIDeviceDescriptor:
def __init__(self, vendorID, productID, interfaces = None):
self.vendorID = vendorID
self.productID = productID
if interfaces is None:
self.interfaces = []
else:
self.interfaces = interfaces
def add_interface(self, config, ifno, ifalt):
self.interfaces.append(USBMIDIConfiguration(config, ifno, ifalt))
def has_interfaces(self):
return len(self.interfaces)
def __str__(self):
return "vid=%04x pid=%04x" % (self.vendorID, self.productID)
def __repr__(self):
return "USBMIDIDeviceDescriptor(0x%04x, 0x%04x, %s)" % (self.vendorID, self.productID, self.interfaces)
class USBMIDI:
cin_sizes = [None, None, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1]
def __init__(self, mididev, midicfg, debug = False):
dev = usb.core.find(idVendor = mididev.vendorID, idProduct = mididev.productID)
self.dev = dev
intf = None
for cfgo in dev:
if cfgo.bConfigurationValue == midicfg.cfg:
cfgo.set()
intf = cfgo[(midicfg.ifno, midicfg.ifalt)]
if not intf:
raise ValueError, "Configuration %d not found" % midicfg.cfg
print intf.bNumEndpoints
self.epIn = None
self.epOut = None
for ep in intf:
if debug:
print "endpoint %x" % ep.bEndpointAddress
if ep.bEndpointAddress > 0x80:
if self.epIn is None:
self.epIn = ep
else:
if self.epOut is None:
self.epOut = ep
def read(self):
try:
data = self.epIn.read(self.epIn.wMaxPacketSize)
if data is None:
return None
return array.array('B', data)
except usb.core.USBError, e:
return None
def encode(self, port, msg):
a = array.array('B')
a.append(16 * port + (msg[0] >> 4))
a.fromlist(msg)
return a
def write(self, data):
self.epOut.write(data)
def parse(self, data):
i = 0
msgs = []
while i < len(data):
if data[i] == 0:
break
cin, cable_id = data[i] & 15, data[i] >> 4
msgs.append(data[i + 1 : i + 1 + KeyRig25.cin_sizes[cin]])
i += 4
return msgs
@staticmethod
def findall(vendorID = None, productID = None, debug = False):
dev_list = []
devices = usb.core.find(find_all = True)
for dev in devices:
if vendorID is not None and dev.idVendor != vendorID:
continue
if productID is not None and dev.idProduct != productID:
continue
thisdev = USBMIDIDeviceDescriptor(dev.idVendor, dev.idProduct)
if debug:
print "Device %04x:%04x, class %d" % (dev.idVendor, dev.idProduct, dev.bDeviceClass)
if dev.bDeviceClass == 0: # device defined at interface level
for cfg in dev:
if debug:
print "Configuration ", cfg.bConfigurationValue
for intf in cfg:
if debug:
print "Interface %d alternate-setting %d" % (intf.bInterfaceNumber, intf.bAlternateSetting)
print "Class %d subclass %d" % (intf.bInterfaceClass, intf.bInterfaceSubClass)
if intf.bInterfaceClass == 1 and intf.bInterfaceSubClass == 3:
if debug:
print "(%d,%d,%d): This is USB MIDI" % (cfg.bConfigurationValue, intf.bInterfaceNumber, intf.bAlternateSetting)
thisdev.add_interface(cfg.bConfigurationValue, intf.bInterfaceNumber, intf.bAlternateSetting)
if thisdev.has_interfaces():
dev_list.append(thisdev)
return dev_list
#print devices
class KnownUSBMIDI(USBMIDI):
def __init__(self, vendorID, productID):
devlist = USBMIDI.findall(vendorID, productID, debug = False)
if not devlist:
raise ValueError
USBMIDI.__init__(self, devlist[0], devlist[0].interfaces[0])
class KeyRig25(KnownUSBMIDI):
def __init__(self):
KnownUSBMIDI.__init__(self, vendorID = 0x763, productID = 0x115)
class XMidi2x2(KnownUSBMIDI):
def __init__(self):
KnownUSBMIDI.__init__(self, vendorID = 0x41e, productID = 0x3f08)
class LexiconOmega(KnownUSBMIDI):
def __init__(self):
KnownUSBMIDI.__init__(self, vendorID = 0x1210, productID = 2)
print USBMIDI.findall()
xmidi = XMidi2x2()
xmidi.write(xmidi.encode(1, [0x90, 36, 100]))
xmidi.write(xmidi.encode(1, [0x80, 36, 100]))
#krig = KeyRig25()
krig = LexiconOmega()
while True:
data = krig.read()
if data is not None:
decoded = krig.parse(data)
reencoded = array.array('B')
for msg in decoded:
reencoded.extend(xmidi.encode(1, list(msg)))
xmidi.write(reencoded)
print decoded