Example #1
0
class SetupPacket:
    """Represents the SETUP stage of a control transfer.
       This is responsible for decoding the bitfields and
       structure of the packet, but not for defining the meaning
       of a particular request.
       """
    _recipNames = Struct.EnumDict({
        0x00: 'device',
        0x01: 'interface',
        0x02: 'endpoint',
        0x03: 'other',
    })
    _typeNames = Struct.EnumDict({
        0x00: 'standard',
        0x20: 'class',
        0x40: 'vendor',
        0x60: 'reserved',
    })

    def __init__(self, event):
        self.event = event

        (self.bitmap, self.request, self.wValue, self.wIndex,
         self.wLength) = struct.unpack("<BBHHH", event.data[:8])

        # Decode self.bitmap
        self.recip = self._recipNames[self.bitmap & 0x1F]
        self.type = self._typeNames[self.bitmap & 0x60]

        # Split up wValue/wIndex for convenience
        self.wValueHigh = self.wValue >> 8
        self.wValueLow = self.wValue & 0xFF
        self.wIndexHigh = self.wIndex >> 8
        self.wIndexLow = self.wIndex & 0xFF
Example #2
0
    def handleTCP(self, event, data, datalen):
        """Decode an IPPROTO_TCP packet header, and log the payload."""

        datalen -= 0x14
        tcpHeader = Struct.Group(None,
                                 Struct.UInt16BEHex("source"),
                                 Struct.UInt16BEHex("dest"),
                                 Struct.UInt32BE("seq"),
                                 Struct.UInt32BE("ack_seq"),
                                 Struct.UInt16BEHex("flags"),
                                 Struct.UInt16BE("window"),
                                 Struct.UInt16BEHex("checksum"),
                                 Struct.UInt16BEHex("urg_ptr"))
        data = tcpHeader.decode(data)

        event.pushDecoded("iPhone TCP [%s -> %s] len=0x%04x" % (
            self.portNumbers[tcpHeader.source],
            self.portNumbers[tcpHeader.dest],
            datalen,
            ))

        event.appendDecoded("\nTCP Header:\n%s" % str(tcpHeader))
        event.appendDecoded("\nTCP Payload:\n%s" % Types.hexDump(data))

        # Look for a protocol-specific handler
        for port in tcpHeader.source, tcpHeader.dest:
            fn = getattr(self, "port_%s" % self.portNumbers[port], None)
            if fn:
                fn(event, data, datalen)
Example #3
0
    def handleEvent(self, event):
        if not event.isDataTransaction():
            return

        header = Struct.Group(None,
            Struct.UInt8("eventCode"),
            Struct.UInt8("numParameters"),
            )
        params = header.decode(event.data)

        event.pushDecoded("BT Event: %s" % self.eventNames[header.eventCode])
Example #4
0
    def __init__(self, cdb):
        self.header = Struct.Group(None, Struct.UInt8("opcode"))
        params = self.header.decode(cdb)
        self.name = self._opcodes[self.header.opcode]

        if self.name in self._structs:
            fmt, children = self._structs[self.name]
            self.params = Struct.Group(None, *children())
            self.params.decode(params)
            self.summary = fmt % self.params.__dict__
        else:
            self.params = None
            self.summary = ''
Example #5
0
class StatusDecoder:
    """Decodes USBS status blocks"""

    _statusCodes = Struct.EnumDict({
        0x00: 'ok',
        0x01: 'FAILED',
        0x02: 'PHASE ERROR',
    })

    def handleEvent(self, event):
        if not event.isDataTransaction():
            return
        if not event.data.startswith("USBS"):
            return

        header = Struct.Group(None, Struct.UInt32("sig"), Struct.UInt32("tag"),
                              Struct.UInt32("residue"), Struct.UInt8("status"))
        header.decode(event.data)

        if header.residue:
            residue = ', residue=%d' % header.residue
        else:
            residue = ''

        event.pushDecoded("Storage Status (%s%s)" %
                          (self._statusCodes[header.status], residue))
        event.appendDecoded("\n%s" % header)
Example #6
0
    def decode_HCICommand(self, setup):
        header = Struct.Group(None,
            Struct.UInt16("opcode"),
            Struct.UInt8("numParameters"),
            )
        params = header.decode(setup.event.data[8:])

        if header.opcode is None:
            ocf = ogf = None
        else:
            ocf = header.opcode & 0x03FF
            ogf = header.opcode >> 10

        ogfName = self.hciOpcodes.get(ogf, (ogf, {}))[0]
        ocfName = self.hciOpcodes.get(ogf, (ogf, {}))[1].get(ocf, ocf)

        setup.event.pushDecoded("BT Command: %s [%s]" % (ocfName, ogfName))
Example #7
0
    def handleEvent(self, event):
        if not event.isDataTransaction():
            return
        if not event.data.startswith("USBS"):
            return

        header = Struct.Group(None, Struct.UInt32("sig"), Struct.UInt32("tag"),
                              Struct.UInt32("residue"), Struct.UInt8("status"))
        header.decode(event.data)

        if header.residue:
            residue = ', residue=%d' % header.residue
        else:
            residue = ''

        event.pushDecoded("Storage Status (%s%s)" %
                          (self._statusCodes[header.status], residue))
        event.appendDecoded("\n%s" % header)
Example #8
0
class EventDecoder:
    """This decodes incoming Interrupt traffic from a bluetooth HCI
       device, representing HCI events.
       """
    eventNames = Struct.EnumDict({
        0x01: 'Inquiry Complete',
        0x02: 'Inquiry Result',
        0x03: 'Connection Complete',
        0x04: 'Connection Request',
        0x05: 'Disconnection Complete',
        0x06: 'Authentication Complete',
        0x07: 'Remote Name Request Complete',
        0x08: 'Encryption Change',
        0x09: 'Change Connection Link Key Complete',
        0x0A: 'Master Link Key Complete',
        0x0B: 'Read Remote Supported Features Complete',
        0x0C: 'Read Remote Version Information Complete',
        0x0D: 'QoS Setup Complete',
        0x0E: 'Command Complete',
        0x0F: 'Command Status',
        0x10: 'Hardware Error',
        0x11: 'Flush Occurred',
        0x12: 'Role Change',
        0x13: 'Number of Completed Packets',
        0x14: 'Mode Change',
        0x15: 'Return Link Keys',
        0x16: 'PIN Code Request',
        0x17: 'Link Key Request',
        0x18: 'Link Key Notification',
        0x19: 'Loopback Command',
        0x1A: 'Data Buffer Overflow',
        0x1B: 'Max Slots Change',
        0x1C: 'Read Clock Offset Complete',
        0x1D: 'Connection Packet Type Changed',
        0x1E: 'QoS Violation',
        0x20: 'Page Scan Repetition Mode Change',
        0x21: 'HCI Flow Specification Complete',
        0x22: 'Inquiry Result With RSSI',
        0x23: 'Read Remote Extended Features Complete',
        0x2C: 'Synchronous Connection Complete',
        0x2D: 'Synchronous Connection Changed',
    })

    def handleEvent(self, event):
        if not event.isDataTransaction():
            return

        header = Struct.Group(
            None,
            Struct.UInt8("eventCode"),
            Struct.UInt8("numParameters"),
        )
        params = header.decode(event.data)

        event.pushDecoded("BT Event: %s" % self.eventNames[header.eventCode])
