Skip to content

Commit 1989b25

Browse files
committed
usb_power_delivery: support Revision 3.2 Extended Data
1 parent 0235970 commit 1989b25

File tree

1 file changed

+90
-17
lines changed
  • decoders/usb_power_delivery

1 file changed

+90
-17
lines changed

decoders/usb_power_delivery/pd.py

Lines changed: 90 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,22 @@
4040
6: 'PS RDY',
4141
7: 'GET SOURCE CAP',
4242
8: 'GET SINK CAP',
43-
9: 'DR SWAP',
44-
10: 'PR SWAP',
45-
11: 'VCONN SWAP',
46-
12: 'WAIT',
47-
13: 'SOFT RESET',
48-
14: 'reserved',
49-
15: 'reserved',
50-
16: 'Not Supported',
43+
9: 'DR_Swap',
44+
10: 'PR_Swap',
45+
11: 'VCONN_Swap',
46+
12: 'Wait',
47+
13: 'Soft_Reset',
48+
14: 'Data_Reset',
49+
15: 'Data_Reset_Complete',
50+
16: 'Not_Supported',
5151
17: 'Get_Source_Cap_Extended',
5252
18: 'Get_Status',
5353
19: 'FR_Swap',
5454
20: 'Get_PPS_Status',
5555
21: 'Get_Country_Codes',
56+
22: 'Get_Sink_Cap_Extended',
57+
23: 'Get_Source_Info',
58+
24: 'Get_Revision'
5659
}
5760

5861
# Data message type
@@ -64,9 +67,37 @@
6467
5: 'Battery_Status',
6568
6: 'Alert',
6669
7: 'Get_Country_Info',
70+
8: 'Enter_USB',
71+
9: 'EPR_Request',
72+
10: 'EPR_Mode',
73+
11: 'Source_Info',
74+
12: 'Revision',
6775
15: 'VDM'
6876
}
6977

