forked from Ivasoft/DSView
Protocol Update: USB PD Extended Message and EPR Message
This commit is contained in:
@@ -19,6 +19,10 @@
|
|||||||
## along with this program; if not, see <http://www.gnu.org/licenses/>.
|
## along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
##
|
##
|
||||||
|
|
||||||
|
#
|
||||||
|
# 2023-8-28 Extended Message and EPR Message Update
|
||||||
|
#
|
||||||
|
|
||||||
import sigrokdecode as srd
|
import sigrokdecode as srd
|
||||||
import struct
|
import struct
|
||||||
import zlib # for crc32
|
import zlib # for crc32
|
||||||
@@ -67,6 +71,11 @@ DATA_TYPES = {
|
|||||||
5: 'Battery_Status',
|
5: 'Battery_Status',
|
||||||
6: 'Alert',
|
6: 'Alert',
|
||||||
7: 'Get_Country_Info',
|
7: 'Get_Country_Info',
|
||||||
|
8: 'Enter_USB',
|
||||||
|
9: 'EPR_Request',
|
||||||
|
10: 'EPR_Mode',
|
||||||
|
11: 'Source_Info',
|
||||||
|
12: 'Revision',
|
||||||
15: 'VDM'
|
15: 'VDM'
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +94,12 @@ EXTENDED_TYPES = {
|
|||||||
11: 'Firmware_Update_Response',
|
11: 'Firmware_Update_Response',
|
||||||
12: 'PPS_Status',
|
12: 'PPS_Status',
|
||||||
13: 'Country_Info',
|
13: 'Country_Info',
|
||||||
14: 'Country_Codes'
|
14: 'Country_Codes',
|
||||||
|
15: 'Sink_Capabilities_Extended',
|
||||||
|
16: 'Extended_Control',
|
||||||
|
17: 'EPR_Source_Capabilities',
|
||||||
|
18: 'EPR_Sink_Capabilities',
|
||||||
|
30: 'Vendor_Defined_Extended'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -212,6 +226,27 @@ VDM_CMDS = {
|
|||||||
}
|
}
|
||||||
VDM_ACK = ['REQ', 'ACK', 'NAK', 'BSY']
|
VDM_ACK = ['REQ', 'ACK', 'NAK', 'BSY']
|
||||||
|
|
||||||
|
EPR_MODE_ACTION = {
|
||||||
|
1: 'Enter',
|
||||||
|
2: 'Enter Acknowledged',
|
||||||
|
3: 'Enter Succeeded',
|
||||||
|
4: 'Enter Failed',
|
||||||
|
5: 'Exit'
|
||||||
|
}
|
||||||
|
EPR_MODE_DATA = {
|
||||||
|
0: 'Unknown cause',
|
||||||
|
1: 'Cable not EPR capable',
|
||||||
|
2: 'Source failed to become Vconn source',
|
||||||
|
3: 'EPR Mode Capable bit not set in RDO',
|
||||||
|
4: 'Source unable to enter EPR Mode at this time',
|
||||||
|
5: 'EPR Mode Capable bit not set in PDO'
|
||||||
|
}
|
||||||
|
EXT_CONTROL_MSG_TYPES = {
|
||||||
|
1: 'EPR Get Source_Cap',
|
||||||
|
2: 'EPR Get Sink Cap',
|
||||||
|
3: 'EPR KeepAlive',
|
||||||
|
4: 'EPR KeepAlive Ack'
|
||||||
|
}
|
||||||
|
|
||||||
class SamplerateError(Exception):
|
class SamplerateError(Exception):
|
||||||
pass
|
pass
|
||||||
@@ -266,7 +301,7 @@ class Decoder(srd.Decoder):
|
|||||||
stored_pdos = {}
|
stored_pdos = {}
|
||||||
|
|
||||||
def get_request(self, rdo):
|
def get_request(self, rdo):
|
||||||
pos = (rdo >> 28) & 7
|
pos = (rdo >> 28) & 0x0F
|
||||||
|
|
||||||
op_ma = ((rdo >> 10) & 0x3ff) * 0.01
|
op_ma = ((rdo >> 10) & 0x3ff) * 0.01
|
||||||
max_ma = (rdo & 0x3ff) * 0.01
|
max_ma = (rdo & 0x3ff) * 0.01
|
||||||
@@ -399,24 +434,52 @@ class Decoder(srd.Decoder):
|
|||||||
return 'mode %s' % (mode_name) if idx == 0 else 'invalid BRO'
|
return 'mode %s' % (mode_name) if idx == 0 else 'invalid BRO'
|
||||||
|
|
||||||
def get_hex(self, idx, data):
|
def get_hex(self, idx, data):
|
||||||
if idx == 0:
|
txt = '%02x' % ((data >> 8)&0xFF)
|
||||||
txt = 'Ext H:%04x' % ( data & 0xFFFF )
|
txt += ' %02x' % ((data >> 0)&0xFF)
|
||||||
txt += ' DATA: %02x' % ((data >> 24)&0xFF)
|
txt += ' %02x' % ((data >> 24)&0xFF)
|
||||||
txt += ' %02x' % ((data >> 16)&0xFF)
|
txt += ' %02x' % ((data >> 16)&0xFF)
|
||||||
else:
|
|
||||||
txt = '%02x' % ((data >> 8)&0xFF)
|
|
||||||
txt += ' %02x' % ((data >> 0)&0xFF)
|
|
||||||
txt += ' %02x' % ((data >> 24)&0xFF)
|
|
||||||
txt += ' %02x' % ((data >> 16)&0xFF)
|
|
||||||
return txt
|
return txt
|
||||||
|
|
||||||
|
def get_hex16(self, data):
|
||||||
|
txt = '%02x' % ((data >> 8)&0xFF)
|
||||||
|
txt += ' %02x' % ((data >> 0)&0xFF)
|
||||||
|
return txt
|
||||||
|
|
||||||
|
def get_epr_mode(self, idx, data):
|
||||||
|
txt = EPR_MODE_ACTION[data >> 24]
|
||||||
|
if data >> 24 == 4:
|
||||||
|
txt += ' '
|
||||||
|
txt += EPR_MODE_DATA[(data >> 16) & 0xFF]
|
||||||
|
return txt
|
||||||
|
|
||||||
|
def get_ext_control_type(self, idx, data):
|
||||||
|
txt = EXT_CONTROL_MSG_TYPES[data >> 16]
|
||||||
|
return txt
|
||||||
|
|
||||||
|
def put_ext_head(self, s0, s1):
|
||||||
|
txt = 'Chunked: {} '. format(self.chunked)
|
||||||
|
txt += 'Chunk Num: {} '.format(self.chunk_num)
|
||||||
|
txt += 'Req Chunk: {} '.format(self.req_chunk)
|
||||||
|
txt += 'Data Size: {} '.format(self.data_size)
|
||||||
|
|
||||||
|
self.putx(s0, s1, [11, [txt, txt]])
|
||||||
|
|
||||||
def putpayload(self, s0, s1, idx):
|
def putpayload(self, s0, s1, idx):
|
||||||
t = self.head_type() if self.head_ext() == 0 else 255
|
t = self.head_type() if self.head_ext() == 0 else 255
|
||||||
|
|
||||||
txt = '['+str(idx+1)+'] '
|
txt = '['+str(idx+1)+'] '
|
||||||
|
# Extended Message
|
||||||
if t == 255:
|
if t == 255:
|
||||||
txt += self.get_hex(idx, self.data[idx])
|
t = self.head_type()
|
||||||
|
|
||||||
|
if t == 16:
|
||||||
|
txt += self.get_ext_control_type(idx, self.data[idx])
|
||||||
|
elif s1 - s0 < 40:
|
||||||
|
txt += self.get_hex16(self.ext_data[idx] & 0xFFFF)
|
||||||
|
else:
|
||||||
|
txt += self.get_hex(idx, self.ext_data[idx])
|
||||||
|
|
||||||
|
# Others
|
||||||
elif t == 2:
|
elif t == 2:
|
||||||
txt += self.get_request(self.data[idx])
|
txt += self.get_request(self.data[idx])
|
||||||
elif t == 1 or t == 4:
|
elif t == 1 or t == 4:
|
||||||
@@ -425,6 +488,14 @@ class Decoder(srd.Decoder):
|
|||||||
txt += self.get_vdm(idx, self.data[idx])
|
txt += self.get_vdm(idx, self.data[idx])
|
||||||
elif t == 3:
|
elif t == 3:
|
||||||
txt += self.get_bist(idx, self.data[idx])
|
txt += self.get_bist(idx, self.data[idx])
|
||||||
|
elif t == 10:
|
||||||
|
txt += self.get_epr_mode(idx, self.data[idx])
|
||||||
|
elif t == 9:
|
||||||
|
if idx == 0:
|
||||||
|
txt += self.get_request(self.data[idx])
|
||||||
|
else:
|
||||||
|
txt += self.get_source_sink_cap(self.data[idx], idx+1, True)
|
||||||
|
|
||||||
self.putx(s0, s1, [11, [txt, txt]])
|
self.putx(s0, s1, [11, [txt, txt]])
|
||||||
self.text += ' - ' + txt
|
self.text += ' - ' + txt
|
||||||
|
|
||||||
@@ -563,7 +634,7 @@ class Decoder(srd.Decoder):
|
|||||||
self.half_one = False
|
self.half_one = False
|
||||||
self.start_one = 0
|
self.start_one = 0
|
||||||
self.stored_pdos = {}
|
self.stored_pdos = {}
|
||||||
self.cap_mark = [0, 0, 0, 0, 0, 0, 0, 0]
|
self.cap_mark = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
|
|
||||||
def metadata(self, key, value):
|
def metadata(self, key, value):
|
||||||
if key == srd.SRD_CONF_SAMPLERATE:
|
if key == srd.SRD_CONF_SAMPLERATE:
|
||||||
@@ -586,6 +657,8 @@ class Decoder(srd.Decoder):
|
|||||||
|
|
||||||
def decode_packet(self):
|
def decode_packet(self):
|
||||||
self.data = []
|
self.data = []
|
||||||
|
self.ext_head = 0
|
||||||
|
self.ext_data = []
|
||||||
self.idx = 0
|
self.idx = 0
|
||||||
self.text = ''
|
self.text = ''
|
||||||
|
|
||||||
@@ -604,15 +677,63 @@ class Decoder(srd.Decoder):
|
|||||||
|
|
||||||
# Packet header
|
# Packet header
|
||||||
self.head = self.get_short()
|
self.head = self.get_short()
|
||||||
self.putx(self.idx-20, self.idx, [3, ['H:%04x' % (self.head), 'HD']])
|
self.putx(self.idx-20, self.idx, [3, ['H:%04X' % (self.head), 'HD']])
|
||||||
self.puthead()
|
self.puthead()
|
||||||
|
|
||||||
# Decode data payload
|
# Decode data payload
|
||||||
for i in range(self.head_count()):
|
if self.head_ext() == 1:
|
||||||
self.data.append(self.get_word())
|
# Extend Header
|
||||||
self.putx(self.idx-40, self.idx,[4, ['[%d]%08x' % (i, self.data[i]), 'D%d' % (i)]])
|
self.ext_head = self.get_short()
|
||||||
self.putpayload(self.idx-40, self.idx, i)
|
self.chunked = (self.ext_head >> 15) & 0x01
|
||||||
|
self.chunk_num = (self.ext_head >> 11) & 0x0F
|
||||||
|
self.req_chunk = (self.ext_head >> 10) & 0x01
|
||||||
|
self.data_size = self.ext_head & 0x01FF
|
||||||
|
|
||||||
|
self.putx(self.idx-20, self.idx, [3, ['Ext H:%04X' % (self.ext_head), 'EXHD']])
|
||||||
|
self.put_ext_head(self.idx-20, self.idx)
|
||||||
|
self.idx -= 20
|
||||||
|
|
||||||
|
# Save Data For Calculate CRC
|
||||||
|
for i in range(self.head_count()):
|
||||||
|
self.data.append(self.get_word())
|
||||||
|
self.idx -= (self.head_count()-1) * 40 + 20
|
||||||
|
|
||||||
|
# Extended Message
|
||||||
|
if self.chunk_num == 0: # First Part of Extended Message Data
|
||||||
|
for i in range(self.head_count()):
|
||||||
|
if i == self.head_count() - 1:
|
||||||
|
data = self.get_short()
|
||||||
|
self.ext_data.append(data)
|
||||||
|
|
||||||
|
self.putx(self.idx-20, self.idx,[4, ['[%d]%04x' % (i, data), 'D%d' % (i)]])
|
||||||
|
self.putpayload(self.idx-20, self.idx, i)
|
||||||
|
else:
|
||||||
|
data = self.get_word()
|
||||||
|
self.ext_data.append(data)
|
||||||
|
self.putx(self.idx-40, self.idx,[4, ['[%d]%08x' % (i, data), 'D%d' % (i)]])
|
||||||
|
self.putpayload(self.idx-40, self.idx, i)
|
||||||
|
|
||||||
|
else: # Second Part
|
||||||
|
for i in range(self.head_count()):
|
||||||
|
if i == 0:
|
||||||
|
data = self.get_short()
|
||||||
|
self.ext_data.append(data)
|
||||||
|
|
||||||
|
self.putx(self.idx-20, self.idx,[4, ['[%d]%04x' % (i, data), 'D%d' % (i)]])
|
||||||
|
self.putpayload(self.idx-20, self.idx, i)
|
||||||
|
else:
|
||||||
|
data = self.get_word()
|
||||||
|
self.ext_data.append(data)
|
||||||
|
self.putx(self.idx-40, self.idx,[4, ['[%d]%08x' % (i, data), 'D%d' % (i)]])
|
||||||
|
self.putpayload(self.idx-40, self.idx, i)
|
||||||
|
|
||||||
|
# Control Message or Data Message
|
||||||
|
else:
|
||||||
|
for i in range(self.head_count()):
|
||||||
|
self.data.append(self.get_word())
|
||||||
|
self.putx(self.idx-40, self.idx,[4, ['[%d]%08x' % (i, self.data[i]), 'D%d' % (i)]])
|
||||||
|
self.putpayload(self.idx-40, self.idx, i)
|
||||||
|
|
||||||
# CRC check
|
# CRC check
|
||||||
self.crc = self.get_word()
|
self.crc = self.get_word()
|
||||||
ccrc = self.compute_crc32()
|
ccrc = self.compute_crc32()
|
||||||
|
|||||||
Reference in New Issue
Block a user