Example #9
0
    def handleEvent(self, event):
        if not event.isDataTransaction():
            return
        setup = SetupPacket(event)

        # Look up the request name
        setup.requestName = getattr(self, "%sRequests" % setup.type,
                                    Struct.EnumDict())[setup.request]

        # Look up a corresponding decoder
        getattr(self, "decode_%s" % setup.requestName, self.decodeGeneric)(setup)
Example #10
0
    def handleEvent(self, event):
        if not event.isDataTransaction():
            return

        header = Struct.Group(None,
            Struct.UInt16("handle"),
            Struct.UInt16("dataTotalLength"),
            )
        params = header.decode(event.data)
        if header.handle is None:
            return

        boundaryFlag = (header.handle >> 12) & 3
        broadcastFlag = (header.handle >> 14) & 3
        handle = header.handle & 0x0FFF

        event.pushDecoded("BT ACL: handle=0x%04x len=0x%04x (%s%s)" %
                          (handle, header.dataTotalLength,
                           self.packetBoundaryNames[boundaryFlag],
                           self.broadcastFlagNames[broadcastFlag]))
Example #11
0
    def handleGenericPacket(self, event):
        """Decode the usbmuxd header."""

        muxHeader = Struct.Group(None,
                                 Struct.UInt32BE("protocol"),
                                 Struct.UInt32BE("length"))

        data = muxHeader.decode(event.data)
        description = "iPhone usbmuxd: "

        if muxHeader.length is None:
            description += "ERROR"

        else:
            self.remainingLength = muxHeader.length - event.datalen
            description += "proto=%s len=0x%04x" % (self.ipProto[muxHeader.protocol],
                                              muxHeader.length)
            if self.remainingLength:
                description += " (0x%04x remaining)" % self.remainingLength

        event.pushDecoded(description)

        if self.ipProto[muxHeader.protocol] == 'TCP':
            self.handleTCP(event, data, muxHeader.length - 0x08)
Example #12
0
    def handleEvent(self, event):
        if not event.isDataTransaction():
            return
        if not event.data.startswith("USBC"):
            return

        header = Struct.Group(None, Struct.UInt32("sig"), Struct.UInt32("tag"),
                              Struct.UInt32("datalen"), Struct.UInt8("flag"),
                              Struct.UInt8("lun"), Struct.UInt8("cdblen"))
        cdb = header.decode(event.data)
        command = SCSICommand(cdb)

        event.pushDecoded("Storage Command: %s" % command)
        event.appendDecoded("\n%s" % command.params)
Example #13
0
class USBMuxDecoder:
    """Decodes incoming or outgoing usbmuxd bulk plackets."""

    ipProto = Struct.EnumDict({
        0: 'VERSION',
        1: 'ICMP',
        6: 'TCP',
        17: 'UDP',
        41: 'IPv6',
        })

    portNumbers = Struct.EnumDict({
        62078: 'lockdownd',
        })

    remainingLength = 0
    lockdownBuffer = ""

    def handleEvent(self, event):
        if not event.isDataTransaction():
            return

        if self.remainingLength == 0:
            # Beginning a new packet
            self.handleGenericPacket(event)

        elif self.remainingLength >= event.datalen:
            # Continuing a packet
            self.remainingLength -= event.datalen
            event.pushDecoded("[usbmuxd continuation, %d bytes left]" %
                              self.remainingLength)

        else:
            event.pushDecoded("[usbmuxd ERROR, only expected %d bytes]" %
                              self.remainingLength)
            self.remainingLength = 0

    def handleGenericPacket(self, event):
        """Decode the usbmuxd header."""

        muxHeader = Struct.Group(None,
                                 Struct.UInt32BE("protocol"),
                                 Struct.UInt32BE("length"))

        data = muxHeader.decode(event.data)
        description = "iPhone usbmuxd: "

        if muxHeader.length is None:
            description += "ERROR"

        else:
            self.remainingLength = muxHeader.length - event.datalen
            description += "proto=%s len=0x%04x" % (self.ipProto[muxHeader.protocol],
                                              muxHeader.length)
            if self.remainingLength:
                description += " (0x%04x remaining)" % self.remainingLength

        event.pushDecoded(description)

        if self.ipProto[muxHeader.protocol] == 'TCP':
            self.handleTCP(event, data, muxHeader.length - 0x08)

    def handleTCP(self, event, data, datalen):
        """Decode an IPPROTO_TCP packet header, and log the payload."""

        datalen -= 0x14
        tcpHeader = Struct.Group(None,
                                 Struct.UInt16BEHex("source"),
                                 Struct.UInt16BEHex("dest"),
                                 Struct.UInt32BE("seq"),
                                 Struct.UInt32BE("ack_seq"),
                                 Struct.UInt16BEHex("flags"),
                                 Struct.UInt16BE("window"),
                                 Struct.UInt16BEHex("checksum"),
                                 Struct.UInt16BEHex("urg_ptr"))
        data = tcpHeader.decode(data)

        event.pushDecoded("iPhone TCP [%s -> %s] len=0x%04x" % (
            self.portNumbers[tcpHeader.source],
            self.portNumbers[tcpHeader.dest],
            datalen,
            ))

        event.appendDecoded("\nTCP Header:\n%s" % str(tcpHeader))
        event.appendDecoded("\nTCP Payload:\n%s" % Types.hexDump(data))

        # Look for a protocol-specific handler
        for port in tcpHeader.source, tcpHeader.dest:
            fn = getattr(self, "port_%s" % self.portNumbers[port], None)
            if fn:
                fn(event, data, datalen)

    def port_lockdownd(self, event, data, datalen):
        """Handle lockdownd packets. These form a stream, which may or
           may not line up with the underlying USB packets. Each
           lockdownd packet is an XML plist, prefixed with a 32-bit
           length.
           """
        summary = []
        self.lockdownBuffer += data

        if datalen == 0:
            # Leave the TCP decoder at the top of the stac
            return

        elif datalen != len(data):
            # Nothing we can reliably do without the whole log.
            self.lockdownBuffer = ""
            summary.append("ERROR, incomplete log!")

        elif (len(self.lockdownBuffer) >= 10 and
              self.lockdownBuffer[0] == '\0' and
              isascii(self.lockdownBuffer[1:])):
            # I haven't seen this documented, but sometimes lockdownd sends
            # ASCII error messages that are prefixed with one NUL byte.
            summary.append("Message, %r" % self.lockdownBuffer[1:])

        elif len(self.lockdownBuffer) >= 10 and self.lockdownBuffer[4:9] != "<?xml":
            # Something else that isn't a plist?
            self.lockdownBuffer = ""
            summary.append("UNRECOGNIZED (SSL encrypted?)")

        else:
            # Decode all the packets we can

            while len(self.lockdownBuffer) >= 4:
                length = struct.unpack(">I", self.lockdownBuffer[:4])[0]
                if len(self.lockdownBuffer) < length + 4:
                    break
                packet = self.lockdownBuffer[4:length + 4]
                self.lockdownBuffer = self.lockdownBuffer[length + 4:]

                event.appendDecoded("\nComplete lockdownd packet:\n%s" %
                                    Types.hexDump(packet))

                kvFull = []
                kvAbbrev = []

                for k, v in plistlib.readPlistFromString(packet).items():
                    kvFull.append("  %s = %s" % (k, v))

                    if isinstance(v, plistlib.Data):
                        v = "(data)"
                    elif isinstance(v, dict):
                        v = "(dict)"

                    kvAbbrev.append("%s=%s" % (k, v))

                event.appendDecoded("\nDecoded plist:\n%s" % "\n".join(kvFull))
                summary.append("{%s}" % " ".join(kvAbbrev))

        event.pushDecoded("lockdownd: %s" % (" ".join(summary) or "fragment"))
