po_hi_driver_linux_serial.c 11.3 KB
Newer Older
1
2
3
4
5
/*
 * This is a part of PolyORB-HI-C distribution, a minimal
 * middleware written for generated code from AADL models.
 * You should use it with the Ocarina toolsuite.
 *
6
7
8
 * For more informations, please visit http://ocarina.enst.fr
 *
 * Copyright (C) 2010, European Space Agency (ESA).
9
10
 */

11
#include <drivers/po_hi_driver_linux_serial.h>
12
#include <drivers/configuration/serial.h>
13

14
15
16
#if defined (__PO_HI_NEED_DRIVER_SERIAL_LINUX) || \
    defined (__PO_HI_NEED_DRIVER_SERIAL_LINUX_SENDER) || \
    defined (__PO_HI_NEED_DRIVER_SERIAL_LINUX_RECEIVER)
17

18
#include <po_hi_debug.h>
jdelange's avatar
jdelange committed
19
#include <po_hi_returns.h>
20
#include <po_hi_utils.h>
21
22
#include <po_hi_messages.h>
#include <po_hi_transport.h>
23
#include <po_hi_gqueue.h>
24
#include <drivers/po_hi_driver_serial_common.h>
25
26
/* po-hi-c related files */

27
28
29
30
31
#include <activity.h>
#include <marshallers.h>
#include <deployment.h>
/* generated files */

32
33
34
35
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
36
#include <unistd.h>
37
#include <string.h>
38
39
/* Linux-specific files */

40
41
42
int      po_hi_c_driver_serial_fd_read;
int      po_hi_c_driver_serial_fd_write;
uint32_t po_hi_c_driver_serial_sending_wait;
43

44
45
#if defined (__PO_HI_NEED_DRIVER_SERIAL_LINUX) || \
    defined (__PO_HI_NEED_DRIVER_SERIAL_LINUX_RECEIVER)
46

47
48
__po_hi_request_t __po_hi_c_driver_serial_linux_request;
__po_hi_msg_t     __po_hi_c_driver_serial_linux_poller_msg;
49
void __po_hi_c_driver_serial_linux_poller (const __po_hi_device_id dev_id)
50
{
51
   (void) dev_id;
52
53
54
   int n;
   int ts;

55
56
   unsigned long* swap_pointer;
   unsigned long swap_value;
57
58


59
   __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Hello, i'm the serial poller , must read %d bytes!\n", __PO_HI_MESSAGES_MAX_SIZE);
60

61
   __po_hi_msg_reallocate (&__po_hi_c_driver_serial_linux_poller_msg);
jdelange's avatar
jdelange committed
62
63
   n = 0;
   while (n < __PO_HI_MESSAGES_MAX_SIZE)
64
   {
65
       if (read (po_hi_c_driver_serial_fd_read, &(__po_hi_c_driver_serial_linux_poller_msg.content[n]), 1) != 1)
jdelange's avatar
jdelange committed
66
67
68
69
70
71
	{
	    __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Cannot read on socket !\n");
	    return;
	}

	n++;
72
   }
73

jdelange's avatar
jdelange committed
74

75
76
   if (n == 0)
   {
jdelange's avatar
jdelange committed
77
    __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] n=0 !\n");
78
79
80
      return;
   }

81
82
   if (n != __PO_HI_MESSAGES_MAX_SIZE)
   {
83
      __PO_HI_DEBUG_CRITICAL ("[LINUX SERIAL] Inconsistent received message size (received %d bytes)!\n", n);
84
85
      return;
   }
86

87
   __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] read() returns %d\n", n);
88

89
   swap_pointer  = (unsigned long*) &__po_hi_c_driver_serial_linux_poller_msg.content[0];
90
91
   swap_value    = *swap_pointer;
   *swap_pointer = __po_hi_swap_byte (swap_value);
92

93
   __po_hi_c_driver_serial_linux_poller_msg.length = n;
94

95
   __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Message after swapped port: 0x");
96
   for (ts = 0 ; ts < __po_hi_c_driver_serial_linux_poller_msg.length ; ts++)
97
   {
98
        __PO_HI_DEBUG_DEBUG ("%x", __po_hi_c_driver_serial_linux_poller_msg.content[ts]);
99
   }
100
   __PO_HI_DEBUG_DEBUG ("\n");
