4 #include <isotp/isotp.h>
12 #define MAX_OBD2_PAYLOAD_LENGTH 7
16 uint16_t arbitration_id;
20 uint8_t payload[MAX_OBD2_PAYLOAD_LENGTH];
21 uint8_t payload_length;
24 // TODO I don't like this, it's hard coding isotp library stuff here
25 typedef bool (*SendIsoTpMessageShim)(IsoTpHandler* handler,
26 const uint8_t* payload, uint16_t payload_size);
29 // http://www.canbushack.com/blog/index.php?title=scanning-for-diagnostic-data&more=1&c=1&tb=1&pb=1
30 // for the list of NRCs
33 NRC_SERVICE_NOT_SUPPORTED = 0x11,
34 NRC_SUB_FUNCTION_NOT_SUPPORTED = 0x12,
35 NRC_CONDITIONS_NOT_CORRECT = 0x22,
36 NRC_REQUEST_OUT_OF_RANGE = 0x31,
37 NRC_SECURITY_ACCESS_DENIED = 0x33,
38 NRC_INVALID_KEY = 0x35,
39 NRC_TOO_MANY_ATTEMPS = 0x36,
40 NRC_TIME_DELAY_NOT_EXPIRED = 0x37,
41 NRC_RESPONSE_PENDING = 0x78
42 } DiagnosticNegativeResponseCode;
45 OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST = 0x1,
46 OBD2_MODE_POWERTRAIN_FREEZE_FRAME_REQUEST = 0x2,
47 OBD2_MODE_EMISSIONS_DTC_REQUEST = 0x3,
48 OBD2_MODE_EMISSIONS_DTC_CLEAR = 0x4,
49 // 0x5 is for non-CAN only
50 // OBD2_MODE_OXYGEN_SENSOR_TEST = 0x5,
51 OBD2_MODE_TEST_RESULTS = 0x6,
52 OBD2_MODE_DRIVE_CYCLE_DTC_REQUEST = 0x7,
53 OBD2_MODE_CONTROL = 0x8,
54 OBD2_MODE_VEHICLE_INFORMATION = 0x9,
55 OBD2_MODE_PERMANENT_DTC_REQUEST = 0xa,
56 // this one isn't technically in OBD2, but both of the enhanced standards
57 // have their PID requests at 0x22
58 OBD2_MODE_ENHANCED_DIAGNOSTIC_REQUEST = 0x22
65 } DiagnosticTroubleCodeType;
68 uint16_t arbitration_id;
71 // if mode is one with a PID, read the correct numbers of PID bytes (1 or 2)
72 // into this field, then store the remainder of the payload in the payload
75 DiagnosticNegativeResponseCode negative_response_code;
76 // if response mode is a negative response, read first byte of payload into
77 // NRC and store remainder of payload in payload field
78 uint8_t payload[MAX_OBD2_PAYLOAD_LENGTH];
79 uint8_t payload_length;
87 } DiagnosticTroubleCodeGroup;
90 DiagnosticTroubleCodeGroup group;
93 } DiagnosticTroubleCode;
95 typedef void (*DiagnosticResponseReceived)(const DiagnosticResponse* response);
96 typedef void (*DiagnosticMilStatusReceived)(bool malfunction_indicator_status);
97 typedef void (*DiagnosticVinReceived)(uint8_t vin[]);
98 typedef void (*DiagnosticTroubleCodesReceived)(
99 DiagnosticMode mode, DiagnosticTroubleCode* codes);
100 typedef void (*DiagnosticPidEnumerationReceived)(
101 const DiagnosticResponse* response, uint16_t* pids);
103 // TODO should we enumerate every OBD-II PID? need conversion formulas, too
106 uint8_t bytes_returned;
109 } DiagnosticParameter;
112 DIAGNOSTIC_REQUEST_TYPE_PID,
113 DIAGNOSTIC_REQUEST_TYPE_DTC,
114 DIAGNOSTIC_REQUEST_TYPE_MIL_STATUS,
115 DIAGNOSTIC_REQUEST_TYPE_VIN
116 } DiagnosticRequestType;
119 IsoTpHandler isotp_handler;
120 // TODO the Handle may need to keep the original request, otherwise we can't
121 // compare an incoming CAN message to see if it matches the service / PID!
122 // TODO i'm not sure this type/callback in here is too useful - see the
123 // comments in obd2.c:diagnostic_request
125 DiagnosticRequestType type;
126 DiagnosticResponseReceived callback;
127 DiagnosticMilStatusReceived mil_status_callback;
128 DiagnosticVinReceived vin_callback;
130 } DiagnosticRequestHandle;
133 DIAGNOSTIC_STANDARD_PID,
134 DIAGNOSTIC_ENHANCED_PID
135 } DiagnosticPidRequestType;
138 SetTimerShim set_timer;
139 SendCanMessageShim send_can_message;
143 DiagnosticShims diagnostic_init_shims(LogShim log,
144 SendCanMessageShim send_can_message,
145 SetTimerShim set_timer);
147 DiagnosticRequestHandle diagnostic_request(DiagnosticShims* shims,
148 DiagnosticRequest* request, DiagnosticResponseReceived callback);
150 // decide mode 0x1 / 0x22 based on pid type
151 DiagnosticRequestHandle diagnostic_request_pid(DiagnosticShims* shims,
152 DiagnosticPidRequestType pid_request_type, uint16_t pid,
153 DiagnosticResponseReceived callback);
155 DiagnosticRequestHandle diagnostic_request_malfunction_indicator_status(
156 DiagnosticShims* shims,
157 DiagnosticMilStatusReceived callback);
159 DiagnosticRequestHandle diagnostic_request_vin(DiagnosticShims* shims,
160 DiagnosticVinReceived callback);
162 DiagnosticRequestHandle diagnostic_request_dtc(DiagnosticShims* shims,
163 DiagnosticTroubleCodeType dtc_type,
164 DiagnosticTroubleCodesReceived callback);
166 bool diagnostic_clear_dtc(DiagnosticShims* shims);
168 DiagnosticRequestHandle diagnostic_enumerate_pids(DiagnosticShims* shims,
169 DiagnosticRequest* request, DiagnosticPidEnumerationReceived callback);
172 // void diagnostic_receive_isotp_message(DiagnosticRequestHandle* handle,
173 // const IsoTpMessage* message);
174 void diagnostic_receive_isotp_message(const IsoTpMessage* message);
176 void diagnostic_receive_can_frame(DiagnosticRequestHandle* handle,
177 const uint16_t arbitration_id, const uint8_t data[],