Example #14
0
class SCSICommand:
    """Decodes a SCSI command block"""

    _opcodes = Struct.EnumDict({
        0x00: 'TEST_UNIT_READY',
        0x01: 'REZERO_UNIT',
        0x03: 'REQUEST_SENSE',
        0x04: 'FORMAT_UNIT',
        0x05: 'READ_BLOCKLIMITS',
        0x07: 'REASSIGN_BLOCKS',
        0x07: 'INIT_ELEMENT_STATUS',
        0x08: 'READ(6)',
        0x0a: 'WRITE(6)',
        0x0a: 'PRINT',
        0x0b: 'SEEK(6)',
        0x0b: 'SLEW_AND_PRINT',
        0x0f: 'READ_REVERSE',
        0x10: 'WRITE_FILEMARKS',
        0x10: 'SYNC_BUFFER',
        0x11: 'SPACE',
        0x12: 'INQUIRY',
        0x14: 'RECOVER_BUFFERED',
        0x15: 'MODE_SELECT',
        0x16: 'RESERVE_UNIT',
        0x17: 'RELEASE_UNIT',
        0x18: 'COPY',
        0x19: 'ERASE',
        0x1a: 'MODE_SENSE',
        0x1b: 'START_UNIT',
        0x1b: 'SCAN',
        0x1b: 'STOP_PRINT',
        0x1c: 'RECV_DIAGNOSTIC',
        0x1d: 'SEND_DIAGNOSTIC',
        0x1e: 'MEDIUM_REMOVAL',
        0x23: 'READ_FORMAT_CAPACITIES',
        0x24: 'SET_WINDOW',
        0x25: 'GET_WINDOW',
        0x25: 'READ_CAPACITY',
        0x28: 'READ(10)',
        0x29: 'READ_GENERATION',
        0x2a: 'WRITE(10)',
        0x2b: 'SEEK(10)',
        0x2b: 'POSITION_TO_ELEMENT',
        0x2d: 'READ_UPDATED_BLOCK',
        0x2e: 'WRITE_VERIFY',
        0x2f: 'VERIFY',
        0x30: 'SEARCH_DATA_HIGH',
        0x31: 'SEARCH_DATA_EQUAL',
        0x32: 'SEARCH_DATA_LOW',
        0x33: 'SET_LIMITS',
        0x34: 'PREFETCH',
        0x34: 'READ_POSITION',
        0x35: 'SYNC_CACHE',
        0x36: 'LOCKUNLOCK_CACHE',
        0x37: 'READ_DEFECT_DATA',
        0x38: 'MEDIUM_SCAN',
        0x39: 'COMPARE',
        0x3a: 'COPY_VERIFY',
        0x3b: 'WRITE_BUFFER',
        0x3c: 'READ_BUFFER',
        0x3d: 'UPDATE_BLOCK',
        0x3e: 'READ_LONG',
        0x3f: 'WRITE_LONG',
        0x40: 'CHANGE_DEF',
        0x41: 'WRITE_SAME',
        0x42: 'READ_SUBCHANNEL',
        0x43: 'READ_TOC',
        0x44: 'READ_HEADER',
        0x45: 'PLAY_AUDIO(10)',
        0x46: 'GET_CONFIGURATION',
        0x47: 'PLAY_AUDIO_MSF',
        0x48: 'PLAY_AUDIO_TRACK',
        0x49: 'PLAY_AUDIO_RELATIVE',
        0x4a: 'GET_EVENT_STATUS_NOTIFICATION',
        0x4b: 'PAUSE',
        0x4c: 'LOG_SELECT',
        0x4d: 'LOG_SENSE',
        0x4e: 'STOP_PLAY',
        0x51: 'READ_DISC_INFO',
        0x52: 'READ_TRACK_INFO',
        0x53: 'RESERVE_TRACK',
        0x54: 'SEND_OPC_INFORMATION',
        0x55: 'MODE_SELECT(10)',
        0x56: 'RESERVE_UNIT(10)',
        0x57: 'RELEASE_UNIT(10)',
        0x5a: 'MODE_SENSE(10)',
        0x5b: 'CLOSE_SESSION',
        0x5c: 'READ_BUFFER_CAPACITY',
        0x5d: 'SEND_CUE_SHEET',
        0x5e: 'PERSISTENT_RESERVE_IN',
        0x5f: 'PERSISTENT_RESERVE_OUT',
        0x88: 'READ(16)',
        0x8a: 'WRITE(16)',
        0x9e: 'READ_CAPACITY(16)',
        0xa0: 'REPORT_LUNS',
        0xa1: 'BLANK',
        0xa3: 'MAINTENANCE_IN',
        0xa4: 'MAINTENANCE_OUT',
        0xa3: 'SEND_KEY',
        0xa4: 'REPORT_KEY',
        0xa5: 'MOVE_MEDIUM',
        0xa5: 'PLAY_AUDIO(12)',
        0xa6: 'EXCHANGE_MEDIUM',
        0xa6: 'LOADCD',
        0xa8: 'READ(12)',
        0xa9: 'PLAY_TRACK_RELATIVE',
        0xaa: 'WRITE(12)',
        0xac: 'ERASE(12)',
        0xac: 'GET_PERFORMANCE',
        0xad: 'READ_DVD_STRUCTURE',
        0xae: 'WRITE_VERIFY(12)',
        0xaf: 'VERIFY(12)',
        0xb0: 'SEARCH_DATA_HIGH(12)',
        0xb1: 'SEARCH_DATA_EQUAL(12)',
        0xb2: 'SEARCH_DATA_LOW(12)',
        0xb3: 'SET_LIMITS(12)',
        0xb5: 'REQUEST_VOLUME_ELEMENT_ADDR',
        0xb6: 'SEND_VOLUME_TAG',
        0xb6: 'SET_STREAMING',
        0xb7: 'READ_DEFECT_DATA(12)',
        0xb8: 'READ_ELEMENT_STATUS',
        0xb8: 'SELECT_CDROM_SPEED',
        0xb9: 'READ_CD_MSF',
        0xba: 'AUDIO_SCAN',
        0xbb: 'SET_CDROM_SPEED',
        0xbc: 'SEND_CDROM_XA_DATA',
        0xbc: 'PLAY_CD',
        0xbd: 'MECH_STATUS',
        0xbe: 'READ_CD',
        0xbf: 'SEND_DVD_STRUCTURE',
    })

    # For every command we want to decode parameters for, this includes
    # a struct definition, and a format string that defines a useful
    # summary of the parameters. The entire struct is included after
    # the summary line.
    _structs = {
        #        'INQUIRY': None, # FIXME: We should decode this. SCSI-2, page 104 (8.2.5)
        'READ(6)': (
            "0x%(length)02x blocks at 0x%(lba)04x",
            lambda: (
                Struct.UInt8('lun'),  # FIXME: lun is actually a bitfield
                Struct.UInt16BE('lba'),
                Struct.UInt8('length'),
                Struct.UInt8('control'))),
        'READ(10)': (
            "0x%(length)04x blocks at 0x%(lba)08x",
            lambda: (
                Struct.UInt8('lun'),  # FIXME: lun is actually a bitfield
                Struct.UInt32BE('lba'),
                Struct.UInt8('reserved_1'),
                Struct.UInt16BE('length'),
                Struct.UInt8('control'))),
        'WRITE(6)': (
            "0x%(length)02x blocks at 0x%(lba)04x",
            lambda: (
                Struct.UInt8('lun'),  # FIXME: lun is actually a bitfield
                Struct.UInt16BE('lba'),
                Struct.UInt8('length'),
                Struct.UInt8('control'))),
        'WRITE(10)': (
            "0x%(length)04x blocks at 0x%(lba)08x",
            lambda: (
                Struct.UInt8('lun'),  # FIXME: lun is actually a bitfield
                Struct.UInt32BE('lba'),
                Struct.UInt8('reserved_1'),
                Struct.UInt16BE('length'),
                Struct.UInt8('control'))),
    }

    def __init__(self, cdb):
        self.header = Struct.Group(None, Struct.UInt8("opcode"))
        params = self.header.decode(cdb)
        self.name = self._opcodes[self.header.opcode]

        if self.name in self._structs:
            fmt, children = self._structs[self.name]
            self.params = Struct.Group(None, *children())
            self.params.decode(params)
            self.summary = fmt % self.params.__dict__
        else:
            self.params = None
            self.summary = ''

    def __str__(self):
        return "%s %s" % (self.name, self.summary)
