1""" 2Controller Area Network, ISO 11898-1, see https://en.wikipedia.org/wiki/CAN_bus 3SocketCAN message format handling 4 5API examples: 6https://github.com/rhyttr/SocketCAN/tree/3c46872d9af0885b42526b70853400c6d94b7c54/can-utils 7""" 8import logging 9import sys 10 11from pypacker import pypacker 12 13logger = logging.getLogger("pypacker") 14 15module_this = sys.modules[__name__] 16 17 18""" 19OBDII modes: 20 2101 Show current data 2202 Show freeze frame data 2303 Show stored Diagnostic Trouble Codes 2404 Clear Diagnostic Trouble Codes and stored values 2505 Test results, oxygen sensor monitoring (non CAN only) 2606 Test results, other component/system monitoring 2707 Show pending Diagnostic Trouble Codes (detected during current or last driving cycle) 2808 Control operation of on-board component/system 2909 Request vehicle information 300A Permanent Diagnostic Trouble Codes (DTCs) (Cleared DTCs) 31""" 32 33 34OBD2_MODE_01_PIDS = { 35 0x00 : "PIDS_SUPPORTED_1_20", 36 0x01 : "MONITOR_STATUS", 37 0x02 : "FREEZE_DTC", 38 0x03 : "FUEL_SYSTEM_STATUS", 39 0x04 : "CALCULATED_ENGINE_LOAD", 40 0x05 : "ENGINE_COOLANT_TEMP", 41 0x06 : "SHORT_TERM_FUEL_BANK1", 42 0x07 : "LONG_TERM_FUEL_BANK1", 43 0x08 : "SHORT_TERM_FUEL_BANK2", 44 0x09 : "LONG_TERM_FUEK_BANK2", 45 0x0A : "FUELPRESSURE", 46 0x0B : "INTAKE_MANIFOLD_PRESSURE", 47 0x0C : "ENGINE_RPM", 48 0x0D : "VEHICLE_SPEED", 49 0x0E : "TIMING_ADVANCE", 50 0x0F : "INTAKGE_AIR_TEMP", 51 0x10 : "MAF_AIR_FLOW", 52 0x11 : "THROTTLE_POS", 53 0x12 : "COMMANDED_SECONDARY_AIR_STATUS", 54 0x13 : "OXYGEN_SENSORS_PRESENT", 55 0x14 : "OXYGEN_SENSOR1", 56 0x15 : "OXYGEN_SENSOR2", 57 0x16 : "OXYGEN_SENSOR3", 58 0x17 : "OXYGEN_SENSOR4", 59 0x18 : "OXYGEN_SENSOR5", 60 0x19 : "OXYGEN_SENSOR6", 61 0x1A : "OXYGEN_SENSOR7", 62 0x1B : "OXYGEN_SENSOR8", 63 0x1C : "OBD_STANDARDS_", 64 0x1D : "OXYGEN_SENSORS", 65 0x1E : "AUXILIARY_INPUT_STATUS", 66 0x1F : "RUNTIME_SINCE_ENGINE", 67 0x20 : "PIDS_SUPPORTED_21_40", 68 0x21 : "DISTANCE_TRAVELED_WITH_MALFUNCTION", 69 0x22 : "FUEL_RAIL_PRESSURE", 70 0x23 : "FUEL_RAIL_GAUGE_PRESSURE", 71 0x24 : "OXYGEN_SENSOR1", 72 0x25 : "OXYGEN_SENSOR2", 73 0x26 : "OXYGEN_SENSOR3", 74 0x27 : "OXYGEN_SENSOR4", 75 0x28 : "OXYGEN_SENSOR5", 76 0x29 : "OXYGEN_SENSOR6", 77 0x2A : "OXYGEN_SENSOR7", 78 0x2B : "OXYGEN_SENSOR8", 79 0x2C : "COMMANDED_EGR", 80 0x2D : "EGR_ERROR", 81 0x2E : "COMMANDED_EVAPORATIVE_PURGE", 82 0x2F : "FUEL_TANK_LEVEL_INPUT", 83 0x30 : "WARMUPS_SINCE_CODES_CLEARED", 84 0x31 : "DISTANCE_TRAVELED_SINCE_CODES_CLEARED", 85 0x32 : "EVAP_SYSTEM_VAPOR_PRESSURE", 86 0x33 : "ABSOLUTE_BAROMETIC_PRESSURE", 87 0x34 : "OXYGEN_SENSOR1_FUELAIR", 88 0x35 : "OXYGEN_SENSOR2_FUELAIR", 89 0x36 : "OXYGEN_SENSOR3_FUELAIR", 90 0x37 : "OXYGEN_SENSOR4_FUELAIR", 91 0x38 : "OXYGEN_SENSOR5_FUELAIR", 92 0x39 : "OXYGEN_SENSOR6_FUELAIR", 93 0x3A : "OXYGEN_SENSOR7_FUELAIR", 94 0x3B : "OXYGEN_SENSOR8_FUELAIR", 95 0x3C : "CATALYST_TEMP_B1S1", 96 0x3D : "CATALYST_TEMP_B2S1", 97 0x3E : "CATALYST_TEMP_B1S2", 98 0x3F : "CATALYST_TEMP_B2S2", 99 0x40 : "PIDS_SUPPORTED_41_60", 100 0x41 : "MONITOR_STATUS_", 101 0x42 : "CTRL_MODULE_VOLTAGE", 102 0x43 : "ABS_LOAD_VALUE", 103 0x44 : "FUEL_AIR_COMMANDED", 104 0x45 : "RELATIVE_THROTTLE_POS", 105 0x46 : "AMBIENT_AIR_TEMP", 106 0x47 : "ABSOLUTE_THROTTLE_POS_B", 107 0x48 : "ABSOLUTE_THROTTLE_POS_C", 108 0x49 : "ABSOLUTE_THROTTLE_POS_D", 109 0x4A : "ABSOLUTE_THROTTLE_POS_E", 110 0x4B : "ABSOLUTE_THROTTLE_POS_F", 111 0x4C : "COMMANDED_THROTTLE_ACTUATOR", 112 0x4D : "TIME_RUN_WITH_MIL", 113 0x4E : "TIME_SINCE_TROUBLE_CODES_CLEARED", 114 0x4F : "MAX_FUEL_AIR_EQ_RATIO", 115 0x50 : "MAX_AIR_FLOW", 116 0x51 : "FUEL_TYPE", 117 0x52 : "ETHANOL_FUEL", 118 0x53 : "ABS_EVAP_SYSTEM_VAPOR_PRESSURE", 119 0x54 : "EVAP_SYSTEM_VAPOR_PRESSURE", 120 0x55 : "SHORT_TERM_SECONDARY_OXYGEN_1_3", 121 0x56 : "LONG_TERM_SECONDARY_OXYGEN_1_3", 122 0x57 : "SHORT_TERM_SECONDARY_OXYGEN_2_4", 123 0x58 : "LONG_TERM_SECONDARY_OXYGEN_2_4", 124 0x59 : "FUEL_RAIL_ABS_PRESSURE", 125 0x5A : "RELATIVE_ACCELERATOR", 126 0x5B : "HYBRID_BATTERY_PACK", 127 0x5C : "ENGINE_OIL_TEMP", 128 0x5D : "FUEL_INJECTION_TIMING", 129 0x5E : "ENGINE_FUEL_RATE", 130 0x5F : "EMISSION_REQUIREMENTS", 131 0x60 : "PIDS_SUPPORTED_61_80", 132 0x61 : "DEMAND_ENGINE", 133 0x62 : "ACTUAL_ENGINE", 134 0x63 : "ENGINE_REF_TORQUE", 135 0x64 : "ENGINE_PERCENT_TORQUE", 136 0x65 : "AUXILIARY_INPUT", 137 0x66 : "MASS_AIR_FLOW_SENSOR", 138 0x67 : "ENGINE_COOLANT_TEMP", 139 0x68 : "INTAKE_AIR_TEMP_SENSOR", 140 0x69 : "COMMANDED_EGR_ERROR", 141 0x6A : "COMMANDED_DIESEL_INTAKE", 142 0x6B : "EXHAUST_GAS_RECIRCULATION", 143 0x6C : "COMMANDED_THROTTLE_ACTUATOR", 144 0x6D : "FUEL_PRESSURE_CONTROL_SYSTEM", 145 0x6E : "INJECTION_PRESSURE_CONTROL_SYSTEM", 146 0x6F : "TURBOCHARGER_COMPRESSOR", 147 0x70 : "BOOST_PRESSURE", 148 0x71 : "VARIABLE_GEOMETRY", 149 0x72 : "WASTEGATE_CONTROL", 150 0x73 : "EXHAUST_PRESSURE", 151 0x74 : "TURBOCHARGER_RPM", 152 0x75 : "TURBOCHARGER_TEMP", 153 0x76 : "TURBOCHARGER_TEMP", 154 0x77 : "CHARGER_AIR_COOLER_TEMP", 155 0x78 : "EXHAUST_GAS_TEMP", 156 0x79 : "EXHAUST_GAS_TEMP", 157 0x7A : "DIESEL_PARTICULATE_FILTER", 158 0x7B : "DIESEL_PARTICULATE_FILTER", 159 0x7C : "DIESEL_PARTICULATE_FILTER_TEMP", 160 0x7D : "NOX_CTRL_AREA", 161 0x7E : "PM_NTE_CTLR_AREA", 162 0x7F : "ENGINE_RUN_TIME", 163 0x80 : "PIDS_SUPPORTED_81_A0", 164 0x81 : "ENGINE_RUNTIME_AUXILIARY", 165 0x82 : "ENGINE_RUNTIME_AUXILIARY", 166 0x83 : "NOX_SENSOR", 167 0x84 : "MANIFOLD_SURFACE_TEMP", 168 0x85 : "NOX_REAGENT_SYSTEM", 169 0x86 : "PARTICULATE_MATTER_SENSOR", 170 0x87 : "INTAKE_MANIFOLD_PRESSURE", 171 0xA0 : "PIDS_SUPPORTED_A1_C0", 172 0xC0 : "PIDS_SUPPORTED_C1_E0", 173 0xC3 : "?", 174 0xC4 : "?" 175} 176 177OBD2_MODE_02_PIDS = { 178 0x02 : "DTC_FREEZE_STORED", 179} 180 181OBD2_MODE_05_PIDS = { 182 0x0100 : "OBD_MONITOR_IDS", 183 0x0101 : "O2_SENSOR_1_1", 184 0x0102 : "O2_SENSOR_1_2", 185 0x0103 : "O2_SENSOR_1_3", 186 0x0104 : "O2_SENSOR_1_4", 187 0x0105 : "O2_SENSOR_2_1", 188 0x0106 : "O2_SENSOR_2_2", 189 0x0107 : "O2_SENSOR_2_3", 190 0x0108 : "O2_SENSOR_2_4", 191 0x0109 : "O2_SENSOR_3_1", 192 0x010A : "O2_SENSOR_3_2", 193 0x010B : "O2_SENSOR_3_3", 194 0x010C : "O2_SENSOR_3_4", 195 0x010D : "O2_SENSOR_4_1", 196 0x010E : "O2_SENSOR_4_2", 197 0x010F : "O2_SENSOR_4_3", 198 0x0110 : "O2_SENSOR_4_4", 199 0x0201 : "O2_SENSOR_1_1", 200 0x0202 : "O2_SENSOR_1_2", 201 0x0203 : "O2_SENSOR_1_3", 202 0x0204 : "O2_SENSOR_1_4", 203 0x0205 : "O2_SENSOR_2_1", 204 0x0206 : "O2_SENSOR_2_2", 205 0x0207 : "O2_SENSOR_2_3", 206 0x0208 : "O2_SENSOR_2_4", 207 0x0209 : "O2_SENSOR_3_1", 208 0x020A : "O2_SENSOR_3_2", 209 0x020B : "O2_SENSOR_3_3", 210 0x020C : "O2_SENSOR_3_4", 211 0x020D : "O2_SENSOR_4_1", 212 0x020E : "O2_SENSOR_4_2", 213 0x020F : "O2_SENSOR_4_3", 214 0x0210 : "O2_SENSOR_4_4" 215} 216 217OBD2_MODE_0A_PIDS = { 218 0x00 : "MODE_9_SUPPORTED_PIDS_1_20", 219 0x01 : "VIN_MESSAGE_COUNT", 220 0x02 : "VIN", 221 0x03 : "CALIBRATION_ID_MESSAGE_COUNT", 222 0x04 : "CALLIBRATION_ID", 223 0x05 : "CVN_MESSAGE_COUNT", 224 0x06 : "CVN", 225 0x07 : "PERFORMANCE_TRACKING_MESSAGE_COUNT", 226 0x08 : "PERFORMANCE_TRACKING", 227 0x09 : "ECU_NAME_MESSAGE_COUNT", 228 0x0A : "ECU_NAME", 229 0x0B : "PERFORMANCE_TRACKING_COMPRESSION" 230} 231 232OBD2_MODE_DESCR = { 233 0x01 : "OBD2_MODE_SHOW_CURRENT_DATA1", 234 0x02 : "OBD2_MODE_SHOW_CURRENT_DATA2", 235 0x03 : "OBD2_MODE_SHOW_STORED_TROUBLECODES", 236 0x04 : "OBD2_MODE_CLEAR_DIAGNOSTIC_TROUBLECODES", 237 0x05 : "OBD2_MODE_TEST_RESULTS_OXYGEN", 238 0x06 : "OBD2_MODE_TEST_RESULTS_OTHER", 239 0x07 : "OBD2_MODE_SHOW_PENDING_DIAGNOSTIC_TROUBLECODES", 240 0x08 : "OBD2_MODE_CONTROL_OPERATION", 241 0x09 : "OBD2_MODE_REQUEST_VEHICLE_INFO", 242 0x0A : "OBD2_MODE_PERMANENT_DIAGNOSTIC_TROUBLECODES" 243} 244 245for obdid, name in OBD2_MODE_DESCR.items(): 246 setattr(module_this, name, obdid) 247 248# Diagnostic and Communications Management 249UDS_SID_DESCR = { 250 0x10 : "UDS_SID_DIAGNOSTIC_SESSION_CONTORL", 251 0x11 : "UDS_SID_ECU_RESET", 252 0x12 : "UDS_SID_GMLAN_READ_FAILURE_RECORD", 253 0x14 : "UDS_SID_CLEAR_DIAGNOSTIC_INFORMATION", 254 0x19 : "UDS_SID_READ_DTC_INFORMATION", 255 0x1A : "UDS_SID_GMLAN_READ_DIAGNOSTIC_ID", 256 0x20 : "UDS_SID_RETURN_TO_NORMAL", 257 0x22 : "UDS_SID_READ_DATA_BY_ID", 258 0x23 : "UDS_SID_READ_MEMORY_BY_ADDRESS", 259 0x24 : "UDS_SID_READ_SCALING_DATA_BY_ID", 260 0x27 : "UDS_SID_SECURITY_ACCESS", 261 0x28 : "UDS_SID_COMMUNICATION_CONTROL", 262 0x2A : "UDS_SID_READ_DATA_BY_PERIODIC_ID", 263 0x2C : "UDS_SID_DYNAMICALLY_DEFINE_DATA_ID", 264 0x2D : "UDS_SID_DEFINE_PID_BY_MEMORY_ADDRESS", 265 0x2E : "UDS_SID_WRITE_DATA_BY_ID", 266 0x2F : "UDS_SID_IO_CONTORL_BY_ID", 267 0x31 : "UDS_SID_ROUTINE_CONTROL", 268 0x34 : "UDS_SID_REQUEST_DOWNLOAD", 269 0x35 : "UDS_SID_REQUEST_UPLOAD", 270 0x36 : "UDS_SID_TRANSFER_DATA", 271 0x37 : "UDS_SID_REQUEST_TANSFER_EXIT", 272 0x38 : "UDS_SID_REQUEST_FILE_TRANSFER", 273 0x3B : "UDS_SID_GMLAN_WRITE_DID", 274 0x3D : "UDS_SID_WRITE_MEMORY_BY_ADDRESS", 275 0x3E : "UDS_SID_TESTER_PRESENT", 276 0x83 : "UDS_SID_ACCESS_TIMING_PARAMETER", 277 0x84 : "UDS_SID_SECURED_TRANSMISSION", 278 0x85 : "UDS_SID_CONTORL_DTC_SETTING", 279 0x86 : "UDS_SID_RESPONSE_ON_EVENT", 280 0x87 : "UDS_SID_LINK_CONTORL", 281 0xA2 : "UDS_SID_GMLAN_REPORT_PROGRAMMING_STATE", 282 0xA5 : "UDS_SID_GMLAN_ENTER_PROGRAMMING_MODE", 283 0xA9 : "UDS_SID_GMLAN_CHECK_CODES", 284 0xAA : "UDS_SID_GMLAN_READ_DPID", 285 0xAE : "UDS_SID_GMLAN_DEVICE_CONTROL", 286} 287 288for udsid, name in UDS_SID_DESCR.items(): 289 setattr(module_this, name, udsid) 290 291# UDS = 0x7F [SID_requested] [NRC] 292UDS_NRC_DESCR = { 293 0x10 : "UDS_NRC_GENERAL_REJECT", 294 0x11 : "UDS_NRC_SERVICE_NOT_SUPPORTED", 295 0x12 : "UDS_NRC_SUBFUNCTION_NOT_SUPPORTED", 296 0x13 : "UDS_NRC_INCORRECT_MESSAGE_LENGTH_OR_FORMAT", 297 0x14 : "UDS_NRC_RESPONSE_TOO_BIG", 298 0x21 : "UDS_NRC_BUSY_REPEAT_REQUEST", 299 0x22 : "UDS_NRC_CONDITION_NOT_CORRECT", 300 0x24 : "UDS_NRC_REQUEST_SEQUENCE_ERROR", 301 0x25 : "UDS_NRC_NONRESPONSE_FROM_SUBNET_COMPONENT", 302 0x26 : "UDS_NRC_FAILURE_PREVENTS_EXEC_OR_ACTION", 303 0x31 : "UDS_NRC_REQUEST_OUT_OF_RANGE", 304 0x33 : "UDS_NRC_SECURITY_ACCESS_DENIED", 305 0x35 : "UDS_NRC_INVALID_KEY", 306 0x36 : "UDS_NRC_EXCEEDED_NUMBER_OF_ATTEMPTS", 307 0x37 : "UDS_NRC_REQUIRED_TIME_DELEAY_NOT_EXPIRED", 308 0x70 : "UDS_NRC_UPLOAD_DOWNLOAD_NOT_ACCEPTED", 309 0x71 : "UDS_NRC_TRANSFER_DATA_SUSPENDED", 310 0x72 : "UDS_NRC_GENERAL_PROGRAMMING_FAILURE", 311 0x73 : "UDS_NRC_WRONG_BLOCK_SEQUENCE_COUNTER", 312 0x78 : "UDS_NRC_REQUEST_CORRECTLY_RESPONSE_PENDING", 313 0x7E : "UDS_NRC_SUBFUNCTION_NOT_SUPPORTED_IN_SESSION", 314 0x7F : "UDS_NRC_SERVICE_NOT_SUPPORTED_IN_SESSION" 315} 316 317for x in range(0x38, 0x4F): 318 UDS_NRC_DESCR[x] = "UDS_NRC_RESERVED_%X" % x 319 320for udsid, name in UDS_NRC_DESCR.items(): 321 setattr(module_this, name, udsid) 322 323 324class OBD2(pypacker.Packet): 325 __hdr__ = ( 326 ("mode", "B", 0), 327 ("pid", "B", 0) 328 ) 329 330 331class UDS(pypacker.Packet): 332 __hdr__ = ( 333 ("sid", "B", 0), 334 ("lev", "B", 0) 335 ) 336 337 def _dissect(self, buf): 338 # TODO: lev not always present 339 return 2 340 341 342ISOTP_TYPE_SF = 0x00 # single frame 343ISOTP_TYPE_FF = 0x01 # first frame 344ISOTP_TYPE_CF = 0x02 # consecutive frame 345ISOTP_TYPE_FC = 0x03 # flow control 346 347 348types_isotp_offset_upper = { 349 ISOTP_TYPE_SF: 1, 350 ISOTP_TYPE_FF: 2, 351 ISOTP_TYPE_CF: 1, 352 ISOTP_TYPE_FC: 3 353} 354 355types_isotp_offset_upper_got_type = {ISOTP_TYPE_SF, ISOTP_TYPE_FF} 356 357 358class ISOTPBase(pypacker.Packet): 359 def __get_sig(self): 360 return (self.pci & 0xF0) >> 4 361 362 def __set_sig(self, value): 363 self.pci = (value & 0xF) << 4 | (self.pci & 0xF) 364 365 sig = property(__get_sig, __set_sig) 366 367 def _dissect(self, buf): 368 #logger.debug("dissect in base class") 369 # OBD/UDS can one be differentiated in ISOTP_TYPE_SF and ISOTP_TYPE_FF 370 sig = buf[0] >> 4 371 #logger.debug("bytes in ISOTP: %r" % buf) 372 #logger.debug("ISOTP type: %X, offset: %d" % (sig, types_isotp_offset_upper[sig])) 373 #logger.debug("upper bytes: %r" % buf[types_isotp_offset_upper[sig]: ]) 374 375 # check by request/response SID, on both OBD2 and UDS response will be SID+0x40 376 if sig in types_isotp_offset_upper_got_type or (sig - 0x40) in types_isotp_offset_upper_got_type: 377 obd_mode = buf[types_isotp_offset_upper[sig]] 378 379 if obd_mode in OBD2_MODE_DESCR: 380 # assume OBD2 381 #logger.debug("got OBD2") 382 self._init_handler(0, buf[types_isotp_offset_upper[sig]:]) 383 else: 384 # assume UDS 385 #logger.debug("got UDS, will use bytes: %r" % buf[types_isotp_offset_upper[sig]: ]) 386 self._init_handler(1, buf[types_isotp_offset_upper[sig]:]) 387 388 return types_isotp_offset_upper[sig] 389 390 391class ISOTPSingleFrame(ISOTPBase): 392 __hdr__ = ( 393 ("pci", "B", ISOTP_TYPE_SF), 394 ) 395 396 def __get_dl(self): 397 return self.pci & 0xF 398 399 def __set_dl(self, value): 400 self.pci = (self.pci & 0xF0) | (value & 0xF) 401 402 dl = property(__get_dl, __set_dl) 403 404 __handler__ = { 405 0: OBD2, 1: UDS 406 } 407 408 409class ISOTPFirstFrame(ISOTPBase): 410 __hdr__ = ( 411 ("pci", "H", ISOTP_TYPE_FF), 412 ) 413 414 __handler__ = { 415 0: OBD2, 1: UDS 416 } 417 418 def __get_sig(self): 419 return (self.pci & 0xF000) >> 12 420 421 def __set_sig(self, value): 422 self.pci = (value & 0xF) << 12 | (self.pci & 0xFFF) 423 424 sig = property(__get_sig, __set_sig) 425 426 def __get_dl(self): 427 return self.pci & 0xFFF 428 429 def __set_dl(self, value): 430 self.pci = (self.pci & 0xF000) | (value & 0xFFF) 431 432 dl = property(__get_dl, __set_dl) 433 434 435class ISOTPConsecutiveFrame(ISOTPBase): 436 __hdr__ = ( 437 ("pci", "B", ISOTP_TYPE_CF), 438 ) 439 440 __handler__ = { 441 0: OBD2, 1: UDS 442 } 443 444 def __get_sn(self): 445 return self.pci & 0xF 446 447 def __set_sn(self, value): 448 self.pci = (self.pci & 0xF0) | (value & 0xF) 449 450 sn = property(__get_sn, __set_sn) 451 452 453class ISOTPFlowControl(ISOTPBase): 454 __hdr__ = ( 455 ("pci", "B", ISOTP_TYPE_FC), 456 ("pci_blocksize", "B", 0), 457 ("pci_minsep", "B", 0), 458 ) 459 460 __handler__ = { 461 0: OBD2, 1: UDS 462 } 463 464 def __get_flowstatus(self): 465 return self.pci & 0xF 466 467 def __set_flowstatus(self, value): 468 self.pci = (self.pci & 0xF0) | (value & 0xF) 469 470 flowstatus = property(__get_flowstatus, __set_flowstatus) 471 472 473isotp_type_class = { 474 ISOTP_TYPE_SF: ISOTPSingleFrame, 475 ISOTP_TYPE_FF: ISOTPFirstFrame, 476 ISOTP_TYPE_CF: ISOTPConsecutiveFrame, 477 ISOTP_TYPE_FC: ISOTPFlowControl 478} 479 480# CAN flags, little endian..wtf? 481CAN_MASK_EXT = 0x80000000 482CAN_MASK_EXT_SHIFT = 31 483CAN_MASK_RTR = 0x40000000 484CAN_MASK_RTR_SHIFT = 30 485CAN_MASK_ERR = 0x20000000 486CAN_MASK_ERR_SHIFT = 29 487# big endian 488MASK_ID = 0x1FFFFFFF 489MASK_FLAGS = ~MASK_ID 490 491 492ISOTP_PKT_CLZES = {ISOTPConsecutiveFrame, ISOTPFirstFrame, ISOTPFlowControl, ISOTPSingleFrame} 493 494 495class CAN(pypacker.Packet): 496 """ 497 Format: 498 499 The field containing the CAN ID and flags is in network byte order (big-endian). 500 The bottom 29 bits contain the CAN ID of the frame. The remaining bits are: 501 502 0x20000000 - set if the frame is an error message rather than a data frame. 503 0x40000000 - set if the frame is a remote transmission request frame. 504 0x80000000 - set if the frame is an extended 29-bit frame rather than a standard 11-bit frame. frame. 505 Source: http://www.tcpdump.org/linktypes/LINKTYPE_CAN_SOCKETCAN.html 506 507 508 SocketCan Packet, see https://www.kernel.org/doc/Documentation/networking/can.txt 509 510 struct can_frame { 511 canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */ 512 __u8 can_dlc; /* frame payload length in byte (0 .. 8) */ 513 __u8 __pad; /* padding */ 514 __u8 __res0; /* reserved / padding */ 515 __u8 __res1; /* reserved / padding */ 516 __u8 data[8] __attribute__((aligned(8))); 517 }; 518 special address description flags for the CAN_ID 519 CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */ 520 CAN_RTR_FLAG 0x40000000U /* remote transmission request */ 521 CAN_ERR_FLAG 0x20000000U /* error message frame */ 522 523 Native CAN structure (on wire): 524 525 CAN lengths (11-bit ID): 526 - Arbitration Field (12) 527 -- ID: unique id/prio (11) 528 -- Remote transmission request: 0/dominant for data, 1 for remote request (1) 529 - Control (6) 530 -- ID ext.: 0 for 11-bit ID (1) 531 -- Reserved: must be 0 (1) 532 -- Data length code: Number of bytes, 0 up to 8 (4) 533 - Data: 0 up to 8 bytes (8) 534 535 CAN lengths (29-bit ID): 536 - Arbitration Field (40) 537 -- ID: unique id/prio (11) 538 -- Substitute remote request, must be 1 (1) 539 -- Identifier extension bit: must be 1 (1) 540 -- ID: unique id/prio (18) 541 -- Remote transmission request: 0/dominant for data, 1 for remote request (1) 542 - Control (6) 543 -- Reserved: must be 0 (2) 544 -- Data length code: Number of bytes, 0 up to 8 (4) 545 - Data: 0 up to 8 bytes (8) 546 547 """ 548 __hdr__ = ( 549 ("flag_id", "I", 0), 550 ("dlc", "B", 0), 551 ("pad", "B", 0), 552 ("res1", "B", 0), 553 ("res2", "B", 0) 554 ) 555 556 __handler__ = { 557 ISOTP_TYPE_SF: ISOTPSingleFrame, 558 ISOTP_TYPE_FF: ISOTPFirstFrame, 559 ISOTP_TYPE_CF: ISOTPConsecutiveFrame, 560 ISOTP_TYPE_FC: ISOTPFlowControl 561 } 562 563 def __get_extended(self): 564 return 0 if (self.flag_id & CAN_MASK_EXT) == 0 else 1 565 566 def __set_extended(self, value): 567 self.flag_id = (self.flag_id & ~CAN_MASK_EXT) | ((value & 1) << CAN_MASK_EXT_SHIFT) 568 569 extended = property(__get_extended, __set_extended) 570 571 def __get_rtr(self): 572 return 0 if (self.flag_id & CAN_MASK_RTR) == 0 else 1 573 574 def __set_rtr(self, value): 575 self.flag_id = (self.flag_id & ~CAN_MASK_RTR) | ((value & 1) << CAN_MASK_RTR_SHIFT) 576 577 rtr = property(__get_rtr, __set_rtr) 578 579 def __get_err(self): 580 return 0 if (self.flag_id & CAN_MASK_ERR) == 0 else 1 581 582 def __set_err(self, value): 583 self.flag_id = (self.flag_id & ~CAN_MASK_ERR) | ((value & 1) << CAN_MASK_ERR_SHIFT) 584 585 err = property(__get_err, __set_err) 586 587 def __get_id(self): 588 return self.flag_id & MASK_ID 589 590 def __set_id(self, value): 591 flags_be = self.flag_id & MASK_FLAGS 592 self.flag_id = flags_be | (value & MASK_ID) 593 594 id = property(__get_id, __set_id) 595 596 def _dissect(self, buf): 597 # assume ISO-TP 598 isotp_type = (buf[8] & 0xF0) >> 4 599 #logger.debug("got ISOTP type: %d, class will be: %r" % 600 #(isotp_type, isotp_type_class[isotp_type])) 601 self._init_handler(isotp_type, buf[8:]) 602 return 8 603 604 def _update_fields(self): 605 if not self._header_changed: 606 return 607 608 if self.id > 0x7FF: 609 self.extended = 1 610 else: 611 self.extended = 0 612 613 def show_packet(self, prefix=""): 614 if self.body_handler.__class__ not in ISOTP_PKT_CLZES: 615 logger.warning("not an isotp packet: %r", self.body_handler) 616 return 617 618 isotp_pkt = self.body_handler 619 output = [] 620 output.append("%s [ID: 0x%05X] " % (prefix, self.id)) 621 622 uds_pkt = self[UDS] 623 624 if uds_pkt is not None: 625 if uds_pkt.sid in UDS_SID_DESCR: 626 output.append("-> %s" % UDS_SID_DESCR.get(uds_pkt.sid)) 627 elif uds_pkt.sid - 0x40 in UDS_SID_DESCR: 628 output.append("<- %s" % UDS_SID_DESCR.get(uds_pkt.sid - 0x40)) 629 elif uds_pkt.sid == module_this.UDS_NRC_SERVICE_NOT_SUPPORTED_IN_SESSION: 630 output.append("Err: %s" % UDS_NRC_DESCR.get(uds_pkt.bin()[2], "0x%X" % uds_pkt.bin()[2])) 631 else: 632 output.append("<unknown: %s>" % uds_pkt.sid) 633 output.append(", content: %r" % uds_pkt.bin()) 634 else: 635 output.append(" %r, content: %s" % (isotp_pkt.__class__.__name__, isotp_pkt.body_bytes)) 636 637 print("%s" % "".join(output)) 638