botsense  3.2.0
RoadNarrows Client-Server Proxied Services Framework
bsI2CServer.c
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: BotSense
4 // Module: bsI2C
5 // Library: libbsserver_i2c
6 // File: bsI2CServer.c
7 //
8 /*! \file
9  *
10  * $LastChangedDate: 2010-09-13 10:25:05 -0600 (Mon, 13 Sep 2010) $
11  * $Rev: 581 $
12  *
13  * \brief \h_botsense bsProxy server plug-in DLL \h_i2c bus 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/i2c.h"
57 
58 #include "botsense/BotSense.h"
59 #include "botsense/libBotSense.h"
60 #include "botsense/bsProxyModIF.h"
61 #include "botsense/bsI2C.h"
62 #include "botsense/bsI2CMsgs.h"
63 
64 
65 // ---------------------------------------------------------------------------
66 // Private Interface
67 // ---------------------------------------------------------------------------
68 
69 /*!
70  * \brief Module static information.
71  */
73 {
75  .brief = "Raw I2C Bus proxied device.",
76  .version = "2.0.0",
77  .date = "2010.07.20",
78  .maintainer = "RaodNarrows LLC",
79  .license = "(C) 2010 RoadNarrows LLC. All rights reserved."
80 };
81 
82 /*!
83  * \ingroup bsmod_i2c_srv
84  * \defgroup bsmod_i2c_srv_tunes Default Tunables
85  *
86  * \h_botsense \h_i2c 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 32
97 
98 /*! \} */
99 
100 /*!
101  * \brief Module resource control block structure type.
102  */
103 typedef struct
104 {
105  uint_t m_uRefCnt; ///< reference count to this device
106  i2c_t m_hndI2C; ///< \h_i2c bus handle
107  const char *m_sDevUri; ///< \h_i2c device path name
108  bool_t m_bTrace; ///< do [not] trace messages
109 } BsModCtlBlk_T;
110 
111 static const char *BsModUri; ///< module canonical name
112 static const BsModProxyCb_T *BsModCallbacks; ///< module to bsProxy callbacks
113 static BsModRsrcTbl_T *BsModRsrcTbl; ///< module resource table
114 
115 
116 /*!
117  * \brief Allocate a new resource control block.
118  *
119  * Multiple virtual connection to the same \h_i2c device share the same
120  * control block.
121  *
122  * \param sDevUri Device URI.
123  * \param bTrace Do [not] trace messages.
124  *
125  * \return Pointer to new allocated control block.
126  */
127 static BsModCtlBlk_T *bsModCtlBlkNew(const char *sDevUri, bool_t bTrace)
128 {
129  BsModCtlBlk_T *pCtlBlk;
130 
131  pCtlBlk = NEW(BsModCtlBlk_T);
132 
133  pCtlBlk->m_uRefCnt = 0;
134  pCtlBlk->m_sDevUri = new_strdup(sDevUri);
135  pCtlBlk->m_bTrace = bTrace;
136 
137  return pCtlBlk;
138 }
139 
140 /*!
141  * \brief Delete an allocated resource control block.
142  *
143  * \param pCtlBlk Pointer to allocated control block.
144  */
145 static void bsModCtlBlkDelete(BsModCtlBlk_T *pCtlBlk)
146 {
147  if( pCtlBlk != NULL )
148  {
149  delete((void *)(pCtlBlk->m_sDevUri));
150  delete(pCtlBlk);
151  }
152 }
153 
154 /*!
155  * \brief Find an already allocated resource control block.
156  *
157  * \param sDevUri Device URI search parameter.
158  *
159  * \return
160  * If found, returns pointer to matched control block. Else returns NULL.
161  */
162 static BsModCtlBlk_T *bsModCtlBlkFind(const char *sDevUri)
163 {
164  int index;
165  BsModCtlBlk_T *pCtlBlk;
166 
167  // search through modul'es resource table
168  for(index=0; index<BSMOD_MAX_HANDLES; ++index)
169  {
170  if( (pCtlBlk = (BsModCtlBlk_T *)BsModRsrcTbl->m_vecRsrc[index]) != NULL )
171  {
172  if( !strcmp(pCtlBlk->m_sDevUri, sDevUri) )
173  {
174  return pCtlBlk;
175  }
176  }
177  }
178  return NULL;
179 }
180 
181 /*!
182  * \brief Service a \h_i2c read request.
183  *
184  * \note A module-specific request service must send a response.
185  *
186  * \param hndVConn Virtual connection handle.
187  * \param uTid Request-Response transaction id.
188  * \param uMsgIdReq Request message id.
189  * \param bufReq Packed request message buffer.
190  * \param uReqLen Size of request in buffer (number of bytes).
191  *
192  * \copydoc doc_return_std
193  */
194 static int bsModI2CReqRead(BsVConnHnd_T hndVConn,
195  BsTid_T uTid,
196  BsMsgId_T uMsgIdReq,
197  byte_t bufReq[],
198  size_t uReqLen)
199 {
200  static BsI2CMsgId_T uMsgIdRsp = BsI2CMsgIdRspRead;
201 
202  BsModCtlBlk_T *pCtlBlk; // resource control block
203  BsI2CReqRead_T msgReq; // request message
204  BsI2CRspRead_T msgRsp; // response message
205  byte_t bufRsp[BSPROXY_MSG_MAX_LEN]; // req/rsp buffer
206  i2c_addr_t addr; // \h_i2c device address
207  int n; // number of bytes/return code
208 
209  //
210  // Parameter checks
211  //
212  if( !BSMOD_IS_VCONN_HANDLE(hndVConn) )
213  {
214  BSMOD_SEND_ERROR_RSP(BsModCallbacks, hndVConn, uTid, BS_ECODE_BAD_VCONN_HND,
215  "Module vconn handle out-of-range.");
216  return -BS_ECODE_BAD_VCONN_HND; \
217  }
218 
219  // retrieve the resource control block
220  pCtlBlk = (BsModCtlBlk_T *)BSMOD_RSRC(BsModRsrcTbl, hndVConn);
221 
222  if( pCtlBlk == NULL )
223  {
224  BSMOD_SEND_ERROR_RSP(BsModCallbacks, hndVConn, uTid, BS_ECODE_NO_VCONN,
225  "No resources for virtual connection found.");
226  return -BS_ECODE_NO_VCONN;
227  }
228 
229  //
230  // Unpack client request.
231  //
232  n = BsI2CUnpackReqRead(bufReq, uReqLen, &msgReq, pCtlBlk->m_bTrace);
233 
234  // check unpacking return code
235  if( n < 0 )
236  {
237  BSMOD_SEND_NMERROR_RSP(BsModCallbacks, hndVConn, uTid, n,
238  "MsgId=%u", uMsgIdReq);
239  return -BS_ECODE_BAD_MSG;
240  }
241 
242  addr = (i2c_addr_t)msgReq.m_addr;
243 
244  //
245  // Execute client request.
246  //
247  n = i2c_read(&pCtlBlk->m_hndI2C, addr, msgRsp.m_readbuf.u.m_buf,
248  (uint_t)msgReq.m_readlen);
249 
250  // check operation return code
251  if( n < 0 )
252  {
253  BSMOD_SEND_SYSERROR_RSP(BsModCallbacks, hndVConn, uTid,
254  "i2c_read(fd=%d, addr=0x%02x, ...).", pCtlBlk->m_hndI2C.fd, addr);
255  return -BS_ECODE_SYS;
256  }
257 
258  LOGDIAG3("VConn=%d: %d=i2c_read(fd=%d, addr=0x%02x, buf=%p, count=%zu).",
259  hndVConn, n, pCtlBlk->m_hndI2C.fd, addr, msgRsp.m_readbuf.u.m_buf,
260  (size_t)msgReq.m_readlen);
261 
262  //
263  // Pack server response.
264  //
265  msgRsp.m_readbuf.m_count = (byte_t)n;
266 
267  // pack
268  n = BsI2CPackRspRead(&msgRsp, BSPROXY_BUF_BODY(bufRsp), pCtlBlk->m_bTrace);
269 
270  // check packing return code
271  if( n < 0 )
272  {
273  BSMOD_SEND_NMERROR_RSP(BsModCallbacks, hndVConn, uTid, n,
274  "MsgId=%u", uMsgIdRsp);
275  return -BS_ECODE_BAD_MSG;
276  }
277 
278  //
279  // Send response.
280  //
281  BsModCallbacks->m_cbSendRsp(hndVConn, uTid, uMsgIdRsp, bufRsp, (size_t)n);
282 
283  return BS_OK;
284 }
285 
286 /*!
287  * \brief Service a \h_i2c write request.
288  *
289  * \note A module-specific request service must send a response.
290  *
291  * \param hndVConn Virtual connection handle.
292  * \param uTid Request-Response transaction id.
293  * \param uMsgIdReq Request message id.
294  * \param bufReq Packed request message buffer.
295  * \param uReqLen Size of request in buffer (number of bytes).
296  *
297  * \copydoc doc_return_std
298  */
299 static int bsModI2CReqWrite(BsVConnHnd_T hndVConn,
300  BsTid_T uTid,
301  BsMsgId_T uMsgIdReq,
302  byte_t bufReq[],
303  size_t uReqLen)
304 {
305  static BsI2CMsgId_T uMsgIdRsp = BsI2CMsgIdRspWrite;
306 
307  BsModCtlBlk_T *pCtlBlk; // resource control block
308  BsI2CReqWrite_T msgReq; // request message
309  BsI2CRspWrite_T msgRsp; // response message
310  byte_t bufRsp[BSPROXY_MSG_MAX_LEN]; // req/rsp buffer
311  i2c_addr_t addr; // \h_i2c device address
312  int n; // number of bytes/return code
313 
314  //
315  // Parameter checks
316  //
317  if( !BSMOD_IS_VCONN_HANDLE(hndVConn) )
318  {
319  BSMOD_SEND_ERROR_RSP(BsModCallbacks, hndVConn, uTid, BS_ECODE_BAD_VCONN_HND,
320  "Module vconn handle out-of-range.");
321  return -BS_ECODE_BAD_VCONN_HND; \
322  }
323 
324  // retrieve the resource control block
325  pCtlBlk = (BsModCtlBlk_T *)BSMOD_RSRC(BsModRsrcTbl, hndVConn);
326 
327  if( pCtlBlk == NULL )
328  {
329  BSMOD_SEND_ERROR_RSP(BsModCallbacks, hndVConn, uTid, BS_ECODE_NO_VCONN,
330  "No resources for virtual connection found.");
331  return -BS_ECODE_NO_VCONN;
332  }
333 
334  //
335  // Unpack client request.
336  //
337  n = BsI2CUnpackReqWrite(bufReq, uReqLen, &msgReq, pCtlBlk->m_bTrace);
338 
339  // check unpacking return code
340  if( n < 0 )
341  {
342  BSMOD_SEND_NMERROR_RSP(BsModCallbacks, hndVConn, uTid, n,
343  "MsgId=%u", uMsgIdReq);
344  return -BS_ECODE_BAD_MSG;
345  }
346 
347  addr = (i2c_addr_t)msgReq.m_addr;
348 
349  //
350  // Execute client request.
351  //
352  n = i2c_write(&pCtlBlk->m_hndI2C, addr, msgReq.m_writebuf.u.m_buf,
353  (uint_t)msgReq.m_writebuf.m_count);
354 
355  // check operation return code
356  if( n < 0 )
357  {
358  BSMOD_SEND_SYSERROR_RSP(BsModCallbacks, hndVConn, uTid,
359  "i2c_write(fd=%d, addr=0x%02x, ...).", pCtlBlk->m_hndI2C.fd, addr);
360  return -BS_ECODE_SYS;
361  }
362 
363  LOGDIAG3("VConn=%d: %d=i2c_write(fd=%d, addr=0x%02x, buf=%p, count=%zu).",
364  hndVConn, n, pCtlBlk->m_hndI2C.fd, addr, msgReq.m_writebuf.u.m_buf,
365  (size_t)msgReq.m_writebuf.m_count);
366 
367  //
368  // Pack server response.
369  //
370  msgRsp.m_byteswritten = (byte_t)n;
371 
372  // pack
373  n = BsI2CPackRspWrite(&msgRsp, BSPROXY_BUF_BODY(bufRsp), pCtlBlk->m_bTrace);
374 
375  // check packing return code
376  if( n < 0 )
377  {
378  BSMOD_SEND_NMERROR_RSP(BsModCallbacks, hndVConn, uTid, n,
379  "MsgId=%u", uMsgIdRsp);
380  return -BS_ECODE_BAD_MSG;
381  }
382 
383  //
384  // Send response.
385  //
386  BsModCallbacks->m_cbSendRsp(hndVConn, uTid, uMsgIdRsp, bufRsp, (size_t)n);
387 
388  return BS_OK;
389 }
390 
391 /*!
392  * \brief Service a \h_i2c write-read transaction request.
393  *
394  * \note A module-specific request service must send a response.
395  *
396  * \param hndVConn Virtual connection handle.
397  * \param uTid Request-Response transaction id.
398  * \param uMsgIdReq Request message id.
399  * \param bufReq Packed request message buffer.
400  * \param uReqLen Size of request in buffer (number of bytes).
401  *
402  * \copydoc doc_return_std
403  */
404 static int bsModI2CReqTrans(BsVConnHnd_T hndVConn,
405  BsTid_T uTid,
406  BsMsgId_T uMsgIdReq,
407  byte_t bufReq[],
408  size_t uReqLen)
409 {
410  static BsI2CMsgId_T uMsgIdRsp = BsI2CMsgIdRspRead;
411 
412  BsModCtlBlk_T *pCtlBlk; // resource control block
413  BsI2CReqTrans_T msgReq; // request message
414  BsI2CRspRead_T msgRsp; // response message
415  byte_t bufRsp[BSPROXY_MSG_MAX_LEN]; // req/rsp buffer
416  i2c_addr_t addr; // \h_i2c device address
417  int n; // number of bytes/return code
418  int rc; // return code
419 
420  //
421  // Parameter checks
422  //
423  if( !BSMOD_IS_VCONN_HANDLE(hndVConn) )
424  {
425  BSMOD_SEND_ERROR_RSP(BsModCallbacks, hndVConn, uTid, BS_ECODE_BAD_VCONN_HND,
426  "Module vconn handle out-of-range.");
427  return -BS_ECODE_BAD_VCONN_HND; \
428  }
429 
430  // retrieve the resource control block
431  pCtlBlk = (BsModCtlBlk_T *)BSMOD_RSRC(BsModRsrcTbl, hndVConn);
432 
433  if( pCtlBlk == NULL )
434  {
435  BSMOD_SEND_ERROR_RSP(BsModCallbacks, hndVConn, uTid, BS_ECODE_NO_VCONN,
436  "No resources for virtual connection found.");
437  return -BS_ECODE_NO_VCONN;
438  }
439 
440  //
441  // Unpack client request.
442  //
443  n = BsI2CUnpackReqTrans(bufReq, uReqLen, &msgReq, pCtlBlk->m_bTrace);
444 
445  // check unpacking return code
446  if( n < 0 )
447  {
448  BSMOD_SEND_NMERROR_RSP(BsModCallbacks, hndVConn, uTid, n,
449  "MsgId=%u", uMsgIdReq);
450  return -BS_ECODE_BAD_MSG;
451  }
452 
453  addr = (i2c_addr_t)msgReq.m_addr;
454 
455  //
456  // Execute client request.
457  //
458  rc = i2c_transfer(&pCtlBlk->m_hndI2C, addr,
459  msgReq.m_writebuf.u.m_buf, (uint_t)msgReq.m_writebuf.m_count,
460  msgRsp.m_readbuf.u.m_buf, (uint_t)msgReq.m_readlen);
461 
462  // check operation return code
463  if( rc < 0 )
464  {
465  BSMOD_SEND_SYSERROR_RSP(BsModCallbacks, hndVConn, uTid,
466  "i2c_transfer(fd=%d, addr=0x%02x, ...).", pCtlBlk->m_hndI2C.fd, addr);
467  return -BS_ECODE_SYS;
468  }
469 
470  LOGDIAG3("VConn=%d: i2c_transfer(fd=%d, addr=0x%02x, wbuf=%p, wcount=%zu, "
471  "rbuf=%p, rcount=%zu).",
472  hndVConn, pCtlBlk->m_hndI2C.fd,
473  msgReq.m_writebuf.u.m_buf, (size_t)msgReq.m_writebuf.m_count,
474  msgRsp.m_readbuf.u.m_buf, (size_t)msgReq.m_readlen);
475 
476  //
477  // Pack server response. Note: transfer fails if full number of bytes are
478  // not read.
479  //
480  msgRsp.m_readbuf.m_count = (byte_t)msgReq.m_readlen;
481 
482  // pack
483  n = BsI2CPackRspRead(&msgRsp, BSPROXY_BUF_BODY(bufRsp), pCtlBlk->m_bTrace);
484 
485  // check packing return code
486  if( n < 0 )
487  {
488  BSMOD_SEND_NMERROR_RSP(BsModCallbacks, hndVConn, uTid, n,
489  "MsgId=%u", uMsgIdRsp);
490  return -BS_ECODE_BAD_MSG;
491  }
492 
493  //
494  // Send response.
495  //
496  BsModCallbacks->m_cbSendRsp(hndVConn, uTid, uMsgIdRsp, bufRsp, (size_t)n);
497 
498  return BS_OK;
499 }
500 
501 /*!
502  * \brief \h_i2c scan callback function.
503  *
504  * \param pHndI2C Pointer to \h_i2c Bus handle.
505  * \param addr Discovered \h_i2c device address during scan.
506  * \param pContext Callback context.
507  *
508  * \return
509  * On success, returns current number of scanned device found.
510  * On error, errno is set and - \ref BS_ECODE_SYS is returned.
511  */
512 static int bsModI2CScanCallback(i2c_t *pHndI2C, i2c_addr_t addr, void *pContext)
513 {
514  BsI2CRspScan_T *pMsgRsp = (BsI2CRspScan_T *)pContext; // response message
515 
516  if( pMsgRsp->m_scan.m_count < BSI2C_RSPSCAN_SCAN_LEN )
517  {
518  pMsgRsp->m_scan.u.m_buf[pMsgRsp->m_scan.m_count++] = addr;
519  return pMsgRsp->m_scan.m_count;
520  }
521  else
522  {
523  errno = E2BIG;
524  return -BS_ECODE_SYS;
525  }
526 }
527 
528 /*!
529  * \brief Service a \h_i2c scan for devices request.
530  *
531  * \note A module-specific request service must send a response.
532  *
533  * \param hndVConn Virtual connection handle.
534  * \param uTid Request-Response transaction id.
535  * \param uMsgIdReq Request message id.
536  * \param bufReq Packed request message buffer.
537  * \param uReqLen Size of request in buffer (number of bytes).
538  *
539  * \copydoc doc_return_std
540  */
541 static int bsModI2CReqScan(BsVConnHnd_T hndVConn,
542  BsTid_T uTid,
543  BsMsgId_T uMsgIdReq,
544  byte_t bufReq[],
545  size_t uReqLen)
546 {
547  static BsI2CMsgId_T uMsgIdRsp = BsI2CMsgIdRspScan;
548 
549  BsModCtlBlk_T *pCtlBlk; // resource control block
550  BsI2CRspScan_T msgRsp; // response message
551  byte_t bufRsp[BSPROXY_MSG_MAX_LEN]; // req/rsp buffer
552  int n; // number of bytes/return code
553 
554  //
555  // Parameter checks
556  //
557  if( !BSMOD_IS_VCONN_HANDLE(hndVConn) )
558  {
559  BSMOD_SEND_ERROR_RSP(BsModCallbacks, hndVConn, uTid, BS_ECODE_BAD_VCONN_HND,
560  "Module vconn handle out-of-range.");
561  return -BS_ECODE_BAD_VCONN_HND; \
562  }
563 
564  // retrieve the resource control block
565  pCtlBlk = (BsModCtlBlk_T *)BSMOD_RSRC(BsModRsrcTbl, hndVConn);
566 
567  if( pCtlBlk == NULL )
568  {
569  BSMOD_SEND_ERROR_RSP(BsModCallbacks, hndVConn, uTid, BS_ECODE_NO_VCONN,
570  "No resources for virtual connection found.");
571  return -BS_ECODE_NO_VCONN;
572  }
573 
574  // no devices yet
575  msgRsp.m_scan.m_count = (byte_t)0;
576 
577  //
578  // Execute client request.
579  //
580  n = i2c_scan(&pCtlBlk->m_hndI2C, bsModI2CScanCallback, &msgRsp);
581 
582  // check operation return code
583  if( n < 0 )
584  {
585  BSMOD_SEND_SYSERROR_RSP(BsModCallbacks, hndVConn, uTid,
586  "i2c_scan(fd=%d, ...).", pCtlBlk->m_hndI2C.fd);
587  return -BS_ECODE_SYS;
588  }
589 
590  LOGDIAG3("VConn=%d: %d=i2c_scan(fd=%d, ...).",
591  hndVConn, n, pCtlBlk->m_hndI2C.fd);
592 
593  //
594  // Pack server response.
595  //
596  // pack
597  n = BsI2CPackRspScan(&msgRsp, BSPROXY_BUF_BODY(bufRsp), pCtlBlk->m_bTrace);
598 
599  // check packing return code
600  if( n < 0 )
601  {
602  BSMOD_SEND_NMERROR_RSP(BsModCallbacks, hndVConn, uTid, n,
603  "MsgId=%u", uMsgIdRsp);
604  return -BS_ECODE_BAD_MSG;
605  }
606 
607  //
608  // Send response.
609  //
610  BsModCallbacks->m_cbSendRsp(hndVConn, uTid, uMsgIdRsp, bufRsp, (size_t)n);
611 
612  return BS_OK;
613 }
614 
615 
616 // ---------------------------------------------------------------------------
617 // Exported Interface
618 // ---------------------------------------------------------------------------
619 
620 /*!
621  * \brief Initialize \h_i2c module.
622  *
623  * Called once after module is loaded.
624  *
625  * \param sModUri Expanded, canonical module path name.
626  * \param pCallbacks Pointer to a set of module -> bsProxy core callback
627  * functions.
628  *
629  * \copydoc doc_return_std
630  */
631 int bsModInit(const char *sModUri, const BsModProxyCb_T *pCallbacks)
632 {
633  BsModUri = new_strdup(sModUri);
634 
635  // save bsProxy server callbacks
636  BsModCallbacks = pCallbacks;
637 
638  // create module resource table
639  BsModRsrcTbl = BsModCallbacks->m_cbModRsrcTblNew(BSMOD_MAX_HANDLES);
640 
641  return BS_OK;
642 }
643 
644 /*!
645  * \brief Exit \h_i2c module.
646  *
647  * Called once prior to module being unloaded.
648  *
649  * All open \h_i2c devices will be closed.
650  */
651 void bsModExit()
652 {
653  int index;
654  BsModCtlBlk_T *pCtlBlk;
655 
656  // free all module virtual connnection resources.
657  for(index=0; index<BSMOD_MAX_HANDLES; ++index)
658  {
659  if( (pCtlBlk = (BsModCtlBlk_T *)BsModRsrcTbl->m_vecRsrc[index]) != NULL )
660  {
661  if( pCtlBlk->m_uRefCnt <= 1 )
662  {
663  i2c_close(&pCtlBlk->m_hndI2C);
664  bsModCtlBlkDelete(pCtlBlk);
665  }
666  else
667  {
668  pCtlBlk->m_uRefCnt--;
669  }
670  }
671  }
672 
673  // free resource table
674  BsModCallbacks->m_cbModRsrcTblDelete(BsModRsrcTbl);
675 
676  delete((char *)BsModUri);
677 }
678 
679 /*!
680  * \brief Open an \h_i2c device and associate with the given handle.
681  *
682  * Subsequent calls to the module use the given handle to associate the
683  * specific module-device instance.
684  *
685  * The argument buffer contains packed message arguements specific to the
686  * device and module. For this \h_i2c module, there are now additional
687  * arguments.
688  *
689  * \note Each call to this exported function will only open the \h_i2c device
690  * if it is the first call. All virtual connections to the same device share
691  * the same opened file resource descriptor.
692  *
693  * \note
694  * It is the responsibile of the client to ensure consistency if more than
695  * one virtual connection is established.
696  *
697  * \param hndVConn Virtual connection handle.
698  * \param bTrace Do [not] enable message tracing on this handle.
699  * \param sDevUri Device URI.
700  * \param argbuf Packed specific open configuration arguments submessage.
701  * \param uArgSize Size of packed argumets in buffer (number of bytes).
702  *
703  * \return
704  * On success, returns a unique resource descriptor \h_ge 0 which is typically
705  * an opened file descriptor or socket descriptor, but can be module defined.\n
706  * \copydoc doc_return_ecode
707  */
708 int bsModOpen(BsVConnHnd_T hndVConn,
709  bool_t bTrace,
710  const char *sDevUri,
711  byte_t argbuf[],
712  size_t uArgSize)
713 {
714  BsModCtlBlk_T *pCtlBlk;
715  int rc;
716 
717  // Check if handle is in valid range.
718  BSMOD_TRY_VCONN_HND_RANGE(hndVConn);
719 
720  // Check if resources are available.
721  if( BSMOD_RSRC_INUSE_COUNT(BsModRsrcTbl) >= BSMOD_MAX_HANDLES )
722  {
724  "InUseCount=%u: No more resources available.",
725  BSMOD_RSRC_INUSE_COUNT(BsModRsrcTbl));
726  return -BS_ECODE_NO_RSRC;
727  }
728 
729  // Check if the handle in this module's resource table is not already in-use.
730  else if( BSMOD_RSRC_IS_INUSE(BsModRsrcTbl, hndVConn) )
731  {
732  BSMOD_LOG_ERROR(hndVConn, BS_ECODE_BUSY,
733  "Module virtual connection handle already in use");
734  return -BS_ECODE_BUSY;
735  }
736 
737  //
738  // Search for an existing opened device control block. If this is a first
739  // reference to the device, then create a shared control block and open
740  // the actual device.
741  //
742  if( (pCtlBlk = bsModCtlBlkFind(sDevUri)) == NULL )
743  {
744  // allocate a new control block and initialize
745  pCtlBlk = bsModCtlBlkNew(sDevUri, bTrace);
746 
747  // open the device
748  rc = i2c_open(&pCtlBlk->m_hndI2C, sDevUri);
749 
750  if( rc < 0 )
751  {
752  BSMOD_LOG_SYSERROR(hndVConn, "i2c_open(%p, %s).",
753  &pCtlBlk->m_hndI2C, sDevUri);
754  bsModCtlBlkDelete(pCtlBlk);
755  return -BS_ECODE_SYS;
756  }
757  }
758 
759  // bump device reference count
760  pCtlBlk->m_uRefCnt++;
761 
762  // add (a copy) to this module's resource table
763  BsModCallbacks->m_cbModRsrcAdd(BsModRsrcTbl, hndVConn, pCtlBlk);
764 
765  LOGDIAG2("VConn=%d: %d=i2c_open(%p, dev=%s).",
766  hndVConn, pCtlBlk->m_hndI2C.fd, &pCtlBlk->m_hndI2C, sDevUri);
767 
768  return pCtlBlk->m_hndI2C.fd;
769 }
770 
771 /*!
772  * \brief Close the \h_i2c device and disassociate virtual connection handle.
773  *
774  * The actual device and resources are only cleared if this is the last
775  * virtual connection reference to this device.
776  *
777  * \param hndVConn Virtual connection handle.
778  *
779  * \return
780  * \copydoc doc_return_std
781  */
783 {
784  BsModCtlBlk_T *pCtlBlk;
785 
786  // check if handle is in valid range
787  BSMOD_TRY_VCONN_HND_RANGE(hndVConn);
788 
789  // check is resouce is in-use (i.e. opened)
790  if( !BSMOD_RSRC_IS_INUSE(BsModRsrcTbl, hndVConn) )
791  {
793  "Resources for virtual connection not found.");
794  return -BS_ECODE_NO_VCONN;
795  }
796 
797  // remove from module's resource table
798  pCtlBlk = (BsModCtlBlk_T *)BsModCallbacks->m_cbModRsrcRemove(BsModRsrcTbl,
799  hndVConn);
800 
801  if( pCtlBlk == NULL )
802  {
803  BSMOD_LOG_ERROR(hndVConn, BS_ECODE_INTERNAL, "No module resource found.");
804  return -BS_ECODE_INTERNAL;
805  }
806 
807  //
808  // Closing last reference to device. So really close and free resources.
809  //
810  if( pCtlBlk->m_uRefCnt <= 1 )
811  {
812  i2c_close(&pCtlBlk->m_hndI2C);
813 
814  LOGDIAG2("VConn=%d: i2c_close(fd=%d).", hndVConn, pCtlBlk->m_hndI2C.fd);
815 
816  bsModCtlBlkDelete(pCtlBlk);
817  }
818 
819  // Simply decrement reference count.
820  else
821  {
822  pCtlBlk->m_uRefCnt--;
823  }
824 
825  return BS_OK;
826 }
827 
828 /*!
829  * \brief Service an \h_i2c request.
830  *
831  * \note A module-specific request service must send a response.
832  *
833  * \param hndVConn Virtual connection handle.
834  * \param uTid Request-Response transaction id.
835  * \param uMsgIdReq Request message id.
836  * \param bufReq Packed request message buffer.
837  * \param uReqLen Size of request in buffer (number of bytes).
838  *
839  * \copydoc doc_return_std
840  */
842  BsTid_T uTid,
843  BsMsgId_T uMsgIdReq,
844  byte_t bufReq[],
845  size_t uReqLen)
846 {
847  BsModCtlBlk_T *pCtlBlk;
848 
849  // check if handle is in valid range
850  if( !BSMOD_IS_VCONN_HANDLE(hndVConn) )
851  {
852  BSMOD_SEND_ERROR_RSP(BsModCallbacks, hndVConn, uTid, BS_ECODE_BAD_VCONN_HND,
853  "Module vconn handle out-of-range.");
854  return -BS_ECODE_BAD_VCONN_HND; \
855  }
856 
857  // retrieve resource control block
858  pCtlBlk = (BsModCtlBlk_T *)BSMOD_RSRC(BsModRsrcTbl, hndVConn);
859 
860  // check resource
861  if( pCtlBlk == NULL )
862  {
863  BSMOD_SEND_ERROR_RSP(BsModCallbacks, hndVConn, uTid, BS_ECODE_NO_VCONN,
864  "No resources for virtual connection found.");
865  return -BS_ECODE_NO_VCONN;
866  }
867 
868  switch( uMsgIdReq )
869  {
870  case BsI2CMsgIdReqRead:
871  return bsModI2CReqRead(hndVConn, uTid, uMsgIdReq, bufReq, uReqLen);
872  case BsI2CMsgIdReqTrans:
873  return bsModI2CReqTrans(hndVConn, uTid, uMsgIdReq, bufReq, uReqLen);
874  case BsI2CMsgIdReqWrite:
875  return bsModI2CReqWrite(hndVConn, uTid, uMsgIdReq, bufReq, uReqLen);
876  case BsI2CMsgIdReqScan:
877  return bsModI2CReqScan(hndVConn, uTid, uMsgIdReq, bufReq, uReqLen);
878  default:
879  BSMOD_SEND_ERROR_RSP(BsModCallbacks, hndVConn, uTid, BS_ECODE_UNKNOWN_REQ,
880  "MsgId=%u.", uMsgIdReq);
881  return -BS_ECODE_UNKNOWN_REQ;
882  }
883 }
884 
885 /*!
886  * \brief Enable/disable message tracing on handle.
887  *
888  * \param hndVConn Virtual connection handle.
889  * \param bTrace Do [not] enable message tracing on this handle.
890  *
891  * \copydoc doc_return_std
892  */
893 int bsModTrace(BsVConnHnd_T hndVConn, bool_t bTrace)
894 {
895  BsModCtlBlk_T *pCtlBlk;
896 
897  // check if handle is in valid range
898  if( !BSMOD_IS_VCONN_HANDLE(hndVConn) )
899  {
901  "Module vconn handle out-of-range.");
902  return -BS_ECODE_BAD_VCONN_HND;
903  }
904 
905  // retrieve resource control block
906  pCtlBlk = (BsModCtlBlk_T *)BSMOD_RSRC(BsModRsrcTbl, hndVConn);
907 
908  // check resource
909  if( pCtlBlk == NULL )
910  {
912  "No resources for virtual connection found.");
913  return -BS_ECODE_NO_VCONN;
914  }
915 
916  pCtlBlk->m_bTrace = bTrace;
917 
918  return BS_OK;
919 }
920 
921 /*!
922  * \brief Query for the static module information.
923  *
924  * \return
925  * Pointer to module static information.
926  */
928 {
929  return &BsModInfo;
930 }
uint_t BsMsgId_T
client message id type [0-64k].
Definition: BotSense.h:188
RspRead.
Definition: bsI2CMsgs.h:42
#define BSMOD_LOG_ERROR(hndVConn, ecode, efmt,...)
Log Interface Module Error.
Definition: bsProxyModIF.h:405
ushort_t m_addr
addr
Definition: bsI2CMsgs.h:134
static const char * BsModUri
module canonical name
Definition: bsI2CServer.c:111
#define BS_ECODE_UNKNOWN_REQ
unknown request
Definition: BotSense.h:81
struct BsI2CReqTrans_T::@0 m_writebuf
vector
Useful indirect indexing of handle to resource instance structure.
Definition: bsProxyModIF.h:136
#define BSI2C_RSPSCAN_SCAN_LEN
Definition: bsI2CMsgs.h:166
#define BSMOD_RSRC_IS_INUSE(pRsrcTbl, hndVConn)
Test if the resource table resource handle slot is in-use.
Definition: bsProxyModIF.h:169
void(* m_cbModRsrcTblDelete)(BsModRsrcTbl_T *pRsrcTbl)
Delete an allocated resource table.
Definition: bsProxyModIF.h:294
size_t m_count
vector item count
Definition: bsI2CMsgs.h:175
union BsI2CReqWrite_T::@4::@5 u
aligned vector items
void bsModExit()
Exit I2C module.
Definition: bsI2CServer.c:651
INLINE_IN_H int BsI2CPackRspRead(BsI2CRspRead_T *pStruct, byte_t buf[], size_t bufSize, bool_t bTrace)
Pack a BsI2CRspRead ITV message in big-endian byte order into the output buffer.
Definition: bsI2CMsgs.h:323
int bsModClose(BsVConnHnd_T hndVConn)
Close the I2C device and disassociate virtual connection handle.
Definition: bsI2CServer.c:782
byte_t m_readlen
readlen
Definition: bsI2CMsgs.h:93
uint_t BsTid_T
client transaction id type [0-255].
Definition: BotSense.h:172
uint_t m_uRefCnt
reference count to this device
Definition: bsI2CServer.c:105
const BsModInfo_T * bsModInfo()
Query for the static module information.
Definition: bsI2CServer.c:927
#define BSMOD_LOG_SYSERROR(hndVConn, efmt,...)
Log Interface Module System Error.
Definition: bsProxyModIF.h:431
<b><i>BotSense</i></b> bsProxy client library I2C bus interface.
#define BS_I2C_SERVER_MOD
server plugin dll module
Definition: bsI2C.h:62
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
RspScan.
Definition: bsI2CMsgs.h:46
const char * m_sDevUri
I2C device path name.
Definition: bsI2CServer.c:107
struct BsI2CReqWrite_T::@4 m_writebuf
vector
ushort_t m_addr
addr
Definition: bsI2CMsgs.h:65
int(* m_cbModRsrcAdd)(BsModRsrcTbl_T *pRsrcTbl, BsVConnHnd_T hndVConn, void *pRsrc)
Add a new resource to the resource table.
Definition: bsProxyModIF.h:305
ReqRead.
Definition: bsI2CMsgs.h:40
#define BS_OK
not an error, success
Definition: BotSense.h:66
struct BsI2CRspRead_T::@2 m_readbuf
vector
#define BS_ECODE_BAD_VCONN_HND
bad virtual connection handle
Definition: BotSense.h:79
size_t m_count
vector item count
Definition: bsI2CMsgs.h:85
#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
BsI2CMsgId_T
Definition: bsI2CMsgs.h:37
#define BSMOD_MAX_HANDLES
Maximum number of module supported simultaneous virtual connections.
Definition: bsI2CServer.c:96
ReqTrans.
Definition: bsI2CMsgs.h:41
#define BSMOD_TRY_VCONN_HND_RANGE(hndVConn)
Check if handle is within the range of module handles.
Definition: bsProxyModIF.h:499
Interface Module callbacks to bsProxy services type.
Definition: bsProxyModIF.h:235
ushort_t m_addr
addr
Definition: bsI2CMsgs.h:82
BotSense bsProxy server - client raw I2C NetMsgs XML Definition.
<b><i>BotSense</i></b> client library declarations.
#define BS_ECODE_BAD_MSG
bad message
Definition: BotSense.h:76
int bsModTrace(BsVConnHnd_T hndVConn, bool_t bTrace)
Enable/disable message tracing on handle.
Definition: bsI2CServer.c:893
#define BSMOD_RSRC_INUSE_COUNT(pRsrcTbl)
Get the resouce table current in-use count.
Definition: bsProxyModIF.h:208
union BsI2CReqTrans_T::@0::@1 u
aligned vector items
RspWrite.
Definition: bsI2CMsgs.h:44
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
INLINE_IN_H int BsI2CPackRspWrite(BsI2CRspWrite_T *pStruct, byte_t buf[], size_t bufSize, bool_t bTrace)
Pack a BsI2CRspWrite ITV message in big-endian byte order into the output buffer. ...
Definition: bsI2CMsgs.h:409
static int bsModI2CReqTrans(BsVConnHnd_T hndVConn, BsTid_T uTid, BsMsgId_T uMsgIdReq, byte_t bufReq[], size_t uReqLen)
Service a I2C write-read transaction request.
Definition: bsI2CServer.c:404
static int bsModI2CReqRead(BsVConnHnd_T hndVConn, BsTid_T uTid, BsMsgId_T uMsgIdReq, byte_t bufReq[], size_t uReqLen)
Service a I2C read request.
Definition: bsI2CServer.c:194
ReqScan.
Definition: bsI2CMsgs.h:45
struct BsI2CRspScan_T::@6 m_scan
vector
INLINE_IN_H int BsI2CUnpackReqWrite(byte_t buf[], size_t uMsgLen, BsI2CReqWrite_T *pStruct, bool_t bTrace)
Unpack a BsI2CReqWrite ITV message in big-endian byte order from the input buffer.
Definition: bsI2CMsgs.h:387
size_t m_count
vector item count
Definition: bsI2CMsgs.h:111
#define BS_ECODE_NO_RSRC
no resource available
Definition: BotSense.h:85
i2c_t m_hndI2C
I2C bus handle.
Definition: bsI2CServer.c:106
int bsModOpen(BsVConnHnd_T hndVConn, bool_t bTrace, const char *sDevUri, byte_t argbuf[], size_t uArgSize)
Open an I2C device and associate with the given handle.
Definition: bsI2CServer.c:708
byte_t m_byteswritten
byteswritten
Definition: bsI2CMsgs.h:157
#define BSMOD_RSRC(pRsrcTbl, hndVConn)
Get the resource given the handle.
Definition: bsProxyModIF.h:196
Standard bsProxy static interface module information structure type.
Definition: bsProxyModIF.h:119
ReqWrite.
Definition: bsI2CMsgs.h:43
static BsModCtlBlk_T * bsModCtlBlkFind(const char *sDevUri)
Find an already allocated resource control block.
Definition: bsI2CServer.c:162
size_t m_count
vector item count
Definition: bsI2CMsgs.h:137
byte_t m_readlen
readlen
Definition: bsI2CMsgs.h:66
void *(* m_cbModRsrcRemove)(BsModRsrcTbl_T *pRsrcTbl, BsVConnHnd_T hndVConn)
Remove a resource from the resource table.
Definition: bsProxyModIF.h:320
int bsModRequest(BsVConnHnd_T hndVConn, BsTid_T uTid, BsMsgId_T uMsgIdReq, byte_t bufReq[], size_t uReqLen)
Service an I2C request.
Definition: bsI2CServer.c:841
INLINE_IN_H int BsI2CUnpackReqTrans(byte_t buf[], size_t uMsgLen, BsI2CReqTrans_T *pStruct, bool_t bTrace)
Unpack a BsI2CReqTrans ITV message in big-endian byte order from the input buffer.
Definition: bsI2CMsgs.h:301
static int bsModI2CScanCallback(i2c_t *pHndI2C, i2c_addr_t addr, void *pContext)
I2C scan callback function.
Definition: bsI2CServer.c:512
#define BSMOD_SEND_NMERROR_RSP(pCb, hndVConn, uTid, nmecode, efmt,...)
Log NetMsgs (Un)Packing Error and Send Error Response.
Definition: bsProxyModIF.h:464
static int bsModI2CReqScan(BsVConnHnd_T hndVConn, BsTid_T uTid, BsMsgId_T uMsgIdReq, byte_t bufReq[], size_t uReqLen)
Service a I2C scan for devices request.
Definition: bsI2CServer.c:541
<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
static BsModCtlBlk_T * bsModCtlBlkNew(const char *sDevUri, bool_t bTrace)
Allocate a new resource control block.
Definition: bsI2CServer.c:127
#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
#define BS_ECODE_NO_VCONN
virtual connection not found
Definition: BotSense.h:80
int bsModInit(const char *sModUri, const BsModProxyCb_T *pCallbacks)
Initialize I2C module.
Definition: bsI2CServer.c:631
#define BSMOD_SEND_SYSERROR_RSP(pCb, hndVConn, uTid, efmt,...)
Log System Error and Send Error Response.
Definition: bsProxyModIF.h:481
static int bsModI2CReqWrite(BsVConnHnd_T hndVConn, BsTid_T uTid, BsMsgId_T uMsgIdReq, byte_t bufReq[], size_t uReqLen)
Service a I2C write request.
Definition: bsI2CServer.c:299
static BsModRsrcTbl_T * BsModRsrcTbl
module resource table
Definition: bsI2CServer.c:113
static const BsModProxyCb_T * BsModCallbacks
module to bsProxy callbacks
Definition: bsI2CServer.c:112
#define BSPROXY_MSG_MAX_LEN
total message maximum length
Definition: BotSense.h:259
void ** m_vecRsrc
vecRsrc[index] -> rsrc
Definition: bsProxyModIF.h:139
union BsI2CRspScan_T::@6::@7 u
aligned vector items
#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
union BsI2CRspRead_T::@2::@3 u
aligned vector items
static BsModInfo_T BsModInfo
Module static information.
Definition: bsI2CServer.c:72
INLINE_IN_H int BsI2CUnpackReqRead(byte_t buf[], size_t uMsgLen, BsI2CReqRead_T *pStruct, bool_t bTrace)
Unpack a BsI2CReqRead ITV message in big-endian byte order from the input buffer. ...
Definition: bsI2CMsgs.h:258
#define BS_ECODE_BUSY
resource busy
Definition: BotSense.h:86
<b><i>BotSense</i></b> package top-level, unifying header declarations.
int BsVConnHnd_T
virtual connection handle type
Definition: BotSense.h:151
static void bsModCtlBlkDelete(BsModCtlBlk_T *pCtlBlk)
Delete an allocated resource control block.
Definition: bsI2CServer.c:145
INLINE_IN_H int BsI2CPackRspScan(BsI2CRspScan_T *pStruct, byte_t buf[], size_t bufSize, bool_t bTrace)
Pack a BsI2CRspScan ITV message in big-endian byte order into the output buffer.
Definition: bsI2CMsgs.h:452