Example #15
0
class ControlDecoder(Decode.ControlDecoder):
    """This extends the default ControlDecoder with support for
       HCI commands encapsulated within class-specific control requests.
       """
    classRequests = Struct.EnumDict({
        0x00: 'HCICommand',
        })

    hciOpcodes = {
        0x01: ("LC", { 0x0001: "HCI_Inquiry",
                       0x0002: "HCI_Inquiry_Cancel",
                       0x0003: "HCI_Periodic_Inquiry_Mode",
                       0x0004: "HCI_Exit_Periodic_Inquiry_Mode",
                       0x0005: "HCI_Create_Connection",
                       0x0006: "HCI_Disconnect",
                       0x0008: "HCI_Create_Connection_Cancel",
                       0x0009: "HCI_Accept_Connection_Request",
                       0x000A: "HCI_Reject_Connection_Request",
                       0x000B: "HCI_Link_Key_Request_Reply",
                       0x000C: "HCI_Link_Key_Request_Negative_Reply",
                       0x000D: "HCI_PIN_Code_Request_Reply",
                       0x000E: "HCI_PIN_Code_Request_Negative_Reply",
                       0x000F: "HCI_Change_Connection_Packet_Type",
                       0x0011: "HCI_Authentication_Requested",
                       0x0013: "HCI_Set_Connection_Encryption",
                       0x0015: "HCI_Change_Connection_Link_Key",
                       0x0017: "HCI_Master_Link_Key",
                       0x0019: "HCI_Remote_Name_Request",
                       0x001A: "HCI_Remote_Name_Request_Cancel",
                       0x001B: "HCI_Read_Remote_Supported_Features",
                       0x001C: "HCI_Read_Remote_Extended_Features",
                       0x001D: "HCI_Read_Remote_Version_Information",
                       0x001F: "HCI_Read_Clock_Offset",
                       0x0020: "HCI_Read_LMP_Handle",
                       0x0028: "HCI_Setup_Synchronous_Connection",
                       0x0029: "HCI_Accept_Synchronous_Connection_Request",
                       0x002A: "HCI_Reject_Synchronous_Connection_Request",
                       }),
        0x02: ("LP", { 0x0001: "HCI_Hold_Mode",
                       0x0003: "HCI_Sniff_Mode",
                       0x0004: "HCI_Exit_Sniff_Mode",
                       0x0005: "HCI_Park_State",
                       0x0006: "HCI_Exit_Park_State",
                       0x0007: "HCI_QoS_Setup",
                       0x0009: "HCI_Role_Discovery",
                       0x000B: "HCI_Switch_Role",
                       0x000C: "HCI_Read_Link_Policy_Settings",
                       0x000D: "HCI_Write_Link_Policy_Settings",
                       0x000E: "HCI_Read_Default_Link_Policy_Settings",
                       0x000F: "HCI_Write_Default_Link_Policy_Settings",
                       0x0010: "HCI_Flow_Specification",
                       }),
        0x03: ("C&B", {0x0001: "HCI_Set_Event_Mask",
                       0x0003: "HCI_Reset",
                       0x0005: "HCI_Set_Event_Filter",
                       0x0008: "HCI_Flush",
                       0x0009: "HCI_Read_PIN_Type",
                       0x000A: "HCI_Write_PIN_Type",
                       0x000B: "HCI_Create_New_Unit_Key",
                       0x000D: "HCI_Read_Stored_Link_Key",
                       0x0011: "HCI_Write_Stored_Link_Key",
                       0x0012: "HCI_Delete_Stored_Link_Key",
                       0x0013: "HCI_Write_Local_Name",
                       0x0014: "HCI_Read_Local_Name",
                       0x0015: "HCI_Read_Connection_Accept_Timeout",
                       0x0016: "HCI_Write_Connection_Accept_Timeout",
                       0x0017: "HCI_Read_Page_Timeout",
                       0x0018: "HCI_Write_Page_Timeout",
                       0x0019: "HCI_Read_Scan_Enable",
                       0x001A: "HCI_Write_Scan_Enable",
                       0x001B: "HCI_Read_Page_Scan_Activity",
                       0x001C: "HCI_Write_Page_Scan_Activity",
                       0x001D: "HCI_Read_Inquiry_Scan_Activity",
                       0x001E: "HCI_Write_Inquiry_Scan_Activity",
                       0x001F: "HCI_Read_Authentication_Enable",
                       0x0020: "HCI_Write_Authentication_Enable",
                       0x0021: "HCI_Read_Encryption_Mode",
                       0x0022: "HCI_Write_Encryption_Mode",
                       0x0023: "HCI_Read_Class_of_Device",
                       0x0024: "HCI_Write_Class_of_Device",
                       0x0025: "HCI_Read_Voice_Setting",
                       0x0026: "HCI_Write_Voice_Setting",
                       0x0027: "HCI_Read_Automatic_Flush_Timeout",
                       0x0028: "HCI_Write_Automatic_Flush_Timeout",
                       0x0029: "HCI_Read_Num_Broadcast_Transmissions",
                       0x002A: "HCI_Write_Num_Broadcast_Transmissions",
                       0x002B: "HCI_Read_Hold_Mode_Activity",
                       0x002C: "HCI_Write_Hold_Mode_Activity",
                       0x002D: "HCI_Read_Transmit_Power_Level",
                       0x002E: "HCI_Read_Synchronous_Flow_Control_Enable",
                       0x002F: "HCI_Write_Synchronous_Flow_Control_Enable",
                       0x0031: "HCI_Set_Controller_To_Host_Flow_Control",
                       0x0033: "HCI_Host_Buffer_Size",
                       0x0035: "HCI_Host_Number_Of_Completed_Packets",
                       0x0036: "HCI_Read_Link_Supervision_Timeout",
                       0x0037: "HCI_Write_Link_Supervision_Timeout",
                       0x0038: "HCI_Read_Number_Of_Supported_IAC",
                       0x0039: "HCI_Read_Current_IAC_LAP",
                       0x003A: "HCI_Write_Current_IAC_LAP",
                       0x003B: "HCI_Read_Page_Scan_Period_Mode",
                       0x003C: "HCI_Write_Page_Scan_Period_Mode",
                       0x003F: "Set_AFH_Host_Channel_Classification",
                       0x0042: "HCI_Read_Inquiry_Scan_Type",
                       0x0043: "HCI_Write_Inquiry_Scan_Type",
                       0x0044: "HCI_Read_Inquiry_Mode",
                       0x0045: "HCI_Write_Inquiry_Mode",
                       0x0046: "HCI_Read_Page_Scan_Type",
                       0x0047: "HCI_Write_Page_Scan_Type",
                       0x0048: "Read_AFH_Channel_Assignment_Mode",
                       0x0049: "Write_AFH_Channel_Assignment_Mode",
                       }),
        0x04: ("IP", { 0x0001: "HCI_Read_Local_Version_Information",
                       0x0002: "HCI_Read_Local_Supported_Commands",
                       0x0003: "HCI_Read_Local_Supported_Features",
                       0x0004: "HCI_Read_Local_Extended_Features",
                       0x0005: "HCI_Read_Buffer_Size",
                       0x0009: "HCI_Read_BD_Addr",
                       }),
        0x05: ("SP", { 0x0001: "HCI_Read_Failed_Contact_Counter",
                       0x0002: "HCI_Reset_Failed_Contact_Counter",
                       0x0003: "HCI_Read_Link_Quality",
                       0x0005: "HCI_Read_RSSI",
                       0x0006: "HCI_Read_AFH_Channel_Map",
                       0x0007: "HCI_Read_Clock",
                       }),
        0x06: ("Test",{0x0001: "HCI_Read_Loopback_Mode",
                       0x0002: "HCI_Write_Loopback_Mode",
                       0x0003: "HCI_Enable_Device_Under_Test_Mode",
                       }),
        }

    def decode_HCICommand(self, setup):
        header = Struct.Group(None,
            Struct.UInt16("opcode"),
            Struct.UInt8("numParameters"),
            )
        params = header.decode(setup.event.data[8:])

        if header.opcode is None:
            ocf = ogf = None
        else:
            ocf = header.opcode & 0x03FF
            ogf = header.opcode >> 10

        ogfName = self.hciOpcodes.get(ogf, (ogf, {}))[0]
        ocfName = self.hciOpcodes.get(ogf, (ogf, {}))[1].get(ocf, ocf)

        setup.event.pushDecoded("BT Command: %s [%s]" % (ocfName, ogfName))
