+ def handle_packet(self):
+ packet = ''
+ for (bit, ss, es) in self.bits:
+ packet += bit
+
+ if len(packet) < 8:
+ self.putp([28, ['Invalid packet (shorter than 8 bits)']])
+ return
+
+ # Bits[0:7]: SYNC
+ sync = packet[:7 + 1]
+ self.ss, self.es = self.bits[0][1], self.bits[7][2]
+ # The SYNC pattern for low-speed/full-speed is KJKJKJKK (00000001).
+ if sync != '00000001':
+ self.putpb(['SYNC ERROR', sync])
+ self.putb([1, ['SYNC ERROR: %s' % sync, 'SYNC ERR: %s' % sync,
+ 'SYNC ERR', 'SE', 'S']])
+ else:
+ self.putpb(['SYNC', sync])
+ self.putb([0, ['SYNC: %s' % sync, 'SYNC', 'S']])
+ self.packet.append(sync)
+
+ if len(packet) < 16:
+ self.putp([28, ['Invalid packet (shorter than 16 bits)']])
+ return
+
+ # Bits[8:15]: PID
+ pid = packet[8:15 + 1]
+ pidname = pids.get(pid, ('UNKNOWN', 'Unknown PID'))[0]
+ self.ss, self.es = self.bits[8][1], self.bits[15][2]
+ self.putpb(['PID', pidname])
+ self.putb([2, ['PID: %s' % pidname, pidname, pidname[0]]])
+ self.packet.append(pid)
+ self.packet_summary += pidname
+
+ if pidname in ('OUT', 'IN', 'SOF', 'SETUP', 'PING'):
+ if len(packet) < 32:
+ self.putp([28, ['Invalid packet (shorter than 32 bits)']])
+ return
+
+ if pidname == 'SOF':
+ # Bits[16:26]: Framenum
+ framenum = bitstr_to_num(packet[16:26 + 1])
+ self.ss, self.es = self.bits[16][1], self.bits[26][2]
+ self.putpb(['FRAMENUM', framenum])
+ self.putb([3, ['Frame: %d' % framenum, 'Frame', 'Fr', 'F']])
+ self.packet.append(framenum)
+ self.packet_summary += ' %d' % framenum
+ else:
+ # Bits[16:22]: Addr
+ addr = bitstr_to_num(packet[16:22 + 1])
+ self.ss, self.es = self.bits[16][1], self.bits[22][2]
+ self.putpb(['ADDR', addr])
+ self.putb([4, ['Address: %d' % addr, 'Addr: %d' % addr,
+ 'Addr', 'A']])
+ self.packet.append(addr)
+ self.packet_summary += ' ADDR %d' % addr
+
+ # Bits[23:26]: EP
+ ep = bitstr_to_num(packet[23:26 + 1])
+ self.ss, self.es = self.bits[23][1], self.bits[26][2]
+ self.putpb(['EP', ep])
+ self.putb([5, ['Endpoint: %d' % ep, 'EP: %d' % ep, 'EP', 'E']])
+ self.packet.append(ep)
+ self.packet_summary += ' EP %d' % ep
+
+ # Bits[27:31]: CRC5
+ crc5 = bitstr_to_num(packet[27:31 + 1])
+ crc5_calc = calc_crc5(packet[16:27])
+ self.ss, self.es = self.bits[27][1], self.bits[31][2]
+ if crc5 == crc5_calc:
+ self.putpb(['CRC5', crc5])
+ self.putb([6, ['CRC5: 0x%02X' % crc5, 'CRC5', 'C']])
+ else:
+ self.putpb(['CRC5 ERROR', crc5])
+ self.putb([7, ['CRC5 ERROR: 0x%02X' % crc5, 'CRC5 ERR', 'CE', 'C']])
+ self.packet.append(crc5)
+ elif pidname in ('DATA0', 'DATA1', 'DATA2', 'MDATA'):
+ # Bits[16:packetlen-16]: Data
+ data = packet[16:-16]
+ # TODO: len(data) must be a multiple of 8.
+ databytes = []
+ self.packet_summary += ' ['
+ for i in range(0, len(data), 8):
+ db = bitstr_to_num(data[i:i + 8])
+ self.ss, self.es = self.bits[16 + i][1], self.bits[23 + i][2]
+ self.putpb(['DATABYTE', db])
+ self.putb([8, ['Databyte: %02X' % db, 'Data: %02X' % db,
+ 'DB: %02X' % db, '%02X' % db]])
+ databytes.append(db)
+ self.packet_summary += ' %02X' % db
+ self.packet_summary += ' ]'
+
+ # Convenience Python output (no annotation) for all bytes together.
+ self.ss, self.es = self.bits[16][1], self.bits[-16][2]
+ self.putpb(['DATABYTES', databytes])
+ self.packet.append(databytes)
+
+ # Bits[packetlen-16:packetlen]: CRC16
+ crc16 = bitstr_to_num(packet[-16:])
+ crc16_calc = calc_crc16(packet[16:-16])
+ self.ss, self.es = self.bits[-16][1], self.bits[-1][2]
+ if crc16 == crc16_calc:
+ self.putpb(['CRC16', crc16])
+ self.putb([9, ['CRC16: 0x%04X' % crc16, 'CRC16', 'C']])
+ else:
+ self.putpb(['CRC16 ERROR', crc16])
+ self.putb([10, ['CRC16 ERROR: 0x%04X' % crc16, 'CRC16 ERR', 'CE', 'C']])
+ self.packet.append(crc16)
+ elif pidname in ('ACK', 'NAK', 'STALL', 'NYET', 'ERR'):
+ pass # Nothing to do, these only have SYNC+PID+EOP fields.
+ elif pidname in ('PRE'):
+ pass # Nothing to do, PRE only has SYNC+PID fields.
+ else:
+ pass # TODO: Handle 'SPLIT' and possibly 'Reserved' packets.
+
+ # Output a (summary of) the whole packet.
+ pcategory, pname, pinfo = get_category(pidname), pidname, self.packet
+ self.putpp(['PACKET', [pcategory, pname, pinfo]])
+ self.putp([ann_index(pidname), ['%s' % self.packet_summary]])
+
+ self.packet, self.packet_summary = [], ''