botsense  3.2.0
RoadNarrows Client-Server Proxied Services Framework
bsSerialServer.c
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: BotSense
4 // Module: bsSerial
5 // Library: libbsserver_serial
6 // File: bsSerialServer.c
7 //
8 /*! \file
9  *
10  * $LastChangedDate: 2010-08-20 11:36:38 -0600 (Fri, 20 Aug 2010) $
11  * $Rev: 568 $
12  *
13  * \brief \h_botsense bsProxy server plug-in DLL RS-232 serial device module.
14  *
15  * \author Robin Knight (robin.knight@roadnarrows.com)
16  *
17  * \copyright
18  * \h_copy 2010-2017. RoadNarrows LLC.\n
19  * http://www.roadnarrows.com\n
20  * All Rights Reserved
21  */
22 // Permission is hereby granted, without written agreement and without
23 // license or royalty fees, to use, copy, modify, and distribute this
24 // software and its documentation for any purpose, provided that
25 // (1) The above copyright notice and the following two paragraphs
26 // appear in all copies of the source code and (2) redistributions
27 // including binaries reproduces these notices in the supporting
28 // documentation. Substantial modifications to this software may be
29 // copyrighted by their authors and need not follow the licensing terms
30 // described here, provided that the new terms are clearly indicated in
31 // all files where they apply.
32 //
33 // IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY MEMBERS/EMPLOYEES
34 // OF ROADNARROW LLC OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY
35 // PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
36 // DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
37 // EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF
38 // THE POSSIBILITY OF SUCH DAMAGE.
39 //
40 // THE AUTHOR AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
41 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
42 // FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
43 // "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
44 // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
45 //
46 ////////////////////////////////////////////////////////////////////////////////
47 
48 #include <stdio.h>
49 #include <string.h>
50 #include <errno.h>
51 
52 #include "rnr/rnrconfig.h"
53 #include "rnr/log.h"
54 #include "rnr/new.h"
55 #include "rnr/netmsgs.h"
56 #include "rnr/serdev.h"
57 
58 #include "botsense/BotSense.h"
59 #include "botsense/libBotSense.h"
60 #include "botsense/bsProxyModIF.h"
61 #include "botsense/bsSerial.h"
62 #include "botsense/bsSerialMsgs.h"
63 
64 
65 // ---------------------------------------------------------------------------
66 // Private Interface
67 // ---------------------------------------------------------------------------
68 
69 /*!
70  * \brief Module static information.
71  */
73 {
75  .brief = "Raw R2-232 serial proxied device.",
76  .version = "2.0.0",
77  .date = "2010.03.09",
78  .maintainer = "RaodNarrows LLC",
79  .license = "(C) 2010 RoadNarrows LLC. All rights reserved."
80 };
81 
82 /*!
83  * \ingroup bsmod_serial_srv
84  * \defgroup bsmod_serial_srv_tunes Default Tunables
85  *
86  * \h_botsense Serial Interface Module Tunables
87  *
88  * \note These can be overriden in the configuration XML file.
89  *
90  * \{
91  */
92 
93 /*!
94  * \brief Maximum number of module supported simultaneous virtual connections.
95  */
96 #define BSMOD_MAX_HANDLES 8
97 
98 // timeouts
99 #define BSMOD_T_READ 1000000 ///< default read time out (usec)
100 #define BSMOD_T_TRANS 2000000 ///< default transaction time out (usec)
101 #define BSMOD_T_WRITE 1000000 ///< default write time out (usec)
102 
103 /*! \} */
104 
105 /*!
106  * \brief Module resource control block structure type.
107  */
108 typedef struct
109 {
110  int m_fd; ///< serial device open file descriptor
111  const char *m_sDevUri; ///< serial device path name
112  BsSerialReqOpenArgs_T m_stDevCfg; ///< serial device configuration
113  bool_t m_bTrace; ///< do [not] trace messages
114 } BsModCtlBlk_T;
115 
116 static const char *BsModUri; ///< module canonical name
117 static const BsModProxyCb_T *BsModCallbacks; ///< module to bsProxy callbacks
118 static BsModRsrcTbl_T *BsModRsrcTbl; ///< module resource table
119 
120 
121 /*!
122  * \brief Allocate a new resource control block.
123  *
124  * \param fd Opened device file descriptor \h_ge 0.
125  * \param sDevUri Device URI.
126  * \param pDevCfg Device configuration parameters.
127  * \param bTrace Do [not] trace messages.
128  *
129  * \return Pointer to new allocated control block.
130  */
132  const char *sDevUri,
133  BsSerialReqOpenArgs_T *pDevCfg,
134  bool_t bTrace)
135 {
136  BsModCtlBlk_T *pCtlBlk;
137 
138  pCtlBlk = NEW(BsModCtlBlk_T);
139 
140  pCtlBlk->m_fd = fd;
141  pCtlBlk->m_sDevUri = new_strdup(sDevUri);
142  pCtlBlk->m_stDevCfg = *pDevCfg;
143  pCtlBlk->m_bTrace = bTrace;
144 
145  return pCtlBlk;
146 }
147 
148 /*!
149  * \brief Delete an allocated resource control block.
150  *
151  * \param pCtlBlk Pointer to allocated control block.
152  */
153 static void bsModCtlBlkDelete(BsModCtlBlk_T *pCtlBlk)
154 {
155  if( pCtlBlk != NULL )
156  {
157  delete((void *)(pCtlBlk->m_sDevUri));
158  delete(pCtlBlk);
159  }
160 }
161 
162 /*!
163  * \brief Service a serial read request.
164  *
165  * \note A module-specific request service must send a response.
166  *
167  * \param hndVConn Virtual connection handle.
168  * \param uTid Request-Response transaction id.
169  * \param uMsgIdReq Request message id.
170  * \param bufReq Packed request message buffer.
171  * \param uReqLen Size of request in buffer (number of bytes).
172  *
173  * \copydoc doc_return_std
174  */
175 static int bsModSerialReqRead(BsVConnHnd_T hndVConn,
176  BsTid_T uTid,
177  BsMsgId_T uMsgIdReq,
178  byte_t bufReq[],
179  size_t uReqLen)
180 {
181  static BsSerialMsgId_T uMsgIdRsp = BsSerialMsgIdRspRead;
182 
183  BsModCtlBlk_T *pCtlBlk; // resource control block
184  BsSerialReqRead_T msgReq; // request message
185  BsSerialRspRead_T msgRsp; // response message
186  byte_t bufRsp[BSPROXY_MSG_MAX_LEN]; // req/rsp buffer
187  int n; // number of bytes/return code
188 
189  //
190  // Parameter checks
191  //
192  if( !BSMOD_IS_VCONN_HANDLE(hndVConn) )
193  {
194  BSMOD_SEND_ERROR_RSP(BsModCallbacks, hndVConn, uTid, BS_ECODE_BAD_VCONN_HND,
195  "Module vconn handle out-of-range.");
196  return -BS_ECODE_BAD_VCONN_HND; \
197  }
198 
199  // retrieve the resource control block
200  pCtlBlk = (BsModCtlBlk_T *)BSMOD_RSRC(BsModRsrcTbl, hndVConn);
201 
202  if( pCtlBlk == NULL )
203  {
204  BSMOD_SEND_ERROR_RSP(BsModCallbacks, hndVConn, uTid, BS_ECODE_NO_VCONN,
205  "No resources for virtual connection found.");
206  return -BS_ECODE_NO_VCONN;
207  }
208 
209  //
210  // Unpack client request.
211  //
212  n = BsSerialUnpackReqRead(bufReq, uReqLen, &msgReq, pCtlBlk->m_bTrace);
213 
214  // check unpacking return code
215  if( n < 0 )
216  {
217  BSMOD_SEND_NMERROR_RSP(BsModCallbacks, hndVConn, uTid, n,
218  "MsgId=%u", uMsgIdReq);
219  return -BS_ECODE_BAD_MSG;
220  }
221 
222  //
223  // Execute client request.
224  //
225  n = (int)SerDevRead(pCtlBlk->m_fd, msgRsp.m_readbuf.u.m_buf,
226  (size_t)msgReq.m_readlen, BSMOD_T_READ);
227 
228  // check operation return code
229  if( n < 0 )
230  {
231  BSMOD_SEND_SYSERROR_RSP(BsModCallbacks, hndVConn, uTid,
232  "SerDevRead(%d,...).", pCtlBlk->m_fd);
233  return -BS_ECODE_SYS;
234  }
235 
236  LOGDIAG3("VConn=%d: %d=SerDevRead(fd=%d, buf=%p, count=%zu, usec=%u).",
237  hndVConn, n, pCtlBlk->m_fd, msgRsp.m_readbuf.u.m_buf,
238  (size_t)msgReq.m_readlen, BSMOD_T_READ);
239 
240  //
241  // Pack server response.
242  //
243  msgRsp.m_readbuf.m_count = (byte_t)n;
244 
245  // pack
246  n = BsSerialPackRspRead(&msgRsp, BSPROXY_BUF_BODY(bufRsp), pCtlBlk->m_bTrace);
247 
248  // check packing return code
249  if( n < 0 )
250  {
251  BSMOD_SEND_NMERROR_RSP(BsModCallbacks, hndVConn, uTid, n,
252  "MsgId=%u", uMsgIdRsp);
253  return -BS_ECODE_BAD_MSG;
254  }
255 
256  //
257  // Send response.
258  //
259  BsModCallbacks->m_cbSendRsp(hndVConn, uTid, uMsgIdRsp, bufRsp, (size_t)n);
260 
261  return BS_OK;
262 }
263 
264 /*!
265  * \brief Service a serial write request.
266  *
267  * \note A module-specific request service must send a response.
268  *
269  * \param hndVConn Virtual connection handle.
270  * \param uTid Request-Response transaction id.
271  * \param uMsgIdReq Request message id.
272  * \param bufReq Packed request message buffer.
273  * \param uReqLen Size of request in buffer (number of bytes).
274  *
275  * \copydoc doc_return_std
276  */
277 static int bsModSerialReqWrite(BsVConnHnd_T hndVConn,
278  BsTid_T uTid,
279  BsMsgId_T uMsgIdReq,
280  byte_t bufReq[],
281  size_t uReqLen)
282 {
283  static BsSerialMsgId_T uMsgIdRsp = BsSerialMsgIdRspWrite;
284 
285  BsModCtlBlk_T *pCtlBlk; // resource control block
286  BsSerialReqWrite_T msgReq; // request message
287  BsSerialRspWrite_T msgRsp; // response message
288  byte_t bufRsp[BSPROXY_MSG_MAX_LEN]; // req/rsp buffer
289  int n; // number of bytes/return code
290 
291  //
292  // Parameter checks
293  //
294  if( !BSMOD_IS_VCONN_HANDLE(hndVConn) )
295  {
296  BSMOD_SEND_ERROR_RSP(BsModCallbacks, hndVConn, uTid, BS_ECODE_BAD_VCONN_HND,
297  "Module vconn handle out-of-range.");
298  return -BS_ECODE_BAD_VCONN_HND; \
299  }
300 
301  // retrieve the resource control block
302  pCtlBlk = (BsModCtlBlk_T *)BSMOD_RSRC(BsModRsrcTbl, hndVConn);
303 
304  if( pCtlBlk == NULL )
305  {
306  BSMOD_SEND_ERROR_RSP(BsModCallbacks, hndVConn, uTid, BS_ECODE_NO_VCONN,
307  "No resources for virtual connection found.");
308  return -BS_ECODE_NO_VCONN;
309  }
310 
311  //
312  // Unpack client request.
313  //
314  n = BsSerialUnpackReqWrite(bufReq, uReqLen, &msgReq, pCtlBlk->m_bTrace);
315 
316  // check unpacking return code
317  if( n < 0 )
318  {
319  BSMOD_SEND_NMERROR_RSP(BsModCallbacks, hndVConn, uTid, n,
320  "MsgId=%u", uMsgIdReq);
321  return -BS_ECODE_BAD_MSG;
322  }
323 
324  //
325  // Execute client request.
326  //
327  n = (int)SerDevWrite(pCtlBlk->m_fd, msgReq.m_writebuf.u.m_buf,
328  (size_t)msgReq.m_writebuf.m_count, BSMOD_T_WRITE);
329 
330  // check operation return code
331  if( n < 0 )
332  {
333  BSMOD_SEND_SYSERROR_RSP(BsModCallbacks, hndVConn, uTid,
334  "SerDevWrite(%d,...).", pCtlBlk->m_fd);
335  return -BS_ECODE_SYS;
336  }
337 
338  LOGDIAG3("VConn=%d: %d=SerDevWrite(fd=%d, buf=%p, count=%zu, usec=%u).",
339  hndVConn, n, pCtlBlk->m_fd, msgReq.m_writebuf.u.m_buf,
340  (size_t)msgReq.m_writebuf.m_count, BSMOD_T_WRITE);
341 
342  //
343  // Pack server response.
344  //
345  msgRsp.m_byteswritten = (byte_t)n;
346 
347  // pack
348  n = BsSerialPackRspWrite(&msgRsp, BSPROXY_BUF_BODY(bufRsp),
349  pCtlBlk->m_bTrace);
350 
351  // check packing return code
352  if( n < 0 )
353  {
354  BSMOD_SEND_NMERROR_RSP(BsModCallbacks, hndVConn, uTid, n,
355  "MsgId=%u", uMsgIdRsp);
356  return -BS_ECODE_BAD_MSG;
357  }
358 
359  //
360  // Send response.
361  //
362  BsModCallbacks->m_cbSendRsp(hndVConn, uTid, uMsgIdRsp, bufRsp, (size_t)n);
363 
364  return BS_OK;
365 }
366 
367 /*!
368  * \brief Service a serial write-read transaction request.
369  *
370  * \note A module-specific request service must send a response.
371  *
372  * \param hndVConn Virtual connection handle.
373  * \param uTid Request-Response transaction id.
374  * \param uMsgIdReq Request message id.
375  * \param bufReq Packed request message buffer.
376  * \param uReqLen Size of request in buffer (number of bytes).
377  *
378  * \copydoc doc_return_std
379  */
380 static int bsModSerialReqTrans(BsVConnHnd_T hndVConn,
381  BsTid_T uTid,
382  BsMsgId_T uMsgIdReq,
383  byte_t bufReq[],
384  size_t uReqLen)
385 {
386  static BsSerialMsgId_T uMsgIdRsp = BsSerialMsgIdRspRead;
387 
388  BsModCtlBlk_T *pCtlBlk; // resource control block
389  BsSerialReqTrans_T msgReq; // request message
390  BsSerialRspRead_T msgRsp; // response message
391  byte_t bufRsp[BSPROXY_MSG_MAX_LEN]; // req/rsp buffer
392  int n; // number of bytes/return code
393 
394  //
395  // Parameter checks
396  //
397  if( !BSMOD_IS_VCONN_HANDLE(hndVConn) )
398  {
399  BSMOD_SEND_ERROR_RSP(BsModCallbacks, hndVConn, uTid, BS_ECODE_BAD_VCONN_HND,
400  "Module vconn handle out-of-range.");
401  return -BS_ECODE_BAD_VCONN_HND; \
402  }
403 
404  // retrieve the resource control block
405  pCtlBlk = (BsModCtlBlk_T *)BSMOD_RSRC(BsModRsrcTbl, hndVConn);
406 
407  if( pCtlBlk == NULL )
408  {
409  BSMOD_SEND_ERROR_RSP(BsModCallbacks, hndVConn, uTid, BS_ECODE_NO_VCONN,
410  "No resources for virtual connection found.");
411  return -BS_ECODE_NO_VCONN;
412  }
413 
414  //
415  // Unpack client request.
416  //
417  n = BsSerialUnpackReqTrans(bufReq, uReqLen, &msgReq, pCtlBlk->m_bTrace);
418 
419  // check unpacking return code
420  if( n < 0 )
421  {
422  BSMOD_SEND_NMERROR_RSP(BsModCallbacks, hndVConn, uTid, n,
423  "MsgId=%u", uMsgIdReq);
424  return -BS_ECODE_BAD_MSG;
425  }
426 
427  //
428  // Execute client request.
429  //
430  n = (int)SerDevWrite(pCtlBlk->m_fd, msgReq.m_writebuf.u.m_buf,
431  (size_t)msgReq.m_writebuf.m_count, BSMOD_T_WRITE);
432 
433  // check operation return code
434  if( n < 0 )
435  {
436  BSMOD_SEND_SYSERROR_RSP(BsModCallbacks, hndVConn, uTid,
437  "SerDevWrite(%d,...).", pCtlBlk->m_fd);
438  return -BS_ECODE_SYS;
439  }
440 
441  LOGDIAG3("VConn=%d: %d=SerDevWrite(fd=%d, buf=%p, count=%zu, usec=%u).",
442  hndVConn, n, pCtlBlk->m_fd, msgReq.m_writebuf.u.m_buf,
443  (size_t)msgReq.m_writebuf.m_count, BSMOD_T_WRITE);
444 
445  n = (int)SerDevRead(pCtlBlk->m_fd, msgRsp.m_readbuf.u.m_buf,
446  (size_t)msgReq.m_readlen, BSMOD_T_READ);
447 
448  // check operation return code
449  if( n < 0 )
450  {
451  BSMOD_SEND_SYSERROR_RSP(BsModCallbacks, hndVConn, uTid,
452  "SerDevRead(%d,...).", pCtlBlk->m_fd);
453  return -BS_ECODE_SYS;
454  }
455 
456  LOGDIAG3("VConn=%d: %d=SerDevRead(fd=%d, buf=%p, count=%zu, usec=%u)).",
457  hndVConn, n, pCtlBlk->m_fd, msgRsp.m_readbuf.u.m_buf,
458  (size_t)msgReq.m_readlen, BSMOD_T_READ);
459 
460  //
461  // Pack server response.
462  //
463  msgRsp.m_readbuf.m_count = (byte_t)n;
464 
465  // pack
466  n = BsSerialPackRspRead(&msgRsp, BSPROXY_BUF_BODY(bufRsp), pCtlBlk->m_bTrace);
467 
468  // check packing return code
469  if( n < 0 )
470  {
471  BSMOD_SEND_NMERROR_RSP(BsModCallbacks, hndVConn, uTid, n,
472  "MsgId=%u", uMsgIdRsp);
473  return -BS_ECODE_BAD_MSG;
474  }
475 
476  //
477  // Send response.
478  //
479  BsModCallbacks->m_cbSendRsp(hndVConn, uTid, uMsgIdRsp, bufRsp, (size_t)n);
480 
481  return BS_OK;
482 }
483 
484 
485 // ---------------------------------------------------------------------------
486 // Exported Interface
487 // ---------------------------------------------------------------------------
488 
489 /*!
490  * \brief Initialize serial module.
491  *
492  * Called once after module is loaded.
493  *
494  * \param sModUri Expanded, canonical module path name.
495  * \param pCallbacks Pointer to a set of module -> bsProxy core callback
496  * functions.
497  *
498  * \copydoc doc_return_std
499  */
500 int bsModInit(const char *sModUri, const BsModProxyCb_T *pCallbacks)
501 {
502  BsModUri = new_strdup(sModUri);
503 
504  // save bsProxy server callbacks
505  BsModCallbacks = pCallbacks;
506 
507  // create module resource table
508  BsModRsrcTbl = BsModCallbacks->m_cbModRsrcTblNew(BSMOD_MAX_HANDLES);
509 
510  return BS_OK;
511 }
512 
513 /*!
514  * \brief Exit serial module.
515  *
516  * Called once prior to module being unloaded.
517  *
518  * All open serial devices will be closed.
519  */
520 void bsModExit()
521 {
522  int index;
523  BsModCtlBlk_T *pCtlBlk;
524 
525  // free all module virtual connnection resources.
526  for(index=0; index<BSMOD_MAX_HANDLES; ++index)
527  {
528  if( (pCtlBlk = (BsModCtlBlk_T *)BsModRsrcTbl->m_vecRsrc[index]) != NULL )
529  {
530  if( pCtlBlk->m_fd >= 0 )
531  {
532  SerDevClose(pCtlBlk->m_fd);
533  }
534  bsModCtlBlkDelete(pCtlBlk);
535  }
536  }
537 
538  // free resource table
539  BsModCallbacks->m_cbModRsrcTblDelete(BsModRsrcTbl);
540 
541  delete((char *)BsModUri);
542 }
543 
544 /*!
545  * \brief Open a serial device and associate with the given handle.
546  *
547  * Subsequent calls to the module use the given handle to associate the
548  * specific module-device instance.
549  *
550  * The argument buffer contains packed message arguements specific to the
551  * device and module.
552  *
553  * \note Each call to this exported function will open the serial device and
554  * set the appropriate configuration, even if the device is already opened
555  * by this or another module.
556  *
557  * \note
558  * It is the responsibile of the client to ensure consistency if more than
559  * one virtual connection is established.
560  *
561  * \param hndVConn Virtual connection handle.
562  * \param bTrace Do [not] enable message tracing on this handle.
563  * \param sDevUri Device URI.
564  * \param argbuf Packed specific open configuration arguments submessage.
565  * \param uArgSize Size of packed argumets in buffer (number of bytes).
566  *
567  * \return
568  * On success, returns a unique resource descriptor \h_ge 0 which is typically
569  * an opened file descriptor or socket descriptor, but can be module defined.\n
570  * \copydoc doc_return_ecode
571  */
572 int bsModOpen(BsVConnHnd_T hndVConn,
573  bool_t bTrace,
574  const char *sDevUri,
575  byte_t argbuf[],
576  size_t uArgSize)
577 {
578  BsModCtlBlk_T *pCtlBlk;
579  BsSerialReqOpenArgs_T devcfg;
580  int fd;
581  int rc;
582 
583  // Check if handle is in valid range.
584  BSMOD_TRY_VCONN_HND_RANGE(hndVConn);
585 
586  // Check if resources are available.
587  if( BSMOD_RSRC_INUSE_COUNT(BsModRsrcTbl) >= BSMOD_MAX_HANDLES )
588  {
590  "InUseCount=%u: No more resources available.",
591  BSMOD_RSRC_INUSE_COUNT(BsModRsrcTbl));
592  return -BS_ECODE_NO_RSRC;
593  }
594 
595  // Check if the resource in resource table is not already in-use.
596  else if( BSMOD_RSRC_IS_INUSE(BsModRsrcTbl, hndVConn) )
597  {
598  BSMOD_LOG_ERROR(hndVConn, BS_ECODE_BUSY,
599  "Module virtual connection handle already in use");
600  return -BS_ECODE_BUSY;
601  }
602 
603  // unpack device configuration arguments submessage
604  rc = BsSerialUnpackReqOpenArgs(argbuf, uArgSize, &devcfg, bTrace);
605 
606  if( rc < 0 )
607  {
608  BSMOD_LOG_NMERROR(hndVConn, rc,
609  "Unpacking failed on BsSerialReqOpenArgs submessage");
610  return -BS_ECODE_BAD_MSG;
611  }
612 
613  // open serial device
614  fd = SerDevOpen(sDevUri, (int)devcfg.m_baudrate, (int)devcfg.m_bytesize,
615  (int)devcfg.m_parity, (int)devcfg.m_stopbits,
616  devcfg.m_rtscts, devcfg.m_xonxoff);
617 
618  if( fd < 0 )
619  {
620  BSMOD_LOG_SYSERROR(hndVConn, "SerDevOpen(%s,...).", sDevUri);
621  return -BS_ECODE_SYS;
622  }
623 
624  // allocate a new control block and initialize
625  pCtlBlk = bsModCtlBlkNew(fd, sDevUri, &devcfg, bTrace);
626 
627  // add to module resource table
628  BsModCallbacks->m_cbModRsrcAdd(BsModRsrcTbl, hndVConn, pCtlBlk);
629 
630  LOGDIAG2("VConn=%d: %d=SerDevOpen(dev=%s, %d,%d,%c,%d, rts=%s, xon=%s).",
631  hndVConn, fd, sDevUri,
632  (int)devcfg.m_baudrate, (int)devcfg.m_bytesize,
633  devcfg.m_parity, (int)devcfg.m_stopbits,
634  (devcfg.m_rtscts? "true": "false"),
635  (devcfg.m_xonxoff? "true": "false"));
636 
637  return fd;
638 }
639 
640 /*!
641  * \brief Close the serial device and disassociate virtual connection handle.
642  *
643  * The specific serial resources are freed.
644  *
645  * \param hndVConn Virtual connection handle.
646  *
647  * \return
648  * \copydoc doc_return_std
649  */
651 {
652  BsModCtlBlk_T *pCtlBlk;
653 
654  // check if handle is in valid range
655  BSMOD_TRY_VCONN_HND_RANGE(hndVConn);
656 
657  // check is resouce is in-use (i.e. opened)
658  if( !BSMOD_RSRC_IS_INUSE(BsModRsrcTbl, hndVConn) )
659  {
661  "Resources for virtual connection not found.");
662  return -BS_ECODE_NO_VCONN;
663  }
664 
665  // remove resource from module's resource table
666  pCtlBlk = (BsModCtlBlk_T *)BsModCallbacks->m_cbModRsrcRemove(BsModRsrcTbl,
667  hndVConn);
668 
669  if( pCtlBlk == NULL )
670  {
671  BSMOD_LOG_ERROR(hndVConn, BS_ECODE_INTERNAL, "No module resource found.");
672  return -BS_ECODE_INTERNAL;
673  }
674 
675  if( pCtlBlk->m_fd >= 0 )
676  {
677  SerDevClose(pCtlBlk->m_fd);
678  LOGDIAG2("VConn=%d: SerDevClose(fd=%d).", hndVConn, pCtlBlk->m_fd);
679  }
680 
681  bsModCtlBlkDelete(pCtlBlk);
682 
683  return BS_OK;
684 }
685 
686 /*!
687  * \brief Service a serial request.
688  *
689  * \note A module-specific request service must send a response.
690  *
691  * \param hndVConn Virtual connection handle.
692  * \param uTid Request-Response transaction id.
693  * \param uMsgIdReq Request message id.
694  * \param bufReq Packed request message buffer.
695  * \param uReqLen Size of request in buffer (number of bytes).
696  *
697  * \copydoc doc_return_std
698  */
700  BsTid_T uTid,
701  BsMsgId_T uMsgIdReq,
702  byte_t bufReq[],
703  size_t uReqLen)
704 {
705  BsModCtlBlk_T *pCtlBlk;
706 
707  // check if handle is in valid range
708  if( !BSMOD_IS_VCONN_HANDLE(hndVConn) )
709  {
710  BSMOD_SEND_ERROR_RSP(BsModCallbacks, hndVConn, uTid, BS_ECODE_BAD_VCONN_HND,
711  "Module vconn handle out-of-range.");
712  return -BS_ECODE_BAD_VCONN_HND; \
713  }
714 
715  // retrieve resource control block
716  pCtlBlk = (BsModCtlBlk_T *)BSMOD_RSRC(BsModRsrcTbl, hndVConn);
717 
718  // check resource
719  if( pCtlBlk == NULL )
720  {
721  BSMOD_SEND_ERROR_RSP(BsModCallbacks, hndVConn, uTid, BS_ECODE_NO_VCONN,
722  "No resources for virtual connection found.");
723  return -BS_ECODE_NO_VCONN;
724  }
725 
726  switch( uMsgIdReq )
727  {
729  return bsModSerialReqRead(hndVConn, uTid, uMsgIdReq, bufReq, uReqLen);
731  return bsModSerialReqTrans(hndVConn, uTid, uMsgIdReq, bufReq, uReqLen);
733  return bsModSerialReqWrite(hndVConn, uTid, uMsgIdReq, bufReq, uReqLen);
734  default:
735  BSMOD_SEND_ERROR_RSP(BsModCallbacks, hndVConn, uTid, BS_ECODE_UNKNOWN_REQ,
736  "MsgId=%u.", uMsgIdReq);
737  return -BS_ECODE_UNKNOWN_REQ;
738  }
739 }
740 
741 /*!
742  * \brief Enable/disable message tracing on handle.
743  *
744  * \param hndVConn Virtual connection handle.
745  * \param bTrace Do [not] enable message tracing on this handle.
746  *
747  * \copydoc doc_return_std
748  */
749 int bsModTrace(BsVConnHnd_T hndVConn, bool_t bTrace)
750 {
751  BsModCtlBlk_T *pCtlBlk;
752 
753  // check if handle is in valid range
754  if( !BSMOD_IS_VCONN_HANDLE(hndVConn) )
755  {
757  "Module vconn handle out-of-range.");
758  return -BS_ECODE_BAD_VCONN_HND;
759  }
760 
761  // retrieve resource control block
762  pCtlBlk = (BsModCtlBlk_T *)BSMOD_RSRC(BsModRsrcTbl, hndVConn);
763 
764  // check resource
765  if( pCtlBlk == NULL )
766  {
768  "No resources for virtual connection found.");
769  return -BS_ECODE_NO_VCONN;
770  }
771 
772  pCtlBlk->m_bTrace = bTrace;
773 
774  return BS_OK;
775 }
776 
777 /*!
778  * \brief Query for the static module information.
779  *
780  * \return
781  * Pointer to module static information.
782  */
784 {
785  return &BsModInfo;
786 }
INLINE_IN_H int BsSerialUnpackReqRead(byte_t buf[], size_t uMsgLen, BsSerialReqRead_T *pStruct, bool_t bTrace)
Unpack a BsSerialReqRead ITV message in big-endian byte order from the input buffer.
Definition: bsSerialMsgs.h:288
uint_t BsMsgId_T
client message id type [0-64k].
Definition: BotSense.h:188
union BsSerialReqWrite_T::@18::@19 u
aligned vector items
#define BSMOD_LOG_ERROR(hndVConn, ecode, efmt,...)
Log Interface Module Error.
Definition: bsProxyModIF.h:405
static BsModInfo_T BsModInfo
Module static information.
#define BS_ECODE_UNKNOWN_REQ
unknown request
Definition: BotSense.h:81
#define BSMOD_LOG_NMERROR(hndVConn, nmecode, efmt,...)
Log Interface Module NetMsgs (Un)Packing Error.
Definition: bsProxyModIF.h:419
Useful indirect indexing of handle to resource instance structure.
Definition: bsProxyModIF.h:136
static const char * BsModUri
module canonical name
#define BSMOD_RSRC_IS_INUSE(pRsrcTbl, hndVConn)
Test if the resource table resource handle slot is in-use.
Definition: bsProxyModIF.h:169
bool_t m_xonxoff
xonxoff
Definition: bsSerialMsgs.h:67
byte_t m_readlen
readlen
Definition: bsSerialMsgs.h:80
static int bsModSerialReqRead(BsVConnHnd_T hndVConn, BsTid_T uTid, BsMsgId_T uMsgIdReq, byte_t bufReq[], size_t uReqLen)
Service a serial read request.
void(* m_cbModRsrcTblDelete)(BsModRsrcTbl_T *pRsrcTbl)
Delete an allocated resource table.
Definition: bsProxyModIF.h:294
int bsModRequest(BsVConnHnd_T hndVConn, BsTid_T uTid, BsMsgId_T uMsgIdReq, byte_t bufReq[], size_t uReqLen)
Service a serial request.
int bsModClose(BsVConnHnd_T hndVConn)
Close the serial device and disassociate virtual connection handle.
#define BSMOD_T_WRITE
default write time out (usec)
void bsModExit()
Exit serial module.
union BsSerialRspRead_T::@16::@17 u
aligned vector items
bool_t m_rtscts
rtscts
Definition: bsSerialMsgs.h:66
uint_t BsTid_T
client transaction id type [0-255].
Definition: BotSense.h:172
#define BSMOD_T_READ
default read time out (usec)
#define BSMOD_LOG_SYSERROR(hndVConn, efmt,...)
Log Interface Module System Error.
Definition: bsProxyModIF.h:431
struct BsSerialReqWrite_T::@18 m_writebuf
vector
char m_parity
parity
Definition: bsSerialMsgs.h:64
INLINE_IN_H int BsSerialPackRspRead(BsSerialRspRead_T *pStruct, byte_t buf[], size_t bufSize, bool_t bTrace)
Pack a BsSerialRspRead ITV message in big-endian byte order into the output buffer.
Definition: bsSerialMsgs.h:353
size_t m_count
vector item count
Definition: bsSerialMsgs.h:124
BsSerialMsgId_T
Definition: bsSerialMsgs.h:35
Module resource control block structure type.
Definition: bsI2CServer.c:103
bool_t m_bTrace
do [not] trace messages
Definition: bsI2CServer.c:108
#define BSMOD_IS_VCONN_HANDLE(hndVConn)
Test if the handle is in the valid module virtual connection range.
Definition: bsProxyModIF.h:149
byte_t m_bytesize
bytesize
Definition: bsSerialMsgs.h:63
uint_t m_baudrate
baudrate
Definition: bsSerialMsgs.h:62
const BsModInfo_T * bsModInfo()
Query for the static module information.
const char * m_sDevUri
I2C device path name.
Definition: bsI2CServer.c:107
int(* m_cbModRsrcAdd)(BsModRsrcTbl_T *pRsrcTbl, BsVConnHnd_T hndVConn, void *pRsrc)
Add a new resource to the resource table.
Definition: bsProxyModIF.h:305
union BsSerialReqTrans_T::@14::@15 u
aligned vector items
#define BS_OK
not an error, success
Definition: BotSense.h:66
byte_t m_readlen
readlen
Definition: bsSerialMsgs.h:106
static int bsModSerialReqTrans(BsVConnHnd_T hndVConn, BsTid_T uTid, BsMsgId_T uMsgIdReq, byte_t bufReq[], size_t uReqLen)
Service a serial write-read transaction request.
static void bsModCtlBlkDelete(BsModCtlBlk_T *pCtlBlk)
Delete an allocated resource control block.
#define BS_ECODE_BAD_VCONN_HND
bad virtual connection handle
Definition: BotSense.h:79
struct BsSerialReqTrans_T::@14 m_writebuf
vector
#define BS_ECODE_SYS
system (errno) error
Definition: BotSense.h:92
const char * mod_name
module load name sans OS dependent substrings
Definition: bsProxyModIF.h:121
BsSerialReqOpenArgs_T m_stDevCfg
serial device configuration
#define BSMOD_TRY_VCONN_HND_RANGE(hndVConn)
Check if handle is within the range of module handles.
Definition: bsProxyModIF.h:499
<b><i>BotSense</i></b> bsProxy client library RS-232 serial interface.
Interface Module callbacks to bsProxy services type.
Definition: bsProxyModIF.h:235
int bsModOpen(BsVConnHnd_T hndVConn, bool_t bTrace, const char *sDevUri, byte_t argbuf[], size_t uArgSize)
Open a serial device and associate with the given handle.
static int bsModSerialReqWrite(BsVConnHnd_T hndVConn, BsTid_T uTid, BsMsgId_T uMsgIdReq, byte_t bufReq[], size_t uReqLen)
Service a serial write request.
#define BS_SER_SERVER_MOD
server plugin dll module
Definition: bsSerial.h:66
INLINE_IN_H int BsSerialUnpackReqWrite(byte_t buf[], size_t uMsgLen, BsSerialReqWrite_T *pStruct, bool_t bTrace)
Unpack a BsSerialReqWrite ITV message in big-endian byte order from the input buffer.
Definition: bsSerialMsgs.h:417
<b><i>BotSense</i></b> client library declarations.
#define BS_ECODE_BAD_MSG
bad message
Definition: BotSense.h:76
#define BSMOD_RSRC_INUSE_COUNT(pRsrcTbl)
Get the resouce table current in-use count.
Definition: bsProxyModIF.h:208
void(* m_cbSendRsp)(BsVConnHnd_T hndVConn, BsTid_T uTid, BsMsgId_T uMsgId, byte_t bufRsp[], size_t uRspLen)
Send module-specific repsonse callback function.
Definition: bsProxyModIF.h:246
BotSense bsProxy server - client raw serial NetMsgs XML Definition.
int bsModInit(const char *sModUri, const BsModProxyCb_T *pCallbacks)
Initialize serial module.
#define BS_ECODE_NO_RSRC
no resource available
Definition: BotSense.h:85
int bsModTrace(BsVConnHnd_T hndVConn, bool_t bTrace)
Enable/disable message tracing on handle.
#define BSMOD_RSRC(pRsrcTbl, hndVConn)
Get the resource given the handle.
Definition: bsProxyModIF.h:196
#define BSMOD_MAX_HANDLES
Maximum number of module supported simultaneous virtual connections.
Standard bsProxy static interface module information structure type.
Definition: bsProxyModIF.h:119
void *(* m_cbModRsrcRemove)(BsModRsrcTbl_T *pRsrcTbl, BsVConnHnd_T hndVConn)
Remove a resource from the resource table.
Definition: bsProxyModIF.h:320
size_t m_count
vector item count
Definition: bsSerialMsgs.h:98
INLINE_IN_H int BsSerialUnpackReqOpenArgs(byte_t buf[], size_t uMsgLen, BsSerialReqOpenArgs_T *pStruct, bool_t bTrace)
Unpack a BsSerialReqOpenArgs ITV message in big-endian byte order from the input buffer.
Definition: bsSerialMsgs.h:245
size_t m_count
vector item count
Definition: bsSerialMsgs.h:149
#define BSMOD_SEND_NMERROR_RSP(pCb, hndVConn, uTid, nmecode, efmt,...)
Log NetMsgs (Un)Packing Error and Send Error Response.
Definition: bsProxyModIF.h:464
<b><i>BotSense</i></b> bsProxy Dynamically Linked Library module interface.
BsModRsrcTbl_T *(* m_cbModRsrcTblNew)(int nMaxResources)
Allocatae a new module resource table of fixed size.
Definition: bsProxyModIF.h:284
byte_t m_stopbits
stopbits
Definition: bsSerialMsgs.h:65
byte_t m_byteswritten
byteswritten
Definition: bsSerialMsgs.h:169
INLINE_IN_H int BsSerialUnpackReqTrans(byte_t buf[], size_t uMsgLen, BsSerialReqTrans_T *pStruct, bool_t bTrace)
Unpack a BsSerialReqTrans ITV message in big-endian byte order from the input buffer.
Definition: bsSerialMsgs.h:331
#define BS_ECODE_INTERNAL
internal error (bug)
Definition: BotSense.h:93
#define BSPROXY_BUF_BODY(buf)
Convenience macro to produce a buffer (offset, size) 2-tuple.
Definition: BotSense.h:272
static BsModRsrcTbl_T * BsModRsrcTbl
module resource table
#define BS_ECODE_NO_VCONN
virtual connection not found
Definition: BotSense.h:80
INLINE_IN_H int BsSerialPackRspWrite(BsSerialRspWrite_T *pStruct, byte_t buf[], size_t bufSize, bool_t bTrace)
Pack a BsSerialRspWrite ITV message in big-endian byte order into the output buffer.
Definition: bsSerialMsgs.h:439
#define BSMOD_SEND_SYSERROR_RSP(pCb, hndVConn, uTid, efmt,...)
Log System Error and Send Error Response.
Definition: bsProxyModIF.h:481
static BsModCtlBlk_T * bsModCtlBlkNew(int fd, const char *sDevUri, BsSerialReqOpenArgs_T *pDevCfg, bool_t bTrace)
Allocate a new resource control block.
#define BSPROXY_MSG_MAX_LEN
total message maximum length
Definition: BotSense.h:259
void ** m_vecRsrc
vecRsrc[index] -> rsrc
Definition: bsProxyModIF.h:139
#define BSMOD_SEND_ERROR_RSP(pCb, hndVConn, uTid, ecode, efmt,...)
Log <b><i>BotSense</i></b> Error and Send Error Response.
Definition: bsProxyModIF.h:447
#define BS_ECODE_BUSY
resource busy
Definition: BotSense.h:86
<b><i>BotSense</i></b> package top-level, unifying header declarations.
struct BsSerialRspRead_T::@16 m_readbuf
vector
int BsVConnHnd_T
virtual connection handle type
Definition: BotSense.h:151
static const BsModProxyCb_T * BsModCallbacks
module to bsProxy callbacks
int m_fd
/dev/null open file descriptor
Definition: bsNullServer.c:109