summaryrefslogtreecommitdiffstats
path: root/src/obd2/obd2.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/obd2/obd2.c')
-rw-r--r--src/obd2/obd2.c84
1 files changed, 74 insertions, 10 deletions
diff --git a/src/obd2/obd2.c b/src/obd2/obd2.c
index 7188af0d..d8ef190c 100644
--- a/src/obd2/obd2.c
+++ b/src/obd2/obd2.c
@@ -1,8 +1,12 @@
#include <obd2/obd2.h>
+#define MODE_RESPONSE_OFFSET 0x40
+#define NEGATIVE_RESPONSE_MODE 0x7f
#define MAX_DIAGNOSTIC_PAYLOAD_SIZE 6
#define MODE_BYTE_INDEX 0
#define PID_BYTE_INDEX 1
+#define NEGATIVE_RESPONSE_MODE_INDEX 1
+#define NEGATIVE_RESPONSE_NRC_INDEX 2
DiagnosticShims diagnostic_init_shims(LogShim log,
SendCanMessageShim send_can_message,
@@ -18,11 +22,13 @@ DiagnosticShims diagnostic_init_shims(LogShim log,
DiagnosticRequestHandle diagnostic_request(DiagnosticShims* shims,
DiagnosticRequest* request, DiagnosticResponseReceived callback) {
DiagnosticRequestHandle handle = {
- type: DIAGNOSTIC_REQUEST_TYPE_PID,
+ // TODO can we copy the request?
+ request: *request,
callback: callback,
success: false,
completed: false
};
+
uint8_t payload[MAX_DIAGNOSTIC_PAYLOAD_SIZE];
payload[MODE_BYTE_INDEX] = request->mode;
if(request->pid_length > 0) {
@@ -125,22 +131,80 @@ DiagnosticResponse diagnostic_receive_can_frame(DiagnosticShims* shims,
DiagnosticRequestHandle* handle,
const uint16_t arbitration_id, const uint8_t data[],
const uint8_t size) {
- if(!handle->isotp_send_handle.completed) {
- } else if(!handle->isotp_receive_handle.completed) {
- } else {
- shims->log("Handle is already completed");
- }
- // TODO determine which isotp handler to pass it to based on our state
- IsoTpMessage message = isotp_receive_can_frame(&handle->isotp_shims,
- &handle->isotp_send_handle, arbitration_id, data, size);
DiagnosticResponse response = {
+ arbitration_id: arbitration_id,
success: false,
completed: false
};
- if(message.completed) {
+ if(!handle->isotp_send_handle.completed) {
+ // TODO when completing a send, this returns...a Message? we have to
+ // check when the isotp_send_handle is completed, and if it is, start
+ isotp_receive_can_frame(&handle->isotp_shims,
+ &handle->isotp_send_handle, arbitration_id, data, size);
+ } else if(!handle->isotp_receive_handle.completed) {
+ IsoTpMessage message = isotp_receive_can_frame(&handle->isotp_shims,
+ &handle->isotp_receive_handle, arbitration_id, data, size);
+
+ if(message.completed) {
+ if(message.size > 0) {
+ response.mode = message.payload[0];
+ if(response.mode == NEGATIVE_RESPONSE_MODE) {
+ if(message.size > NEGATIVE_RESPONSE_MODE_INDEX) {
+ // TODO we're setting the mode to the originating
+ // request for the error, so the user can confirm - i
+ // think this is OK since we're storing the failure
+ // status elsewhere, but think about it.
+ response.mode = message.payload[NEGATIVE_RESPONSE_MODE_INDEX];
+ }
+
+ if(message.size > NEGATIVE_RESPONSE_NRC_INDEX) {
+ response.negative_response_code = message.payload[NEGATIVE_RESPONSE_NRC_INDEX];
+ }
+ response.success = false;
+ } else {
+ if(response.mode == handle->request.mode + MODE_RESPONSE_OFFSET) {
+ // hide the "response" version of the mode from the user
+ // if it matched
+ response.mode = handle->request.mode;
+ if(handle->request.pid_length > 0 && message.size > 1) {
+ copy_bytes_right_aligned(handle->request.pid, sizeof(handle->request.pid),
+ PID_BYTE_INDEX, handle->request.pid_length, response.pid,
+ sizeof(response.pid));
+ }
+
+ uint8_t payload_index = 1 + handle->request.pid_length;
+ response.payload_length = message.size - payload_index;
+ if(response.payload_length > 0) {
+ memcpy(response.payload, &message.payload[payload_index],
+ response.payload_length);
+ }
+ response.success = true;
+ } else {
+ shims->log("Response was for a mode %d request, not our mode %d request",
+ response.mode - MODE_RESPONSE_OFFSET,
+ handle->request.mode);
+ }
+ }
+ }
+
+ response.completed = true;
+ // TODO what does it mean for the handle to be successful, vs. the
+ // request to be successful? if we get a NRC, is that a successful
+ // request?
+ handle->success = true;
+ handle->completed = true;
+
+ if(handle->callback != NULL) {
+ handle->callback(&response);
+ }
+ }
+
+ } else {
+ shims->log("Handle is already completed");
}
+ return response;
}
// TODO everything below here is for future work...not critical for now.