CogniBoost/sw/libCogniBoost/cbLibDev.c
int cbTransLow(cbHnd_T    hnd,
               cbMsgId_T  eReqMsgId,
               byte_t     bufReqPkt[],
               size_t     uReqMsgLen,
               cbMsgId_T  eRspMsgId,
               byte_t     bufRspMsg[],
               size_t     sizeRspBuf)
{
  cbTid_T       uTidReq;      // request transaction id
  cbPktHdr_T    hdrRsp;       // response packet header
  cbMsgId_T     eRcvMsgId;    // received message id
  cbRspErr_T    msgRspErr;    // common error response message
  bool_t        bPending;     // resposne is [not] pending
  int           nRspMsgLen;   // response message length
  uint_t        uRspECode;    // response error message error code
  int           n;            // number of bytes/return code

  CHK_DEV(hnd);

  CHK_EXPR(hnd, (sizeRspBuf >= CB_MSG_MIN_SIZE),
      CB_LIB_ECODE_TOO_SMALL, "Response buffer size=%zu < message minimum=%zu.",
      sizeRspBuf, CB_MSG_MIN_SIZE);

  // this request's transaction id
  uTidReq = cbNextTid(hnd);

  // mark request for tracking
  cbCacheMark(hnd, uTidReq);

  //
  // send request
  //
  cbLock(hnd);

  n = cbSendReq(hnd, uTidReq, eReqMsgId, bufReqPkt, uReqMsgLen);

  cbUnlock(hnd);

  CHK_ECODE(hnd, n, "Failed to send request %s(%d).",
      CB_MSG_NAME_ID(eReqMsgId));

  //
  // receive response
  //
  bPending = true;

  while( bPending )
  {
    // check transaction cache for any cached response.
    n = cbCacheLoad(hnd, uTidReq, &hdrRsp, bufRspMsg, sizeRspBuf);

    CHK_ECODE(hnd, n, "Cached response failed for request %s(%d).",
        CB_MSG_NAME_ID(eReqMsgId));

    // found a good, cached response
    if( n > 0 )
    {
      cbCacheForget(hnd, uTidReq);
      bPending = false;
    }

    // nothing cached, receive a response
    else
    {
      cbLock(hnd);

      n = (int)cbRecvRsp(hnd, &hdrRsp, bufRspMsg, sizeRspBuf);
      
      cbUnlock(hnd);

      CHK_ECODE(hnd, n, "Failed to receive response %s(%d).",
          CB_MSG_NAME_ID(eRspMsgId));

      // response was for this request
      if( uTidReq == hdrRsp.m_hdrTid )
      {
        cbCacheForget(hnd, uTidReq);
        bPending = false;
      }

      // response is for another thread - cache it
      else
      {
        cbCacheSave(hnd, uTidReq, &hdrRsp, bufRspMsg);
      }
    }
  }

  nRspMsgLen  = (int)hdrRsp.m_hdrMsgLen;
  eRcvMsgId   = cbGetMsgId(bufRspMsg, (size_t)n);

  // received common error response
  if( eRcvMsgId == cbMsgIdRspErr )
  {
    n = cbUnpackRspErr(bufRspMsg, (size_t)n, &msgRspErr, hnd->m_bTrace);

    CHK_ECODE(hnd, n, "Failed to unpack error response message.");

    uRspECode = (uint_t)(msgRspErr.m_ecode);

    // unknown response error code
    if( uRspECode >= CB_RSP_ECODE_NUMOF )
    {
      uRspECode = CB_LIB_ECODE_RSP_BADEC;
    }

    CB_LOG_ERROR(hnd, (int)uRspECode, "%s.", msgRspErr.m_emsg);

    return -(int)uRspECode;
  }

  CHK_EXPR(hnd, (eRcvMsgId == eRspMsgId), CB_LIB_ECODE_RECV,
        "Received unexpected message %s(%d), "
        "expected message %s(%d).",
        CB_MSG_NAME_ID(eRcvMsgId), CB_MSG_NAME_ID(eRspMsgId));

  return nRspMsgLen;
}
/*!
 * \brief Execute a low-level request-response transaction with the CogniBoost
 * server.
 *
 * \note The request and response buffer can be the same buffer if the packed 
 * request contents does not need to be preserved.
 *
 * \warning There must be exactly \ref CB_PKT_HDR_SIZE bytes at the front
 * of the request buffer available to pack the \h_botsense header. (Reduces the
 * number of buffer copies.)
 *
 * \par Request Format:
 * packet ::= pkthdr msg\n
 * msg ::=  msghdr msgbody
 *
 * \par Response Format:
 * packet ::= pkthdr msg\n
 * msg ::=  msghdr msgbody
 *
 * \param hnd             CogniBoost device handle.
 * \param eReqMsgId       Request message id.
 * \param [in] bufReqPkt  Packet buffer with the prepacked request message.
 *                        The buffer has empty head space for the packet header.
 * \param uReqMsgLen      Length of packed request message.
 * \param eRspMsgId       Expected response message id.
 * \param [out] bufRspMsg Buffer with received packed response message. 
 * \param sizeRspBuf      Size of response buffer (number of bytes).
 *
 * \return 
 * On success, returns the length of the response message.\n
 * \copydoc doc_return_ecode
 */
