po_hi_driver_linux_serial.c 9.94 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
int po_hi_c_driver_serial_fd_read;
int po_hi_c_driver_serial_fd_write;
42

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

void __po_hi_c_driver_serial_linux_poller (void)
{
48
49
50
   int n;
   int ts;

51
52
   unsigned long* swap_pointer;
   unsigned long swap_value;
53

54
55
   __po_hi_msg_t msg;
   __po_hi_request_t request;
56

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

   __po_hi_msg_reallocate (&msg);
60

61
   n = read (po_hi_c_driver_serial_fd_read, &(msg.content[0]), __PO_HI_MESSAGES_MAX_SIZE); 
62

63
#ifdef __PO_HI_DEBUG_INFO
64
   __PO_HI_DEBUG_INFO  ("[LINUX SERIAL] Message: 0x");
65
66
67

   for (ts = 0 ; ts < __PO_HI_MESSAGES_MAX_SIZE ; ts++)
   {
68
      __PO_HI_DEBUG_INFO ("%x", msg.content[ts]);
69
   }
70
   __PO_HI_DEBUG_INFO ("\n");
71
#endif
72
73
   
   if (n == -1)
74
   {
75
      __PO_HI_DEBUG_CRITICAL ("[LINUX SERIAL] Cannot read on socket !\n");
76
      return;
77
   }
78

79
80
81
82
83
   if (n == 0)
   {
      return;
   }

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

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

92
   msg.length = n;
93
94
95
   swap_pointer  = (unsigned long*) &msg.content[0];
   swap_value    = *swap_pointer;
   *swap_pointer = __po_hi_swap_byte (swap_value);
96

97
#ifdef __PO_HI_DEBUG_INFO
98
   __PO_HI_DEBUG_INFO ("[LINUX SERIAL] Message after swapped port: 0x");
99
   for (ts = 0 ; ts < msg.length ; ts++)
100
   {
101
        __PO_HI_DEBUG_INFO ("%x", msg.content[ts]);
102
   }
103
   __PO_HI_DEBUG_INFO ("\n");
104

105
   __PO_HI_DEBUG_INFO ("[LINUX SERIAL] Received: %s\n", msg.content);
106
#endif
107

108
109
   __po_hi_unmarshall_request (&request, &msg);

110
111
112
113
114
115
   if (request.port > __PO_HI_NB_PORTS)
   {
      __PO_HI_DEBUG_WARNING ("[LINUX SERIAL] Invalid port number !\n");
      return;
   }

116
   __PO_HI_DEBUG_INFO ("[LINUX SERIAL] Destination port: %d\n", request.port);
117
   __po_hi_main_deliver (&request);
118
}
119
120
121
122
123
124
125
126
#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)
{
127
128
   struct termios             oldtio,newtio;
   __po_hi_c_serial_conf_t*   serialconf;
129

130
   __PO_HI_DEBUG_INFO ("[LINUX SERIAL] Init sender\n");
131

132
   serialconf = (__po_hi_c_serial_conf_t*)__po_hi_get_device_configuration (id);
133

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

140
   po_hi_c_driver_serial_fd_write = open (serialconf->devname, O_WRONLY | O_NOCTTY | O_NDELAY);
141
142
143

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

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

   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
165
         __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Set speed to 19200\n");
166
167
168
169
         break;

      case __PO_HI_DRIVER_SERIAL_COMMON_SPEED_38400:
         newtio.c_cflag |= B38400;
jdelange's avatar
jdelange committed
170
         __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Set speed to 38400\n");
171
172
173
174
         break;

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

      case __PO_HI_DRIVER_SERIAL_COMMON_SPEED_115200:
jdelange's avatar
jdelange committed
179
         __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Set speed to 115200\n");
180
181
182
183
184
185
186
187
         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;
   }

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

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

201
    __PO_HI_DEBUG_INFO ("[LINUX SERIAL] End of init\n");