101

102
   __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Received: %s\n", __po_hi_c_driver_serial_linux_poller_msg.content);
103

104
   __po_hi_unmarshall_request (&__po_hi_c_driver_serial_linux_request, &__po_hi_c_driver_serial_linux_poller_msg);
105

106
   if (__po_hi_c_driver_serial_linux_request.port > __PO_HI_NB_PORTS)
107
   {
108
      __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Invalid port number !\n");
109
110
111
      return;
   }

112
113
   __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Destination port: %d\n", __po_hi_c_driver_serial_linux_request.port);
   __po_hi_main_deliver (&__po_hi_c_driver_serial_linux_request);
114
}
115
116
117
118
119
120
121
122
#endif


#if defined (__PO_HI_NEED_DRIVER_SERIAL_LINUX) || \
    defined (__PO_HI_NEED_DRIVER_SERIAL_LINUX_SENDER)

void __po_hi_c_driver_serial_linux_init_sender (__po_hi_device_id id)
{
123
124
   struct termios             oldtio,newtio;
   __po_hi_c_serial_conf_t*   serialconf;
125

126
127
   po_hi_c_driver_serial_sending_wait = 0;

128
   __PO_HI_DEBUG_INFO ("[LINUX SERIAL] Init sender\n");
129

130
   serialconf = (__po_hi_c_serial_conf_t*)__po_hi_get_device_configuration (id);
131

132
   if (serialconf == NULL)
133
   {
134
      __PO_HI_DEBUG_INFO ("[LINUX SERIAL] Cannot get the configuration of the device !\n");
135
136
137
      return;
   }

138
139
140
141
142
143
   if (serialconf->exist.sending_wait == 1)
   {
      po_hi_c_driver_serial_sending_wait = (uint32_t) serialconf->sending_wait;
      __PO_HI_DEBUG_INFO ("[LINUX SERIAL] Set sending delay to %u!\n",po_hi_c_driver_serial_sending_wait);
   }

144
   po_hi_c_driver_serial_fd_write = open (serialconf->devname, O_WRONLY | O_NOCTTY | O_NDELAY);
145
146
147

   if (po_hi_c_driver_serial_fd_write < 0)
   {
148
      __PO_HI_DEBUG_CRITICAL ("[LINUX SERIAL] Error while opening device %s\n", serialconf->devname);
149
150
151
   }
   else
   {
152
      __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Device %s successfully opened for sending, fd=%d\n", serialconf->devname, po_hi_c_driver_serial_fd_write);
153
154
155
   }

   tcgetattr (po_hi_c_driver_serial_fd_write, &oldtio);  /* save current serial port settings */
156
   tcgetattr (po_hi_c_driver_serial_fd_write, &newtio);  /* save current serial port settings */
157
        
158
   newtio.c_cflag |= CREAD ;
159
160
161
162
163
   newtio.c_iflag = IGNPAR | IGNBRK;
   newtio.c_lflag |= ICANON;
   newtio.c_cc[VMIN]=1;
   newtio.c_cc[VTIME]=0;
   cfmakeraw (&newtio);
164
165
166
167
168

   switch (__po_hi_c_driver_serial_common_get_speed (id))
   {
      case __PO_HI_DRIVER_SERIAL_COMMON_SPEED_19200:
         newtio.c_cflag |= B19200;
jdelange's avatar
jdelange committed
169
         __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Set speed to 19200\n");
170
171
172
173
         break;

      case __PO_HI_DRIVER_SERIAL_COMMON_SPEED_38400:
         newtio.c_cflag |= B38400;
jdelange's avatar
jdelange committed
174
         __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Set speed to 38400\n");
175
176
177
178
         break;

      case __PO_HI_DRIVER_SERIAL_COMMON_SPEED_57600:
         newtio.c_cflag |= B57600;
jdelange's avatar
jdelange committed
179
         __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Set speed to 57600\n");
180
181
182
         break;

      case __PO_HI_DRIVER_SERIAL_COMMON_SPEED_115200:
jdelange's avatar
jdelange committed
183
         __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Set speed to 115200\n");
184
185
186
187
188
189
190
191
         newtio.c_cflag |= B115200;
         break;

      case __PO_HI_DRIVER_SERIAL_COMMON_SPEED_UNKNWON:
         __PO_HI_DEBUG_INFO ("[LINUX SERIAL] Unknwon speed for the serial line\n");
         break;
   }

192
193
194
195
196
   /* 
    * clean the serial line and activate the settings for the port
    */
   if (tcflush (po_hi_c_driver_serial_fd_write, TCIOFLUSH) == -1)
   {
197
      __PO_HI_DEBUG_CRITICAL ("[LINUX SERIAL] Error in tcflush()\n");
198
199
200
201
   }

   if (tcsetattr (po_hi_c_driver_serial_fd_write, TCSANOW, &newtio) == -1)
   {
202
      __PO_HI_DEBUG_CRITICAL ("[LINUX SERIAL] Error in tcsetattr()\n");
203
204
   }

205
    __PO_HI_DEBUG_INFO ("[LINUX SERIAL] End of init\n");
206
207
208
209
210
211
212
213
}
#endif


