socketinterface.c
Go to the documentation of this file.
1 
24 #ifndef _GNU_SOURCE // needed for asprintf to avoid warning
25 #define _GNU_SOURCE 1
26 #endif
27 
28 /*---- "module header" ----------------------------------------------------------------*/
30 /*---- <system includes> --------------------------------------------------------------*/
31 #ifdef CAN_AVAILABLE
32 #include <linux/can/raw.h>
33 #include <net/if.h>
34 #include <pthread.h>
35 #include <semaphore.h>
36 #include <stdbool.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <sys/ioctl.h>
41 #include <sys/socket.h>
42 #include <sys/time.h>
43 #include <unistd.h>
44 
45 /*---- "library includes" -------------------------------------------------------------*/
46 
47 /*---- "project includes" -------------------------------------------------------------*/
48 
49 /*---- local macros and constants -----------------------------------------------------*/
53 #define SOCKET_TIMEOUT 1
54 
57 #define SOCKET_TIMEOUT_US 0
58 /*---- local types --------------------------------------------------------------------*/
59 
60 /*---- local functions prototypes -----------------------------------------------------*/
61 
67 static void PrintCanFrame(struct can_frame* frame);
68 
77 static int SetupInterface(char* InterfaceName_cp, uint32_t InterfaceBitrate_u32);
78 
83 static void StartReceiverThread();
84 
91 int ReceiverThreadShouldRunCAN_b();
92 
98 static void* Receiver();
99 
106 static struct can_frame ReadFrame();
107 /*---- local inline functions ---------------------------------------------------------*/
108 
109 /*---- local variables (static) -------------------------------------------------------*/
110 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
111 static int s = 0;
112 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
113 static pthread_t receiver_thread_id;
114 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
115 static bool ReceiverThreadShouldRun = false;
116 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
117 static sem_t socket_sem;
118 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
119 static sem_t thread_sem;
120 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
121 static void (*ReadCallback)(struct can_frame* frame) = NULL;
122 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
123 static pthread_mutex_t mutex_socket_receiver = PTHREAD_MUTEX_INITIALIZER;
124 
125 static bool ConnectedToSocket_b = false;
126 /*---- public variables ---------------------------------------------------------------*/
127 
128 /*---- functions ----------------------------------------------------------------------*/
129 
130 void RegisterReadCallback(void (*Callback)(struct can_frame* frame))
131 {
132  MPRINTF("RegisterReadCallback\n");
133  ReadCallback = Callback;
134 }
135 
136 static struct can_frame ReadFrame()
137 {
138  struct can_frame frame = {0};
139  if (read(s, &frame, sizeof(struct can_frame)) < 0)
140  {
141  frame.can_dlc = 0;
142  }
143  return frame;
144 }
145 
146 int WriteFrame(struct can_frame* frame)
147 {
148  MPRINTF("Write Frame\n");
149  if (ConnectedToSocket_b)
150  {
151  MPRINTF("WriteFrame: \t");
152  if (write(s, frame, sizeof(struct can_frame)) != sizeof(struct can_frame))
153  {
154  perror("Write");
155  return 1;
156  }
157 
158  PrintCanFrame(frame);
159  return 0;
160  }
161  MPRINTF(
162  "An attempt was made to send CAN messages via a socket that has not yet been configured.\n");
163  return 1;
164 }
165 
166 static void PrintCanFrame(struct can_frame* frame)
167 {
168  MPRINTF("0x%03X [%d] ", frame->can_id, frame->can_dlc);
169 
170  for (int i = 0; i < frame->can_dlc; i++)
171  {
172  MPRINTF("%02X ", frame->data[i]);
173  }
174  MPRINTF("\r\n");
175 }
176 
177 static int SetupInterface(char* InterfaceName_cp, uint32_t InterfaceBitrate_u32)
178 {
179  MPRINTF("SetupInterface\n");
180  char* init_command = NULL;
181  char* down_command = NULL;
182  if (asprintf(&init_command, "ip link set %s up type can bitrate %d dbitrate %d fd off",
183  InterfaceName_cp, InterfaceBitrate_u32, InterfaceBitrate_u32) == -1)
184  {
185  return -1;
186  }
187  if (asprintf(&down_command, "ifconfig %s down", InterfaceName_cp) == -1)
188  {
189  return 1;
190  }
191  if (getuid() == 0)
192  {
193  // NOLINTNEXTLINE(cert-env33-c): Using Systemcall is currently the quickest way to get this
194  // done. Since the usage of "system" is potential dangerous, I might try to find a workaround
195  if (system(init_command) != 0)
196  {
197  MPRINTF(
198  "Interface Setup failed on first try.\nTrying to disable can0 interface and try "
199  "again.\n");
200  MPRINTF("%s\n", init_command);
201  MPRINTF("%s\n", down_command);
202  // NOLINTNEXTLINE(cert-env33-c): Using Systemcall is currently the quickest way to get this
203  // done. Since the usage of "system" is potential dangerous, I might try to find a workaround
204  if (system(down_command) == 0)
205  {
206  // NOLINTNEXTLINE(cert-env33-c): Using Systemcall is currently the quickest way to get this
207  // done. Since the usage of "system" is potential dangerous, I might try to find a
208  // workaround
209  if (system(init_command) != 0)
210  {
211  free(init_command);
212  free(down_command);
213  return 1;
214  }
215  }
216  else
217  {
218  free(init_command);
219  free(down_command);
220  return 1;
221  }
222  }
223  free(init_command);
224  free(down_command);
225  return 0;
226  }
227  MPRINTF("---------------Warning---------------\n");
228  MPRINTF(
229  "Current User is not root - will not attempt to configure the interface. Please take care of "
230  "proper interface setup yourself!\n");
231  MPRINTF("-------------------------------------\n");
232  free(init_command);
233  free(down_command);
234  return 0;
235 }
236 
237 int SetupSocket(char* InterfaceName_cp, uint32_t InterfaceBitrate_u32)
238 {
239  MPRINTF("SetupSocket for interface %s / %d\n", InterfaceName_cp, InterfaceBitrate_u32);
240  if (SetupInterface(InterfaceName_cp, InterfaceBitrate_u32) == 0)
241  {
242  MPRINTF("Interface setup successful\n");
243  }
244  else
245  {
246  MPRINTF("Interface setup failed\n");
247  return 1;
248  }
249  struct sockaddr_can addr = {0};
250  struct ifreq ifr;
251  struct timeval tv;
252  tv.tv_sec = SOCKET_TIMEOUT;
253  tv.tv_usec = SOCKET_TIMEOUT_US;
254 
255  if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
256  {
257  perror("Socket");
258  return 1;
259  }
260  setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
261  strncpy(ifr.ifr_name, "can0", IFNAMSIZ);
262  ioctl(s, SIOCGIFINDEX, &ifr);
263 
264  addr.can_family = AF_CAN;
265  addr.can_ifindex = ifr.ifr_ifindex;
266 
267  if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0)
268  {
269  perror("Bind");
270  return 1;
271  }
272  sem_init(&socket_sem, 0, 1);
273  sem_init(&thread_sem, 0, 1);
274  pthread_mutex_lock(&mutex_socket_receiver);
276  pthread_mutex_unlock(&mutex_socket_receiver);
277  sem_wait(&thread_sem);
279  sem_wait(&thread_sem);
280  sem_post(&thread_sem);
281 
282  ConnectedToSocket_b = true;
283  return 0;
284 }
285 
286 int DeinitSocket()
287 {
288  if (close(s) < 0)
289  {
290  perror("Close");
291  return 1;
292  }
293  pthread_mutex_lock(&mutex_socket_receiver);
294  ReceiverThreadShouldRun = false;
295  pthread_mutex_unlock(&mutex_socket_receiver);
296  (void)pthread_join(receiver_thread_id, NULL);
297  return 0;
298 }
299 
300 static void StartReceiverThread()
301 {
302  MPRINTF("StartReceiverThread\n");
303  int err = 0;
304  err = pthread_create(&(receiver_thread_id), NULL, &Receiver, NULL);
305  if (err != 0)
306  {
307  MPRINTF("\ncan't create thread :[%s]", strerror(err));
308  }
309  else
310  {
311  MPRINTF("\nCAN-Receiver Thread created successfully\n");
312  }
313  sem_post(&thread_sem);
314 }
315 
316 int ReceiverThreadShouldRunCAN_b()
317 {
318  int value = 0;
319 
320  pthread_mutex_lock(&mutex_socket_receiver);
321  value = ReceiverThreadShouldRun;
322  pthread_mutex_unlock(&mutex_socket_receiver);
323 
324  return value;
325 }
326 
327 static void* Receiver()
328 {
329  MPRINTF("Start Receiver\n");
330  while (ReceiverThreadShouldRunCAN_b())
331  {
332  MPRINTF("Reading now:\n");
333  struct can_frame frame = ReadFrame();
334  if (frame.can_dlc > 0)
335  {
336  if (ReadCallback != NULL)
337  {
338  ReadCallback(&frame);
339  }
340  }
341  }
342  MPRINTF("End Receiver\n");
343  return NULL;
344 }
345 #endif
s
XmlRpcServer s
thread_sem
static sem_t thread_sem
Definition: uartinterface.c:113
receiver_thread_id
static pthread_t receiver_thread_id
Definition: uartinterface.c:109
StartReceiverThread
static void StartReceiverThread(uint8_t InterfaceId_u8, uint32_t InterfaceBitrate_u32, char *InterfaceName_cp)
Creates the Receiver Thread.
Definition: uartinterface.c:213
socketinterface.h
This file contains the linux-can-socket interface prototypes.
ReadCallback
static void(* ReadCallback)(uint8_t *UARTMsg_pu8, uint16_t DataSize_u16, uint8_t InterfaceId_u8)
Definition: uartinterface.c:117
SetupInterface
static int SetupInterface(char *InterfaceName_cp, uint32_t InterfaceBitrate_u32)
Setup of uart-device with given paramters. Currently via system-call.
Definition: uartinterface.c:163
MPRINTF
#define MPRINTF(f_,...)
Definition: sensor_lib_config.h:53
Receiver
void * Receiver(void *arg)
Tries to read CAN frames as long as it is desired. Reacts to abort commands within the set CAN timeou...
Definition: uartinterface.c:244
ReceiverThreadShouldRun
static bool ReceiverThreadShouldRun
Definition: uartinterface.c:111


toposens_echo_driver
Author(s): Tobias Roth , Dennis Maier , Baris Yazici
autogenerated on Wed Mar 2 2022 01:12:32