202
203
204
205
206
207
208
209
}
#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)
{
210
211
   struct termios             oldtio,newtio;
   __po_hi_c_serial_conf_t*   serialconf;
212

213
   __PO_HI_DEBUG_INFO ("[LINUX SERIAL] Init receiver\n");
214

215
   serialconf = (__po_hi_c_serial_conf_t*)__po_hi_get_device_configuration (id);
216

217
   if (serialconf == NULL)
218
219
220
221
222
   {
      __PO_HI_DEBUG_INFO ("[LINUX SERIAL] Cannot get the name of the device !\n");
      return;
   }

223
   po_hi_c_driver_serial_fd_read = open (serialconf->devname, O_RDONLY | O_NOCTTY | O_NONBLOCK);
224
225
226

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


235
236
237
238
239
240
241
242
243
   tcgetattr (po_hi_c_driver_serial_fd_write, &oldtio);  /* save current serial port settings */
   tcgetattr (po_hi_c_driver_serial_fd_write, &newtio);  /* save current serial port settings */
        
   newtio.c_cflag |= B115200 | CREAD ;
   newtio.c_iflag = IGNPAR | IGNBRK;
   newtio.c_lflag |= ICANON;
   newtio.c_cc[VMIN]=1;
   newtio.c_cc[VTIME]=0;
   cfmakeraw (&newtio);
244
245
246
247
248

   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
249
         __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Set speed to 19200\n");
250
251
252
253
         break;

      case __PO_HI_DRIVER_SERIAL_COMMON_SPEED_38400:
         newtio.c_cflag |= B38400;
jdelange's avatar
jdelange committed
254
         __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Set speed to 38400\n");
255
256
257
258
         break;

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

      case __PO_HI_DRIVER_SERIAL_COMMON_SPEED_115200:
jdelange's avatar
jdelange committed
263
         __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Set speed to 115200\n");
264
265
266
267
268
269
270
         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
271

272
273
   if (tcflush (po_hi_c_driver_serial_fd_read, TCIOFLUSH) == -1)
   {
274
      __PO_HI_DEBUG_CRITICAL ("[LINUX SERIAL] Error in tcflush()\n");
275
276
277
278
   }

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

282
    __PO_HI_DEBUG_INFO ("[LINUX SERIAL] End of init\n");
283
284
285
286
287
}
#endif


#if defined (__PO_HI_NEED_DRIVER_SERIAL_LINUX)
288

289
void __po_hi_c_driver_serial_linux_init (__po_hi_device_id id)
290
{
291

jdelange's avatar
jdelange committed
292
293
294
   __po_hi_c_driver_serial_linux_init_receiver (id);
   __po_hi_c_driver_serial_linux_init_sender (id);
   return;
295
}
296
297
298
299
300
#endif


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

302
int  __po_hi_c_driver_serial_linux_sender (__po_hi_task_id task_id, __po_hi_port_t port)
303
{
304
305
306
307
308
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_msg_t msg;
   __po_hi_port_t destination_port;

   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
317
318
   if (request->port == -1)
   {
319
      __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
320
321
322
      return __PO_HI_SUCCESS;
   }

323
324
325
326
327
328
   destination_port     = __po_hi_gqueue_get_destination (task_id, local_port, 0);

   __po_hi_msg_reallocate (&msg);

   request->port = destination_port;

329
   __po_hi_marshall_request (request, &msg);
330

331
332
333
334
   /* Swap only the port (first 32 bytes) */
   swap_pointer  = (unsigned long*) &msg.content[0];
   swap_value    = *swap_pointer;
   *swap_pointer = __po_hi_swap_byte (swap_value);
335

336
   n = write (po_hi_c_driver_serial_fd_write, &msg, __PO_HI_MESSAGES_MAX_SIZE);
337

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

340
341
   for (ts = 0 ; ts < __PO_HI_MESSAGES_MAX_SIZE ; ts++)
   {
342
      __PO_HI_DEBUG_DEBUG ("%x", msg.content[ts]);
343
   }
344
   __PO_HI_DEBUG_DEBUG ("\n");
345

jdelange's avatar
jdelange committed
346
347
   request->port = __PO_HI_GQUEUE_INVALID_PORT;

348
   return 1;
349
}
350
#endif
351

352
#endif