class OBD_PID03(OBD_Packet): name = "PID_03_FuelSystemStatus" loopStates = { 0x00: 'OpenLoopInsufficientEngineTemperature', 0x02: 'ClosedLoop', 0x04: 'OpenLoopEngineLoadOrFuelCut', 0x08: 'OpenLoopDueSystemFailure', 0x10: 'ClosedLoopWithFault' } fields_desc = [ XByteEnumField('fuel_system1', 0, loopStates), XByteEnumField('fuel_system2', 0, loopStates) ]
class GMLAN_NR(Packet): negativeResponseCodes = { 0x11: 'ServiceNotSupported', 0x12: 'SubFunctionNotSupported', 0x22: 'ConditionsNotCorrectOrRequestSequenceError', 0x31: 'RequestOutOfRange', 0x35: 'InvalidKey', 0x36: 'ExceedNumberOfAttempts', 0x37: 'RequiredTimeDelayNotExpired', 0x78: 'RequestCorrectlyReceived-ResponsePending', 0x81: 'SchedulerFull', 0x83: 'VoltageOutOfRange', 0x85: 'GeneralProgrammingFailure', 0x89: 'DeviceTypeError', 0x99: 'ReadyForDownload-DTCStored', 0xe3: 'DeviceControlLimitsExceeded', } name = 'NegativeResponse' fields_desc = [ XByteEnumField('requestServiceId', 0, GMLAN.services), ByteEnumField('returnCode', 0, negativeResponseCodes), ShortField('deviceControlLimitExceeded', 0) ] @staticmethod def get_log(pkt): return pkt.sprintf("%GMLAN.service%"), \ (pkt.sprintf("%GMLAN_NR.requestServiceId%"), pkt.sprintf("%GMLAN_NR.returnCode%")) def answers(self, other): return self.requestServiceId == other.service and \ (self.returnCode != 0x78 or conf.contribs['GMLAN']['treat-response-pending-as-answer'])
class KWP_NR(Packet): negativeResponseCodes = { 0x00: 'positiveResponse', 0x10: 'generalReject', 0x11: 'serviceNotSupported', 0x12: 'subFunctionNotSupported-InvalidFormat', 0x21: 'busyRepeatRequest', 0x22: 'conditionsNotCorrect-RequestSequenceError', 0x23: 'routineNotComplete', 0x31: 'requestOutOfRange', 0x33: 'securityAccessDenied-SecurityAccessRequested', 0x35: 'invalidKey', 0x36: 'exceedNumberOfAttempts', 0x37: 'requiredTimeDelayNotExpired', 0x40: 'downloadNotAccepted', 0x50: 'uploadNotAccepted', 0x71: 'transferSuspended', 0x78: 'requestCorrectlyReceived-ResponsePending', 0x80: 'subFunctionNotSupportedInActiveDiagnosticSession', 0x9A: 'dataDecompressionFailed', 0x9B: 'dataDecryptionFailed', 0xA0: 'EcuNotResponding', 0xA1: 'EcuAddressUnknown' } name = 'NegativeResponse' fields_desc = [ XByteEnumField('requestServiceId', 0, KWP.services), ByteEnumField('negativeResponseCode', 0, negativeResponseCodes) ] def answers(self, other): # type: (Packet) -> int return self.requestServiceId == other.service and \ (self.negativeResponseCode != 0x78 or conf.contribs['KWP']['treat-response-pending-as-answer'])
class UDS_NR(Packet): negativeResponseCodes = { 0x00: 'positiveResponse', 0x10: 'generalReject', 0x11: 'serviceNotSupported', 0x12: 'subFunctionNotSupported', 0x13: 'incorrectMessageLengthOrInvalidFormat', 0x14: 'responseTooLong', 0x20: 'ISOSAEReserved', 0x21: 'busyRepeatRequest', 0x22: 'conditionsNotCorrect', 0x23: 'ISOSAEReserved', 0x24: 'requestSequenceError', 0x25: 'noResponseFromSubnetComponent', 0x26: 'failurePreventsExecutionOfRequestedAction', 0x31: 'requestOutOfRange', 0x33: 'securityAccessDenied', 0x35: 'invalidKey', 0x36: 'exceedNumberOfAttempts', 0x37: 'requiredTimeDelayNotExpired', 0x70: 'uploadDownloadNotAccepted', 0x71: 'transferDataSuspended', 0x72: 'generalProgrammingFailure', 0x73: 'wrongBlockSequenceCounter', 0x78: 'requestCorrectlyReceived-ResponsePending', 0x7E: 'subFunctionNotSupportedInActiveSession', 0x7F: 'serviceNotSupportedInActiveSession', 0x80: 'ISOSAEReserved', 0x81: 'rpmTooHigh', 0x82: 'rpmTooLow', 0x83: 'engineIsRunning', 0x84: 'engineIsNotRunning', 0x85: 'engineRunTimeTooLow', 0x86: 'temperatureTooHigh', 0x87: 'temperatureTooLow', 0x88: 'vehicleSpeedTooHigh', 0x89: 'vehicleSpeedTooLow', 0x8a: 'throttle/PedalTooHigh', 0x8b: 'throttle/PedalTooLow', 0x8c: 'transmissionRangeNotInNeutral', 0x8d: 'transmissionRangeNotInGear', 0x8e: 'ISOSAEReserved', 0x8f: 'brakeSwitch(es)NotClosed', 0x90: 'shifterLeverNotInPark', 0x91: 'torqueConverterClutchLocked', 0x92: 'voltageTooHigh', 0x93: 'voltageTooLow', } name = 'NegativeResponse' fields_desc = [ XByteEnumField('requestServiceId', 0, UDS.services), ByteEnumField('negativeResponseCode', 0, negativeResponseCodes) ] def answers(self, other): return self.requestServiceId == other.service and \ (self.negativeResponseCode != 0x78 or conf.contribs['UDS']['treat-response-pending-as-answer'])
class GMLAN_WDBIPR(Packet): name = 'WriteDataByIdentifierPositiveResponse' fields_desc = [ XByteEnumField('dataIdentifier', 0, GMLAN_RDBI.dataIdentifiers) ] def answers(self, other): return isinstance(other, GMLAN_WDBI) \ and other.dataIdentifier == self.dataIdentifier
class KWP_WDBLIPR(Packet): name = 'WriteDataByLocalIdentifierPositiveResponse' fields_desc = [ XByteEnumField('recordLocalIdentifier', 0, KWP_RDBLI.localIdentifiers) ] def answers(self, other): # type: (Packet) -> int return isinstance(other, KWP_WDBLI) \ and self.recordLocalIdentifier == other.recordLocalIdentifier
class MQTTSN(Packet): name = "MQTT-SN header" fields_desc = [ # Since the size of the len field depends on the next layer, we # need to "cheat" with the length_of parameter and use adjust # parameter to calculate the value. VariableFieldLenField("len", None, length_of="len", adjust=_mqttsn_len_adjust), XByteEnumField("type", 0, PACKET_TYPE), ]
class KWP_RECUIPR(Packet): name = 'ReadECUIdentificationPositiveResponse' fields_desc = [ XByteEnumField('localIdentifier', 0, KWP_RECUI.localIdentifiers) ] def answers(self, other): # type: (Packet) -> int return isinstance(other, KWP_RECUI) and \ self.localIdentifier == other.localIdentifier
class OBD_PID12(OBD_Packet): name = "PID_12_CommandedSecondaryAirStatus" states = { 0x00: 'upstream', 0x02: 'downstreamCatalyticConverter', 0x04: 'outsideAtmosphereOrOff', 0x08: 'pumpCommanded' } fields_desc = [XByteEnumField('data', 0, states)]
class GMLAN_WDBI(Packet): name = 'WriteDataByIdentifier' fields_desc = [ XByteEnumField('dataIdentifier', 0, GMLAN_RDBI.dataIdentifiers), StrField("dataRecord", b'\x00') ] @staticmethod def get_log(pkt): return pkt.sprintf("%GMLAN.service%"), \ (pkt.sprintf("%GMLAN_WDBI.dataIdentifier%"), pkt.dataRecord)
class KWP_RRRBLIPR(Packet): name = 'RequestRoutineResultsByLocalIdentifierPositiveResponse' fields_desc = [ XByteEnumField('routineLocalIdentifier', 0, KWP_SRBLI.routineLocalIdentifiers) ] def answers(self, other): # type: (Packet) -> int return isinstance(other, KWP_RRRBLI) \ and other.routineLocalIdentifier == self.routineLocalIdentifier
class MTP3(Packet): name = "MTP3" fields_desc = [ XByteField("version", 1), XByteField("reserved", 1), XByteEnumField("class", 1, MessageClassEnum), XByteField("type", 1), XIntField("len", 1), PacketListField("parameters", [], TransferMessage, length_from=lambda pkt: pkt.len - 8) ]
class KWP_IOCBLIPR(Packet): name = 'InputOutputControlByLocalIdentifierPositiveResponse' fields_desc = [ XByteField('localIdentifier', 0), XByteEnumField('inputOutputControlParameter', 0, KWP_IOCBLI.inputOutputControlParameters), StrField('controlState', b"", fmt="B") ] def answers(self, other): # type: (Packet) -> int return isinstance(other, KWP_IOCBLI) \ and other.localIdentifier == self.localIdentifier
class UDS_RFT(Packet): name = 'RequestFileTransfer' modeOfOperations = { 0x00: "ISO/SAE Reserved", 0x01: "Add File", 0x02: "Delete File", 0x03: "Replace File", 0x04: "Read File", 0x05: "Read Directory" } @staticmethod def _contains_file_size(packet): return packet.modeOfOperation not in [2, 4, 5] fields_desc = [ XByteEnumField('modeOfOperation', 0, modeOfOperations), FieldLenField('filePathAndNameLength', 0, length_of='filePathAndName', fmt='H'), StrLenField('filePathAndName', b"", length_from=lambda p: p.filePathAndNameLength), ConditionalField(BitField('compressionMethod', 0, 4), lambda p: p.modeOfOperation not in [2, 5]), ConditionalField(BitField('encryptingMethod', 0, 4), lambda p: p.modeOfOperation not in [2, 5]), ConditionalField( FieldLenField('fileSizeParameterLength', 0, fmt="B", length_of='fileSizeUnCompressed'), lambda p: UDS_RFT._contains_file_size(p)), ConditionalField( StrLenField('fileSizeUnCompressed', b"", length_from=lambda p: p.fileSizeParameterLength), lambda p: UDS_RFT._contains_file_size(p)), ConditionalField( StrLenField('fileSizeCompressed', b"", length_from=lambda p: p.fileSizeParameterLength), lambda p: UDS_RFT._contains_file_size(p)) ] @staticmethod def get_log(pkt): return pkt.sprintf("%UDS.service%"),\ pkt.modeOfOperation
class GMLAN_WDBIPR(Packet): name = 'WriteDataByIdentifierPositiveResponse' fields_desc = [ XByteEnumField('dataIdentifier', 0, GMLAN_RDBI.dataIdentifiers) ] @staticmethod def get_log(pkt): return pkt.sprintf("%GMLAN.service%"), \ pkt.sprintf("%GMLAN_WDBIPR.dataIdentifier%") def answers(self, other): return other.__class__ == GMLAN_WDBI \ and other.dataIdentifier == self.dataIdentifier
class UDS_RFTPR(Packet): name = 'RequestFileTransferPositiveResponse' @staticmethod def _contains_data_format_identifier(packet): return packet.modeOfOperation != 0x02 fields_desc = [ XByteEnumField('modeOfOperation', 0, UDS_RFT.modeOfOperations), ConditionalField( FieldLenField('lengthFormatIdentifier', 0, length_of='maxNumberOfBlockLength', fmt='B'), lambda p: p.modeOfOperation != 2), ConditionalField( StrLenField('maxNumberOfBlockLength', b"", length_from=lambda p: p.lengthFormatIdentifier), lambda p: p.modeOfOperation != 2), ConditionalField(BitField('compressionMethod', 0, 4), lambda p: p.modeOfOperation != 0x02), ConditionalField(BitField('encryptingMethod', 0, 4), lambda p: p.modeOfOperation != 0x02), ConditionalField( FieldLenField('fileSizeOrDirInfoParameterLength', 0, length_of='fileSizeUncompressedOrDirInfoLength'), lambda p: p.modeOfOperation not in [1, 2, 3]), ConditionalField( StrLenField( 'fileSizeUncompressedOrDirInfoLength', b"", length_from=lambda p: p.fileSizeOrDirInfoParameterLength), lambda p: p.modeOfOperation not in [1, 2, 3]), ConditionalField( StrLenField( 'fileSizeCompressed', b"", length_from=lambda p: p.fileSizeOrDirInfoParameterLength), lambda p: p.modeOfOperation not in [1, 2, 3, 5]), ] def answers(self, other): return other.__class__ == UDS_RFT @staticmethod def get_log(pkt): return pkt.sprintf("%UDS.service%"),\ pkt.modeOfOperation
class GMLAN_RDBIPR(Packet): name = 'ReadDataByIdentifierPositiveResponse' fields_desc = [ XByteEnumField('dataIdentifier', 0, GMLAN_RDBI.dataIdentifiers), ] @staticmethod def get_log(pkt): return pkt.sprintf("%GMLAN.service%"), \ (pkt.sprintf("%GMLAN_RDBIPR.dataIdentifier%"), bytes(pkt[1].payload)) def answers(self, other): return other.__class__ == GMLAN_RDBI and \ other.dataIdentifier == self.dataIdentifier
class GMLAN_RDBPKTI(Packet): name = 'ReadDataByPacketIdentifier' subfunctions = { 0x00: "stopSending", 0x01: "sendOneResponse", 0x02: "scheduleAtSlowRate", 0x03: "scheduleAtMediumRate", 0x04: "scheduleAtFastRate" } fields_desc = [ XByteEnumField('subfunction', 0, subfunctions), ConditionalField(StrField('request_DPIDs', b''), lambda pkt: pkt.subfunction > 0x0) ]
class KWP_IOCBLI(Packet): name = 'InputOutputControlByLocalIdentifier' inputOutputControlParameters = { 0x00: "Return Control to ECU", 0x01: "Report Current State", 0x04: "Reset to Default", 0x05: "Freeze Current State", 0x07: "Short Term Adjustment", 0x08: "Long Term Adjustment" } fields_desc = [ XByteField('localIdentifier', 0), XByteEnumField('inputOutputControlParameter', 0, inputOutputControlParameters), StrField('controlState', b"", fmt="B") ]
class OBD_NR(Packet): name = "NegativeResponse" responses = { 0x10: 'generalReject', 0x11: 'serviceNotSupported', 0x12: 'subFunctionNotSupported-InvalidFormat', 0x21: 'busy-RepeatRequest', 0x22: 'conditionsNotCorrectOrRequestSequenceError', 0x78: 'requestCorrectlyReceived-ResponsePending' } fields_desc = [ XByteField('request_service_id', 0), XByteEnumField('response_code', 0, responses) ]
class OBD(ISOTP): services = { 0x01: 'CurrentPowertrainDiagnosticDataRequest', 0x02: 'PowertrainFreezeFrameDataRequest', 0x03: 'EmissionRelatedDiagnosticTroubleCodesRequest', 0x04: 'ClearResetDiagnosticTroubleCodesRequest', 0x05: 'OxygenSensorMonitoringTestResultsRequest', 0x06: 'OnBoardMonitoringTestResultsRequest', 0x07: 'PendingEmissionRelatedDiagnosticTroubleCodesRequest', 0x08: 'ControlOperationRequest', 0x09: 'VehicleInformationRequest', 0x0A: 'PermanentDiagnosticTroubleCodesRequest', 0x41: 'CurrentPowertrainDiagnosticDataResponse', 0x42: 'PowertrainFreezeFrameDataResponse', 0x43: 'EmissionRelatedDiagnosticTroubleCodesResponse', 0x44: 'ClearResetDiagnosticTroubleCodesResponse', 0x45: 'OxygenSensorMonitoringTestResultsResponse', 0x46: 'OnBoardMonitoringTestResultsResponse', 0x47: 'PendingEmissionRelatedDiagnosticTroubleCodesResponse', 0x48: 'ControlOperationResponse', 0x49: 'VehicleInformationResponse', 0x4A: 'PermanentDiagnosticTroubleCodesResponse', 0x7f: 'NegativeResponse' } name = "On-board diagnostics" fields_desc = [XByteEnumField('service', 0, services)] def hashret(self): if self.service == 0x7f: return struct.pack('B', self.request_service_id & ~0x40) return struct.pack('B', self.service & ~0x40) def answers(self, other): if other.__class__ != self.__class__: return False if self.service == 0x7f: return self.payload.answers(other) if self.service == (other.service + 0x40): if isinstance(self.payload, NoPayload) or \ isinstance(other.payload, NoPayload): return True else: return self.payload.answers(other.payload) return False
class KWP_SRBLI(Packet): routineLocalIdentifiers = ObservableDict({ 0xE0: "FlashEraseRoutine", 0xE1: "FlashCheckRoutine", 0xE2: "Tell-TaleRetentionStack", 0xE3: "RequestDTCsFromShadowErrorMemory", 0xE4: "RequestEnvironmentDataFromShadowErrorMemory", 0xE5: "RequestEventInformation", 0xE6: "RequestEventEnvironmentData", 0xE7: "RequestSoftwareModuleInformation", 0xE8: "ClearTell-TaleRetentionStack", 0xE9: "ClearEventInformation" }) name = 'StartRoutineByLocalIdentifier' fields_desc = [ XByteEnumField('routineLocalIdentifier', 0, routineLocalIdentifiers) ]
class KWP_RECUI(Packet): name = 'ReadECUIdentification' localIdentifiers = ObservableDict({ 0x86: "DCS ECU Identification", 0x87: "DCX / MMC ECU Identification", 0x88: "VIN (Original)", 0x89: "Diagnostic Variant Code", 0x90: "VIN (Current)", 0x96: "Calibration Identification", 0x97: "Calibration Verification Number", 0x9A: "ECU Code Fingerprint", 0x98: "ECU Data Fingerprint", 0x9C: "ECU Code Software Identification", 0x9D: "ECU Data Software Identification", 0x9E: "ECU Boot Software Identification", 0x9F: "ECU Boot Fingerprint" }) fields_desc = [XByteEnumField('localIdentifier', 0, localIdentifiers)]
class KWP_RDBLI(Packet): localIdentifiers = ObservableDict({ 0xE0: "Development Data", 0xE1: "ECU Serial Number", 0xE2: "DBCom Data", 0xE3: "Operating System Version", 0xE4: "Ecu Reprogramming Identification", 0xE5: "Vehicle Information", 0xE6: "Flash Info 1", 0xE7: "Flash Info 2", 0xE8: "System Diagnostic general parameter data", 0xE9: "System Diagnostic global parameter data", 0xEA: "Ecu Configuration", 0xEB: "Diagnostic Protocol Information" }) name = 'ReadDataByLocalIdentifier' fields_desc = [ XByteEnumField('recordLocalIdentifier', 0, localIdentifiers) ]
class OBD_PID1C(OBD_Packet): name = "PID_1C_ObdStandardsThisVehicleConformsTo" obdStandards = { 0x01: 'OBD-II as defined by the CARB', 0x02: 'OBD as defined by the EPA', 0x03: 'OBD and OBD-II', 0x04: 'OBD-I', 0x05: 'Not OBD compliant', 0x06: 'EOBD (Europe)', 0x07: 'EOBD and OBD-II', 0x08: 'EOBD and OBD', 0x09: 'EOBD, OBD and OBD II', 0x0A: 'JOBD (Japan)', 0x0B: 'JOBD and OBD II', 0x0C: 'JOBD and EOBD', 0x0D: 'JOBD, EOBD, and OBD II', 0x0E: 'Reserved', 0x0F: 'Reserved', 0x10: 'Reserved', 0x11: 'Engine Manufacturer Diagnostics (EMD)', 0x12: 'Engine Manufacturer Diagnostics Enhanced (EMD+)', 0x13: 'Heavy Duty On-Board Diagnostics (Child/Partial) (HD OBD-C)', 0x14: 'Heavy Duty On-Board Diagnostics (HD OBD)', 0x15: 'World Wide Harmonized OBD (WWH OBD)', 0x16: 'Reserved', 0x17: 'Heavy Duty Euro OBD Stage I without NOx control (HD EOBD-I)', 0x18: 'Heavy Duty Euro OBD Stage I with NOx control (HD EOBD-I N)', 0x19: 'Heavy Duty Euro OBD Stage II without NOx control (HD EOBD-II)', 0x1A: 'Heavy Duty Euro OBD Stage II with NOx control (HD EOBD-II N)', 0x1B: 'Reserved', 0x1C: 'Brazil OBD Phase 1 (OBDBr-1)', 0x1D: 'Brazil OBD Phase 2 (OBDBr-2)', 0x1E: 'Korean OBD (KOBD)', 0x1F: 'India OBD I (IOBD I)', 0x20: 'India OBD II (IOBD II)', 0x21: 'Heavy Duty Euro OBD Stage VI (HD EOBD-IV)', } fields_desc = [ XByteEnumField('data', 0, obdStandards) ]
class OBD(Packet): services = { 0x01: 'CurrentPowertrainDiagnosticDataRequest', 0x02: 'PowertrainFreezeFrameDataRequest', 0x03: 'EmissionRelatedDiagnosticTroubleCodesRequest', 0x04: 'ClearResetDiagnosticTroubleCodesRequest', 0x05: 'OxygenSensorMonitoringTestResultsRequest', 0x06: 'OnBoardMonitoringTestResultsRequest', 0x07: 'PendingEmissionRelatedDiagnosticTroubleCodesRequest', 0x08: 'ControlOperationRequest', 0x09: 'VehicleInformationRequest', 0x0A: 'PermanentDiagnosticTroubleCodesRequest', 0x41: 'CurrentPowertrainDiagnosticDataResponse', 0x42: 'PowertrainFreezeFrameDataResponse', 0x43: 'EmissionRelatedDiagnosticTroubleCodesResponse', 0x44: 'ClearResetDiagnosticTroubleCodesResponse', 0x45: 'OxygenSensorMonitoringTestResultsResponse', 0x46: 'OnBoardMonitoringTestResultsResponse', 0x47: 'PendingEmissionRelatedDiagnosticTroubleCodesResponse', 0x48: 'ControlOperationResponse', 0x49: 'VehicleInformationResponse', 0x4A: 'PermanentDiagnosticTroubleCodesResponse', 0x7f: 'NegativeResponse'} name = "On-board diagnostics" fields_desc = [ XByteEnumField('service', 0, services) ] def hashret(self): if self.service == 0x7f: return struct.pack('B', self.request_service_id) return struct.pack('B', self.service & ~0x40) def answers(self, other): """DEV: true if self is an answer from other""" if other.__class__ == self.__class__: return (other.service + 0x40) == self.service or \ (self.service == 0x7f and self.request_service_id == other.service) return False
class OBD_NR(Packet): name = "NegativeResponse" responses = { 0x10: 'generalReject', 0x11: 'serviceNotSupported', 0x12: 'subFunctionNotSupported-InvalidFormat', 0x21: 'busy-RepeatRequest', 0x22: 'conditionsNotCorrectOrRequestSequenceError', 0x78: 'requestCorrectlyReceived-ResponsePending' } fields_desc = [ XByteField('request_service_id', 0), XByteEnumField('response_code', 0, responses) ] def answers(self, other): return self.request_service_id == other.service and \ (self.response_code != 0x78 or conf.contribs['OBD']['treat-response-pending-as-answer'])
class GMLAN_RDBPKTI(Packet): name = 'ReadDataByPacketIdentifier' subfunctions = { 0x00: "stopSending", 0x01: "sendOneResponse", 0x02: "scheduleAtSlowRate", 0x03: "scheduleAtMediumRate", 0x04: "scheduleAtFastRate" } fields_desc = [ XByteEnumField('subfunction', 0, subfunctions), ConditionalField( FieldListField('request_DPIDs', [], XByteField("", 0)), lambda pkt: pkt.subfunction > 0x0) ] @staticmethod def get_log(pkt): return pkt.sprintf("%GMLAN.service%"), \ pkt.sprintf("%GMLAN_RDBPKTI.subfunction%")
class GMLAN_NR(Packet): negativeResponseCodes = { 0x11: 'ServiceNotSupported', 0x12: 'SubFunctionNotSupported', 0x22: 'ConditionsNotCorrectOrRequestSequenceError', 0x31: 'RequestOutOfRange', 0x35: 'InvalidKey', 0x36: 'ExceedNumberOfAttempts', 0x37: 'RequiredTimeDelayNotExpired', 0x78: 'RequestCorrectlyReceived-ResponsePending', 0x81: 'SchedulerFull', 0x83: 'VoltageOutOfRange', 0x85: 'GeneralProgrammingFailure', 0x89: 'DeviceTypeError', 0x99: 'ReadyForDownload-DTCStored', 0xe3: 'DeviceControlLimitsExceeded', } name = 'NegativeResponse' fields_desc = [ XByteEnumField('requestServiceId', 0, GMLAN.services), ByteEnumField('returnCode', 0, negativeResponseCodes), ShortField('deviceControlLimitExceeded', 0) ]
class UDS(Packet): services = ObservableDict({ 0x10: 'DiagnosticSessionControl', 0x11: 'ECUReset', 0x14: 'ClearDiagnosticInformation', 0x19: 'ReadDTCInformation', 0x22: 'ReadDataByIdentifier', 0x23: 'ReadMemoryByAddress', 0x24: 'ReadScalingDataByIdentifier', 0x27: 'SecurityAccess', 0x28: 'CommunicationControl', 0x2A: 'ReadDataPeriodicIdentifier', 0x2C: 'DynamicallyDefineDataIdentifier', 0x2E: 'WriteDataByIdentifier', 0x2F: 'InputOutputControlByIdentifier', 0x31: 'RoutineControl', 0x34: 'RequestDownload', 0x35: 'RequestUpload', 0x36: 'TransferData', 0x37: 'RequestTransferExit', 0x3D: 'WriteMemoryByAddress', 0x3E: 'TesterPresent', 0x50: 'DiagnosticSessionControlPositiveResponse', 0x51: 'ECUResetPositiveResponse', 0x54: 'ClearDiagnosticInformationPositiveResponse', 0x59: 'ReadDTCInformationPositiveResponse', 0x62: 'ReadDataByIdentifierPositiveResponse', 0x63: 'ReadMemoryByAddressPositiveResponse', 0x64: 'ReadScalingDataByIdentifierPositiveResponse', 0x67: 'SecurityAccessPositiveResponse', 0x68: 'CommunicationControlPositiveResponse', 0x6A: 'ReadDataPeriodicIdentifierPositiveResponse', 0x6C: 'DynamicallyDefineDataIdentifierPositiveResponse', 0x6E: 'WriteDataByIdentifierPositiveResponse', 0x6F: 'InputOutputControlByIdentifierPositiveResponse', 0x71: 'RoutineControlPositiveResponse', 0x74: 'RequestDownloadPositiveResponse', 0x75: 'RequestUploadPositiveResponse', 0x76: 'TransferDataPositiveResponse', 0x77: 'RequestTransferExitPositiveResponse', 0x7D: 'WriteMemoryByAddressPositiveResponse', 0x7E: 'TesterPresentPositiveResponse', 0x83: 'AccessTimingParameter', 0x84: 'SecuredDataTransmission', 0x85: 'ControlDTCSetting', 0x86: 'ResponseOnEvent', 0x87: 'LinkControl', 0xC3: 'AccessTimingParameterPositiveResponse', 0xC4: 'SecuredDataTransmissionPositiveResponse', 0xC5: 'ControlDTCSettingPositiveResponse', 0xC6: 'ResponseOnEventPositiveResponse', 0xC7: 'LinkControlPositiveResponse', 0x7f: 'NegativeResponse' }) name = 'UDS' fields_desc = [XByteEnumField('service', 0, services)] def answers(self, other): """DEV: true if self is an answer from other""" if other.__class__ == self.__class__: return (other.service + 0x40) == self.service or \ (self.service == 0x7f and self.requestServiceId == other.service and (self.negativeResponseCode != 0x78 or conf.contribs['UDS']['treat-response-pending-as-answer'])) return 0 def hashret(self): if self.service == 0x7f: return struct.pack('B', self.requestServiceId) return struct.pack('B', self.service & ~0x40)