78+
# Extended message type
79+
EXT_TYPES = {
80+
1: 'Source_Capabilities_Extended',
81+
2: 'Status',
82+
3: 'Get_Battery_Cap',
83+
4: 'Get_Battery_Status',
84+
5: 'Battery_Capabilities',
85+
6: 'Get_Manufacturer_Info',
86+
7: 'Manufacturer_Info',
87+
8: 'Security_Request',
88+
9: 'Security_Response',
89+
10: 'Firmware_Update_Request',
90+
11: 'Firmware_Update_Response',
91+
12: 'PPS_Status',
92+
13: 'Country_Info',
93+
14: 'Country_Codes',
94+
15: 'Sink_Capabilities_Extended',
95+
16: 'Extended_Control',
96+
17: 'EPR_Source_Capabilities',
97+
18: 'EPR_Sink_Capabilities',
98+
30: 'Vendor_Defined_Extended'
99+
}
100+
70101
# 4b5b encoding of the symbols
71102
DEC4B5B = [
72103
0x10, # Error 00000
@@ -377,6 +408,10 @@ def get_bist(self, idx, data):
377408
return 'mode %s' % (mode_name) if idx == 0 else 'invalid BRO'
378409

379410
def putpayload(self, s0, s1, idx):
411+
if self.head_ext() == 1:
412+
# TODO: to decode Extended Message Types
413+
return
414+
380415
t = self.head_type()
381416
txt = '['+str(idx+1)+'] '
382417
if t == 2:
@@ -396,14 +431,21 @@ def puthead(self):
396431
if self.head_data_role() != self.head_power_role():
397432
role += '/DFP' if self.head_data_role() else '/UFP'
398433
t = self.head_type()
399-
if self.head_count() == 0:
400-
shortm = CTRL_TYPES[t]
434+
if self.head_ext() == 1:
435+
shortm = EXT_TYPES[t] if t in EXT_TYPES else 'EXT???'
436+
elif self.head_count() == 0:
437+
shortm = CTRL_TYPES[t] if t in CTRL_TYPES else 'CTR???'
401438
else:
402439
shortm = DATA_TYPES[t] if t in DATA_TYPES else 'DAT???'
403440

404441
longm = '(r{:d}) {:s}[{:d}]: {:s}'.format(self.head_rev(), role, self.head_id(), shortm)
405442
self.putx(0, -1, [ann_type, [longm, shortm]])
406443
self.text += longm
444+
445+
def head_ext(self):
446+
if self.head_rev() == 3:
447+
return (self.head >> 15) & 1
448+
return 0
407449

408450
def head_id(self):
409451
return (self.head >> 9) & 7
@@ -418,20 +460,29 @@ def head_rev(self):
418460
return ((self.head >> 6) & 3) + 1
419461

420462
def head_type(self):
463+
if self.head_rev() == 3:
464+
return self.head & 0x1F
421465
return self.head & 0xF
422466

423467
def head_count(self):
424468
return (self.head >> 12) & 7
425469

470+
def exthead_size(self):
471+
return (self.exthead) & 511
472+
426473
def putx(self, s0, s1, data):
427474
self.put(self.edges[s0], self.edges[s1], self.out_ann, data)
428475

429476
def putwarn(self, longm, shortm):
430477
self.putx(0, -1, [8, [longm, shortm]])
431478

432479
def compute_crc32(self):
433-
bdata = struct.pack('<H'+'I'*len(self.data), self.head & 0xffff,
434-
*tuple([d & 0xffffffff for d in self.data]))
480+
if self.head_ext() == 1:
481+
bdata = struct.pack('<HH'+'B'*len(self.extdata), self.head & 0xffff, self.exthead & 0xffff,
482+
*tuple([d & 0xff for d in self.extdata]))
483+
else:
484+
bdata = struct.pack('<H'+'I'*len(self.data), self.head & 0xffff,
485+
*tuple([d & 0xffffffff for d in self.data]))
435486
return zlib.crc32(bdata)
436487

437488
def rec_sym(self, i, sym):
@@ -445,6 +496,18 @@ def get_sym(self, i, rec=True):
445496
self.rec_sym(i, sym)
446497
return sym
447498

499+
def get_byte(self):
500+
i = self.idx
501+
# Check it's not a truncated packet.
502+
if len(self.bits) - i <= 10:
503+
self.putwarn('Truncated', '!')
504+
return 0x0BAD
505+
k = [self.get_sym(i), self.get_sym(i+5)]
506+
# TODO: Check bad symbols.
507+
val = k[0] | (k[1] << 4)
508+
self.idx += 10
509+
return val
510+
448511
def get_short(self):
449512
i = self.idx
450513
# Check it's not a truncated packet.
@@ -539,6 +602,7 @@ def us2samples(self, us):
539602

540603
def decode_packet(self):
541604
self.data = []
605+
self.extdata = []
542606
self.idx = 0
543607
self.text = ''
544608

@@ -561,11 +625,20 @@ def decode_packet(self):
561625
self.puthead()
562626

563627
# Decode data payload
564-
for i in range(self.head_count()):
565-
self.data.append(self.get_word())
566-
self.putx(self.idx-40, self.idx,
567-
[4, ['[%d]%08x' % (i, self.data[i]), 'D%d' % (i)]])
568-
self.putpayload(self.idx-40, self.idx, i)
628+
if self.head_ext() == 1:
629+
self.exthead = self.get_short()
630+
self.putx(self.idx-20, self.idx, [3, ['EH:%04x' % (self.exthead), 'EHD']])
631+
for i in range(self.exthead_size()):
632+
self.extdata.append(self.get_byte())
633+
self.putx(self.idx-10, self.idx,
634+
[4, ['[%d]%02x' % (i, self.extdata[i]), 'D%d' % (i)]])
635+
#self.putpayload(self.idx-40, self.idx, i)
636+
else:
637+
for i in range(self.head_count()):
638+
self.data.append(self.get_word())
639+
self.putx(self.idx-40, self.idx,
640+
[4, ['[%d]%08x' % (i, self.data[i]), 'D%d' % (i)]])
641+
self.putpayload(self.idx-40, self.idx, i)
569642

570643
# CRC check
571644
self.crc = self.get_word()

0 commit comments

Comments
 (0)