# HG changeset patch # User Daniel O'Connor # Date 1611034589 -37800 # Node ID 29bcef5592839c0ca603b53d3bb7dea31174262d # Parent 4ca9fdf0795ac6679bbd1db0b90abda6dc6741f8 Add initiateClear and a few others and use it to clear buffers on setup. diff -r 4ca9fdf0795a -r 29bcef559283 usb488.py --- a/usb488.py Fri Jan 08 14:10:24 2021 +1030 +++ b/usb488.py Tue Jan 19 16:06:29 2021 +1030 @@ -35,6 +35,7 @@ # http://sdpha2.ucsd.edu/Lab_Equip_Manuals/usbtmc_usb488_subclass_1_00.pdf # +import time import usb from functools import reduce @@ -89,6 +90,32 @@ REQUEST_DEV_DEP_MSG_IN = 2 DEV_DEP_MSG_IN = 2 +# USB TMC control requests +INITIATE_ABORT_BULK_OUT = 1 +CHECK_ABORT_BULK_OUT_STATUS = 2 +INITIATE_ABORT_BULK_IN = 3 +CHECK_ABORT_BULK_IN_STATUS = 4 +INITIATE_CLEAR = 5 +CHECK_CLEAR_STATUS = 6 +GET_CAPABILITIES = 7 +INDICATOR_PULSE = 64 + +# Interface capability bits +IF_CAP_LISTEN_ONLY = 0x01 +IF_CAP_TALK_ONLY = 0x02 +IF_CAP_HAS_INDICATOR = 0x04 + +# Device capability bits +DEV_CAP_TERM_CHAR = 0x01 + +# USBTMC status definitions +STATUS_SUCCESS = 0x01 +STATUS_PENDING = 0x02 +STATUS_FAILED = 0x80 +STATUS_TRANSFER_NOT_IN_PROGRESS = 0x81 +STATUS_SPLIT_NOT_IN_PROGRESS = 0x82 +STATUS_SPLIT_IN_PROGRESS = 0x83 + class USB488Device(object): def __init__(self, vendor = None, product = None, serial = None, path = None): """Search for a USB488 class device, if specified vendor, @@ -160,7 +187,7 @@ # Determine the endpoints for each operation type self.intrep = self.bulkinep = self.bulkoutep = None - + for ep in altif.endpoints: if ep.type == usb.ENDPOINT_TYPE_INTERRUPT and \ ep.address & usb.ENDPOINT_IN == usb.ENDPOINT_IN: @@ -177,15 +204,16 @@ if self.intrep == None: print("Can't find interrupt endpoint") - # Data from the scope (mandatory) + # Data from the device (mandatory) if self.bulkinep == None: raise BaseException("Can't find bulk-in endpoint") - # Data to the scope (mandatory) + # Data to the device (mandatory) if self.bulkoutep == None: raise BaseException("Can't find bulk-out endpoint") self.tag = 1 + self.initiateClear() def __str__(self): rtn = "Mfg: %s Prod: %s" % (self.vendname, self.prodname) @@ -228,7 +256,7 @@ chunk = pkt[0:self.maxPacket] pkt = pkt[self.maxPacket:] - #print "Sending %s bytes of data: %s" % (len(chunk), chunk) + #print("Sending %s bytes of data: %s" % (len(chunk), chunk)) wrote = self.handle.bulkWrite(self.bulkoutep, chunk) if wrote != len(chunk): raise BaseException("Short write, got %d, expected %d" % (wrote, len(chunk))) @@ -261,14 +289,14 @@ self.incrtag() # Send it - #print "Sending " + str(pkt) + #print("Sending " + str(pkt)) wrote = self.handle.bulkWrite(self.bulkoutep, pkt, _timeout) if wrote != len(pkt): print("Short write, got %d, expected %d" % (wrote, len(pkt))) - #print "Reading.." + #print("Reading..") read = self.handle.bulkRead(self.bulkinep, datalen, _timeout) - #print "Read %s bytes: %s" % (len(read), str(read)) + #print("Read %s bytes: %s" % (len(read), str(read))) if read[0] != DEV_DEP_MSG_IN: raise BaseException("Unexpected Msg ID, got %s expected %d" % (read[0], DEV_DEP_MSG_IN)) @@ -278,10 +306,10 @@ raise BaseException("Unexpected tag inverse, got %d expected %d" % (read[1], ~exptag & 0xff)) actualdata = read[4] | read[5] << 8 | read[6] << 16 | read[7] << 24 - #print "Computed datalen is %d" % (actualdata) + #print("Computed datalen is %d" % (actualdata)) data += read[12:12 + actualdata] if read[8] & 0x01: - #print "Breaking out due to EOM" + #print("Breaking out due to EOM") break # Stringify result for easier consumption @@ -307,4 +335,24 @@ return False return True - + + def getCapabilities(self): + '''Returns interface and device capability bytes (see IF_CAP_* and DEV_CAP_*)''' + res = self.handle.controlMsg(usb.ENDPOINT_IN | usb.TYPE_CLASS | usb.RECIP_INTERFACE, GET_CAPABILITIES, 0x18) + return res[4], res[5] + + def indicatorPulse(self): + '''Send an indicator pulse request''' + res = self.handle.controlMsg(usb.ENDPOINT_IN | usb.TYPE_CLASS | usb.RECIP_INTERFACE, INDICATOR_PULSE, 0x01) + + def initiateClear(self): + '''Send request to clear all transfers and wait until the device reports it is done and clear stalls''' + res = self.handle.controlMsg(usb.ENDPOINT_IN | usb.TYPE_CLASS | usb.RECIP_INTERFACE, INITIATE_CLEAR, 0x01) + if res[0] == STATUS_SUCCESS: + while True: + res = self.handle.controlMsg(usb.ENDPOINT_IN | usb.TYPE_CLASS | usb.RECIP_INTERFACE, CHECK_CLEAR_STATUS, 0x02) + if res[0] != STATUS_PENDING: + break + time.sleep(0.1) + self.handle.clearHalt(usb.ENDPOINT_IN | self.bulkinep) + self.handle.clearHalt(usb.ENDPOINT_OUT | self.bulkoutep)