VCOM Linux Driver
Advantech Inc.
Loading...
Searching...
No Matches
vcom.h
Go to the documentation of this file.
1#ifndef __USER_SPACE_IF
2#define __USER_SPACE_IF
3
4#include <time.h>
5#include <stdarg.h>
6
7#include "advvcom.h"
8#include "vcom_proto.h"
9
10#ifdef _VCOM_SUPPORT_TLS
11#include "ssl_select.h"
12#endif
13
14#define VC_PULL_TIME 10000000
15#define VC_PULL_PSEC (VC_PULL_TIME / 1000000)
16#define VC_PULL_PUSEC (VC_PULL_TIME % 1000000)
17
18#define CONN_TO 10
19
20#define VC_TIME_USED(a) (VC_PULL_TIME - (a.tv_sec * 1000000 + a.tv_usec));
21#define STACK_MAX 10
22#define stk_full(a) ((a)->top>=STACK_MAX-1)
23#define stk_empty(a) ((a)->top<0)
24#define stk_bot(a) ((a)->top==0)
25struct stk_vc{
26 int top;
28};
29
30struct vc_attr{
31 int fd;
32 int sk;
35 int ttyid;
36#ifdef _VCOM_SUPPORT_TLS
37 ssl_info *ssl;
38#endif
39 unsigned int port;
40 unsigned int tid;
41 unsigned short devid;
42 struct stk_vc stk;
43 void * mbase;
44 char * ip_ptr;
45 char * ip_red;
48 struct ring_buf tx;
49 struct ring_buf rx;
50};
51#define ATTR_SAME 0
52#define ATTR_DIFF 1
53#define attr_p(a, b) (((a)->attr[(a)->attr_ptr]).b)
54#define eki_p(a, b) ((a)->eki.b)
55
56#define check_attr_stat(a, b) (attr_p(a, b) == eki_p(a, b)?ATTR_SAME:ATTR_DIFF)
57
58#define update_eki_attr(a, b, c) do{eki_p(a, b) = c;}while(0)
59
60struct vc_ops{
61 struct vc_ops * (*open)(struct vc_attr *);
62 struct vc_ops * (*close)(struct vc_attr *);
63 struct vc_ops * (*ioctl)(struct vc_attr *);
64 struct vc_ops * (*xmit)(struct vc_attr *);
65 struct vc_ops * (*recv)(struct vc_attr *, char * buf, int len);
66 struct vc_ops * (*poll)(struct vc_attr *);
67 struct vc_ops * (*init)(struct vc_attr *);
68 struct vc_ops * (*pause)(struct vc_attr *);
69 struct vc_ops * (*resume)(struct vc_attr *);
70 struct vc_ops * (*event)(struct vc_attr *, struct timeval *, fd_set *r, fd_set *w, fd_set *e);
71 char * (*name)(void);
72};
73#define try_ops1(a, b, c) (((a)->b > 0)?(a)->b(c):a)
74#define try_ops2(a, b, c, d) (((a)->b > 0)?(a)->b(c, d):a)
75#define try_ops3(a, b, c, d, e) (((a)->b > 0)?(a)->b(c, d, e):a)
76#define try_ops4(a, b, c, d, e, f) (((a)->b > 0)?(a)->b(c, d, e, f):a)
77#define try_ops5(a, b, c, d, e, f, g) (((a)->b > 0)?(a)->b(c, d, e, f, g):a)
78
79#define try_ovrld(_1, _2, _3, _4, _5, _6, _7, func,...) func
80#define try_ops(args...) try_ovrld(args, try_ops5 \
81 ,try_ops4 \
82 ,try_ops3 \
83 ,try_ops2 \
84 ,try_ops1 \
85 ,...)(args)
86static inline struct vc_ops * stk_curnt(struct stk_vc *stk);
87
88/*
89 * Vcom Monitor
90 */
91//#include "vcom_monitor.h" // The normal monitor
92#include "vcom_monitor_dbg.h" // monitor with record debug log
93//#include "vcom_monitor_pre_stat.h" // monitor with record pre-state
94
95#ifndef _VCOM_MONITOR_H
96#define mon_update(...) do{}while(0) // do nothing
97#define mon_init(a) do{}while(0) // do nothing
98#define mon_update_check(...) do{}while(0)
99#endif
100
101#define EXCP_SLEEPTIME 3
102#define EXCP_RECONN_TIME 5
103/*
104 * Switch == 1, trigger inotify and record the log
105 * Switch == 0, do nothing
106*/
107#define INO_PUSH_SWITCH 0
108#define INO_POP_SWITCH 0
109#define INO_RPLS_SWITCH 0
110#define INO_RESTART_SWITCH 0
111
112extern void * stk_mon;
113
114
115static inline int _stk_log(struct stk_vc *stk, char * __form, ...)
116{
117 char tmp[512];
118 int len;
119 va_list args;
120
121 len = 0;
122
123 if(stk == 0 || stk->top < 0){
124 printf("%s on empty stk\n", __func__);
125 exit(0);
126 }
127
128 len += snprintf(tmp, sizeof(tmp), "(%s)",
129 stk_curnt(stk)->name());
130
131 va_start(args, __form);
132 len += vsnprintf(&tmp[len], sizeof(tmp) -len , __form, args);
133 va_end(args);
134
135 mon_update_check(stk, 0, tmp);
136
137 return len;
138}
139/*
140 * state machine stack
141 */
142/*
143#define _expmsg(msg, len) \
144do{ if(stk->top >= 0) \
145 snprintf(msg, len, "(%s)%s,%d", stk->stk_stat[stk->top]->name(), __func__, __LINE__); \
146 else \
147 snprintf(msg, len, "(NULL)%s,%d", __func__, __LINE__); \
148}while(0)
149*/
150#define _expmsg_extra(msg, len, ...) \
151do{ int r; if(stk->top >= 0) {\
152_Pragma("GCC diagnostic ignored \"-Wformat-zero-length\"")\
153 r= snprintf(msg, len, "(%s)%s,%d:", stk->stk_stat[stk->top]->name(), \
154 __func__, __LINE__); \
155 snprintf(&msg[r],len -r, "" __VA_ARGS__);\
156 }else{ \
157 r= snprintf(msg, len, "(NULL)%s,%d:", __func__, __LINE__ ); \
158 snprintf(&msg[r],len -r, "" __VA_ARGS__);\
159 }\
160_Pragma("GCC diagnostic warning \"-Wformat-zero-length\"")\
161}while(0)
162
163#define stk_push(a, b) _stk_push(a, b)
164static inline int
165_stk_push(struct stk_vc *stk, struct vc_ops *current)
166{
167 if(stk_full(stk)){
168 printf("%s : stack full\n", __func__);
169 return -1;
170 }
171
172 stk->top += 1;
173 stk->stk_stat[stk->top] = current;
175
176 return 0;
177}
178
179#define stk_pop(a) _stk_pop(a)
180static inline int
181_stk_pop(struct stk_vc *stk)
182{
183 if(stk_empty(stk)){
184 printf("%s : stack empty\n", __func__);
185 return -1;
186 }
187
188 stk->top -= 1;
190
191 return 0;
192}
193
194//#define stk_excp(a) do{char msg[128]; _expmsg(msg, 128); _stk_excp(a, msg);}while(0)
195#define stk_excp(a, ...) do{char msg[256]; _expmsg_extra(msg, sizeof(msg),\
196 __VA_ARGS__);\
197 _stk_excp(a, msg);}while(0)
198static inline int
199_stk_excp(struct stk_vc *stk, char * msg)
200{
201 static time_t pre_excp_t = 0;
202 time_t now_excp_t;
203
204 if(stk_bot(stk)){
205 printf("%s : at the bottom of stack now\n", __func__);
206 return -1;
207 }
208
209 printf("stack exception !! %s\n", msg);
210 stk->top = 0;
211 mon_update_check(stk, 1, msg);
212
213 if(pre_excp_t == 0){ //mean first time excption
214 time(&pre_excp_t);
215 }else{
216 time(&now_excp_t);
217 if((now_excp_t-pre_excp_t) < EXCP_RECONN_TIME){
218 sleep(EXCP_SLEEPTIME);
219 }
220 pre_excp_t = now_excp_t;
221 }
222
223 return 0;
224}
225
226#define stk_rpls(a, b) _stk_rpls(a, b)
227static inline int
228_stk_rpls(struct stk_vc *stk, struct vc_ops *current)
229{
230 stk->stk_stat[stk->top] = current;
232
233 return 0;
234}
235
236static inline struct vc_ops * stk_curnt(struct stk_vc *stk)
237{
238 if(stk_empty(stk)){
239 printf("%s : no state in stack\n", __func__);
240 exit(0);
241 }
242
243 return stk->stk_stat[stk->top];
244}
245
246#define stk_restart(a) _stk_restart(a)
247static inline int
248_stk_restart(struct stk_vc *stk)
249{
250 if(stk_bot(stk)){
251 printf("at the bottom of stack now, should not call <%s> ...\n", __func__);
252 return -1;
253 }
254 stk->top = 0;
256
257 return 0;
258}
259
260static inline int __vc_sock_enblock(int sk, int enable)
261{
262 int skarg;
263 skarg = fcntl(sk, F_GETFL, 0);
264 if(skarg < 0){
265 printf("failed to GETFL\n");
266 return -1;
267 }
268
269 switch(enable){
270 case 0:
271 skarg |= O_NONBLOCK;
272 break;
273 default:
274 skarg &= ~O_NONBLOCK;
275 break;
276 }
277
278 if( fcntl(sk, F_SETFL, skarg) < 0){
279 printf("failed to SETFL\n");
280 return -1;
281 }
282
283 return 0;
284}
285
286#define VC_SKOPT_BLOCK 0
287#define VC_SKOPT_NONBLOCK 1
288#define VC_SKOPT_ENKALIVE 2
289#define VC_SKOPT_DISKALIVE 3
290extern struct vc_ops vc_netdown_ops;
291extern struct vc_ops vc_netup_ops;
292
293static inline int vc_config_sock(int sk, int option, void * arg)
294{
295 int result;
296#define OPT_ISMATCH(OPT, TMP) (OPT==TMP?1:0)
297 switch(option){
298 case VC_SKOPT_BLOCK:
300 result = __vc_sock_enblock(sk, OPT_ISMATCH(option, VC_SKOPT_BLOCK));
301 break;
304 break;
305 default:
306 return -1;
307 };
308#undef OPT_ISMATCH
309 return result;
310}
311
312#define VC_MAX_SKNUM 16
313#define VC_PROTO_PORT 5202
314#define VC_SSL_PROXY 5555
315
316static inline int __set_sockaddr_port(struct addrinfo *info, unsigned short port)
317{
318 struct sockaddr_in * sin;
319 struct sockaddr_in6 * sin6;
320
321 switch(info->ai_family){
322 case AF_INET:
323 printf("adding port %u to IPv4 address\n", port);
324 sin = (struct sockaddr_in *)info->ai_addr;
325 sin->sin_port = htons(port);
326 break;
327 case AF_INET6:
328 printf("adding port %u to IPv6 address\n", port);
329 sin6 = (struct sockaddr_in6 *)info->ai_addr;
330 sin6->sin6_port = htons(port);
331 break;
332 default:
333 printf("unknown address type cannot add port\n");
334 return -1;
335 };
336
337 return 0;
338}
339#define FD_RD_RDY 1
340#define FD_WR_RDY 2
341#define FD_EX_RDY 4
342static inline int fdcheck(int fd, int type, struct timeval * ctv)
343{
344 fd_set rfds;
345 fd_set wfds;
346 struct timeval tv;
347 int ret;
348
349 tv.tv_sec = 0;
350 tv.tv_usec = 0;
351
352 FD_ZERO(&rfds);
353 FD_ZERO(&wfds);
354 if(type& FD_RD_RDY){
355 FD_SET(fd, &rfds);
356 }
357 if(type& FD_WR_RDY){
358 FD_SET(fd, &wfds);
359 }
360 if(ctv > 0){
361 ret = select(fd + 1, &rfds, &wfds, 0, ctv);
362 }else{
363 ret = select(fd + 1, &rfds, &wfds, 0, &tv);
364 }
365
366 if(ret == 0)
367 return 0;
368
369 ret = 0;
370
371 if(FD_ISSET(fd, &rfds)){
372 ret |= FD_RD_RDY;
373 }
374
375 if(FD_ISSET(fd, &wfds)){
376 ret |= FD_WR_RDY;
377 }
378
379 return ret;
380}
381
382static inline int vc_check_send(struct vc_attr *attr,
383 struct vc_proto_packet *packet, int plen, char * dbg_msg)
384{
385#ifdef _VCOM_SUPPORT_TLS
386 int ssl_errno;
387 struct stk_vc * stk;
388
389 stk = &attr->stk;
390 if(attr->ssl){
391 if(ssl_send_simple(attr->ssl, packet, plen, 1000, &ssl_errno) != plen){
392 char ssl_errstr[256];
393 printf("failed to send %s over SSL\n", dbg_msg);
394 ssl_errno_str(attr->ssl, ssl_errno,
395 ssl_errstr,
396 sizeof(ssl_errstr));
397 _stk_log(stk, "%s;%s", dbg_msg, ssl_errstr);
398 return -1;
399 }
400 return 0;
401 }
402#endif
403 if(fdcheck(attr->sk, FD_WR_RDY, 0) == 0){
404 printf("cannot send %s\n", dbg_msg);
405 return -1;
406 }
407
408 if(send(attr->sk, packet, plen, MSG_NOSIGNAL) != plen){
409 printf("failed to send %s\n", dbg_msg);
410 return -1;
411 }
412
413 return 0;
414}
415
416#define VC_BUF_RX 0
417#define VC_BUF_TX 1
418#define VC_BUF_ATTR 2
419static inline int vc_buf_update(struct vc_attr * port, int rb_id)
420{
421 struct ring_buf *buf;
422 int fd = port->fd;
423 int head;
424 int tail;
425 int cmd_head;
426 int cmd_tail;
427
428 switch(rb_id){
429 case VC_BUF_RX:
430 cmd_head = ADVVCOM_IOCGRXHEAD;
431 cmd_tail = ADVVCOM_IOCGRXTAIL;
432 buf = &port->rx;
433 break;
434 case VC_BUF_TX:
435 cmd_head = ADVVCOM_IOCGTXHEAD;
436 cmd_tail = ADVVCOM_IOCGTXTAIL;
437 buf = &port->tx;
438 break;
439 case VC_BUF_ATTR:
440 if(ioctl(fd, ADVVCOM_IOCGATTRPTR, &port->attr_ptr)){
441 printf("get attrptr failed\n");
442 }
443 return 0;
444 default:
445 printf("unknown buf type\n");
446 return -1;
447 }
448
449 if(ioctl(fd, cmd_head, &head) < 0){
450 printf("cannot get head\n");
451 return -1;
452 }
453
454 if(ioctl(fd, cmd_tail, &tail) < 0){
455 printf("cannot get tail\n");
456 return -1;
457 }
458
459 buf->head = head;
460 buf->tail = tail;
461
462 return 0;
463}
464
465static inline void vc_buf_clear(struct vc_attr * port, unsigned int clrflags)
466{
467 int len = 0;
468
469 if(ioctl(port->fd, ADVVCOM_IOCSCLR, &clrflags) < 0){
470 printf("couldn't set iocsclr\n");
471 return;
472 }
473 if(clrflags & ADV_CLR_RX){
474 if(ioctl(port->fd, ADVVCOM_IOCSRXHEAD, &len) < 0){
475 printf("move RX head failed\n");
476 }
477 vc_buf_update(port, VC_BUF_RX);
478 }
479 if(clrflags & ADV_CLR_TX){
480 vc_buf_update(port, VC_BUF_TX);
481 }
482}
483
484static inline int vc_buf_setup(struct vc_attr * port, int rb_id)
485{
486 struct ring_buf *buf;
487 int fd = port->fd;
488 char * mbase = port->mbase;
489 int begin;
490 int size;
491 int cmd_begin;
492 int cmd_size;
493
494 switch(rb_id){
495 case VC_BUF_RX:
496 cmd_begin = ADVVCOM_IOCGRXBEGIN;
497 cmd_size = ADVVCOM_IOCGRXSIZE;
498 buf = &port->rx;
499 break;
500 case VC_BUF_TX:
501 cmd_begin = ADVVCOM_IOCGTXBEGIN;
502 cmd_size = ADVVCOM_IOCGTXSIZE;
503 buf = &port->tx;
504 break;
505 case VC_BUF_ATTR:
506 cmd_begin = ADVVCOM_IOCGATTRBEGIN;
507 break;
508 default:
509 printf("unknown buf type\n");
510 return -1;
511 }
512
513 if(ioctl(fd, cmd_begin, &begin)){
514 return -1;
515 }
516
517 switch(rb_id){
518 case VC_BUF_RX:
519 case VC_BUF_TX:
520 if(ioctl(fd, cmd_size, &size)){
521 printf("failed to get size\n");
522 return -1;
523 }
524 buf->begin = begin;
525 buf->size = size;
526 buf->mbase = &mbase[begin];
527 break;
528
529 case VC_BUF_ATTR:
530 port->attr = (struct adv_port_info *)&mbase[begin];
531 break;
532 }
533
534 return vc_buf_update(port, rb_id);
535}
536#endif
#define ADV_CLR_TX
Definition advioctl.h:30
#define ADVVCOM_IOCGRXTAIL
Definition advioctl.h:8
#define ADVVCOM_IOCSCLR
Definition advioctl.h:18
#define ADVVCOM_IOCGTXBEGIN
Definition advioctl.h:12
#define ADVVCOM_IOCGRXHEAD
Definition advioctl.h:7
#define ADVVCOM_IOCGTXHEAD
Definition advioctl.h:4
#define ADV_CLR_RX
Definition advioctl.h:29
#define ADVVCOM_IOCGRXSIZE
Definition advioctl.h:9
#define ADVVCOM_IOCGATTRPTR
Definition advioctl.h:15
#define ADVVCOM_IOCGTXTAIL
Definition advioctl.h:5
#define ADVVCOM_IOCGATTRBEGIN
Definition advioctl.h:14
#define ADVVCOM_IOCGTXSIZE
Definition advioctl.h:6
#define ADVVCOM_IOCSRXHEAD
Definition advioctl.h:11
#define ADVVCOM_IOCGRXBEGIN
Definition advioctl.h:13
int ssl_errno_str(ssl_info *info, int ssl_errno, char *buf, int buflen)
Definition ssl_select.c:301
int ssl_send_simple(ssl_info *info, void *buf, int len, int to_ms, int *ssl_errno)
Definition advtype.h:31
Definition advvcom.h:25
int head
Definition advvcom.h:27
int size
Definition advvcom.h:30
int begin
Definition advvcom.h:29
int tail
Definition advvcom.h:28
Definition ssl_select.h:18
Definition vcom.h:25
struct vc_ops * stk_stat[STACK_MAX]
Definition vcom.h:27
int top
Definition vcom.h:26
Definition vcom.h:30
int ttyid
Definition vcom.h:35
struct adv_port_info eki
Definition vcom.h:46
int sk
Definition vcom.h:32
int fd
Definition vcom.h:31
unsigned short devid
Definition vcom.h:41
unsigned int tid
Definition vcom.h:40
unsigned int port
Definition vcom.h:39
void * mbase
Definition vcom.h:43
struct adv_port_info * attr
Definition vcom.h:47
char * ip_ptr
Definition vcom.h:44
int xmit_pending
Definition vcom.h:34
int attr_ptr
Definition vcom.h:33
struct ring_buf rx
Definition vcom.h:49
char * ip_red
Definition vcom.h:45
struct ring_buf tx
Definition vcom.h:48
struct stk_vc stk
Definition vcom.h:42
Definition vcom.h:60
char *(* name)(void)
Definition vcom.h:71
Definition vcom_proto.h:52
struct vc_ops vc_netdown_ops
Definition vc_client_netdown.c:27
#define INO_RPLS_SWITCH
Definition vcom.h:109
#define FD_WR_RDY
Definition vcom.h:340
#define VC_SKOPT_ENKALIVE
Definition vcom.h:288
#define STACK_MAX
Definition vcom.h:21
#define VC_BUF_TX
Definition vcom.h:417
#define EXCP_SLEEPTIME
Definition vcom.h:101
#define OPT_ISMATCH(OPT, TMP)
#define VC_SKOPT_DISKALIVE
Definition vcom.h:289
#define VC_BUF_RX
Definition vcom.h:416
#define VC_SKOPT_NONBLOCK
Definition vcom.h:287
#define INO_RESTART_SWITCH
Definition vcom.h:110
#define stk_full(a)
Definition vcom.h:22
struct vc_ops vc_netup_ops
Definition vc_client_netup.c:28
#define VC_BUF_ATTR
Definition vcom.h:418
#define mon_update_check(...)
Definition vcom.h:98
#define stk_bot(a)
Definition vcom.h:24
#define INO_PUSH_SWITCH
Definition vcom.h:107
#define INO_POP_SWITCH
Definition vcom.h:108
void * stk_mon
Definition vcom_client.c:33
#define stk_empty(a)
Definition vcom.h:23
#define EXCP_RECONN_TIME
Definition vcom.h:102
#define VC_SKOPT_BLOCK
Definition vcom.h:286
#define FD_RD_RDY
Definition vcom.h:339
unsigned short len
Definition vcom_proto.h:3