X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=low-can-binding%2Fbinding%2Flow-can-hat.cpp;h=5a268745984da8e66c3ba4e309f478ccfdeecd34;hb=52b04b1c1022b50f9d23692bef6c61b3fdcc1ae0;hp=dae3a4afe2e4e512c1fcfe9add8eb8bb8da6266c;hpb=38f9b3de40b1d1d8e9ed5db0fee40bdaa763d577;p=apps%2Fagl-service-can-low-level.git diff --git a/low-can-binding/binding/low-can-hat.cpp b/low-can-binding/binding/low-can-hat.cpp index dae3a4af..5a268745 100644 --- a/low-can-binding/binding/low-can-hat.cpp +++ b/low-can-binding/binding/low-can-hat.cpp @@ -1,85 +1,88 @@ -/* - * Copyright (C) 2015, 2016 "IoT.bzh" - * Author "Romain Forlot" - * Author "Loic Collignon" - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "low-can-hat.hpp" -#include "low-can-subscription.hpp" - -#include -#include #include -#include -#include +#include #include "application.hpp" +#include "../utils/signals.hpp" +#include "low-can-hat.hpp" +#include "../can/message/message.hpp" #include "../can/can-bus.hpp" -extern "C" -{ - static int initv2(); - static constexpr struct afb_auth loa_afb_auth(const unsigned loa) + +///****************************************************************************** +/// +/// SystemD event loop Callbacks +/// +///*******************************************************************************/ + +static void push_n_notify(std::shared_ptr m) +{ + can_bus_t& cbm = application_t::instance().get_can_bus_manager(); { - struct afb_auth a = {}; - a.type = afb_auth_LOA; - a.loa = loa; - return a; + std::lock_guard can_message_lock(cbm.get_can_message_mutex()); + cbm.push_new_can_message(m); } + cbm.get_new_can_message_cv().notify_one(); +} - static const struct afb_auth loa_1 = { loa_afb_auth(1) }; +void on_no_clients(std::shared_ptr can_subscription, uint32_t pid, std::map >& s) +{ + bool is_permanent_recurring_request = false; - static const struct afb_verb_v2 verbs[]= + if( ! can_subscription->get_diagnostic_message().empty() && can_subscription->get_diagnostic_message(pid) != nullptr) { - { .verb= "subscribe", .callback= subscribe, .auth= NULL, .info="Let subscribe to signals", .session= AFB_SESSION_NONE}, - { .verb= "unsubscribe", .callback= unsubscribe, .auth= NULL, .info="Let unsubscribe signals", .session= AFB_SESSION_NONE}, - { .verb= "swrite", .callback= swrite, .auth= &loa_1, .info="Write a single CAN message on a CAN bus", .session= AFB_SESSION_LOA_1}, - { .verb= NULL, .callback= NULL, .auth= NULL, .info=NULL, .session= 0} - }; - - const struct afb_binding_v2 afbBindingV2 { - .api = "low-can", - .specification = NULL, - .info = "API to Low level CAN service, read and decode the bus", - .verbs = verbs, - .preinit = NULL, - .init = initv2, - .onevent = NULL, - .noconcurrency = 0 - }; - - /// @brief Initialize the binding. - /// - /// @param[in] service Structure which represent the Application Framework Binder. - /// - /// @return Exit code, zero if success. - static int initv2() - { - can_bus_t& can_bus_manager = application_t::instance().get_can_bus_manager(); + DiagnosticRequest diag_req = can_subscription->get_diagnostic_message(pid)->build_diagnostic_request(); + active_diagnostic_request_t* adr = application_t::instance().get_diagnostic_manager().find_recurring_request(diag_req); + if( adr != nullptr) + { + is_permanent_recurring_request = adr->get_permanent(); + + if(! is_permanent_recurring_request) + application_t::instance().get_diagnostic_manager().cleanup_request(adr, true); + } + } - can_bus_manager.set_can_devices(); - can_bus_manager.start_threads(); + if(! is_permanent_recurring_request) + on_no_clients(can_subscription, s); +} - /// Initialize Diagnostic manager that will handle obd2 requests. - /// We pass by default the first CAN bus device to its Initialization. - /// TODO: be able to choose the CAN bus device that will be use as Diagnostic bus. - if(application_t::instance().get_diagnostic_manager().initialize()) - return 0; - AFB_ERROR("There was something wrong with CAN device Initialization."); - return 1; +void on_no_clients(std::shared_ptr can_subscription, std::map >& s) +{ + auto it = s.find(can_subscription->get_index()); + s.erase(it); +} + +int read_message(sd_event_source *event_source, int fd, uint32_t revents, void *userdata) +{ + + low_can_subscription_t* can_subscription = (low_can_subscription_t*)userdata; + + + if ((revents & EPOLLIN) != 0) + { + utils::signals_manager_t& sm = utils::signals_manager_t::instance(); + std::lock_guard subscribed_signals_lock(sm.get_subscribed_signals_mutex()); + if(can_subscription->get_index() != -1) + { + std::shared_ptr s = can_subscription->get_socket(); + if(s->socket() > 0) + { + std::shared_ptr message = s->read_message(); + + // Sure we got a valid CAN message ? + if (message->get_id() && message->get_length() && !(message->get_flags() & INVALID_FLAG)) + push_n_notify(message); + } + } + } + + // check if error or hangup + if ((revents & (EPOLLERR|EPOLLRDHUP|EPOLLHUP)) != 0) + { + sd_event_source_unref(event_source); + can_subscription->get_socket()->close(); } -}; + + return 0; +}