Example #16
0
 def decode_SetFeature(self, setup):
     feature = getattr(self, "%sFeatures" % setup.type,
                       Struct.EnumDict())[setup.wValue]
     setup.event.pushDecoded("%s %s(%s, %s=0x%02x)" %
                             (setup.type, setup.requestName, feature,
                              setup.recip, setup.wIndex))
Example #17
0
class ControlDecoder:
    """Decodes standard control requests, and tries to detect
       additional class decoders based on descriptors we see.

       Control requests first have their names looked up in
       a table of the form <type>Requests. They may then go to
       a default decoder, or we may look up one of the form
       decode_<name> from this class.

       This class defines all standard requests. Subclasses
       may define extra class- or vendor-specific requests.
       """
    standardRequests = Struct.EnumDict({
        0x00: 'GetStatus',
        0x01: 'ClearFeature',
        0x03: 'SetFeature',
        0x05: 'SetAddress',
        0x06: 'GetDescriptor',
        0x07: 'SetDescriptor',
        0x08: 'GetConfiguration',
        0x09: 'SetConfiguration',
        0x0A: 'GetInterface',
        0x0B: 'SetInterface',
        0x0C: 'SynchFrame',
    })
    standardFeatures = Struct.EnumDict({
        0x00: 'ENDPOINT_HALT',
        0x01: 'DEVICE_REMOTE_WAKEUP',
    })
    descriptorClass = DescriptorGroup

    def __init__(self, device):
        self.device = device

    def handleEvent(self, event):
        if not event.isDataTransaction():
            return
        setup = SetupPacket(event)

        # Look up the request name
        setup.requestName = getattr(self, "%sRequests" % setup.type,
                                    Struct.EnumDict())[setup.request]

        # Look up a corresponding decoder
        getattr(self, "decode_%s" % setup.requestName,
                self.decodeGeneric)(setup)

    def decodeGeneric(self, setup):
        """Generic decoder for control requests"""
        setup.event.pushDecoded("%s %s %s(wValue=0x%04x, wIndex=0x%04x)" %
                                (setup.type, setup.recip, setup.requestName,
                                 setup.wValue, setup.wIndex))

    def decode_SetAddress(self, setup):
        setup.event.pushDecoded("SetAddress(%d)" % setup.wValue)

    def decode_SetConfiguration(self, setup):
        setup.event.pushDecoded("SetConfiguration(%d)" % setup.wValue)
        self.device.setConfig(setup.wValue)

    def decode_SetDescriptor(self, setup):
        # Display the get/set descriptor request itself
        setup.event.pushDecoded("%s(%s, %s%s)" % (
            setup.requestName,
            self.descriptorClass.descriptorTypes[setup.wValueHigh],
            setup.wValueLow,
            ("", ", lang=%04X" % setup.wIndex)[setup.wIndex != 0],
        ))

        # Parse out all descriptors
        descriptors = []
        buffer = setup.event.data[8:]
        while buffer:
            desc = self.descriptorClass()
            buffer = desc.decode(buffer)
            setup.event.appendDecoded("\n%s descriptor:\n%s" %
                                      (desc.type, desc))
            descriptors.append(desc)

        self.device.storeDescriptors(descriptors)

    decode_GetDescriptor = decode_SetDescriptor

    def decode_SetFeature(self, setup):
        feature = getattr(self, "%sFeatures" % setup.type,
                          Struct.EnumDict())[setup.wValue]
        setup.event.pushDecoded("%s %s(%s, %s=0x%02x)" %
                                (setup.type, setup.requestName, feature,
                                 setup.recip, setup.wIndex))

    decode_ClearFeature = decode_SetFeature

    def decode_SetInterface(self, setup):
        setup.event.pushDecoded("SetInterface(alt=%d, iface=%d)" %
                                (setup.wValue, setup.wIndex))
        self.device.setInterface(setup.wIndex, setup.wValue)