#if defined (__PO_HI_NEED_DRIVER_SERIAL_LINUX) || \
    defined (__PO_HI_NEED_DRIVER_SERIAL_LINUX_RECEIVER)
void __po_hi_c_driver_serial_linux_init_receiver (__po_hi_device_id id)
{
214
215
   struct termios             oldtio,newtio;
   __po_hi_c_serial_conf_t*   serialconf;
216

217
   __PO_HI_DEBUG_INFO ("[LINUX SERIAL] Init receiver\n");
218

219
   serialconf = (__po_hi_c_serial_conf_t*)__po_hi_get_device_configuration (id);
220

221
   if (serialconf == NULL)
222
223
224
225
226
   {
      __PO_HI_DEBUG_INFO ("[LINUX SERIAL] Cannot get the name of the device !\n");
      return;
   }

227
   po_hi_c_driver_serial_fd_read = open (serialconf->devname, O_RDONLY | O_NOCTTY);
228
229
230

   if (po_hi_c_driver_serial_fd_read < 0)
   {
231
      __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Error while opening device %s\n", serialconf->devname);
232
233
234
   }
   else
   {
235
      __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Device %s successfully opened for reading, fd=%d\n", serialconf->devname , po_hi_c_driver_serial_fd_read);
236
237
238
   }


239
240
   tcgetattr (po_hi_c_driver_serial_fd_read, &oldtio);  /* save current serial port settings */
   tcgetattr (po_hi_c_driver_serial_fd_read, &newtio);  /* save current serial port settings */
241
        
242
   newtio.c_cflag |= CREAD ;
243
244
245
246
247
   newtio.c_iflag = IGNPAR | IGNBRK;
   newtio.c_lflag |= ICANON;
   newtio.c_cc[VMIN]=1;
   newtio.c_cc[VTIME]=0;
   cfmakeraw (&newtio);
248
249
250
251
252

   switch (__po_hi_c_driver_serial_common_get_speed (id))
   {
      case __PO_HI_DRIVER_SERIAL_COMMON_SPEED_19200:
         newtio.c_cflag |= B19200;
jdelange's avatar
jdelange committed
253
         __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Set speed to 19200\n");
254
255
256
257
         break;

      case __PO_HI_DRIVER_SERIAL_COMMON_SPEED_38400:
         newtio.c_cflag |= B38400;
jdelange's avatar
jdelange committed
258
         __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Set speed to 38400\n");
259
260
261
262
         break;

      case __PO_HI_DRIVER_SERIAL_COMMON_SPEED_57600:
         newtio.c_cflag |= B57600;
jdelange's avatar
jdelange committed
263
         __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Set speed to 57600\n");
264
265
266
         break;

      case __PO_HI_DRIVER_SERIAL_COMMON_SPEED_115200:
jdelange's avatar
jdelange committed
267
         __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Set speed to 115200\n");
268
269
270
271
272
273
274
         newtio.c_cflag |= B115200;
         break;

      case __PO_HI_DRIVER_SERIAL_COMMON_SPEED_UNKNWON:
         __PO_HI_DEBUG_INFO ("[LINUX SERIAL] Unknwon speed for the serial line\n");
         break;
   }
jdelange's avatar
jdelange committed
275

276
277
   if (tcflush (po_hi_c_driver_serial_fd_read, TCIOFLUSH) == -1)
   {
278
      __PO_HI_DEBUG_CRITICAL ("[LINUX SERIAL] Error in tcflush()\n");
279
280
281
282
   }

   if (tcsetattr (po_hi_c_driver_serial_fd_read, TCSANOW, &newtio) == -1)
   {
283
      __PO_HI_DEBUG_CRITICAL ("[LINUX SERIAL] Error in tcsetattr()\n");
284
285
   }

286
    __PO_HI_DEBUG_INFO ("[LINUX SERIAL] End of init\n");
287
288
289
290
291
}
#endif


