X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=CAN-binder%2Flow-can-binding%2Fdiagnostic%2Fdiagnostic-manager.cpp;h=f9dc9607151d06832e49b883b80b0846d24f683f;hb=a1a554bd3dc19580c9b80dc6e4beb6bed4711e53;hp=935767a87284f71b78d44127dc737942d9146880;hpb=4f1b1d088afe8eb9a5b75287429104e4175e97e7;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 935767a8..f9dc9607 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 @@ -33,7 +33,7 @@ #define MICRO 1000000 diagnostic_manager_t::diagnostic_manager_t() - : initialized_{false} + : initialized_{false}, event_source_{nullptr} {} /// @brief Diagnostic manager isn't initialized at launch but after @@ -46,7 +46,7 @@ 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; @@ -57,16 +57,6 @@ bool diagnostic_manager_t::initialize() return initialized_; } -void diagnostic_manager_t::read_socket() -{ - can_message_t msg; - can_bus_t& cbm = configuration_t::instance().get_can_bus_manager(); - socket_ >> msg; - std::lock_guard can_message_lock(cbm.get_can_message_mutex()); - { cbm.push_new_can_message(msg); } - cbm.get_new_can_message_cv().notify_one(); -} - utils::socketcan_bcm_t& diagnostic_manager_t::get_socket() { return socket_; @@ -92,16 +82,17 @@ void diagnostic_manager_t::reset() /// 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) +int diagnostic_manager_t::create_rx_filter(uint32_t can_id, float frequency) { // Make sure that socket has been opened. if(! socket_) - socket_.open(bus_); + socket_.open(get_bus_device_name()); struct utils::simple_bcm_msg bcm_msg; - memset(&bcm_msg.msg_head, 0, sizeof(bcm_msg.msg_head)); + memset(&bcm_msg, 0, sizeof(bcm_msg)); - const struct timeval freq = recurring_requests_.back()->get_timeout_clock().get_timeval_from_period(); + const struct timeval freq = (frequency == recurring_requests_.back()->get_frequency_clock().get_frequency() ) ? + recurring_requests_.back()->get_frequency_clock().get_timeval_from_period() : frequency_clock_t(frequency).get_timeval_from_period(); bcm_msg.msg_head.opcode = RX_SETUP; bcm_msg.msg_head.flags = SETTIMER|RX_FILTER_ID; @@ -109,7 +100,7 @@ int diagnostic_manager_t::add_rx_filter(uint32_t can_id) 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_RESPONSE_START) + if(can_id != OBD2_FUNCTIONAL_BROADCAST_ID) { bcm_msg.msg_head.can_id = can_id; @@ -145,14 +136,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; @@ -168,6 +159,7 @@ bool diagnostic_manager_t::shims_send(const uint32_t arbitration_id, const uint8 bcm_msg.msg_head.ival2.tv_sec = freq.tv_sec; bcm_msg.msg_head.ival2.tv_usec = freq.tv_usec; bcm_msg.msg_head.nframes = 1; + cfd.can_dlc = size; ::memcpy(cfd.data, data, size); bcm_msg.frames = cfd; @@ -194,17 +186,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(); @@ -216,6 +215,16 @@ DiagnosticShims& diagnostic_manager_t::get_shims() return shims_; } +bool diagnostic_manager_t::socket_close() +{ + if(non_recurring_requests_.empty() && recurring_requests_.empty()) + { + socket_.close(); + 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 @@ -233,23 +242,9 @@ void diagnostic_manager_t::find_and_erase(active_diagnostic_request_t* entry, st // @brief TODO: implement cancel_request if needed... Don't know. void diagnostic_manager_t::cancel_request(active_diagnostic_request_t* entry) { - - /* TODO: implement acceptance filters. - if(entry.arbitration_id_ == OBD2_FUNCTIONAL_BROADCAST_ID) { - for(uint32_t filter = OBD2_FUNCTIONAL_RESPONSE_START; - filter < OBD2_FUNCTIONAL_RESPONSE_START + - OBD2_FUNCTIONAL_RESPONSE_COUNT; - filter++) { - removeAcceptanceFilter(entry.bus_, filter, - CanMessageFormat::STANDARD, getCanBuses(), - getCanBusCount()); - } - } else { - removeAcceptanceFilter(entry.bus_, - entry.arbitration_id_ + - DIAGNOSTIC_RESPONSE_ARBITRATION_ID_OFFSET, - CanMessageFormat::STANDARD, getCanBuses(), getCanBusCount()); - }*/ + 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 @@ -260,25 +255,24 @@ 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->get_in_flight() && entry->request_completed()))) + if((force || (entry != nullptr && entry->response_received()))) { - entry->set_in_flight(false); - 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_); } + socket_close(); } } @@ -289,12 +283,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 @@ -309,10 +307,7 @@ active_diagnostic_request_t* diagnostic_manager_t::find_recurring_request(const if(entry != nullptr) { if(diagnostic_request_equals(&entry->get_handle()->request, request)) - { - return entry; - break; - } + {return entry;} } } return nullptr; @@ -344,7 +339,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) { @@ -364,7 +359,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); @@ -462,8 +458,12 @@ active_diagnostic_request_t* diagnostic_manager_t::add_recurring_request(Diagnos recurring_requests_.push_back(entry); entry->set_handle(shims_, request); - if(add_rx_filter(OBD2_FUNCTIONAL_BROADCAST_ID) < 0) - { recurring_requests_.pop_back(); } + if(create_rx_filter(OBD2_FUNCTIONAL_BROADCAST_ID, frequencyHz) < 0) + { + recurring_requests_.pop_back(); + delete entry; + entry = nullptr; + } else { start_diagnostic_request(&shims_, entry->get_handle()); @@ -471,7 +471,7 @@ active_diagnostic_request_t* diagnostic_manager_t::add_recurring_request(Diagnos &event_source_, socket_.socket(), EPOLLIN, - read_diagnostic_message, + read_message, nullptr) < 0) { cleanup_request(entry, true); @@ -491,41 +491,6 @@ active_diagnostic_request_t* diagnostic_manager_t::add_recurring_request(Diagnos return entry; } -/// @brief Returns true if there are two active requests running for the same arbitration ID. -bool diagnostic_manager_t::conflicting(active_diagnostic_request_t* request, active_diagnostic_request_t* candidate) const -{ - return (candidate->get_in_flight() && candidate != request && - candidate->get_can_bus_dev() == request->get_can_bus_dev() && - candidate->get_id() == request->get_id()); -} - - -/// @brief Returns true if there are no other active requests to the same arbitration ID -/// and if there aren't more than 8 requests in flight at the same time. -bool diagnostic_manager_t::clear_to_send(active_diagnostic_request_t* request) const -{ - int total_in_flight = 0; - for ( auto entry : non_recurring_requests_) - { - if(conflicting(request, entry)) - return false; - if(entry->get_in_flight()) - total_in_flight++; - } - - for ( auto entry : recurring_requests_) - { - if(conflicting(request, entry)) - return false; - if(entry->get_in_flight()) - total_in_flight++; - } - - if(total_in_flight > MAX_SIMULTANEOUS_IN_FLIGHT_REQUESTS) - return false; - return true; -} - /// @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 @@ -573,7 +538,7 @@ openxc_VehicleMessage diagnostic_manager_t::relay_diagnostic_response(active_dia } // Reset the completed flag handle to make sure that it will be reprocessed the next time. - adr->get_handle()->completed = false; + adr->get_handle()->success = false; return message; } @@ -596,7 +561,8 @@ openxc_VehicleMessage diagnostic_manager_t::relay_diagnostic_handle(active_diagn else if(!response.completed && response.multi_frame) { // Reset the timeout clock while completing the multi-frame receive - entry->get_timeout_clock().tick(); + entry->get_timeout_clock().tick( + entry->get_timeout_clock().get_time_function()()); } return build_VehicleMessage();