+ usec = usec + (uint64_t)(frequency_clock_t::frequency_to_period(adr->get_frequency_clock().get_frequency())*MICRO);
+ DEBUG(binder_interface, "send_request: Event loop state: %d. usec: %ld", sd_event_get_state(afb_daemon_get_event_loop(binder_interface->daemon)), usec);
+ if(sd_event_source_set_time(s, usec) >= 0)
+ if(sd_event_source_set_enabled(s, SD_EVENT_ON) >= 0)
+ return 0;
+ sd_event_source_unref(s);
+ return -1;
+}
+
+/// @brief Systemd timer event callback use to send CAN messages at regular interval. Depending
+/// on the diagnostic message frequency.
+///
+/// This should be called from systemd binder event loop and the event is created on add_recurring_request
+///
+/// @param[in] s - Systemd event source pointer used to reschedule the new iteration.
+/// @param[in] usec - previous call timestamp in microseconds.
+/// @param[in] userdata - the DiagnosticRequest struct, use to retrieve the active request from the list.
+///
+/// @return positive integer if sent and rescheduled or negative value if something wrong. If an error occurs
+/// event will be disabled.
+int diagnostic_manager_t::send_request(sd_event_source *s, uint64_t usec, void *userdata)
+{
+ diagnostic_manager_t& dm = configuration_t::instance().get_diagnostic_manager();
+ DiagnosticRequest* request = (DiagnosticRequest*)userdata;
+ active_diagnostic_request_t* adr = dm.find_recurring_request(request);
+
+ if(adr != nullptr && adr->get_can_bus_dev() == dm.get_can_bus_dev() && adr->should_send() &&
+ dm.clear_to_send(adr))
+ {
+ adr->get_frequency_clock().tick();
+ start_diagnostic_request(&dm.shims_, adr->get_handle());
+ if(adr->get_handle()->completed && !adr->get_handle()->success)
+ {
+ ERROR(binder_interface, "send_request: Fatal error sending diagnostic request");
+ sd_event_source_unref(s);
+ return -1;
+ }
+
+ adr->get_timeout_clock().tick();
+ adr->set_in_flight(true);
+ }
+
+ if(adr->get_recurring())
+ {
+ return dm.reschedule_request(s, usec, adr);
+ }
+
+ sd_event_source_unref(s);
+ ERROR(binder_interface, "send_request: Something goes wrong when submitting a new request to the CAN bus");
+ return -2;
+}
+
+/// @brief Will decode the diagnostic response and build the final openxc_VehicleMessage to return.
+///
+/// @param[in] adr - A pointer to an active diagnostic request holding a valid diagnostic handle
+/// @param[in] response - The response to decode from which the Vehicle message will be built and returned
+///
+/// @return A filled openxc_VehicleMessage or a zeroed struct if there is an error.
+openxc_VehicleMessage diagnostic_manager_t::relay_diagnostic_response(active_diagnostic_request_t* adr, const DiagnosticResponse& response)
+{
+ openxc_VehicleMessage message = build_VehicleMessage();