#if defined (__PO_HI_NEED_DRIVER_SERIAL_LINUX)
292

293
void __po_hi_c_driver_serial_linux_init (__po_hi_device_id id)
294
{
295

jdelange's avatar
jdelange committed
296
297
298
   __po_hi_c_driver_serial_linux_init_receiver (id);
   __po_hi_c_driver_serial_linux_init_sender (id);
   return;
299
}
300
301
302
303
304
#endif


#if defined (__PO_HI_NEED_DRIVER_SERIAL_LINUX) || \
    defined (__PO_HI_NEED_DRIVER_SERIAL_LINUX_SENDER)
305

306
307
__po_hi_msg_t __po_hi_c_driver_serial_linux_sender_msg;

308
int  __po_hi_c_driver_serial_linux_sender (__po_hi_task_id task_id, __po_hi_port_t port)
309
{
310
311
312
313
314
315
316
   int                     n;
   int                     ts;
   unsigned long*          swap_pointer;
   unsigned long           swap_value;
   __po_hi_local_port_t    local_port;
   __po_hi_request_t*      request;
   __po_hi_port_t          destination_port;
317
318
319
320
321

   local_port = __po_hi_get_local_port_from_global_port (port);

   request = __po_hi_gqueue_get_most_recent_value (task_id, local_port);

jdelange's avatar
jdelange committed
322
323
   if (request->port == -1)
   {
324
      __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Send output task %d, port %d (local_port=%d): no value to send\n", task_id, port, local_port);
jdelange's avatar
jdelange committed
325
326
327
      return __PO_HI_SUCCESS;
   }

328
329
   destination_port     = __po_hi_gqueue_get_destination (task_id, local_port, 0);

330
   __po_hi_msg_reallocate (&__po_hi_c_driver_serial_linux_sender_msg);
331
332
333

   request->port = destination_port;

334
   __po_hi_marshall_request (request, &__po_hi_c_driver_serial_linux_sender_msg);
335

336
   /* Swap only the port (first 32 bytes) */
337
   swap_pointer  = (unsigned long*) &__po_hi_c_driver_serial_linux_sender_msg.content[0];
338
339
   swap_value    = *swap_pointer;
   *swap_pointer = __po_hi_swap_byte (swap_value);
340

341
342
   if (po_hi_c_driver_serial_sending_wait != 0)
   {
343
      printf("Wait %u between two sends\n", po_hi_c_driver_serial_sending_wait);
344
345
      for (n = 0 ; n < __PO_HI_MESSAGES_MAX_SIZE ; n++)
      {
346
         write (po_hi_c_driver_serial_fd_write, &(__po_hi_c_driver_serial_linux_sender_msg.content[n]), 1);
347
348
349
350
351
352
         usleep (po_hi_c_driver_serial_sending_wait);
      }

   }
   else
   {
353
      n = write (po_hi_c_driver_serial_fd_write, &__po_hi_c_driver_serial_linux_sender_msg, __PO_HI_MESSAGES_MAX_SIZE);
354
   }
355

jdelange's avatar
jdelange committed
356
   __PO_HI_DEBUG_DEBUG  ("[LINUX SERIAL] write() returns %d, message sent: 0x", n);
357

358
359
   for (ts = 0 ; ts < __PO_HI_MESSAGES_MAX_SIZE ; ts++)
   {
360
      __PO_HI_DEBUG_DEBUG ("%x", __po_hi_c_driver_serial_linux_sender_msg.content[ts]);
361
   }
362
   __PO_HI_DEBUG_DEBUG ("\n");
363

jdelange's avatar
jdelange committed
364
365
   request->port = __PO_HI_GQUEUE_INVALID_PORT;

366
   return 1;
367
}
368
#endif
369

370
#endif