Optionally split up preparing a diag request and actually sending it.
authorChristopher Peplin <chris.peplin@rhubarbtech.com>
Wed, 26 Feb 2014 21:34:35 +0000 (16:34 -0500)
committerChristopher Peplin <chris.peplin@rhubarbtech.com>
Wed, 26 Feb 2014 21:34:35 +0000 (16:34 -0500)
src/uds/uds.c
src/uds/uds.h
tests/test_core.c

index 4e23744..7303677 100644 (file)
@@ -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,37 +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) {
-        char request_string[128] = {0};
-        diagnostic_request_to_string(request, request_string, sizeof(request_string));
-        shims->log("Sending diagnostic request: %s", request_string);
-    }
-
-    setup_receive_handle(&handle);
-
+    return handle;
     // TODO notes on multi frame:
     // TODO what are the timers for exactly?
     //
@@ -118,6 +131,13 @@ 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;
 }
 
@@ -217,11 +237,14 @@ DiagnosticResponse diagnostic_receive_can_frame(DiagnosticShims* shims,
                 if(message.size > 0) {
                     response.mode = message.payload[0];
                     if(handle_negative_response(&message, &response, shims) ||
-                            handle_positive_response(handle, &message, &response, shims)) {
+                            handle_positive_response(handle, &message,
+                                &response, shims)) {
                         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);
+                            diagnostic_response_to_string(&response,
+                                    response_string, sizeof(response_string));
+                            shims->log("Diagnostic response received: %s",
+                                    response_string);
                         }
 
                         handle->success = true;
index 0d40561..22ff36a 100644 (file)
@@ -26,8 +26,8 @@ DiagnosticShims diagnostic_init_shims(LogShim log,
         SendCanMessageShim send_can_message,
         SetTimerShim set_timer);
 
-/* Public: Initiate a diagnostic request and return a handle, ready to completly
- * send the request and process the response via
+/* Public: Generate a new diagnostic request, send the first CAN message frame
+ * and set up the handle required to process the response via
  * diagnostic_receive_can_frame(...).
  *
  * shims -  Low-level shims required to send CAN messages, etc.
@@ -38,11 +38,37 @@ DiagnosticShims diagnostic_init_shims(LogShim log,
  * Returns a handle to be used with diagnostic_receive_can_frame to complete
  * sending the request and receive the response. The 'completed' field in the
  * returned DiagnosticRequestHandle will be true when the message is completely
- * sent.
+ * sent. The first frame of the message will already be sent.
  */
 DiagnosticRequestHandle diagnostic_request(DiagnosticShims* shims,
         DiagnosticRequest* request, DiagnosticResponseReceived callback);
 
+/* Public: Generate the handle for a new diagnostic request, but do not send any
+ * data to CAN yet - you must call start_diagnostic_request(...) on the handle
+ * returned from this function actually kick off the request.
+ *
+ * shims -  Low-level shims required to send CAN messages, etc.
+ * request -
+ * callback - an optional function to be called when the response is receved
+ *      (use NULL if no callback is required).
+ *
+ * Returns a handle to be used with start_diagnostic_request and then
+ * diagnostic_receive_can_frame to complete sending the request and receive the
+ * response. The 'completed' field in the returned DiagnosticRequestHandle will
+ * be true when the message is completely sent.
+ */
+DiagnosticRequestHandle generate_diagnostic_request(DiagnosticShims* shims,
+        DiagnosticRequest* request, DiagnosticResponseReceived callback);
+
+/* Public: Send the first frame of the request to CAN for the handle, generated
+ * by generate_diagnostic_request.
+ *
+ * You can also call this method to re-do the request for a handle that has
+ * already completed.
+ */
+void start_diagnostic_request(DiagnosticShims* shims,
+                DiagnosticRequestHandle* handle);
+
 /* Public: Request a PID from the given arbitration ID, determining the mode
  * automatically based on the PID type.
  *
index 30d19f4..448c0cd 100644 (file)
@@ -4,6 +4,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 
+extern bool can_frame_was_sent;
 extern void setup();
 extern bool last_response_was_received;
 extern DiagnosticResponse last_response_received;
@@ -77,8 +78,8 @@ START_TEST (test_send_functional_request)
     for(uint16_t filter = OBD2_FUNCTIONAL_RESPONSE_START; filter <
             OBD2_FUNCTIONAL_RESPONSE_START + OBD2_FUNCTIONAL_RESPONSE_COUNT;
             filter++) {
-        DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS, &handle,
-                filter, can_data, sizeof(can_data));
+        DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS,
+                &handle, filter, can_data, sizeof(can_data));
         fail_unless(response.success);
         fail_unless(response.completed);
         fail_unless(handle.completed);
@@ -151,6 +152,7 @@ START_TEST (test_send_diag_request)
             response_received_handler);
 
     fail_if(handle.completed);
+    fail_unless(can_frame_was_sent);
     ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
     ck_assert_int_eq(last_can_payload_sent[1], request.mode);
     ck_assert_int_eq(last_can_payload_size, 2);
@@ -172,6 +174,57 @@ START_TEST (test_send_diag_request)
 }
 END_TEST
 
+START_TEST (test_generate_then_send_request)
+{
+    DiagnosticRequest request = {
+        arbitration_id: 0x100,
+        mode: OBD2_MODE_EMISSIONS_DTC_REQUEST,
+        no_frame_padding: true
+    };
+    DiagnosticRequestHandle handle = generate_diagnostic_request(&SHIMS,
+            &request, response_received_handler);
+
+    fail_if(handle.completed);
+    fail_if(can_frame_was_sent);
+
+    start_diagnostic_request(&SHIMS, &handle);
+    fail_unless(can_frame_was_sent);
+    ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
+    ck_assert_int_eq(last_can_payload_sent[1], request.mode);
+    ck_assert_int_eq(last_can_payload_size, 2);
+
+    fail_if(last_response_was_received);
+    const uint8_t can_data[] = {0x2, request.mode + 0x40, 0x23};
+    DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS, &handle,
+            request.arbitration_id + 0x8, can_data, sizeof(can_data));
+    fail_unless(response.success);
+    fail_unless(response.completed);
+    fail_unless(handle.completed);
+    ck_assert(last_response_received.success);
+    ck_assert_int_eq(last_response_received.arbitration_id,
+            request.arbitration_id + 0x8);
+    ck_assert_int_eq(last_response_received.mode, request.mode);
+        fail_if(last_response_received.has_pid);
+    ck_assert_int_eq(last_response_received.payload_length, 1);
+    ck_assert_int_eq(last_response_received.payload[0], can_data[2]);
+}
+END_TEST
+
+START_TEST (test_generate_diag_request)
+{
+    DiagnosticRequest request = {
+        arbitration_id: 0x100,
+        mode: OBD2_MODE_EMISSIONS_DTC_REQUEST,
+        no_frame_padding: true
+    };
+    DiagnosticRequestHandle handle = generate_diagnostic_request(&SHIMS,
+            &request, response_received_handler);
+
+    fail_if(handle.completed);
+    fail_if(can_frame_was_sent);
+}
+END_TEST
+
 START_TEST (test_autoset_pid_length)
 {
     uint16_t arb_id = OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST;
@@ -321,7 +374,8 @@ START_TEST (test_negative_response)
     };
     DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
             response_received_handler);
-    const uint8_t can_data[] = {0x3, 0x7f, request.mode, NRC_SERVICE_NOT_SUPPORTED};
+    const uint8_t can_data[] = {0x3, 0x7f, request.mode,
+        NRC_SERVICE_NOT_SUPPORTED};
     DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS, &handle,
             request.arbitration_id + 0x8, can_data, sizeof(can_data));
     fail_unless(response.completed);
@@ -333,7 +387,8 @@ START_TEST (test_negative_response)
             request.arbitration_id + 0x8);
     ck_assert_int_eq(last_response_received.mode, request.mode);
     ck_assert_int_eq(last_response_received.pid, 0);
-    ck_assert_int_eq(last_response_received.negative_response_code, NRC_SERVICE_NOT_SUPPORTED);
+    ck_assert_int_eq(last_response_received.negative_response_code,
+            NRC_SERVICE_NOT_SUPPORTED);
     ck_assert_int_eq(last_response_received.payload_length, 0);
 }
 END_TEST
@@ -346,8 +401,8 @@ START_TEST (test_payload_to_integer)
 
     fail_if(last_response_was_received);
     const uint8_t can_data[] = {0x4, 0x1 + 0x40, 0x2, 0x45, 0x12};
-    DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8,
-            can_data, sizeof(can_data));
+    DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS, &handle,
+            arb_id + 0x8, can_data, sizeof(can_data));
     ck_assert_int_eq(diagnostic_payload_to_integer(&response), 0x4512);
 }
 END_TEST
@@ -359,6 +414,8 @@ Suite* testSuite(void) {
     tcase_add_test(tc_core, test_sent_message_no_padding);
     tcase_add_test(tc_core, test_sent_message_is_padded);
     tcase_add_test(tc_core, test_sent_message_is_padded_by_default);
+    tcase_add_test(tc_core, test_generate_diag_request);
+    tcase_add_test(tc_core, test_generate_then_send_request);
     tcase_add_test(tc_core, test_send_diag_request);
     tcase_add_test(tc_core, test_send_functional_request);
     tcase_add_test(tc_core, test_send_diag_request_with_payload);