X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=CAN-binder%2Flow-can-binding%2Fdiagnostic%2Fdiagnostic-manager.cpp;h=7dab7495bab403b4dcfa604e2d1db0f176c452c8;hb=4eb1cc0d69804337ac9e35dea6cc2e22c0fc76c6;hp=1a382af9944144bfbed7b18c9ca05af2132000f5;hpb=e4a50a3e96aa39346ad7212cae984524276973dd;p=apps%2Fagl-service-can-low-level.git diff --git a/CAN-binder/low-can-binding/diagnostic/diagnostic-manager.cpp b/CAN-binder/low-can-binding/diagnostic/diagnostic-manager.cpp index 1a382af9..7dab7495 100644 --- a/CAN-binder/low-can-binding/diagnostic/diagnostic-manager.cpp +++ b/CAN-binder/low-can-binding/diagnostic/diagnostic-manager.cpp @@ -23,7 +23,7 @@ #include "../utils/openxc-utils.hpp" #include "../utils/signals.hpp" -#include "../binding/configuration.hpp" +#include "../binding/application.hpp" #define MAX_RECURRING_DIAGNOSTIC_FREQUENCY_HZ 10 #define MAX_SIMULTANEOUS_DIAG_REQUESTS 50 @@ -46,10 +46,9 @@ diagnostic_manager_t::diagnostic_manager_t() bool diagnostic_manager_t::initialize() { // Mandatory to set the bus before intialize shims. - bus_ = configuration_t::instance().get_diagnostic_bus(); + bus_ = application_t::instance().get_diagnostic_bus(); init_diagnostic_shims(); - event_source_ = nullptr; reset(); initialized_ = true; @@ -57,11 +56,6 @@ bool diagnostic_manager_t::initialize() return initialized_; } -utils::socketcan_bcm_t& diagnostic_manager_t::get_socket() -{ - return socket_; -} - /// @brief initialize shims used by UDS lib and set initialized_ to true. /// It is needed before used the diagnostic manager fully because shims are /// required by most member functions. @@ -78,51 +72,6 @@ void diagnostic_manager_t::reset() cleanup_active_requests(true); } -/// @brief Adds 8 RX_SETUP jobs to the BCM rx_socket_ then diagnotic manager -/// listens on CAN ID range 7E8 - 7EF affected to the OBD2 communications. -/// -/// @return -1 or negative value on error, 0 if ok. -int diagnostic_manager_t::add_rx_filter(uint32_t can_id) -{ - // Make sure that socket has been opened. - if(! socket_) - socket_.open(bus_); - - struct utils::simple_bcm_msg bcm_msg; - memset(&bcm_msg.msg_head, 0, sizeof(bcm_msg.msg_head)); - - const struct timeval freq = recurring_requests_.back()->get_timeout_clock().get_timeval_from_period(); - - bcm_msg.msg_head.opcode = RX_SETUP; - bcm_msg.msg_head.flags = SETTIMER|RX_FILTER_ID; - bcm_msg.msg_head.ival2.tv_sec = freq.tv_sec; - bcm_msg.msg_head.ival2.tv_usec = freq.tv_usec; - - // If it isn't an OBD2 CAN ID then just add a simple RX_SETUP job - if(can_id != OBD2_FUNCTIONAL_BROADCAST_ID) - { - bcm_msg.msg_head.can_id = can_id; - - socket_ << bcm_msg; - if(! socket_) - return -1; - } - else - { - for(uint8_t i = 0; i < 8; i++) - { - can_id = OBD2_FUNCTIONAL_RESPONSE_START + i; - bcm_msg.msg_head.can_id = can_id; - - socket_ << bcm_msg; - if(! socket_) - return -1; - } - } - - return 0; -} - /// @brief send function use by diagnostic library. Only one bus used for now /// so diagnostic request is sent using the default diagnostic bus not matter of /// which is specified in the diagnostic message definition. @@ -135,14 +84,14 @@ int diagnostic_manager_t::add_rx_filter(uint32_t can_id) /// @return true if the CAN message was sent successfully. bool diagnostic_manager_t::shims_send(const uint32_t arbitration_id, const uint8_t* data, const uint8_t size) { - diagnostic_manager_t& dm = configuration_t::instance().get_diagnostic_manager(); + diagnostic_manager_t& dm = application_t::instance().get_diagnostic_manager(); active_diagnostic_request_t* current_adr = dm.get_last_recurring_requests(); utils::socketcan_bcm_t& tx_socket = current_adr->get_socket(); // Make sure that socket has been opened. if(! tx_socket) tx_socket.open( - dm.get_can_bus()); + dm.get_bus_device_name()); struct utils::simple_bcm_msg bcm_msg; struct can_frame cfd; @@ -185,17 +134,24 @@ void diagnostic_manager_t::shims_logger(const char* format, ...) vsnprintf(buffer, 256, format, args); DEBUG(binder_interface, "%s: %s", __FUNCTION__, buffer); + va_end(args); } /// @brief The type signature for a... OpenXC TODO: not used yet. void diagnostic_manager_t::shims_timer() {} -std::string diagnostic_manager_t::get_can_bus() +const std::string diagnostic_manager_t::get_bus_name() const { return bus_; } +const std::string diagnostic_manager_t::get_bus_device_name() const +{ + return application_t::instance().get_can_bus_manager() + .get_can_device_name(bus_); +} + active_diagnostic_request_t* diagnostic_manager_t::get_last_recurring_requests() const { return recurring_requests_.back(); @@ -207,6 +163,15 @@ DiagnosticShims& diagnostic_manager_t::get_shims() return shims_; } +bool diagnostic_manager_t::is_active_requests_running() +{ + if(non_recurring_requests_.empty() && recurring_requests_.empty()) + { + return true; + } + return false; +} + /// @brief Search for a specific active diagnostic request in the provided requests list /// and erase it from the vector. This is useful at unsubscription to clean up the list otherwize /// all received CAN messages will be passed to DiagnosticRequestHandle of all active diagnostic request @@ -225,6 +190,8 @@ void diagnostic_manager_t::find_and_erase(active_diagnostic_request_t* entry, st void diagnostic_manager_t::cancel_request(active_diagnostic_request_t* entry) { entry->get_socket().close(); + delete entry; + entry = nullptr; } /// @brief Cleanup a specific request if it isn't running and get complete. As it is almost @@ -235,22 +202,22 @@ void diagnostic_manager_t::cancel_request(active_diagnostic_request_t* entry) /// @param[in] force - Force the cleaning or not ? void diagnostic_manager_t::cleanup_request(active_diagnostic_request_t* entry, bool force) { - if((force || (entry != nullptr && entry->response_received()))) + if(entry != nullptr && (force || entry->response_received())) { char request_string[128] = {0}; diagnostic_request_to_string(&entry->get_handle()->request, request_string, sizeof(request_string)); if(force && entry->get_recurring()) { - find_and_erase(entry, recurring_requests_); cancel_request(entry); + find_and_erase(entry, recurring_requests_); DEBUG(binder_interface, "%s: Cancelling completed, recurring request: %s", __FUNCTION__, request_string); } - else + else if (!entry->get_recurring()) { DEBUG(binder_interface, "%s: Cancelling completed, non-recurring request: %s", __FUNCTION__, request_string); - find_and_erase(entry, non_recurring_requests_); cancel_request(entry); + find_and_erase(entry, non_recurring_requests_); } } } @@ -262,12 +229,16 @@ void diagnostic_manager_t::cleanup_request(active_diagnostic_request_t* entry, b void diagnostic_manager_t::cleanup_active_requests(bool force) { for(auto& entry : non_recurring_requests_) + { if (entry != nullptr) cleanup_request(entry, force); + } for(auto& entry : recurring_requests_) + { if (entry != nullptr) cleanup_request(entry, force); + } } /// @brief Will return the active_diagnostic_request_t pointer for theDiagnosticRequest or nullptr if @@ -275,17 +246,14 @@ void diagnostic_manager_t::cleanup_active_requests(bool force) /// /// @param[in] request - Search key, method will go through recurring list to see if it find that request /// holded by the DiagnosticHandle member. -active_diagnostic_request_t* diagnostic_manager_t::find_recurring_request(const DiagnosticRequest* request) +active_diagnostic_request_t* diagnostic_manager_t::find_recurring_request(DiagnosticRequest& request) { for (auto& entry : recurring_requests_) { if(entry != nullptr) { - if(diagnostic_request_equals(&entry->get_handle()->request, request)) - { - return entry; - break; - } + if(diagnostic_request_equals(&entry->get_handle()->request, &request)) + {return entry;} } } return nullptr; @@ -317,7 +285,7 @@ active_diagnostic_request_t* diagnostic_manager_t::find_recurring_request(const /// @return true if the request was added successfully. Returns false if there /// wasn't a free active request entry, if the frequency was too high or if the /// CAN acceptance filters could not be configured, -active_diagnostic_request_t* diagnostic_manager_t::add_request(DiagnosticRequest* request, const std::string name, +active_diagnostic_request_t* diagnostic_manager_t::add_request(DiagnosticRequest* request, const std::string& name, bool wait_for_multiple_responses, const DiagnosticResponseDecoder decoder, const DiagnosticResponseCallback callback) { @@ -329,7 +297,7 @@ active_diagnostic_request_t* diagnostic_manager_t::add_request(DiagnosticRequest { // TODO: implement Acceptance Filter // if(updateRequiredAcceptanceFilters(bus, request)) { - active_diagnostic_request_t* entry = new active_diagnostic_request_t(bus_, request, name, + active_diagnostic_request_t* entry = new active_diagnostic_request_t(bus_, request->arbitration_id, name, wait_for_multiple_responses, decoder, callback, 0); entry->set_handle(shims_, request); @@ -337,7 +305,8 @@ active_diagnostic_request_t* diagnostic_manager_t::add_request(DiagnosticRequest diagnostic_request_to_string(&entry->get_handle()->request, request_string, sizeof(request_string)); - find_and_erase(entry, non_recurring_requests_); + // Erase any existing request not already cleaned. + cleanup_request(entry, true); DEBUG(binder_interface, "%s: Added one-time diagnostic request on bus %s: %s", __FUNCTION__, bus_.c_str(), request_string); @@ -424,34 +393,16 @@ active_diagnostic_request_t* diagnostic_manager_t::add_recurring_request(Diagnos cleanup_active_requests(false); - if(find_recurring_request(request) == nullptr) + if(find_recurring_request(*request) == nullptr) { if(recurring_requests_.size() <= MAX_SIMULTANEOUS_DIAG_REQUESTS) { - // TODO: implement Acceptance Filter - //if(updateRequiredAcceptanceFilters(bus, request)) { - entry = new active_diagnostic_request_t(bus_, request, name, + entry = new active_diagnostic_request_t(bus_, request->arbitration_id, name, wait_for_multiple_responses, decoder, callback, frequencyHz); recurring_requests_.push_back(entry); entry->set_handle(shims_, request); - if(add_rx_filter(OBD2_FUNCTIONAL_BROADCAST_ID) < 0) - { recurring_requests_.pop_back(); } - else - { - start_diagnostic_request(&shims_, entry->get_handle()); - if(event_source_ == nullptr && sd_event_add_io(afb_daemon_get_event_loop(binder_interface->daemon), - &event_source_, - socket_.socket(), - EPOLLIN, - read_message, - nullptr) < 0) - { - cleanup_request(entry, true); - WARNING(binder_interface, "%s: signal: %s isn't supported. Canceling operation.", __FUNCTION__, entry->get_name().c_str()); - return entry; - } - } + start_diagnostic_request(&shims_, entry->get_handle()); } else { @@ -484,10 +435,12 @@ openxc_VehicleMessage diagnostic_manager_t::relay_diagnostic_response(active_dia // If name, include 'value' instead of payload, and leave of response // details. message = build_VehicleMessage(build_SimpleMessage(adr->get_name(), build_DynamicField(value))); + message.has_diagnostic_response = true; + message.diagnostic_response = build_VehicleMessage(adr, response, value).diagnostic_response; } else { - // If no name, send full details of response but still include 'value' + // If no name, only send full details of response but still include 'value' // instead of 'payload' if they provided a decoder. The one case you // can't get is the full detailed response with 'value'. We could add // another parameter for that but it's onerous to carry that around.