botsense  3.2.0
RoadNarrows Client-Server Proxied Services Framework
bsSerialClient.c
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: BotSense
4 //
5 // Module: bsSerial
6 // Library: libbsclient_serial
7 // File: bsSerialClient.c
8 //
9 /*! \file
10  *
11  * $LastChangedDate: 2010-08-20 11:36:38 -0600 (Fri, 20 Aug 2010) $
12  * $Rev: 568 $
13  *
14  * \brief \h_botsense bsProxy client proxied RS-232 serial device library.
15  *
16  * \author Robin Knight (robin.knight@roadnarrows.com)
17  *
18  * \copyright
19  * \h_copy 2009-2017. RoadNarrows LLC.\n
20  * http://www.roadnarrows.com\n
21  * All Rights Reserved
22  */
23 // Permission is hereby granted, without written agreement and without
24 // license or royalty fees, to use, copy, modify, and distribute this
25 // software and its documentation for any purpose, provided that
26 // (1) The above copyright notice and the following two paragraphs
27 // appear in all copies of the source code and (2) redistributions
28 // including binaries reproduces these notices in the supporting
29 // documentation. Substantial modifications to this software may be
30 // copyrighted by their authors and need not follow the licensing terms
31 // described here, provided that the new terms are clearly indicated in
32 // all files where they apply.
33 //
34 // IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY MEMBERS/EMPLOYEES
35 // OF ROADNARROW LLC OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY
36 // PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
37 // DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
38 // EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF
39 // THE POSSIBILITY OF SUCH DAMAGE.
40 //
41 // THE AUTHOR AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
42 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
43 // FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
44 // "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
45 // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
46 //
47 ////////////////////////////////////////////////////////////////////////////////
48 
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <libgen.h>
52 #include <string.h>
53 
54 #include "rnr/rnrconfig.h"
55 #include "rnr/log.h"
56 #include "rnr/netmsgs.h"
57 #include "rnr/serdev.h"
58 
59 #include "botsense/BotSense.h"
60 #include "botsense/libBotSense.h"
61 #include "botsense/bsSerial.h"
62 #include "botsense/bsSerialMsgs.h"
63 
64 
65 // ---------------------------------------------------------------------------
66 // Private Interface
67 // ---------------------------------------------------------------------------
68 
69 /*!
70  * \brief \h_botsense client application information.
71  */
73 {
74  .app_name = "libbsclient_serial",
75  .brief = "Raw R2-232 serial proxied device.",
76  .version = "2.0.0",
77  .date = "2010.07.14",
78  .maintainer = "RaodNarrows LLC",
79  .license = "(C) 2010 RoadNarrows LLC. All rights reserved.",
80 
81  .fnGetMsgName = bsSerialGetMsgName
82 };
83 
84 // ---------------------------------------------------------------------------
85 // Public Interface
86 // ---------------------------------------------------------------------------
87 
88 /*!
89  * \brief Get the serial message name.
90  *
91  * For each (virtual connection, message id) 2-tuple, there can be a known
92  * name string (provided the id is valid and an application provides the
93  * information).
94  *
95  * \param pClient \h_botsense client.
96  * \param hndVConn Virtual connection handle.
97  * \param uMsgId Message id.
98  *
99  * \return
100  * Returns message name if it can be determined. Otherwise returns "unknown".
101  */
102 const char *bsSerialGetMsgName(BsClient_P pClient,
103  BsVConnHnd_T hndVConn,
104  uint_t uMsgId)
105 {
106  const NMMsgDef_T *pMsgDef;
107 
108  pMsgDef = BsSerialLookupMsgDef((BsSerialMsgId_T)uMsgId);
109 
110  return pMsgDef!=NULL? pMsgDef->m_sMsgName: "unknown";
111 }
112 
113 /*!
114  * \brief Request proxy server to establish a virtual connection to an RS-232
115  * serial device.
116  *
117  * \param pClient \h_botsense client.
118  * \param sDevName Proxied serial device name (e.g. /dev/ttyS0).
119  * \param nBaudRate Baud rate.
120  * \param nByteSize Bytes size in bits 5...8.
121  * \param cParity Parity. One of: 'N', 'E', 'O'
122  * \param nStopBits Number of stop bits 1, 2
123  * \param bRtsCts Do [not] use hardware flow control.
124  * \param bXonXoff Do [not] use software flow control.
125  * \param bInitTrace Initial message tracing enable(true)/disable(false) state.
126  *
127  * \return
128  * On success, the virtual connection handle is returned.\n
129  * \copydoc doc_return_ecode
130  */
132  const char *sDevName,
133  int nBaudRate,
134  int nByteSize,
135  int cParity,
136  int nStopBits,
137  bool_t bRtsCts,
138  bool_t bXonXoff,
139  bool_t bInitTrace)
140 {
141  static BsSerialMsgId_T msgIdReq = BsSerialMsgIdReqOpenArgs;
142 
143  BsSerialReqOpenArgs_T msgReq; // specific open args
144  byte_t buf[BSPROXY_MSG_MAX_LEN]; // specific open args buffer
145  bool_t bTrace; // do [not] trace messages
146  int n; // num of bytes/return code
147 
148  // trace state
149  bTrace = bsClientAttrGetTraceState(pClient, BSPROXY_VCONN_SERVER);
150 
151  //
152  // Set specific open argument values.
153  //
154  msgReq.m_baudrate = (uint_t)nBaudRate;
155  msgReq.m_bytesize = (byte_t)nByteSize;
156  msgReq.m_parity = (char)cParity;
157  msgReq.m_stopbits = (byte_t)nStopBits;
158  msgReq.m_rtscts = bRtsCts;
159  msgReq.m_xonxoff = bXonXoff;
160 
161  //
162  // Pack specific open arguments (returns bytes packed \h_ge 0 on success).
163  //
164  n = BsSerialPackReqOpenArgs(&msgReq, buf, sizeof(buf), bTrace);
165 
166  // check packing return code
167  BSCLIENT_TRY_NM_ECODE(pClient, n, "MsgId=%u", msgIdReq);
168 
169 
170  //
171  // Execute server transaction (returns handle \h_ge 0 on success).
172  //
173  n = bsServerReqOpenDev(pClient, sDevName, BS_SER_SERVER_MOD, buf, (size_t)n,
174  &bsSerialAppInfo, bInitTrace);
175 
176  // check transaction return code
177  BSCLIENT_TRY_ECODE(pClient, n, "bsServerReqOpenDev(dev='%s') failed.",
178  sDevName);
179 
180  // return handle
181  return n;
182 }
183 
184 /*!
185  * \brief Request proxy server to close client's proxied serial device vitual
186  * connection.
187  *
188  * \param pClient \h_botsense client.
189  * \param hndVConn Handle to virtual connection to close.
190  *
191  * \copydoc doc_return_std
192  */
194 {
195  return bsServerReqCloseDev(pClient, hndVConn);
196 }
197 
198 /*!
199  * \brief Proxied request to read from an RS-232 serial device.
200  *
201  * \param pClient \h_botsense client.
202  * \param hndVConn Handle to virtual connection to close.
203  * \param uReadLen Number of bytes to read.
204  * \param [out] rbuf Read buffer.
205  *
206  * \return
207  * Returns number of bytes read on success.\n
208  * \copydoc doc_return_ecode
209  */
211  BsVConnHnd_T hndVConn,
212  size_t uReadLen,
213  byte_t rbuf[])
214 {
215  static BsSerialMsgId_T msgIdReq = BsSerialMsgIdReqRead;
216  static BsSerialMsgId_T msgIdRsp = BsSerialMsgIdRspRead;
217 
218  BsSerialReqRead_T msgReq; // request message
219  BsSerialRspRead_T msgRsp; // response message
220  byte_t buf[BSPROXY_MSG_MAX_LEN]; // req/rsp buffer
221  bool_t bTrace; // do [not] trace messages
222  int n; // number of bytes/return code
223 
224  //
225  // Parameter checks.
226  //
227  BSCLIENT_TRY_EXPR(pClient, BSCLIENT_HAS_VCONN(pClient, hndVConn),
228  BS_ECODE_BAD_VAL, "VConn=%d", hndVConn);
229 
230  BSCLIENT_TRY_EXPR(pClient, (uReadLen <= (size_t)BSSERIAL_RSPREAD_READBUF_LEN),
231  BS_ECODE_BAD_VAL, "read_len=%zu > max_len=%zu",
232  uReadLen, (size_t)BSSERIAL_RSPREAD_READBUF_LEN);
233 
234  // trace state
235  bTrace = bsClientAttrGetTraceState(pClient, hndVConn);
236 
237  //
238  // Set request message values.
239  //
240  msgReq.m_readlen = (byte_t)uReadLen;
241 
242  //
243  // Pack request.
244  //
245  n = BsSerialPackReqRead(&msgReq, BSPROXY_BUF_BODY(buf), bTrace);
246 
247  // check packing return code
248  BSCLIENT_TRY_NM_ECODE(pClient, n, "MsgId=%u", msgIdReq);
249 
250  //
251  // Execute request-response transaction.
252  //
253  n = bsClientTrans(pClient, hndVConn,
254  msgIdReq, buf, (size_t)n,
255  msgIdRsp, buf, sizeof(buf));
256 
257  // check transaction return code
258  BSCLIENT_TRY_ECODE(pClient, n, "MsgId=%u: Transaction failed.", msgIdReq);
259 
260  //
261  // Unpack response.
262  //
263  n = BsSerialUnpackRspRead(buf, (size_t)n, &msgRsp, bTrace);
264 
265  // check unpack return code
266  BSCLIENT_TRY_NM_ECODE(pClient, n, "MsgId=%u", msgIdRsp);
267 
268  //
269  // Set return values from response.
270  //
271  if( uReadLen > msgRsp.m_readbuf.m_count )
272  {
273  uReadLen = msgRsp.m_readbuf.m_count;
274  }
275  memcpy(rbuf, msgRsp.m_readbuf.u.m_buf, uReadLen);
276 
277  return (int)uReadLen;
278 }
279 
280 /*!
281  * \brief Proxied request to write to a RS-232 serial device.
282  *
283  * \param pClient \h_botsense client.
284  * \param hndVConn Handle to virtual connection to close.
285  * \param [in] wbuf Write buffer.
286  * \param uWriteLen Number of bytes to write.
287  *
288  * \return
289  * Returns number of bytes written on success.\n
290  * \copydoc doc_return_ecode
291  */
293  BsVConnHnd_T hndVConn,
294  byte_t wbuf[],
295  size_t uWriteLen)
296 {
297  static BsSerialMsgId_T msgIdReq = BsSerialMsgIdReqWrite;
298  static BsSerialMsgId_T msgIdRsp = BsSerialMsgIdRspWrite;
299 
300  BsSerialReqWrite_T msgReq; // request message
301  BsSerialRspWrite_T msgRsp; // response message
302  byte_t buf[BSPROXY_MSG_MAX_LEN]; // req/rsp buffer
303  bool_t bTrace; // do [not] trace messages
304  int n; // number of bytes/return code
305 
306  //
307  // Parameter checks.
308  //
309  BSCLIENT_TRY_EXPR(pClient, BSCLIENT_HAS_VCONN(pClient, hndVConn),
310  BS_ECODE_BAD_VAL, "VConn=%d", hndVConn);
311 
312  BSCLIENT_TRY_EXPR(pClient,
313  (uWriteLen <= (size_t)BSSERIAL_REQWRITE_WRITEBUF_LEN), BS_ECODE_BAD_VAL,
314  "write_len=%zu > max_len=%zu",
315  uWriteLen, (size_t)BSSERIAL_REQWRITE_WRITEBUF_LEN);
316 
317  // trace state
318  bTrace = bsClientAttrGetTraceState(pClient, hndVConn);
319 
320  //
321  // Set request message values.
322  //
323  memcpy(msgReq.m_writebuf.u.m_buf, wbuf, uWriteLen);
324  msgReq.m_writebuf.m_count = uWriteLen;
325 
326  //
327  // Pack request.
328  //
329  n = BsSerialPackReqWrite(&msgReq, BSPROXY_BUF_BODY(buf), bTrace);
330 
331  // check packing return code
332  BSCLIENT_TRY_NM_ECODE(pClient, n, "MsgId=%u", msgIdReq);
333 
334  //
335  // Execute request-response transaction.
336  //
337  n = bsClientTrans(pClient, hndVConn,
338  msgIdReq, buf, (size_t)n,
339  msgIdRsp, buf, sizeof(buf));
340 
341  // check transaction return code
342  BSCLIENT_TRY_ECODE(pClient, n, "MsgId=%u: Transaction failed.", msgIdReq);
343 
344  //
345  // Unpack response.
346  //
347  n = BsSerialUnpackRspWrite(buf, (size_t)n, &msgRsp, bTrace);
348 
349  // check unpack return code
350  BSCLIENT_TRY_NM_ECODE(pClient, n, "MsgId=%u", msgIdRsp);
351 
352  //
353  // Set return values from response.
354  //
355  return (int)msgRsp.m_byteswritten;
356 }
357 
358 /*!
359  * \brief Proxied request to execute a write-read transaction on a RS-232
360  * serial device.
361  *
362  * \param pClient \h_botsense client.
363  * \param hndVConn Handle to virtual connection to close.
364  * \param [in] wbuf Write buffer.
365  * \param uWriteLen Number of bytes to write.
366  * \param uReadLen Number of bytes to read.
367  * \param [out] rbuf Read buffer.
368  *
369  * \return
370  * Returns number of bytes read on success.\n
371  * \copydoc doc_return_ecode
372  */
374  BsVConnHnd_T hndVConn,
375  byte_t wbuf[],
376  size_t uWriteLen,
377  size_t uReadLen,
378  byte_t rbuf[])
379 {
380  static BsSerialMsgId_T msgIdReq = BsSerialMsgIdReqTrans;
381  static BsSerialMsgId_T msgIdRsp = BsSerialMsgIdRspRead;
382 
383  BsSerialReqTrans_T msgReq; // request message
384  BsSerialRspRead_T msgRsp; // response message
385  byte_t buf[BSPROXY_MSG_MAX_LEN]; // req/rsp buffer
386  bool_t bTrace; // do [not] trace messages
387  int n; // number of bytes/return code
388 
389  //
390  // Parameter checks.
391  //
392  BSCLIENT_TRY_EXPR(pClient, BSCLIENT_HAS_VCONN(pClient, hndVConn),
393  BS_ECODE_BAD_VAL, "VConn=%d", hndVConn);
394 
395  BSCLIENT_TRY_EXPR(pClient,
396  (uWriteLen <= (size_t)BSSERIAL_REQTRANS_WRITEBUF_LEN), BS_ECODE_BAD_VAL,
397  "write_len=%zu > max_len=%zu",
398  uWriteLen, (size_t)BSSERIAL_REQTRANS_WRITEBUF_LEN);
399 
400  BSCLIENT_TRY_EXPR(pClient, (uReadLen <= (size_t)BSSERIAL_RSPREAD_READBUF_LEN),
401  BS_ECODE_BAD_VAL, "read_len=%zu > max_len=%zu",
402  uReadLen, (size_t)BSSERIAL_RSPREAD_READBUF_LEN);
403 
404  // trace state
405  bTrace = bsClientAttrGetTraceState(pClient, hndVConn);
406 
407  //
408  // Set request message values.
409  //
410  memcpy(msgReq.m_writebuf.u.m_buf, wbuf, uWriteLen);
411  msgReq.m_writebuf.m_count = uWriteLen;
412  msgReq.m_readlen = (byte_t)uReadLen;
413 
414  //
415  // Pack request.
416  //
417  n = BsSerialPackReqTrans(&msgReq, BSPROXY_BUF_BODY(buf), bTrace);
418 
419  // check packing return code
420  BSCLIENT_TRY_NM_ECODE(pClient, n, "MsgId=%u", msgIdReq);
421 
422  //
423  // Execute request-response server transaction.
424  //
425  n = bsClientTrans(pClient, hndVConn,
426  msgIdReq, buf, (size_t)n,
427  msgIdRsp, buf, sizeof(buf));
428 
429  // check transaction return code
430  BSCLIENT_TRY_ECODE(pClient, n, "MsgId=%u: Transaction failed.", msgIdReq);
431 
432  //
433  // Unpack response.
434  //
435  n = BsSerialUnpackRspRead(buf, (size_t)n, &msgRsp, bTrace);
436 
437  // check unpack return code
438  BSCLIENT_TRY_NM_ECODE(pClient, n, "MsgId=%u", msgIdRsp);
439 
440  //
441  // Set return values from response.
442  //
443  if( uReadLen > msgRsp.m_readbuf.m_count )
444  {
445  uReadLen = msgRsp.m_readbuf.m_count;
446  }
447  memcpy(rbuf, msgRsp.m_readbuf.u.m_buf, uReadLen);
448 
449  return (int)uReadLen;
450 }
union BsSerialReqWrite_T::@18::@19 u
aligned vector items
int bsSerialReqClose(BsClient_P pClient, BsVConnHnd_T hndVConn)
Request proxy server to close client&#39;s proxied serial device vitual connection.
int bsSerialReqTrans(BsClient_P pClient, BsVConnHnd_T hndVConn, byte_t wbuf[], size_t uWriteLen, size_t uReadLen, byte_t rbuf[])
Proxied request to execute a write-read transaction on a RS-232 serial device.
#define BSCLIENT_TRY_ECODE(pClient, ecode, efmt,...)
Check if <b><i>BotSense</i></b> return value is not an error ( &lt; 0).
Definition: libBotSense.h:214
#define BS_ECODE_BAD_VAL
bad value
Definition: BotSense.h:77
bool_t m_xonxoff
xonxoff
Definition: bsSerialMsgs.h:67
byte_t m_readlen
readlen
Definition: bsSerialMsgs.h:80
INLINE_IN_H int BsSerialPackReqOpenArgs(BsSerialReqOpenArgs_T *pStruct, byte_t buf[], size_t bufSize, bool_t bTrace)
Pack a BsSerialReqOpenArgs ITV message in big-endian byte order into the output buffer.
Definition: bsSerialMsgs.h:224
union BsSerialRspRead_T::@16::@17 u
aligned vector items
bool_t m_rtscts
rtscts
Definition: bsSerialMsgs.h:66
struct BsSerialReqWrite_T::@18 m_writebuf
vector
#define BSPROXY_VCONN_SERVER
handle for server-terminated msgs
Definition: BotSense.h:140
char m_parity
parity
Definition: bsSerialMsgs.h:64
INLINE_IN_H int BsSerialUnpackRspRead(byte_t buf[], size_t uMsgLen, BsSerialRspRead_T *pStruct, bool_t bTrace)
Unpack a BsSerialRspRead ITV message in big-endian byte order from the input buffer.
Definition: bsSerialMsgs.h:374
size_t m_count
vector item count
Definition: bsSerialMsgs.h:124
BsSerialMsgId_T
Definition: bsSerialMsgs.h:35
byte_t m_bytesize
bytesize
Definition: bsSerialMsgs.h:63
uint_t m_baudrate
baudrate
Definition: bsSerialMsgs.h:62
int bsSerialReqWrite(BsClient_P pClient, BsVConnHnd_T hndVConn, byte_t wbuf[], size_t uWriteLen)
Proxied request to write to a RS-232 serial device.
The Client Structure Type.
Definition: bsLibInternal.h:96
union BsSerialReqTrans_T::@14::@15 u
aligned vector items
byte_t m_readlen
readlen
Definition: bsSerialMsgs.h:106
struct BsSerialReqTrans_T::@14 m_writebuf
vector
INLINE_IN_H int BsSerialPackReqWrite(BsSerialReqWrite_T *pStruct, byte_t buf[], size_t bufSize, bool_t bTrace)
Pack a BsSerialReqWrite ITV message in big-endian byte order into the output buffer.
Definition: bsSerialMsgs.h:396
<b><i>BotSense</i></b> bsProxy client library RS-232 serial interface.
#define BSSERIAL_REQTRANS_WRITEBUF_LEN
Definition: bsSerialMsgs.h:89
#define BS_SER_SERVER_MOD
server plugin dll module
Definition: bsSerial.h:66
<b><i>BotSense</i></b> client library declarations.
INLINE_IN_H int BsSerialPackReqRead(BsSerialReqRead_T *pStruct, byte_t buf[], size_t bufSize, bool_t bTrace)
Pack a BsSerialReqRead ITV message in big-endian byte order into the output buffer.
Definition: bsSerialMsgs.h:267
static BsClientAppInfo_T bsSerialAppInfo
<b><i>BotSense</i></b> client application information.
<b><i>BotSense</i></b> client library information and callbacks to application-specific data...
Definition: libBotSense.h:86
INLINE_IN_H int BsSerialUnpackRspWrite(byte_t buf[], size_t uMsgLen, BsSerialRspWrite_T *pStruct, bool_t bTrace)
Unpack a BsSerialRspWrite ITV message in big-endian byte order from the input buffer.
Definition: bsSerialMsgs.h:460
BotSense bsProxy server - client raw serial NetMsgs XML Definition.
#define BSSERIAL_REQWRITE_WRITEBUF_LEN
Definition: bsSerialMsgs.h:140
INLINE_IN_H int BsSerialPackReqTrans(BsSerialReqTrans_T *pStruct, byte_t buf[], size_t bufSize, bool_t bTrace)
Pack a BsSerialReqTrans ITV message in big-endian byte order into the output buffer.
Definition: bsSerialMsgs.h:310
#define BSCLIENT_TRY_EXPR(pClient, expr, ecode, efmt,...)
Check if expression evaluates to true.
Definition: libBotSense.h:259
size_t m_count
vector item count
Definition: bsSerialMsgs.h:98
size_t m_count
vector item count
Definition: bsSerialMsgs.h:149
byte_t m_stopbits
stopbits
Definition: bsSerialMsgs.h:65
byte_t m_byteswritten
byteswritten
Definition: bsSerialMsgs.h:169
#define BSPROXY_BUF_BODY(buf)
Convenience macro to produce a buffer (offset, size) 2-tuple.
Definition: BotSense.h:272
#define BSCLIENT_HAS_VCONN(pClient, hnd)
Tests if the handle is valid and there is an established virtual connection.
Definition: libBotSense.h:285
#define BSCLIENT_TRY_NM_ECODE(pClient, nmecode, efmt,...)
Check if NetMsgs (un)packing return value is not an error ( &lt; 0).
Definition: libBotSense.h:236
const char * bsSerialGetMsgName(BsClient_P pClient, BsVConnHnd_T hndVConn, uint_t uMsgId)
Get the serial message name.
#define BSPROXY_MSG_MAX_LEN
total message maximum length
Definition: BotSense.h:259
int bsSerialReqRead(BsClient_P pClient, BsVConnHnd_T hndVConn, size_t uReadLen, byte_t rbuf[])
Proxied request to read from an RS-232 serial device.
int bsSerialReqOpen(BsClient_P pClient, const char *sDevName, int nBaudRate, int nByteSize, int cParity, int nStopBits, bool_t bRtsCts, bool_t bXonXoff, bool_t bInitTrace)
Request proxy server to establish a virtual connection to an RS-232 serial device.
const char * app_name
application name
Definition: libBotSense.h:88
<b><i>BotSense</i></b> package top-level, unifying header declarations.
const NMMsgDef_T * BsSerialLookupMsgDef(BsSerialMsgId_T eMsgId)
Look up the message definition associated with the message id.
Definition: bsSerialMsgs.c:464
struct BsSerialRspRead_T::@16 m_readbuf
vector
int BsVConnHnd_T
virtual connection handle type
Definition: BotSense.h:151
#define BSSERIAL_RSPREAD_READBUF_LEN
Definition: bsSerialMsgs.h:115