def filter(self, transaction): valueIndex = None if not transaction.control_match( "SEND_H264_TRANSCODER_BITFIELD", wLength=8, write=True): return [transaction] #Filter does not apply value = debyteify(transaction.payload[0:4]) mask = debyteify(transaction.payload[4:8]) maskMinusLowest = mask & (mask - 1) #bit trick, clears lowest bit #of mask. lowBit = mask - maskMinusLowest if lowBit == 0: #No bits set. This is weird enough I'd like to throw a runtime error. raise RuntimeError( "NOP SPARAM that processes zero bits found, mind blown.") lsb = lowBit.bit_length() - 1 rightMask = mask >> lsb bitCount = rightMask.bit_length() originalValue = value >> lsb #well now we have lsb and bitcount, now for sanity checks. regeneratedMask = ((1 << bitCount) - 1) << lsb if (regeneratedMask != mask) or ((value & mask) != value): #This is an atypical SETUP_H264_TRANSCODER_BITFIELD write, this is #weird enough I want to raise an error raise RuntimeError( "Non-SPARAM write to SETUP_H264_TRANSCODER_FIELD found, mind blown." ) #Also make sure we don't ever run over a 16 bit boundary... wordIndex = lsb // 16 wordIndexTop = (lsb + bitCount - 1) // 16 if wordIndex != wordIndexTop: raise RuntimeError( "SPARAM write runs over 16 bit boundary, mind blown.") port = transaction.wIndex if (wordIndex == 0): port += 2 else: lsb -= 16 #Gotta shift #Lookup to see if known lookupValues = [port, lsb, bitCount] name = transaction.device.reverseTranscoderBitfieldLookup(lookupValues) if name == None: returnString = "\tsparam( 0x%4.4x, %d, %d, %d );" % ( port, lsb, bitCount, originalValue) else: returnString = "\tsparam( %s, %d );" % (name[0], originalValue) capInfo = self.capInfo(transaction) if capInfo != "": returnString += " //%s" % self.capInfo(transaction) transaction.filterDecoration = returnString return [transaction]
def filter(self, transaction): valueIndex = None if transaction.control_match("MAIL_SEND_ENABLE_REGISTER_STATE", 2): valueIndex = 1 mask = ~0xd080 #d080 gets autoset on HDNew devices for MAIL_SEND_ENABLE_REGISTER_STATE elif transaction.control_match("ENABLE_REGISTER", 2): valueIndex = 0 mask = ~0xd080 #d080 gets autoset on HDNew devices for MAIL_SEND_ENABLE_REGISTER_STATE else: return [transaction] #No filter. newValue = debyteify(transaction.payload) value = self.values[valueIndex] transaction.noteContext["previous"] = value transaction.noteContext["current"] = newValue changed = value != newValue transaction.noteContext["changed"] = changed if transaction.control_direction(read=True): if (value != None) and ((newValue & mask) != (value & mask)): if valueIndex == 1: raise RuntimeError( "MAIL_SEND_ENABLE_REGISTER_STATE changed on its own, mind blown." ) else: raise RuntimeError( "ENABLE_REGISTER changed on its own, mind blown.") #if valueIndex==1: #Replace actual read text # transaction.filterDecoration="\treadEnableState(); //EXPECTED 0x%4.4x %s" % (newValue, self.capInfo(transaction)) #else: #if not changed and (valueIndex==1): # transaction.filterDecoration="\twriteEnableState(); //EXPECTED WRITE 0x%4.4x %s" % (newValue, self.capInfo(transaction)) self.values[valueIndex] = newValue return [transaction]
def typeParameterize( data, typeTuple, bufferPrefix="" ): if typeTuple[1]==None: return bufferPrefix+"{"+hexdump(data)+"}" else: byteLength=typeTuple[0] format="0x%%%d.%dx" % (byteLength*2, byteLength*2) #each hex digit is one nybble. return format % debyteify( data )
def filter(self, transaction): valueIndex = None if not transaction.control_match( "SEND_H264_TRANSCODER_WORD", wLength=2, write=True): return [transaction] #Filter does not apply value = debyteify(transaction.payload) returnString = "\tslsi( 0x%4.4x, %4.4x );" % (transaction.wIndex, value) capInfo = self.capInfo(transaction) if capInfo != "": returnString += " //%s" % self.capInfo(transaction) transaction.filterDecoration = returnString return [transaction]
def filter_generator(self): #Match first command transaction = yield None firstTransaction = transaction if not transaction.control_match("SCMD_REGISTER", 6, write=True): return command = transaction.payload[2] mode = transaction.payload[3] send = debyteify(transaction.payload[4:6]) fCommand = "0x%2.2x" % command #formatted command fSend = "0x%4.4x" % send #formatted send if command == 1: fCommand = "SCMD_IDLE" elif command == 4: fCommand = "SCMD_RESET" elif command == 4: fCommand = "SCMD_INIT" elif command == 5: fCommand = "SCMD_STATE_CHANGE" if send == 1: fSend = "SCMD_STATE_STOP" elif send == 2: fSend = "SCMD_STATE_START" elif send == 4: fSend = "SCMD_STATE_NULL" printString = "scmd(%s, 0x%2.2x, %s);" % (fCommand, mode, fSend) capInfo = self.capInfo(firstTransaction) if capInfo != "": printString += " //%s" % capInfo newTransaction = USBTransaction.makeCustom("scmd") newTransaction.identityContext = { "command": command, "mode": mode, "send": send } newTransaction.filterDecoration = "\t%s" % printString yield [newTransaction]
def __init__(self, buffer, format=USBPcap, capCounter=None, capBase=0): self.format = format self.rawData = buffer self.capCounter = capCounter if format == USBPcap: self.initialFlag = True #Set when suitable #format for first capture buf of a complete USBTransaction. #Most buffers types are solo in this format, #so defaults to True self.endFlag = True #Set when suitable #format for last buffer capture buf of a complete USBTransaction #Most buffers types are solo in this format, #so defaults to True self.controlDataFlag = False urbLength = debyteifyLittleEndian(buffer[0:2]) if (urbLength < 27) or (urbLength > len(buffer)): raise CaptureFormatError("Data is in wrong format") auxLength = 0 self.irpID = debyteifyLittleEndian(buffer[2:10]) self.usbdStatus = debyteifyLittleEndian(buffer[10:14]) self.busID = buffer[18] self.deviceID = debyteifyLittleEndian(buffer[19:21]) self.endPoint = buffer[21] self.direction = (buffer[21] >> 7) != 0 self.type = buffer[22] packetDataLength = debyteifyLittleEndian(buffer[23:27]) if (packetDataLength + urbLength) != len(buffer): if (packetDataLength + urbLength <= 65535): #Capture gets truncated apparently raise CaptureFormatError("Data is in wrong format") if self.type == USBTransaction.CONTROL: self.initialFlag = False #Control transactions generate 3 capture events, gotta figure out which self.endFlag = False #Control transactions generate 3 capture, gotta figure out which self.controlTransferStage = buffer[ 27] #This is unique to USBPcap if self.controlTransferStage == CapturePoint.SetupStage: self.initialFlag = True #Only SetupStage is an initial even for a control transaction auxLength = 8 #Size of setup stuff. controlData = buffer[urbLength:urbLength + 8] self.setupControl(controlData) self.controlDataFlag = True if self.controlTransferStage == CapturePoint.StatusStage: self.endFlag = True self.mainWriteFlag = (self.direction == USBTransaction.Outbound) and \ (self.controlTransferStage==CapturePoint.DataStage) self.mainReadFlag = (self.direction == USBTransaction.Inbound) and \ (self.controlTransferStage==CapturePoint.DataStage) else: #Single state command, if we read or write, we do it here. self.mainReadFlag = self.direction == USBTransaction.Inbound self.mainWriteFlag = self.direction == USBTransaction.Outbound trueUrbLength = urbLength + auxLength self.payloadLength = packetDataLength - auxLength self.urb = buffer[:trueUrbLength] self.payload = buffer[trueUrbLength:trueUrbLength + self.payloadLength] elif format == Linux: urbLength = 64 if urbLength > len(buffer): raise CaptureFormatError("Data is in wrong format") urb = buffer[:urbLength] self.urb = urb self.irpID = debyteifyLittleEndian(urb[0:8]) urbType = chr(urb[8]) #This is unique to Linux format. #'S' for SUBMIT, 'C' for COMPLETE if (urbType != 'S') and (urbType != 'C'): raise CaptureFormatError("Data is in wrong format") self.urbType = urbType self.initialFlag = self.urbType == 'S' self.endFlag = self.urbType == 'C' self.type = urb[9] self.endPoint = urb[10] self.direction = (urb[10] >> 7) != 0 self.deviceID = urb[11] self.busID = debyteifyLittleEndian(urb[12:14]) self.usbdStatus = debyteifyLittleEndian(urb[28:32]) extraPacketLength = debyteifyLittleEndian(urb[36:40]) self.controlDataFlag = False if self.type == USBTransaction.CONTROL: if self.urbType == 'S': controlData = urb[40:48] self.setupControl(controlData) self.controlDataFlag = True self.mainWriteFlag = (self.direction == USBTransaction.Outbound) and \ (self.urbType == 'S') self.mainReadFlag = (self.direction == USBTransaction.Inbound) and \ (self.urbType == 'C') self.payloadLength = debyteifyLittleEndian(urb[36:40]) self.payload = buffer[urbLength:urbLength + self.payloadLength] if (urbLength + self.payloadLength) != len(buffer): raise CaptureFormatError("Data is in wrong format") elif format == Vizsla: urbLength = 8 #Simulated urb created by DumpVizslaIterator #URB definition #entry 0 is deviceID #entry 1 is endPoint ....bit 7 is set to direction. #entry 2 is type..IE USBTransaaction.CONTROL, etc. #entry 3 is 0 if SETUP, 1 if anything else. #entry 4-7 is 32 bit line number. self.capCounter = debyteify(buffer[4:8]) + capBase if urbLength > len(buffer): raise CaptureFormatError("Data is in wrong format") urb = buffer[:urbLength] self.urb = urb self.busID = None #Unknown in Vizsla captures. self.deviceID = urb[0] self.endPoint = urb[1] self.type = urb[2] self.direction = (self.endPoint >> 7) != 0 self.urbStage = urb[ 3] #0 if SETUP, 1 if IN or OUT, 2 if end of SETUP. self.controlDataFlag = False if self.type == USBTransaction.CONTROL: if self.urbStage == 0: self.controlDataFlag = True controlData = buffer[urbLength:] self.setupControl(controlData) if self.urbStage != 1: self.payloadLength = 0 self.payload = [] else: self.payload = buffer[urbLength:] self.payloadLength = len(self.payload) self.initialFlag = True self.endFlag = True self.mainWriteFlag = (self.direction == USBTransaction.Outbound) self.mainReadFlag = (self.direction == USBTransaction.Inbound) if self.type == USBTransaction.CONTROL: if self.urbStage == 0: self.endFlag = False #Not at main read or write yet. self.mainWriteFlag = False self.mainReadFlag = False elif self.urbStage == 1: self.initialFlag = False self.endFlag = False else: self.initialFlag = False self.mainWriteFlag = False self.mainReadFlag = False
def filter_generator(self): oldTransaction = None firstTransaction = None stateChangeComplete = False while (True): transaction = yield None if not transaction.control_match( "SCMD_STATE_READBACK_REGISTER", 2, read=True): return if firstTransaction == None: firstTransaction = transaction olderTransaction = oldTransaction oldTransaction = transaction transaction = yield None if not transaction.control_match( "SCMD_STATE_CHANGE_COMPLETE", 2, read=True): if transaction.control_match("SCMD_STATE_READBACK_REGISTER", 2, read=True): if not stateChangeComplete: raise RuntimeError( "Unexpected behaviour of GetStreamStatusChange, examine behaviour." ) break else: return else: if stateChangeComplete: raise RuntimeError( "Unexpected behaviour of GetStreamStatusChange, examine behaviour." ) stateChangeComplete = (debyteify(transaction.payload) & 0x4 > 0) transaction = yield None if not transaction.control_match( 0xbc, 0x0900, 0x01b0, 2, read=True): return if olderTransaction == None: return #Fragment, just got two reads from SCMD_STATE_READBACK_REGISTER in a row, didn't #go through the loop once changeOldest = debyteify(transaction.payload) changeOld = debyteify(transaction.payload) change = debyteify(transaction.payload) if (change != changeOld) or (changeOld != changeOldest): raise RuntimeError( "Unexpected transient change, examine behaviour.") transaction = yield None if not transaction.control_match( "SCMD_STATE_CHANGE_COMPLETE", 2, write=True): return if debyteify(transaction.payload) != 4: raise RuntimeError("Unexpected write value !=4, mind blown") transaction = yield None if not transaction.control_match(0xbc, 0x0900, 0x01b0, 2, write=True): return if debyteify(transaction.payload) != 0: raise RuntimeError("Unexpected write value != 0, mind blown.") printString = "\tcompleteStateChange(); //EXPECTED 0x%4.4x %s" % ( change, self.capInfo(firstTransaction)) newTransaction = USBTransaction.makeCustom("GetStreamStatusChange") newTransaction.identityContext = {"change": change} newTransaction.filterDecoration = printString yield [newTransaction] #Substitute transactions.
def filter_generator(self): #Match first command transaction = yield None firstTransaction = transaction if not transaction.control_match("SCMD_REGISTER", 4, write=True): return command = transaction.payload[0] mode = transaction.payload[1] send = debyteify(transaction.payload[2:4]) fCommand = "0x%2.2x" % command #formatted command fSend = "0x%4.4x" % send #formatted send if command == 1: fCommand = "SCMD_IDLE" elif command == 4: fCommand = "SCMD_INIT" elif command == 5: fCommand = "SCMD_STATE_CHANGE" if send == 1: fSend = "SCMD_STATE_STOP" elif send == 2: fSend = "SCMD_STATE_START" elif send == 4: fSend = "SCMD_STATE_NULL" #There are other commands we get...we just haven't identified them if (command == 1) or (command == 4) or (command == 5): #These on the other hand... if (mode & 0xa0) and ((mode & 0xa0) != 0xa0): raise RuntimeException( "Here's a chance to figure what mode in scmd bits mean") if not (mode & 0xa0): #One of these two bits I think disables interrupts. transaction = yield None if not (transaction.type == USBTransaction.INTERRUPT): raise RuntimeError("Unexpectedly no interrupt for scmd.") return modeChanged = False while not modeChanged: transaction = yield None #scmd state readback register if not transaction.control_match( "HDNEW_SCMD_READBACK_REGISTER", 2, read=True): raise RuntimeError("Unexpected exit from scmd.") return if transaction.payload[0] == command: modeChanged = True #And now we are done printString = "scmd(%s, 0x%2.2x, %s);" % (fCommand, mode, fSend) capInfo = self.capInfo(firstTransaction) if capInfo != "": printString += " //%s" % capInfo newTransaction = USBTransaction.makeCustom("scmd") newTransaction.identityContext = { "command": command, "mode": mode, "send": send } newTransaction.filterDecoration = "\t%s" % printString yield [newTransaction]