Add gitlab issue/merge request templates
[apps/agl-service-can-low-level.git] / low-can-binding / binding / low-can-hat.cpp
1 #include <mutex>
2 #include <systemd/sd-event.h>
3
4 #include "application.hpp"
5 #include "../utils/signals.hpp"
6 #include "low-can-hat.hpp"
7 #include "../can/message/message.hpp"
8 #include "../can/can-bus.hpp"
9
10
11
12 ///******************************************************************************
13 ///
14 ///             SystemD event loop Callbacks
15 ///
16 ///*******************************************************************************/
17
18 static void push_n_notify(std::shared_ptr<message_t> m)
19 {
20         can_bus_t& cbm = application_t::instance().get_can_bus_manager();
21         {
22                 std::lock_guard<std::mutex> can_message_lock(cbm.get_can_message_mutex());
23                 cbm.push_new_can_message(m);
24         }
25         cbm.get_new_can_message_cv().notify_one();
26 }
27
28 void on_no_clients(std::shared_ptr<low_can_subscription_t> can_subscription, uint32_t pid, std::map<int, std::shared_ptr<low_can_subscription_t> >& s)
29 {
30         bool is_permanent_recurring_request = false;
31
32         if( ! can_subscription->get_diagnostic_message().empty() && can_subscription->get_diagnostic_message(pid) != nullptr)
33         {
34                 DiagnosticRequest diag_req = can_subscription->get_diagnostic_message(pid)->build_diagnostic_request();
35                 active_diagnostic_request_t* adr = application_t::instance().get_diagnostic_manager().find_recurring_request(diag_req);
36                 if( adr != nullptr)
37                 {
38                         is_permanent_recurring_request = adr->get_permanent();
39
40                         if(! is_permanent_recurring_request)
41                                 application_t::instance().get_diagnostic_manager().cleanup_request(adr, true);
42                 }
43         }
44
45         if(! is_permanent_recurring_request)
46                 on_no_clients(can_subscription, s);
47 }
48
49
50 void on_no_clients(std::shared_ptr<low_can_subscription_t> can_subscription, std::map<int, std::shared_ptr<low_can_subscription_t> >& s)
51 {
52         auto it = s.find(can_subscription->get_index());
53         s.erase(it);
54 }
55
56 int read_message(sd_event_source *event_source, int fd, uint32_t revents, void *userdata)
57 {
58
59         low_can_subscription_t* can_subscription = (low_can_subscription_t*)userdata;
60
61
62         if ((revents & EPOLLIN) != 0)
63         {
64                 utils::signals_manager_t& sm = utils::signals_manager_t::instance();
65                 std::lock_guard<std::mutex> subscribed_signals_lock(sm.get_subscribed_signals_mutex());
66                 if(can_subscription->get_index() != -1)
67                 {
68                         std::shared_ptr<utils::socketcan_t> s = can_subscription->get_socket();
69                         if(s->socket() > 0)
70                         {
71                                 std::shared_ptr<message_t> message = s->read_message();
72
73                                 // Sure we got a valid CAN message ?
74                                 if (message->get_id() &&
75                                     message->get_length() &&
76                                     ! (message->get_flags() & INVALID_FLAG) )
77                                 {
78                                         if(can_subscription->get_signal() != nullptr && can_subscription->get_signal()->get_message()->get_flags() & BYTE_FRAME_IS_BIG_ENDIAN)
79                                                 message->frame_swap();
80                                         push_n_notify(message);
81                                 }
82                         }
83                 }
84         }
85
86         // check if error or hangup
87         if ((revents & (EPOLLERR|EPOLLRDHUP|EPOLLHUP)) != 0)
88         {
89                 sd_event_source_unref(event_source);
90                 can_subscription->get_socket()->close();
91         }
92
93         return 0;
94 }