\brief Execute a low-level request-response transaction with the CogniBoost
server.

\note The request and response buffer can be the same buffer if the packed
request contents does not need to be preserved.

\warning There must be exactly \ref CB_PKT_HDR_SIZE bytes at the front
of the request buffer available to pack the \h_botsense header. (Reduces the
number of buffer copies.)





\param hnd             CogniBoost device handle.
\param eReqMsgId       Request message id.
\param [in] bufReqPkt  Packet buffer with the prepacked request message.
The buffer has empty head space for the packet header.
\param uReqMsgLen      Length of packed request message.
\param eRspMsgId       Expected response message id.
\param [out] bufRspMsg Buffer with received packed response message.
\param sizeRspBuf      Size of response buffer (number of bytes).

\return
On success, returns the length of the response message.\n
\copydoc doc_return_ecode
\ brief Execute a low - level request - response transaction with the CogniBoost server . \ note The request and response buffer can be the same buffer if the packed request contents does not need to be preserved . \ warning There must be exactly \ ref CB_PKT_HDR_SIZE bytes at the front of the request buffer available to pack the \ h_botsense header . ( Reduces the number of buffer copies . ) \ param hnd CogniBoost device handle . \ param eReqMsgId Request message id . \ param [ in ] bufReqPkt Packet buffer with the prepacked request message . The buffer has empty head space for the packet header . \ param uReqMsgLen Length of packed request message . \ param eRspMsgId Expected response message id . \ param [ out ] bufRspMsg Buffer with received packed response message . \ param sizeRspBuf Size of response buffer ( number of bytes ) . \ return On success returns the length of the response message . \ n \ copydoc doc_return_ecode
int cbTransLow(cbHnd_T    hnd,
               cbMsgId_T  eReqMsgId,
               byte_t     bufReqPkt[],
               size_t     uReqMsgLen,
               cbMsgId_T  eRspMsgId,
               byte_t     bufRspMsg[],
               size_t     sizeRspBuf)
{
  cbTid_T       uTidReq;      
  cbPktHdr_T    hdrRsp;       
  cbMsgId_T     eRcvMsgId;    
  cbRspErr_T    msgRspErr;    
  bool_t        bPending;     
  int           nRspMsgLen;   
  uint_t        uRspECode;    
  int           n;            
  CHK_DEV(hnd);
  CHK_EXPR(hnd, (sizeRspBuf >= CB_MSG_MIN_SIZE),
      CB_LIB_ECODE_TOO_SMALL, "Response buffer size=%zu < message minimum=%zu.",
      sizeRspBuf, CB_MSG_MIN_SIZE);
  uTidReq = cbNextTid(hnd);
  cbCacheMark(hnd, uTidReq);
   send request
  cbLock(hnd);
  n = cbSendReq(hnd, uTidReq, eReqMsgId, bufReqPkt, uReqMsgLen);
  cbUnlock(hnd);
  CHK_ECODE(hnd, n, "Failed to send request %s(%d).",
      CB_MSG_NAME_ID(eReqMsgId));
   receive response
  bPending = true;
  while( bPending )
  {
     check transaction cache for any cached response.
    n = cbCacheLoad(hnd, uTidReq, &hdrRsp, bufRspMsg, sizeRspBuf);
    CHK_ECODE(hnd, n, "Cached response failed for request %s(%d).",
        CB_MSG_NAME_ID(eReqMsgId));
     found a good, cached response
    if( n > 0 )
    {
      cbCacheForget(hnd, uTidReq);
      bPending = false;
    }
     nothing cached, receive a response
    else
    {
      cbLock(hnd);
      n = (int)cbRecvRsp(hnd, &hdrRsp, bufRspMsg, sizeRspBuf);
      cbUnlock(hnd);
      CHK_ECODE(hnd, n, "Failed to receive response %s(%d).",
          CB_MSG_NAME_ID(eRspMsgId));
       response was for this request
      if( uTidReq == hdrRsp.m_hdrTid )
      {
        cbCacheForget(hnd, uTidReq);
        bPending = false;
      }
       response is for another thread - cache it
      else
      {
        cbCacheSave(hnd, uTidReq, &hdrRsp, bufRspMsg);
      }
    }
  }
  nRspMsgLen  = (int)hdrRsp.m_hdrMsgLen;
  eRcvMsgId   = cbGetMsgId(bufRspMsg, (size_t)n);
   received common error response
  if( eRcvMsgId == cbMsgIdRspErr )
  {
    n = cbUnpackRspErr(bufRspMsg, (size_t)n, &msgRspErr, hnd->m_bTrace);
    CHK_ECODE(hnd, n, "Failed to unpack error response message.");
    uRspECode = (uint_t)(msgRspErr.m_ecode);
     unknown response error code
    if( uRspECode >= CB_RSP_ECODE_NUMOF )
    {
      uRspECode = CB_LIB_ECODE_RSP_BADEC;
    }
    CB_LOG_ERROR(hnd, (int)uRspECode, "%s.", msgRspErr.m_emsg);
    return -(int)uRspECode;
  }
  CHK_EXPR(hnd, (eRcvMsgId == eRspMsgId), CB_LIB_ECODE_RECV,
        "Received unexpected message %s(%d), "
        "expected message %s(%d).",
        CB_MSG_NAME_ID(eRcvMsgId), CB_MSG_NAME_ID(eRspMsgId));
  return nRspMsgLen;
}
int cbTransLow ( cbHnd_T hnd , cbMsgId_T eReqMsgId , byte_t bufReqPkt [ ] , size_t uReqMsgLen , cbMsgId_T eRspMsgId , byte_t bufRspMsg [ ] , size_t sizeRspBuf ) { cbTid_T uTidReq ; cbPktHdr_T hdrRsp ; cbMsgId_T eRcvMsgId ; cbRspErr_T msgRspErr ; bool_t bPending ; int nRspMsgLen ; uint_t uRspECode ; int n ; CHK_DEV ( hnd ) ; CHK_EXPR ( hnd , ( sizeRspBuf >= CB_MSG_MIN_SIZE ) , CB_LIB_ECODE_TOO_SMALL , " " , sizeRspBuf , CB_MSG_MIN_SIZE ) ; uTidReq = cbNextTid ( hnd ) ; cbCacheMark ( hnd , uTidReq ) ; cbLock ( hnd ) ; n = cbSendReq ( hnd , uTidReq , eReqMsgId , bufReqPkt , uReqMsgLen ) ; cbUnlock ( hnd ) ; CHK_ECODE ( hnd , n , " " , CB_MSG_NAME_ID ( eReqMsgId ) ) ; bPending = true ; while ( bPending ) { n = cbCacheLoad ( hnd , uTidReq , & hdrRsp , bufRspMsg , sizeRspBuf ) ; CHK_ECODE ( hnd , n , " " , CB_MSG_NAME_ID ( eReqMsgId ) ) ; if ( n > 0 ) { cbCacheForget ( hnd , uTidReq ) ; bPending = false ; } else { cbLock ( hnd ) ; n = ( int ) cbRecvRsp ( hnd , & hdrRsp , bufRspMsg , sizeRspBuf ) ; cbUnlock ( hnd ) ; CHK_ECODE ( hnd , n , " " , CB_MSG_NAME_ID ( eRspMsgId ) ) ; if ( uTidReq == hdrRsp . m_hdrTid ) { cbCacheForget ( hnd , uTidReq ) ; bPending = false ; } else { cbCacheSave ( hnd , uTidReq , & hdrRsp , bufRspMsg ) ; } } } nRspMsgLen = ( int ) hdrRsp . m_hdrMsgLen ; eRcvMsgId = cbGetMsgId ( bufRspMsg , ( size_t ) n ) ; if ( eRcvMsgId == cbMsgIdRspErr ) { n = cbUnpackRspErr ( bufRspMsg , ( size_t ) n , & msgRspErr , hnd -> m_bTrace ) ; CHK_ECODE ( hnd , n , " " ) ; uRspECode = ( uint_t ) ( msgRspErr . m_ecode ) ; if ( uRspECode >= CB_RSP_ECODE_NUMOF ) { uRspECode = CB_LIB_ECODE_RSP_BADEC ; } CB_LOG_ERROR ( hnd , ( int ) uRspECode , " " , msgRspErr . m_emsg ) ; return - ( int ) uRspECode ; } CHK_EXPR ( hnd , ( eRcvMsgId == eRspMsgId ) , CB_LIB_ECODE_RECV , " " " " , CB_MSG_NAME_ID ( eRcvMsgId ) , CB_MSG_NAME_ID ( eRspMsgId ) ) ; return nRspMsgLen ; }
\brief Execute a low-level request-response transaction with the CogniBoost
 server.
\ brief Execute a low - level request - response transaction with the CogniBoost server .
// request transaction id // response packet header // received message id // common error response message // resposne is [not] pending // response message length // response error message error code // number of bytes/return code // this request's transaction id // mark request for tracking // // send request // // // receive response // // check transaction cache for any cached response. // found a good, cached response // nothing cached, receive a response // response was for this request // response is for another thread - cache it // received common error response // unknown response error code