Example #18
0
class DescriptorGroup(Struct.Group):
    """Parses out USB descriptors into a Struct.Group tree.
       This class handles any standard descriptor, but
       subclasses can add class-specific descriptors as needed.
       """
    descriptorTypes = Struct.EnumDict({
        0x01: "device",
        0x02: "config",
        0x03: "string",
        0x04: "interface",
        0x05: "endpoint",
    })

    headerStruct = lambda self: (
        Struct.UInt8("bLength"),
        Struct.UInt8("bDescriptorType"),
    )
    struct_device = lambda self: (
        Struct.UInt16Hex("bcdUSB"),
        Struct.UInt8Hex("bDeviceClass"),
        Struct.UInt8Hex("bDeviceSubClass"),
        Struct.UInt8Hex("bDeviceProtocol"),
        Struct.UInt8("bMaxPacketSize0"),
        Struct.UInt16Hex("idVendor"),
        Struct.UInt16Hex("idProduct"),
        Struct.UInt16Hex("bcdDevice"),
        Struct.UInt8("iManufacturer"),
        Struct.UInt8("iProduct"),
        Struct.UInt8("iSerialNumber"),
        Struct.UInt8("bNumConfigurations"),
    )
    struct_config = lambda self: (
        Struct.UInt16("wTotalLength"),
        Struct.UInt8("bNumInterfaces"),
        Struct.UInt8("bConfigurationValue"),
        Struct.UInt8("iConfiguration"),
        Struct.UInt8Hex("bmAttributes"),
        Struct.UInt8("MaxPower"),
    )
    struct_string = lambda self: (Struct.Utf16String("string"), )
    struct_interface = lambda self: (
        Struct.UInt8("bInterfaceNumber"),
        Struct.UInt8("bAlternateSetting"),
        Struct.UInt8("bNumEndpoints"),
        Struct.UInt8Hex("bInterfaceClass"),
        Struct.UInt8Hex("bInterfaceSubClass"),
        Struct.UInt8Hex("bInterfaceProtocol"),
        Struct.UInt8("iInterface"),
    )
    struct_endpoint = lambda self: (
        Struct.UInt8Hex("bEndpointAddress"),
        Struct.UInt8Hex("bmAttributes"),
        Struct.UInt16("wMaxPacketSize"),
        Struct.UInt8("bInterval"),
    )

    def __init__(self):
        Struct.Group.__init__(self, "descriptors")

    def decode(self, buffer):
        # Common descriptor header
        buffer = Struct.Group.decode(self, buffer, self.headerStruct())

        # Decode descriptor type
        self.type = self.descriptorTypes[self.bDescriptorType]

        # Make sure that we eat exactly the right number of bytes,
        # according to the descriptor header
        descriptor = buffer[:self.bLength - 2]
        buffer = buffer[self.bLength - 2:]

        # The rest of the decoding is done by a hander, in the form of a child item list.
        Struct.Group.decode(
            self, descriptor,
            getattr(self, "struct_%s" % self.type, lambda: None)())
        return buffer
