Increase arb IDs to uint32_t to fit extended IDs.
[apps/low-level-can-service.git] / src / uds / uds.c
index 412f077..510cdd4 100644 (file)
@@ -32,7 +32,7 @@ DiagnosticShims diagnostic_init_shims(LogShim log,
 
 static void setup_receive_handle(DiagnosticRequestHandle* handle) {
     if(handle->request.arbitration_id == OBD2_FUNCTIONAL_BROADCAST_ID) {
-        uint16_t response_id;
+        uint32_t response_id;
         for(response_id = 0;
                 response_id < OBD2_FUNCTIONAL_RESPONSE_COUNT; ++response_id) {
             handle->isotp_receive_handles[response_id] = isotp_receive(
@@ -61,7 +61,45 @@ static uint16_t autoset_pid_length(uint8_t mode, uint16_t pid,
     return pid_length;
 }
 
-DiagnosticRequestHandle diagnostic_request(DiagnosticShims* shims,
+static void send_diagnostic_request(DiagnosticShims* shims,
+        DiagnosticRequestHandle* handle) {
+    uint8_t payload[MAX_DIAGNOSTIC_PAYLOAD_SIZE] = {0};
+    payload[MODE_BYTE_INDEX] = handle->request.mode;
+    if(handle->request.has_pid) {
+        handle->request.pid_length = autoset_pid_length(handle->request.mode,
+                handle->request.pid, handle->request.pid_length);
+        handle->request.pid_length = handle->request.pid_length;
+        set_bitfield(handle->request.pid, PID_BYTE_INDEX * CHAR_BIT,
+                handle->request.pid_length * CHAR_BIT, payload,
+                sizeof(payload));
+    }
+
+    if(handle->request.payload_length > 0) {
+        memcpy(&payload[PID_BYTE_INDEX + handle->request.pid_length],
+                handle->request.payload, handle->request.payload_length);
+    }
+
+    handle->isotp_send_handle = isotp_send(&handle->isotp_shims,
+            handle->request.arbitration_id, payload,
+            1 + handle->request.payload_length + handle->request.pid_length,
+            NULL);
+    if(shims->log != NULL) {
+        char request_string[128] = {0};
+        diagnostic_request_to_string(&handle->request, request_string,
+                sizeof(request_string));
+        shims->log("Sending diagnostic request: %s", request_string);
+    }
+}
+
+void start_diagnostic_request(DiagnosticShims* shims,
+        DiagnosticRequestHandle* handle) {
+    handle->success = false;
+    handle->completed = false;
+    send_diagnostic_request(shims, handle);
+    setup_receive_handle(handle);
+}
+
+DiagnosticRequestHandle generate_diagnostic_request(DiagnosticShims* shims,
         DiagnosticRequest* request, DiagnosticResponseReceived callback) {
     DiagnosticRequestHandle handle = {
         request: *request,
@@ -70,46 +108,12 @@ DiagnosticRequestHandle diagnostic_request(DiagnosticShims* shims,
         completed: false
     };
 
-    uint8_t payload[MAX_DIAGNOSTIC_PAYLOAD_SIZE] = {0};
-    payload[MODE_BYTE_INDEX] = request->mode;
-    if(request->has_pid) {
-        request->pid_length = autoset_pid_length(request->mode,
-                request->pid, request->pid_length);
-        handle.request.pid_length = request->pid_length;
-        set_bitfield(request->pid, PID_BYTE_INDEX * CHAR_BIT,
-                request->pid_length * CHAR_BIT, payload, sizeof(payload));
-    }
-    if(request->payload_length > 0) {
-        memcpy(&payload[PID_BYTE_INDEX + request->pid_length],
-                request->payload, request->payload_length);
-    }
-
     handle.isotp_shims = isotp_init_shims(shims->log,
             shims->send_can_message,
             shims->set_timer);
     handle.isotp_shims.frame_padding = !request->no_frame_padding;
 
-    handle.isotp_send_handle = isotp_send(&handle.isotp_shims,
-            request->arbitration_id, payload,
-            1 + request->payload_length + request->pid_length,
-            NULL);
-    if(shims->log != NULL) {
-        shims->log("Sending diagnostic request: arb_id: 0x%02x, mode: 0x%x, pid: 0x%x, payload: 0x%02x%02x%02x%02x%02x%02x%02x, size: %d\r\n",
-                request->arbitration_id,
-                request->mode,
-                request->pid,
-                request->payload[0],
-                request->payload[1],
-                request->payload[2],
-                request->payload[3],
-                request->payload[4],
-                request->payload[5],
-                request->payload[6],
-                request->payload_length);
-    }
-
-    setup_receive_handle(&handle);
-
+    return handle;
     // TODO notes on multi frame:
     // TODO what are the timers for exactly?
     //
@@ -127,11 +131,18 @@ DiagnosticRequestHandle diagnostic_request(DiagnosticShims* shims,
     // of the information but arg, memory allocation. look at how it's done in
     // the other library again
     //
+}
+
+DiagnosticRequestHandle diagnostic_request(DiagnosticShims* shims,
+        DiagnosticRequest* request, DiagnosticResponseReceived callback) {
+    DiagnosticRequestHandle handle = generate_diagnostic_request(
+            shims, request, callback);
+    start_diagnostic_request(shims, &handle);
     return handle;
 }
 
 DiagnosticRequestHandle diagnostic_request_pid(DiagnosticShims* shims,
-        DiagnosticPidRequestType pid_request_type, uint16_t arbitration_id,
+        DiagnosticPidRequestType pid_request_type, uint32_t arbitration_id,
         uint16_t pid, DiagnosticResponseReceived callback) {
     DiagnosticRequest request = {
         arbitration_id: arbitration_id,
@@ -184,17 +195,17 @@ static bool handle_positive_response(DiagnosticRequestHandle* handle,
 
         }
 
-        uint8_t payload_index = 1 + handle->request.pid_length;
-        response->payload_length = MAX(0, message->size - payload_index);
-        if(response->payload_length > 0) {
-            memcpy(response->payload, &message->payload[payload_index],
-                    response->payload_length);
-        }
-
         if((!handle->request.has_pid && !response->has_pid)
                 || response->pid == handle->request.pid) {
             response->success = true;
             response->completed = true;
+
+            uint8_t payload_index = 1 + handle->request.pid_length;
+            response->payload_length = MAX(0, message->size - payload_index);
+            if(response->payload_length > 0) {
+                memcpy(response->payload, &message->payload[payload_index],
+                        response->payload_length);
+            }
         } else {
             response_was_positive = false;
         }
@@ -203,7 +214,7 @@ static bool handle_positive_response(DiagnosticRequestHandle* handle,
 }
 
 DiagnosticResponse diagnostic_receive_can_frame(DiagnosticShims* shims,
-        DiagnosticRequestHandle* handle, const uint16_t arbitration_id,
+        DiagnosticRequestHandle* handle, const uint32_t arbitration_id,
         const uint8_t data[], const uint8_t size) {
 
     DiagnosticResponse response = {
@@ -225,26 +236,25 @@ DiagnosticResponse diagnostic_receive_can_frame(DiagnosticShims* shims,
             if(message.completed) {
                 if(message.size > 0) {
                     response.mode = message.payload[0];
-                    if(handle_negative_response(&message, &response, shims)) {
-                        shims->log("Received a negative response to mode 0x%x on arb ID 0x%x",
-                                response.mode, response.arbitration_id);
-                        handle->success = true;
-                        handle->completed = true;
-                    } else if(handle_positive_response(handle, &message,
+                    if(handle_negative_response(&message, &response, shims) ||
+                            handle_positive_response(handle, &message,
                                 &response, shims)) {
-                        shims->log("Received a positive mode 0x%x response on arb ID 0x%x",
-                                response.mode, response.arbitration_id);
+                        if(shims->log != NULL) {
+                            char response_string[128] = {0};
+                            diagnostic_response_to_string(&response,
+                                    response_string, sizeof(response_string));
+                            shims->log("Diagnostic response received: %s",
+                                    response_string);
+                        }
+
                         handle->success = true;
                         handle->completed = true;
-                    } else {
-                        shims->log("Response was for a mode 0x%x request (pid 0x%x), not our mode 0x%x request (pid 0x%x)",
-                                MAX(0, response.mode - MODE_RESPONSE_OFFSET),
-                                response.pid, handle->request.mode,
-                                handle->request.pid);
                     }
                 } else {
-                    shims->log("Received an empty response on arb ID 0x%x",
-                            response.arbitration_id);
+                    if(shims->log != NULL) {
+                        shims->log("Received an empty response on arb ID 0x%x",
+                                response.arbitration_id);
+                    }
                 }
 
                 if(handle->completed && handle->callback != NULL) {
@@ -263,8 +273,7 @@ int diagnostic_payload_to_integer(const DiagnosticResponse* response) {
             response->payload_length * CHAR_BIT);
 }
 
-float diagnostic_decode_obd2_pid(const DiagnosticResponse* response,
-        int parsed_payload) {
+float diagnostic_decode_obd2_pid(const DiagnosticResponse* response) {
     // handles on the single number values, not the bit encoded ones
     switch(response->pid) {
         case 0xa:
@@ -296,3 +305,79 @@ float diagnostic_decode_obd2_pid(const DiagnosticResponse* response,
             return 0;
     }
 }
+
+void diagnostic_response_to_string(const DiagnosticResponse* response,
+        char* destination, size_t destination_length) {
+    int bytes_used = snprintf(destination, destination_length,
+            "arb_id: 0x%02x, mode: 0x%x, ",
+            response->arbitration_id,
+            response->mode);
+
+    if(response->has_pid) {
+        bytes_used += snprintf(destination + bytes_used,
+                destination_length - bytes_used,
+                "pid: 0x%x, ",
+                response->pid);
+    }
+
+    if(!response->success) {
+        bytes_used += snprintf(destination + bytes_used,
+                destination_length - bytes_used,
+                "nrc: 0x%x, ",
+                response->negative_response_code);
+    }
+
+    if(response->payload_length > 0) {
+        snprintf(destination + bytes_used, destination_length - bytes_used,
+                "payload: 0x%02x%02x%02x%02x%02x%02x%02x",
+                response->payload[0],
+                response->payload[1],
+                response->payload[2],
+                response->payload[3],
+                response->payload[4],
+                response->payload[5],
+                response->payload[6]);
+    } else {
+        snprintf(destination + bytes_used, destination_length - bytes_used,
+                "no payload");
+    }
+}
+
+void diagnostic_request_to_string(const DiagnosticRequest* request,
+        char* destination, size_t destination_length) {
+    int bytes_used = snprintf(destination, destination_length,
+            "arb_id: 0x%02x, mode: 0x%x, ",
+            request->arbitration_id,
+            request->mode);
+
+    if(request->has_pid) {
+        bytes_used += snprintf(destination + bytes_used,
+                destination_length - bytes_used,
+                "pid: 0x%x, ",
+                request->pid);
+    }
+
+    int remaining_space = destination_length - bytes_used;
+    if(request->payload_length > 0) {
+        snprintf(destination + bytes_used, remaining_space,
+                "payload: 0x%02x%02x%02x%02x%02x%02x%02x",
+                request->payload[0],
+                request->payload[1],
+                request->payload[2],
+                request->payload[3],
+                request->payload[4],
+                request->payload[5],
+                request->payload[6]);
+    } else {
+        snprintf(destination + bytes_used, remaining_space, "no payload");
+    }
+}
+
+bool diagnostic_request_equals(const DiagnosticRequest* ours,
+        const DiagnosticRequest* theirs) {
+    bool equals = ours->arbitration_id == theirs->arbitration_id &&
+        ours->mode == theirs->mode;
+    equals &= ours->has_pid == theirs->has_pid;
+    equals &= ours->pid == theirs->pid;
+    return equals;
+}