1616 BitEnumField , BitField , XByteField , FieldListField , \
1717 XShortField , X3BytesField , XIntField , ByteField , \
1818 ShortField , ObservableDict , XShortEnumField , XByteEnumField , StrLenField , \
19- FieldLenField , XStrFixedLenField , XStrLenField
19+ FieldLenField , XStrFixedLenField , XStrLenField , FlagsField , PacketListField , \
20+ PacketField
2021from scapy .packet import Packet , bind_layers , NoPayload
2122from scapy .config import conf
2223from scapy .error import log_loading
@@ -956,12 +957,39 @@ class UDS_RDTCI(Packet):
956957 20 : 'reportDTCFaultDetectionCounter' ,
957958 21 : 'reportDTCWithPermanentStatus'
958959 }
960+ dtcStatus = {
961+ 1 : 'TestFailed' ,
962+ 2 : 'TestFailedThisOperationCycle' ,
963+ 4 : 'PendingDTC' ,
964+ 8 : 'ConfirmedDTC' ,
965+ 16 : 'TestNotCompletedSinceLastClear' ,
966+ 32 : 'TestFailedSinceLastClear' ,
967+ 64 : 'TestNotCompletedThisOperationCycle' ,
968+ 128 : 'WarningIndicatorRequested'
969+ }
970+ dtcStatusMask = {
971+ 1 : 'ActiveDTCs' ,
972+ 4 : 'PendingDTCs' ,
973+ 8 : 'ConfirmedOrStoredDTCs' ,
974+ 255 : 'AllRecordDTCs'
975+ }
976+ dtcSeverityMask = {
977+ # 0: 'NoSeverityInformation',
978+ 1 : 'NoClassInformation' ,
979+ 2 : 'WWH-OBDClassA' ,
980+ 4 : 'WWH-OBDClassB1' ,
981+ 8 : 'WWH-OBDClassB2' ,
982+ 16 : 'WWH-OBDClassC' ,
983+ 32 : 'MaintenanceRequired' ,
984+ 64 : 'CheckAtNextHalt' ,
985+ 128 : 'CheckImmediately'
986+ }
959987 name = 'ReadDTCInformation'
960988 fields_desc = [
961989 ByteEnumField ('reportType' , 0 , reportTypes ),
962- ConditionalField (ByteField ('DTCSeverityMask' , 0 ),
990+ ConditionalField (FlagsField ('DTCSeverityMask' , 0 , 8 , dtcSeverityMask ),
963991 lambda pkt : pkt .reportType in [0x07 , 0x08 ]),
964- ConditionalField (XByteField ('DTCStatusMask' , 0 ),
992+ ConditionalField (FlagsField ('DTCStatusMask' , 0 , 8 , dtcStatusMask ),
965993 lambda pkt : pkt .reportType in [
966994 0x01 , 0x02 , 0x07 , 0x08 , 0x0f , 0x11 , 0x12 , 0x13 ]),
967995 ConditionalField (ByteField ('DTCHighByte' , 0 ),
@@ -983,16 +1011,47 @@ class UDS_RDTCI(Packet):
9831011bind_layers (UDS , UDS_RDTCI , service = 0x19 )
9841012
9851013
1014+ class DTC (Packet ):
1015+ name = 'Diagnostic Trouble Code'
1016+ fields_desc = [
1017+ BitEnumField ("system" , 0 , 2 , {
1018+ 0 : "Powertrain" ,
1019+ 1 : "Chassis" ,
1020+ 2 : "Body" ,
1021+ 3 : "Network" }),
1022+ BitEnumField ("type" , 0 , 2 , {
1023+ 0 : "Generic" ,
1024+ 1 : "ManufacturerSpecific" ,
1025+ 2 : "Generic" ,
1026+ 3 : "Generic" }),
1027+ BitField ("numeric_value_code" , 0 , 12 ),
1028+ ByteField ("additional_information_code" , 0 ),
1029+ ]
1030+
1031+ def extract_padding (self , s ):
1032+ return '' , s
1033+
1034+
1035+ class DTC_Status (Packet ):
1036+ name = 'DTC and status record'
1037+ fields_desc = [
1038+ PacketField ("dtc" , None , pkt_cls = DTC ),
1039+ FlagsField ("status" , 0 , 8 , UDS_RDTCI .dtcStatus )
1040+ ]
1041+
1042+ def extract_padding (self , s ):
1043+ return '' , s
1044+
1045+
9861046class UDS_RDTCIPR (Packet ):
9871047 name = 'ReadDTCInformationPositiveResponse'
9881048 fields_desc = [
9891049 ByteEnumField ('reportType' , 0 , UDS_RDTCI .reportTypes ),
990- ConditionalField (XByteField ('DTCStatusAvailabilityMask' , 0 ),
991- lambda pkt : pkt .reportType in [0x01 , 0x07 , 0x11 ,
992- 0x12 , 0x02 , 0x0A ,
993- 0x0B , 0x0C , 0x0D ,
994- 0x0E , 0x0F , 0x13 ,
995- 0x15 ]),
1050+ ConditionalField (
1051+ FlagsField ('DTCStatusAvailabilityMask' , 0 , 8 , UDS_RDTCI .dtcStatus ),
1052+ lambda pkt : pkt .reportType in [0x01 , 0x07 , 0x11 , 0x12 , 0x02 , 0x0A ,
1053+ 0x0B , 0x0C , 0x0D , 0x0E , 0x0F , 0x13 ,
1054+ 0x15 ]),
9961055 ConditionalField (ByteEnumField ('DTCFormatIdentifier' , 0 ,
9971056 {0 : 'ISO15031-6DTCFormat' ,
9981057 1 : 'UDS-1DTCFormat' ,
@@ -1003,7 +1062,8 @@ class UDS_RDTCIPR(Packet):
10031062 ConditionalField (ShortField ('DTCCount' , 0 ),
10041063 lambda pkt : pkt .reportType in [0x01 , 0x07 ,
10051064 0x11 , 0x12 ]),
1006- ConditionalField (StrField ('DTCAndStatusRecord' , b"" ),
1065+ ConditionalField (PacketListField ('DTCAndStatusRecord' , None ,
1066+ pkt_cls = DTC_Status ),
10071067 lambda pkt : pkt .reportType in [0x02 , 0x0A , 0x0B ,
10081068 0x0C , 0x0D , 0x0E ,
10091069 0x0F , 0x13 , 0x15 ]),
@@ -1259,24 +1319,24 @@ def _contains_data_format_identifier(packet):
12591319 fmt = 'B' ),
12601320 lambda p : p .modeOfOperation != 2 ),
12611321 ConditionalField (StrLenField ('maxNumberOfBlockLength' , b"" ,
1262- length_from = lambda p : p .lengthFormatIdentifier ),
1322+ length_from = lambda p : p .lengthFormatIdentifier ),
12631323 lambda p : p .modeOfOperation != 2 ),
12641324 ConditionalField (BitField ('compressionMethod' , 0 , 4 ),
12651325 lambda p : p .modeOfOperation != 0x02 ),
12661326 ConditionalField (BitField ('encryptingMethod' , 0 , 4 ),
12671327 lambda p : p .modeOfOperation != 0x02 ),
12681328 ConditionalField (FieldLenField ('fileSizeOrDirInfoParameterLength' ,
1269- None ,
1270- length_of = 'fileSizeUncompressedOrDirInfoLength' ),
1329+ None ,
1330+ length_of = 'fileSizeUncompressedOrDirInfoLength' ),
12711331 lambda p : p .modeOfOperation not in [1 , 2 , 3 ]),
12721332 ConditionalField (StrLenField ('fileSizeUncompressedOrDirInfoLength' ,
12731333 b"" ,
12741334 length_from = lambda p :
12751335 p .fileSizeOrDirInfoParameterLength ),
12761336 lambda p : p .modeOfOperation not in [1 , 2 , 3 ]),
12771337 ConditionalField (StrLenField ('fileSizeCompressed' , b"" ,
1278- length_from = lambda p :
1279- p .fileSizeOrDirInfoParameterLength ),
1338+ length_from = lambda p :
1339+ p .fileSizeOrDirInfoParameterLength ),
12801340 lambda p : p .modeOfOperation not in [1 , 2 , 3 , 5 ]),
12811341 ]
12821342
0 commit comments