Example #19
0
class FX2Decoder(Decode.ControlDecoder):
    """Decodes the control endpoint on Cypress FX2 chips. This endpoint
       has vendor-specific commands, implemented in hardware, to read and write RAM.
       """
    vendorRequests = Struct.EnumDict({
        0xA0: 'FirmwareCommand',
    })

    registerInfo = {
        0xE600: ('CPUCS', 'Control & Status'),
        0xE601: ('IFCONFIG', 'Interface Configuration'),
        0xE602: ('PINFLAGSAB', 'FIFO FLAGA and FLAGB Assignments'),
        0xE603: ('PINFLAGSCD', 'FIFO FLAGC and FLAGD Assignments'),
        0xE604: ('FIFORESET', 'Restore FIFOS to default state'),
        0xE605: ('BREAKPT', 'Breakpoint'),
        0xE606: ('BPADDRH', 'Breakpoint Address H'),
        0xE607: ('BPADDRL', 'Breakpoint Address L'),
        0xE608: ('UART230', '230 Kbaud clock for T0,T1,T2'),
        0xE609: ('FIFOPINPOLAR', 'FIFO polarities'),
        0xE60A: ('REVID', 'Chip Revision'),
        0xE60B: ('REVCTL', 'Chip Revision Control'),
        0xE610: ('EP1OUTCFG', 'Endpoint 1-OUT Configuration'),
        0xE611: ('EP1INCFG', 'Endpoint 1-IN Configuration'),
        0xE612: ('EP2CFG', 'Endpoint 2 Configuration'),
        0xE613: ('EP4CFG', 'Endpoint 4 Configuration'),
        0xE614: ('EP6CFG', 'Endpoint 6 Configuration'),
        0xE615: ('EP8CFG', 'Endpoint 8 Configuration'),
        0xE618: ('EP2FIFOCFG', 'Endpoint 2 FIFO configuration'),
        0xE619: ('EP4FIFOCFG', 'Endpoint 4 FIFO configuration'),
        0xE61A: ('EP6FIFOCFG', 'Endpoint 6 FIFO configuration'),
        0xE61B: ('EP8FIFOCFG', 'Endpoint 8 FIFO configuration'),
        0xE620: ('EP2AUTOINLENH', 'Endpoint 2 Packet Length H (IN only)'),
        0xE621: ('EP2AUTOINLENL', 'Endpoint 2 Packet Length L (IN only)'),
        0xE622: ('EP4AUTOINLENH', 'Endpoint 4 Packet Length H (IN only)'),
        0xE623: ('EP4AUTOINLENL', 'Endpoint 4 Packet Length L (IN only)'),
        0xE624: ('EP6AUTOINLENH', 'Endpoint 6 Packet Length H (IN only)'),
        0xE625: ('EP6AUTOINLENL', 'Endpoint 6 Packet Length L (IN only)'),
        0xE626: ('EP8AUTOINLENH', 'Endpoint 8 Packet Length H (IN only)'),
        0xE627: ('EP8AUTOINLENL', 'Endpoint 8 Packet Length L (IN only)'),
        0xE630: ('EP2FIFOPFH', 'EP2 Programmable Flag trigger H'),
        0xE631: ('EP2FIFOPFL', 'EP2 Programmable Flag trigger L'),
        0xE632: ('EP4FIFOPFH', 'EP4 Programmable Flag trigger H'),
        0xE633: ('EP4FIFOPFL', 'EP4 Programmable Flag trigger L'),
        0xE634: ('EP6FIFOPFH', 'EP6 Programmable Flag trigger H'),
        0xE635: ('EP6FIFOPFL', 'EP6 Programmable Flag trigger L'),
        0xE636: ('EP8FIFOPFH', 'EP8 Programmable Flag trigger H'),
        0xE637: ('EP8FIFOPFL', 'EP8 Programmable Flag trigger L'),
        0xE640: ('EP2ISOINPKTS', 'EP2 (if ISO) IN Packets per frame (1-3)'),
        0xE641: ('EP4ISOINPKTS', 'EP4 (if ISO) IN Packets per frame (1-3)'),
        0xE642: ('EP6ISOINPKTS', 'EP6 (if ISO) IN Packets per frame (1-3)'),
        0xE643: ('EP8ISOINPKTS', 'EP8 (if ISO) IN Packets per frame (1-3)'),
        0xE648: ('INPKTEND', 'Force IN Packet End'),
        0xE649: ('OUTPKTEND', 'Force OUT Packet End'),
        0xE650: ('EP2FIFOIE', 'Endpoint 2 Flag Interrupt Enable'),
        0xE651: ('EP2FIFOIRQ', 'Endpoint 2 Flag Interrupt Request'),
        0xE652: ('EP4FIFOIE', 'Endpoint 4 Flag Interrupt Enable'),
        0xE653: ('EP4FIFOIRQ', 'Endpoint 4 Flag Interrupt Request'),
        0xE654: ('EP6FIFOIE', 'Endpoint 6 Flag Interrupt Enable'),
        0xE655: ('EP6FIFOIRQ', 'Endpoint 6 Flag Interrupt Request'),
        0xE656: ('EP8FIFOIE', 'Endpoint 8 Flag Interrupt Enable'),
        0xE657: ('EP8FIFOIRQ', 'Endpoint 8 Flag Interrupt Request'),
        0xE658: ('IBNIE', 'IN-BULK-NAK Interrupt Enable'),
        0xE659: ('IBNIRQ', 'IN-BULK-NAK interrupt Request'),
        0xE65A: ('NAKIE', 'Endpoint Ping NAK interrupt Enable'),
        0xE65B: ('NAKIRQ', 'Endpoint Ping NAK interrupt Request'),
        0xE65C: ('USBIE', 'USB Int Enables'),
        0xE65D: ('USBIRQ', 'USB Interrupt Requests'),
        0xE65E: ('EPIE', 'Endpoint Interrupt Enables'),
        0xE65F: ('EPIRQ', 'Endpoint Interrupt Requests'),
        0xE660: ('GPIFIE', 'GPIF Interrupt Enable'),
        0xE661: ('GPIFIRQ', 'GPIF Interrupt Request'),
        0xE662: ('USBERRIE', 'USB Error Interrupt Enables'),
        0xE663: ('USBERRIRQ', 'USB Error Interrupt Requests'),
        0xE664: ('ERRCNTLIM', 'USB Error counter and limit'),
        0xE665: ('CLRERRCNT', 'Clear Error Counter EC[3..0]'),
        0xE666: ('INT2IVEC', 'Interupt 2 (USB) Autovector'),
        0xE667: ('INT4IVEC', 'Interupt 4 (FIFOS & GPIF) Autovector'),
        0xE668: ('INTSETUP', 'Interrupt 2&4 Setup'),
        0xE670: ('PORTACFG', 'I/O PORTA Alternate Configuration'),
        0xE671: ('PORTCCFG', 'I/O PORTC Alternate Configuration'),
        0xE672: ('PORTECFG', 'I/O PORTE Alternate Configuration'),
        0xE678: ('I2CS', 'Control & Status'),
        0xE679: ('I2DAT', 'Data'),
        0xE67A: ('I2CTL', 'I2C Control'),
        0xE67B: ('EXTAUTODAT1', 'Autoptr1 MOVX access'),
        0xE67C: ('EXTAUTODAT2', 'Autoptr2 MOVX access'),
        0xE680: ('USBCS', 'USB Control & Status'),
        0xE681: ('SUSPEND', 'Put chip into suspend'),
        0xE682: ('WAKEUPCS', 'Wakeup source and polarity'),
        0xE683: ('TOGCTL', 'Toggle Control'),
        0xE684: ('USBFRAMEH', 'USB Frame count H'),
        0xE685: ('USBFRAMEL', 'USB Frame count L'),
        0xE686: ('MICROFRAME', 'Microframe count, 0-7'),
        0xE687: ('FNADDR', 'USB Function address'),
        0xE68A: ('EP0BCH', 'Endpoint 0 Byte Count H'),
        0xE68B: ('EP0BCL', 'Endpoint 0 Byte Count L'),
        0xE68D: ('EP1OUTBC', 'Endpoint 1 OUT Byte Count'),
        0xE68F: ('EP1INBC', 'Endpoint 1 IN Byte Count'),
        0xE690: ('EP2BCH', 'Endpoint 2 Byte Count H'),
        0xE691: ('EP2BCL', 'Endpoint 2 Byte Count L'),
        0xE694: ('EP4BCH', 'Endpoint 4 Byte Count H'),
        0xE695: ('EP4BCL', 'Endpoint 4 Byte Count L'),
        0xE698: ('EP6BCH', 'Endpoint 6 Byte Count H'),
        0xE699: ('EP6BCL', 'Endpoint 6 Byte Count L'),
        0xE69C: ('EP8BCH', 'Endpoint 8 Byte Count H'),
        0xE69D: ('EP8BCL', 'Endpoint 8 Byte Count L'),
        0xE6A0: ('EP0CS', 'Endpoint  Control and Status'),
        0xE6A1: ('EP1OUTCS', 'Endpoint 1 OUT Control and Status'),
        0xE6A2: ('EP1INCS', 'Endpoint 1 IN Control and Status'),
        0xE6A3: ('EP2CS', 'Endpoint 2 Control and Status'),
        0xE6A4: ('EP4CS', 'Endpoint 4 Control and Status'),
        0xE6A5: ('EP6CS', 'Endpoint 6 Control and Status'),
        0xE6A6: ('EP8CS', 'Endpoint 8 Control and Status'),
        0xE6A7: ('EP2FIFOFLGS', 'Endpoint 2 Flags'),
        0xE6A8: ('EP4FIFOFLGS', 'Endpoint 4 Flags'),
        0xE6A9: ('EP6FIFOFLGS', 'Endpoint 6 Flags'),
        0xE6AA: ('EP8FIFOFLGS', 'Endpoint 8 Flags'),
        0xE6AB: ('EP2FIFOBCH', 'EP2 FIFO total byte count H'),
        0xE6AC: ('EP2FIFOBCL', 'EP2 FIFO total byte count L'),
        0xE6AD: ('EP4FIFOBCH', 'EP4 FIFO total byte count H'),
        0xE6AE: ('EP4FIFOBCL', 'EP4 FIFO total byte count L'),
        0xE6AF: ('EP6FIFOBCH', 'EP6 FIFO total byte count H'),
        0xE6B0: ('EP6FIFOBCL', 'EP6 FIFO total byte count L'),
        0xE6B1: ('EP8FIFOBCH', 'EP8 FIFO total byte count H'),
        0xE6B2: ('EP8FIFOBCL', 'EP8 FIFO total byte count L'),
        0xE6B3: ('SUDPTRH', 'Setup Data Pointer high address byte'),
        0xE6B4: ('SUDPTRL', 'Setup Data Pointer low address byte'),
        0xE6B5: ('SUDPTRCTL', 'Setup Data Pointer Auto Mode'),
        0xE6B8: ('SETUPDAT[8]', '8 bytes of SETUP data'),
        0xE6C0: ('GPIFWFSELECT', 'Waveform Selector'),
        0xE6C1: ('GPIFIDLECS', 'GPIF Done, GPIF IDLE drive mode'),
        0xE6C2: ('GPIFIDLECTL', 'Inactive Bus, CTL states'),
        0xE6C3: ('GPIFCTLCFG', 'CTL OUT pin drive'),
        0xE6C4: ('GPIFADRH', 'GPIF Address H'),
        0xE6C5: ('GPIFADRL', 'GPIF Address L'),
        0xE6CE: ('GPIFTCB3', 'GPIF Transaction Count Byte 3'),
        0xE6CF: ('GPIFTCB2', 'GPIF Transaction Count Byte 2'),
        0xE6D0: ('GPIFTCB1', 'GPIF Transaction Count Byte 1'),
        0xE6D1: ('GPIFTCB0', 'GPIF Transaction Count Byte 0'),
        0xE6D0: ('EP2GPIFTCH', 'EP2 GPIF Transaction Count High'),
        0xE6D1: ('EP2GPIFTCL', 'EP2 GPIF Transaction Count Low'),
        0xE6D2: ('EP2GPIFFLGSEL', 'EP2 GPIF Flag select'),
        0xE6D3: ('EP2GPIFPFSTOP', 'Stop GPIF EP2 transaction on prog. flag'),
        0xE6D4: ('EP2GPIFTRIG', 'EP2 FIFO Trigger'),
        0xE6D8: ('EP4GPIFTCH', 'EP4 GPIF Transaction Count High'),
        0xE6D9: ('EP4GPIFTCL', 'EP4 GPIF Transactionr Count Low'),
        0xE6DA: ('EP4GPIFFLGSEL', 'EP4 GPIF Flag select'),
        0xE6DB: ('EP4GPIFPFSTOP', 'Stop GPIF EP4 transaction on prog. flag'),
        0xE6DC: ('EP4GPIFTRIG', 'EP4 FIFO Trigger'),
        0xE6E0: ('EP6GPIFTCH', 'EP6 GPIF Transaction Count High'),
        0xE6E1: ('EP6GPIFTCL', 'EP6 GPIF Transaction Count Low'),
        0xE6E2: ('EP6GPIFFLGSEL', 'EP6 GPIF Flag select'),
        0xE6E3: ('EP6GPIFPFSTOP', 'Stop GPIF EP6 transaction on prog. flag'),
        0xE6E4: ('EP6GPIFTRIG', 'EP6 FIFO Trigger'),
        0xE6E8: ('EP8GPIFTCH', 'EP8 GPIF Transaction Count High'),
        0xE6E9: ('EP8GPIFTCL', 'EP8GPIF Transaction Count Low'),
        0xE6EA: ('EP8GPIFFLGSEL', 'EP8 GPIF Flag select'),
        0xE6EB: ('EP8GPIFPFSTOP', 'Stop GPIF EP8 transaction on prog. flag'),
        0xE6EC: ('EP8GPIFTRIG', 'EP8 FIFO Trigger'),
        0xE6F0: ('XGPIFSGLDATH', 'GPIF Data H (16-bit mode only)'),
        0xE6F1: ('XGPIFSGLDATLX', 'Read/Write GPIF Data L & trigger transac'),
        0xE6F2: ('XGPIFSGLDATLNOX', 'Read GPIF Data L, no transac trigger'),
        0xE6F3: ('GPIFREADYCFG', 'Internal RDY,Sync/Async, RDY5CFG'),
        0xE6F4: ('GPIFREADYSTAT', 'RDY pin states'),
        0xE6F5: ('GPIFABORT', 'Abort GPIF cycles'),
        0xE6C6: ('FLOWSTATE', 'Defines GPIF flow state'),
        0xE6C7: ('FLOWLOGIC', 'Defines flow/hold decision criteria'),
        0xE6C8: ('FLOWEQ0CTL', 'CTL states during active flow state'),
        0xE6C9: ('FLOWEQ1CTL', 'CTL states during hold flow state'),
        0xE6CA: ('FLOWHOLDOFF', ''),
        0xE6CB: ('FLOWSTB', 'CTL/RDY Signal to use as master data strobe'),
        0xE6CC: ('FLOWSTBEDGE', 'Defines active master strobe edge'),
        0xE6CD: ('FLOWSTBHPERIOD', 'Half Period of output master strobe'),
        0xE60C: ('GPIFHOLDAMOUNT', 'Data delay shift'),
        0xE67D: ('UDMACRCH', 'CRC Upper byte'),
        0xE67E: ('UDMACRCL', 'CRC Lower byte'),
        0xE67F: ('UDMACRCQUAL', 'UDMA In only, host terminated use only'),
        0xE6F8: ('DBUG', 'Debug'),
        0xE6F9: ('TESTCFG', 'Test configuration'),
        0xE6FA: ('USBTEST', 'USB Test Modes'),
        0xE6FB: ('CT1', 'Chirp Test--Override'),
        0xE6FC: ('CT2', 'Chirp Test--FSM'),
        0xE6FD: ('CT3', 'Chirp Test--Control Signals'),
        0xE6FE: ('CT4', 'Chirp Test--Inputs'),
    }

    def decode_FirmwareCommand(self, setup):
        direction = setup.bitmap & 0x80 != 0
        address = setup.wValue
        length = setup.wLength

        setup.event.pushDecoded("FX2 %s at 0x%04x (%s)" %
                                (('Write', 'Read')[direction], address,
                                 self.getAddressDescription(address)))

    def getAddressDescription(self, address):
        if address < 0x2000:
            return "Program Memory"

        if address < 0xE000:
            return "INVALID"

        if address < 0xE200:
            return "Scratch RAM"

        if address < 0xE400:
            return "RESERVED"

        if address < 0xE480:
            return "GPIF Waveforms"

        if address < 0xE600:
            return "RESERVED"

        if address < 0xE700:
            try:
                return "Register [%s] %s" % self.registerInfo[address]
            except KeyError:
                return "Unknown Register"

        if address < 0xE740:
            return "UNAVAILABLE"

        if address < 0xE780:
            return "EP0 Buffer"

        if address < 0xE800:
            return "EP1 Buffer"

        if address < 0xF000:
            return "RESERVED"

        return "EP2/4/6/8 Buffer"