+DiagnosticResponse diagnostic_receive_can_frame(DiagnosticShims* shims,
+ DiagnosticRequestHandle* handle, const uint16_t arbitration_id,
+ const uint8_t data[], const uint8_t size) {
+
+ DiagnosticResponse response = {
+ arbitration_id: arbitration_id,
+ success: false,
+ completed: false
+ };
+
+ if(!handle->isotp_send_handle.completed) {
+ isotp_continue_send(&handle->isotp_shims,
+ &handle->isotp_send_handle, arbitration_id, data, size);
+ } else {
+ uint8_t i;
+ for(i = 0; i < handle->isotp_receive_handle_count; ++i) {
+ IsoTpMessage message = isotp_continue_receive(&handle->isotp_shims,
+ &handle->isotp_receive_handles[i], arbitration_id, data, size);
+
+ // TODO as of now we're completing the handle as soon as one
+ // broadcast response is received....need to hang on for 100ms
+ 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 %d on arb ID 0x%x",
+ response.mode, response.arbitration_id);
+ handle->success = true;
+ handle->completed = true;
+ } else if(handle_positive_response(handle, &message, &response,
+ shims)) {
+ shims->log("Received a positive mode %d response on arb ID 0x%x",
+ response.mode, response.arbitration_id);
+ 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);
+ // TODO just leave handles open until the user decides
+ // to be done with it - keep a count of valid responses
+ // received.
+ }
+ } else {
+ shims->log("Received an empty response on arb ID 0x%x",
+ response.arbitration_id);
+ }
+
+ if(handle->completed && handle->callback != NULL) {
+ handle->callback(&response);
+ }
+ }
+ }
+ }
+ return response;