bsproxy/client.c

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //
00003 // Package:   botsense
00004 //
00005 // File:      client.c
00006 //
00007 /*! \file
00008  *
00009  * \version $LastChangedDate$ $Rev$
00010  *
00011  * \brief Process client requests and services.
00012  *
00013  * \author Robin Knight (robin.knight@roadnarrows.com)
00014  *
00015  * \par Copyright:
00016  * (C) 2007.  RoadNarrows LLC.
00017  * (http://www.roadnarrows.com)
00018  * \n All Rights Reserved
00019  */
00020 // Permission is hereby granted, without written agreement and without
00021 // license or royalty fees, to use, copy, modify, and distribute this
00022 // software and its documentation for any purpose, provided that
00023 // (1) The above copyright notice and the following two paragraphs
00024 // appear in all copies of the source code and (2) redistributions
00025 // including binaries reproduces these notices in the supporting
00026 // documentation.   Substantial modifications to this software may be
00027 // copyrighted by their authors and need not follow the licensing terms
00028 // described here, provided that the new terms are clearly indicated in
00029 // all files where they apply.
00030 //
00031 // IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY MEMBERS/EMPLOYEES
00032 // OF ROADNARROW LLC OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY
00033 // PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
00034 // DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
00035 // EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF
00036 // THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // THE AUTHOR AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
00039 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
00040 // FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
00041 // "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
00042 // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
00043 //
00044 ////////////////////////////////////////////////////////////////////////////////
00045 
00046 #include <stdio.h>
00047 #include <stdlib.h>
00048 #include <string.h>
00049 
00050 #include "rnr/rnrconfig.h"
00051 #include "rnr/log.h"
00052 #include "rnr/opts.h"
00053 #include "rnr/new.h"
00054 #include "rnr/sock.h"
00055 #include "rnr/char.h"
00056 
00057 #include "botsense/bsproxy_if.h"
00058 
00059 #include "version.h"
00060 #include "bsproxy.h"
00061 
00062 
00063 // ---------------------------------------------------------------------------
00064 // Private Interface 
00065 // ---------------------------------------------------------------------------
00066 
00067 /*!
00068  * \brief Find empty client device slot.
00069  *
00070  * \param pClient   BotSense client.
00071  *
00072  * \return Returns slot index >= 0 on success, <0 on failure.
00073  */
00074 static int ClientDevFindEmptySlot(BsProxyClient_T *pClient)
00075 {
00076   int i;
00077 
00078   for(i=0; i<BSPROXY_CLIENT_DEV_MAX; ++i)
00079   {
00080     if( pClient->m_tblClientDev[i].m_eDevType == BSPROXY_DEVTYPE_NONE )
00081     {
00082       return i;
00083     }
00084   }
00085   return -1;
00086 }
00087 
00088 /*!
00089  * \brief Send error response to the client on receiving bad command header.
00090  *
00091  * \param pClient   BotSense client.
00092  * \param bufCmd    Received command buffer.
00093  * \param lenCmd    Received command length (number of bytes).
00094  *
00095  * \return Returns OK on success, RC_ERROR on failure.
00096  */
00097 static int ClientSendHdrError(BsProxyClient_T *pClient,
00098                             byte_t bufCmd[], size_t lenCmd)
00099 {
00100   byte_t  buf[BSPROXY_CMD_HDR_LEN];
00101 
00102   switch( lenCmd )
00103   {
00104     case 0:
00105       buf[BSPROXY_CMD_HDR_MSGID_IDX] = BSPROXY_MSGID_ERROR;
00106       buf[BSPROXY_CMD_HDR_TID_IDX]   = 0;
00107       buf[BSPROXY_CMD_HDR_BLEN_IDX]  = 0;
00108       return ClientSendFailRsp(pClient, buf, "no command header");
00109     case 1:
00110       buf[BSPROXY_CMD_HDR_MSGID_IDX] = bufCmd[BSPROXY_CMD_HDR_MSGID_IDX];
00111       buf[BSPROXY_CMD_HDR_TID_IDX]   = 0;
00112       buf[BSPROXY_CMD_HDR_BLEN_IDX]  = 0;
00113       return ClientSendFailRsp(pClient, buf, "bad header - no transation id");
00114     case 2:
00115     default:
00116       buf[BSPROXY_CMD_HDR_MSGID_IDX] = bufCmd[BSPROXY_CMD_HDR_MSGID_IDX];
00117       buf[BSPROXY_CMD_HDR_TID_IDX]   = bufCmd[BSPROXY_CMD_HDR_TID_IDX];
00118       buf[BSPROXY_CMD_HDR_BLEN_IDX]  = 0;
00119       return ClientSendFailRsp(pClient, buf, "bad header - no body length");
00120   }
00121 }
00122 
00123 /*!
00124  * \brief Get the device handle from the recieved client command.
00125  *
00126  * The handle is assumed to be the first byte of the command message body.
00127  *
00128  * On error, a fail response message is automatically sent to the client.
00129  *
00130  * \param pClient   BotSense client.
00131  * \param bufCmd    Received command buffer.
00132  *
00133  * \return Returns OK on success, RC_ERROR on failure.
00134  */
00135 static int ClientGetHandle(BsProxyClient_T *pClient, byte_t bufCmd[])
00136 {
00137   int           nHandle;
00138 
00139   chkCmdBLenGE(pClient, bufCmd, 1);
00140 
00141   nHandle = (int)bufCmd[BSPROXY_CMD_HDR_LEN];
00142 
00143   if( (nHandle < 0) || (nHandle >= BSPROXY_CLIENT_DEV_MAX) )
00144   {
00145     LOGERROR("%s: %d: device handle out of range.",
00146         pClient->m_sClientName, nHandle);
00147     return ClientSendFailRsp(pClient, bufCmd, "bad parameter");
00148   }
00149 
00150   if( pClient->m_tblClientDev[nHandle].m_eDevType == BSPROXY_DEVTYPE_NONE )
00151   {
00152     LOGERROR("%s: %d: no proxied device.", pClient->m_sClientName, nHandle);
00153     return ClientSendFailRsp(pClient, bufCmd, "no proxied device");
00154   }
00155 
00156   return nHandle;
00157 }
00158 
00159 
00160 // ...........................................................................
00161 // Client Commands
00162 // ...........................................................................
00163 
00164 /*!
00165  * \brief Client comand to loopback the client's message body.
00166  *
00167  * \par Command Format:
00168  *  cmdhdr body
00169  *
00170  * \par Response Format:
00171  *  rsphdr body \n
00172  *  rsphdr errmsg
00173  *
00174  * \param pServer   BotSense server.
00175  * \param pClient   BotSense client.
00176  * \param bufCmd    Received command buffer.
00177  * \param lenCmd    Received command length (number of bytes).
00178  *
00179  * \return Returns OK on success, RC_ERROR on failure.
00180  */
00181 static int CmdLoopback(BsProxyServer_T *pServer,
00182                        BsProxyClient_T *pClient,
00183                        byte_t bufCmd[], size_t lenCmd)
00184 {
00185   byte_t        bufRsp[BSPROXY_MSG_MAX_LEN];
00186   size_t        lenBody;
00187 
00188   BSPROXY_LOG_CMD(pClient, bufCmd, lenCmd);
00189 
00190   lenBody = bufCmd[BSPROXY_CMD_HDR_BLEN_IDX];
00191 
00192   if( lenBody > BSPROXY_RSP_BODY_LEN_MAX )
00193   {
00194     lenBody = BSPROXY_RSP_BODY_LEN_MAX;
00195   }
00196 
00197   fprintf(stderr, "%s: ", pClient->m_sClientName);
00198   PrettyPrintBuf(stderr, &bufCmd[BSPROXY_CMD_HDR_LEN],
00199                 lenCmd-BSPROXY_CMD_HDR_LEN);
00200   fprintf(stderr, "\n");
00201 
00202 
00203   memcpy(bufRsp+BSPROXY_RSP_HDR_LEN, bufCmd+BSPROXY_CMD_HDR_LEN, lenBody);
00204 
00205   return ClientSendPassRsp(pClient, bufCmd, bufRsp,
00206                             BSPROXY_RSP_HDR_LEN+lenBody);
00207 }
00208 
00209 /*!
00210  * \brief Client command to set the server's logging level.
00211  *
00212  * \par Command Format:
00213  *  cmdhdr level \n
00214  *
00215  * \par Response Format:
00216  *  rsphdr level \n
00217  *  rsphdr errmsg 
00218  *
00219  * \param pServer   BotSense server.
00220  * \param pClient   BotSense client.
00221  * \param bufCmd    Received command buffer.
00222  * \param lenCmd    Received command length (number of bytes).
00223  *
00224  * \return Returns OK on success, RC_ERROR on failure.
00225  */
00226 static int CmdLog(BsProxyServer_T *pServer,
00227                   BsProxyClient_T *pClient,
00228                   byte_t bufCmd[], size_t lenCmd)
00229 {
00230   byte_t        bufRsp[BSPROXY_MSG_MAX_LEN];
00231   size_t        lenRsp;
00232   int           nLevel;
00233 
00234   BSPROXY_LOG_CMD(pClient, bufCmd, lenCmd);
00235 
00236   chkCmdBLenEQ(pClient, bufCmd, 1);
00237 
00238   nLevel = (int)bufCmd[BSPROXY_CMD_HDR_LEN];
00239 
00240   nLevel = LOG_SET_THRESHOLD(nLevel);
00241 
00242   lenRsp            = BSPROXY_RSP_HDR_LEN;
00243   bufRsp[lenRsp++]  = (byte_t)nLevel;
00244 
00245   return ClientSendPassRsp(pClient, bufCmd, bufRsp, lenRsp);
00246 }
00247 
00248 /*!
00249  * \brief Client command to get the server's version string.
00250  *
00251  * \par Command Format:
00252  *  cmdhdr \n
00253  *
00254  * \par Response Format:
00255  *  rsphdr version \n
00256  *  rsphdr errmsg 
00257  *
00258  * \param pServer   BotSense server.
00259  * \param pClient   BotSense client.
00260  * \param bufCmd    Received command buffer.
00261  * \param lenCmd    Received command length (number of bytes).
00262  *
00263  * \return Returns OK on success, RC_ERROR on failure.
00264  */
00265 static int CmdVersion(BsProxyServer_T *pServer,
00266                   BsProxyClient_T *pClient,
00267                   byte_t bufCmd[], size_t lenCmd)
00268 {
00269   byte_t        bufRsp[BSPROXY_MSG_MAX_LEN];
00270   size_t        lenRsp;
00271   char         *sVersion;
00272 
00273   BSPROXY_LOG_CMD(pClient, bufCmd, lenCmd);
00274 
00275   lenRsp = BSPROXY_RSP_HDR_LEN;
00276 
00277   sVersion = (char *)&bufRsp[lenRsp];
00278 
00279   snprintf(sVersion, (size_t)(BSPROXY_CMD_HDR_LEN-BSPROXY_RSP_HDR_LEN),
00280             "bsproxy %s %s", PKG_VERSION, PKG_TIMESTAMP);
00281 
00282   sVersion[BSPROXY_CMD_HDR_LEN-BSPROXY_RSP_HDR_LEN-1] = 0; // make sure of null
00283 
00284   lenRsp += strlen(sVersion) + 1;   // include null
00285 
00286   return ClientSendPassRsp(pClient, bufCmd, bufRsp, lenRsp);
00287 }
00288 
00289 /*!
00290  * \brief Client command to get list of all supported  proxied device types.
00291  *
00292  * \par Command Format:
00293  *  cmdhdr \n
00294  *
00295  * \par Response Format:
00296  *  rsphdr prox_dev0 ... \n
00297  *  rsphdr errmsg 
00298  *
00299  * \param pServer   BotSense server.
00300  * \param pClient   BotSense client.
00301  * \param bufCmd    Received command buffer.
00302  * \param lenCmd    Received command length (number of bytes).
00303  *
00304  * \return Returns OK on success, RC_ERROR on failure.
00305  */
00306 static int CmdProxyInfo(BsProxyServer_T *pServer,
00307                        BsProxyClient_T *pClient,
00308                        byte_t bufCmd[], size_t lenCmd)
00309 {
00310   byte_t        bufRsp[BSPROXY_MSG_MAX_LEN];
00311   size_t        lenRsp;
00312 
00313   BSPROXY_LOG_CMD(pClient, bufCmd, lenCmd);
00314 
00315   lenRsp            = BSPROXY_RSP_HDR_LEN;
00316   bufRsp[lenRsp++]  = (byte_t)BSPROXY_DEVTYPE_I2C;
00317   bufRsp[lenRsp++]  = (byte_t)BSPROXY_DEVTYPE_BPFOOT;
00318   bufRsp[lenRsp++]  = (byte_t)BSPROXY_DEVTYPE_BPIMU;
00319   bufRsp[lenRsp++]  = (byte_t)BSPROXY_DEVTYPE_RCB3;
00320 
00321   return ClientSendPassRsp(pClient, bufCmd, bufRsp, lenRsp);
00322 }
00323 
00324 /*!
00325  * \brief Client command to open a proxied device for the client.
00326  *
00327  * The underlining device may already be open, in which case the device is 
00328  * shared.
00329  *
00330  * \par Command Format:
00331  * <table border="0">
00332  * <tr><td>BrainPack I<sup>2</sup>C:</td><td>cmdhdr i2c_addr dev_name</td></tr>
00333  * <tr><td>other:</td><td>cmdhdr dev_name</td></tr>
00334  * </table>
00335  *
00336  * \par Response Format:
00337  *  rsphdr handle \n
00338  *  rsphdr errmsg
00339  *
00340  * \param pServer   BotSense server.
00341  * \param pClient   BotSense client.
00342  * \param bufCmd    Received command buffer.
00343  * \param lenCmd    Received command length (number of bytes).
00344  *
00345  * \return Returns OK on success, RC_ERROR on failure.
00346  */
00347 static int CmdDevOpen(BsProxyServer_T *pServer,
00348                       BsProxyClient_T *pClient,
00349                       byte_t bufCmd[], size_t lenCmd)
00350 {
00351   byte_t        bufRsp[BSPROXY_MSG_MAX_LEN];
00352   size_t        lenRsp;
00353   size_t        n;
00354   byte_t        eDevType;
00355   byte_t        i2cAddr;
00356   char         *sDevName;
00357   BsProxyDev_T *pProxDev;
00358   int           nHandle;
00359 
00360   BSPROXY_LOG_CMD(pClient, bufCmd, lenCmd);
00361 
00362   chkCmdBLenGE(pClient, bufCmd, 1);
00363 
00364   n = BSPROXY_CMD_HDR_LEN;
00365 
00366   eDevType = bufCmd[n++];
00367 
00368   switch( eDevType )
00369   {
00370     case BSPROXY_DEVTYPE_BPFOOT:    // BrainPack I2C foot device
00371     case BSPROXY_DEVTYPE_BPIMU:     // BrainPack I2C IMU device
00372     case BSPROXY_DEVTYPE_BPHAND:    // BrainPack I2C hand device
00373     case BSPROXY_DEVTYPE_BPCOMPASS: // BrainPack I2C compass device
00374       if( lenCmd <= n )
00375       {
00376         LOGERROR("%s: no I2C device address specified.",
00377             pClient->m_sClientName);
00378         return ClientSendFailRsp(pClient, bufCmd, "no parameter");
00379       }
00380       else if( (bufCmd[n] < 0x01) || (bufCmd[n] > 0x7f) )
00381       {
00382         LOGERROR("%s: 0x%x: I2C device address out of range.",
00383             pClient->m_sClientName, bufCmd[1]);
00384         return ClientSendFailRsp(pClient, bufCmd, "bad parameter");
00385       }
00386       i2cAddr = bufCmd[n++];
00387       break;
00388     case BSPROXY_DEVTYPE_I2C:     // I2C device
00389     case BSPROXY_DEVTYPE_RS232:   // RS-232 serial device
00390     case BSPROXY_DEVTYPE_RCB3:    // RCB-3 device
00391       i2cAddr = 0;
00392       break;
00393     default:
00394       LOGERROR("%s: 0x%02x: unknown proxied device type.",
00395             pClient->m_sClientName, bufCmd[0]);
00396       return ClientSendFailRsp(pClient, bufCmd, "bad parameter");
00397   }
00398 
00399   if( lenCmd <= n+1 )
00400   {
00401     LOGERROR("%s: no I2C device name specified.", pClient->m_sClientName);
00402     return ClientSendFailRsp(pClient, bufCmd, "no parameter");
00403   }
00404 
00405   bufCmd[lenCmd-1] = 0;
00406   sDevName = (char *)&bufCmd[n];
00407 
00408   if( (nHandle = ClientDevFindEmptySlot(pClient)) < 0 )
00409   {
00410     LOGERROR("%s: 0x%02x: cannot add device, currently at maximum %d",
00411             pClient->m_sClientName, bufCmd[1],
00412             BSPROXY_CLIENT_DEV_MAX);
00413     return ClientSendFailRsp(pClient, bufCmd, "too many devices");
00414   }
00415 
00416   if( (pProxDev = ProxDevOpen(eDevType, sDevName)) == NULL )
00417   {
00418     LOGERROR("%s: %s: cannot open device", pClient->m_sClientName, sDevName);
00419     return ClientSendFailRsp(pClient, bufCmd, "cannot open device");
00420   }
00421     
00422   pClient->m_tblClientDev[nHandle].m_eDevType = eDevType;
00423   pClient->m_tblClientDev[nHandle].m_pProxDev = pProxDev;
00424   pClient->m_tblClientDev[nHandle].m_i2cAddr  = i2cAddr;
00425 
00426   lenRsp            = BSPROXY_RSP_HDR_LEN;
00427   bufRsp[lenRsp++]  = (byte_t)nHandle;
00428 
00429   LOGDIAG2("%s: created client handle=%d", pClient->m_sClientName, nHandle);
00430 
00431   return ClientSendPassRsp(pClient, bufCmd, bufRsp, lenRsp);
00432 }
00433 
00434 /*!
00435  * \brief Client command to close a proxied device for the client.
00436  *
00437  * The underlining device may be shared, in which case the device is actually 
00438  * closed when its reference count is zero.
00439  *
00440  * \par Command Format:
00441  *  cmdhdr handle \n
00442  *
00443  * \par Response Format:
00444  *  rsphdr handle \n
00445  *  rsphdr errmsg 
00446  *
00447  * \param pServer   BotSense server.
00448  * \param pClient   BotSense client.
00449  * \param bufCmd    Received command buffer.
00450  * \param lenCmd    Received command length (number of bytes).
00451  *
00452  * \return Returns OK on success, RC_ERROR on failure.
00453  */
00454 static int CmdDevClose(BsProxyServer_T *pServer,
00455                        BsProxyClient_T *pClient,
00456                        byte_t bufCmd[], size_t lenCmd)
00457 {
00458   byte_t        bufRsp[BSPROXY_MSG_MAX_LEN];
00459   size_t        lenRsp;
00460   int           nHandle;
00461 
00462   BSPROXY_LOG_CMD(pClient, bufCmd, lenCmd);
00463 
00464   if( (nHandle = ClientGetHandle(pClient, bufCmd)) < 0 )
00465   {
00466     return RC_ERROR;
00467   }
00468 
00469   ProxDevClose(pClient->m_tblClientDev[nHandle].m_pProxDev);
00470 
00471   pClient->m_tblClientDev[nHandle].m_eDevType = BSPROXY_DEVTYPE_NONE;
00472   pClient->m_tblClientDev[nHandle].m_pProxDev = NULL;
00473   pClient->m_tblClientDev[nHandle].m_i2cAddr  = 0;
00474 
00475   lenRsp            = BSPROXY_RSP_HDR_LEN;
00476   bufRsp[lenRsp++]  = (byte_t)nHandle;
00477 
00478   LOGDIAG2("%s: deleted client handle=%d", pClient->m_sClientName, nHandle);
00479 
00480   return ClientSendPassRsp(pClient, bufCmd, bufRsp, lenRsp);
00481 }
00482 
00483 /*!
00484  * \brief Client command to read data from a proxied device.
00485  *
00486  * \par Command Format:
00487  * <table border="0">
00488  * <tr><td>I<sup>2</sup>C:</td><td>cmdhdr handle i2c_addr rlen</td></tr>
00489  * <tr><td>BrainPack I<sup>2</sup>C:</td><td>cmdhdr handle rlen</td></tr>
00490  * <tr><td>RS-232:</td><td>cmdhdr handle rlen</td></tr>
00491  * <tr><td>RCB-3:</td><td>cmdhdr handle rlen</td></tr>
00492  * </table>
00493  *
00494  * \par Response Format:
00495  *  rsphdr byte0 ... \n
00496  *  rsphdr errmsg 
00497  *
00498  * \param pServer   BotSense server.
00499  * \param pClient   BotSense client.
00500  * \param bufCmd    Received command buffer.
00501  * \param lenCmd    Received command length (number of bytes).
00502  *
00503  * \return Returns OK on success, RC_ERROR on failure.
00504  */
00505 static int CmdDevRead(BsProxyServer_T *pServer,
00506                       BsProxyClient_T *pClient,
00507                       byte_t bufCmd[], size_t lenCmd)
00508 {
00509   byte_t              bufRsp[BSPROXY_MSG_MAX_LEN];
00510   size_t              lenRsp;
00511   int                 nHandle;
00512   size_t              n;
00513   BsProxyClientDev_T *pDev;
00514   byte_t              i2cAddr = 0;
00515   size_t              rlen;
00516   int                 nRead;
00517 
00518   BSPROXY_LOG_CMD(pClient, bufCmd, lenCmd);
00519 
00520   if( (nHandle = ClientGetHandle(pClient, bufCmd)) < 0 )
00521   {
00522     return RC_ERROR;
00523   }
00524 
00525   pDev = &pClient->m_tblClientDev[nHandle];
00526 
00527   n = BSPROXY_CMD_HDR_LEN+1;
00528 
00529   switch( pDev->m_eDevType )
00530   {
00531     case BSPROXY_DEVTYPE_I2C:     // I2C device
00532       chkCmdBLenEQ(pClient, bufCmd, 3);
00533       i2cAddr = bufCmd[n++];
00534       rlen    = (size_t)bufCmd[n++];
00535       break;
00536     case BSPROXY_DEVTYPE_BPFOOT:    // BrainPack I2C foot device
00537     case BSPROXY_DEVTYPE_BPIMU:     // BrainPack I2C IMU device
00538     case BSPROXY_DEVTYPE_BPHAND:    // BrainPack I2C hand device
00539     case BSPROXY_DEVTYPE_BPCOMPASS: // BrainPack I2C compass device
00540       chkCmdBLenEQ(pClient, bufCmd, 2);
00541       i2cAddr = pDev->m_i2cAddr;
00542       rlen    = (size_t)bufCmd[n++];
00543       break;
00544     case BSPROXY_DEVTYPE_RCB3:    // RCB-3 device
00545       chkCmdBLenEQ(pClient, bufCmd, 2);
00546       rlen  = (size_t)bufCmd[n++];
00547       break;
00548     case BSPROXY_DEVTYPE_RS232:   // RS-232 serial device
00549       LOGERROR("%s: %s: read operation not implemented.",
00550         pClient->m_sClientName, pDev->m_pProxDev->m_sDevName);
00551       return ClientSendFailRsp(pClient, bufCmd, "operation not implemented");
00552     default:
00553       LOGERROR("%s: 0x%02x: unknown proxied device type.",
00554             pClient->m_sClientName, bufCmd[0]);
00555       return ClientSendFailRsp(pClient, bufCmd, "bad parameter");
00556   }
00557  
00558   if(( rlen == 0) || (rlen > BSPROXY_RSP_BODY_LEN_MAX) )
00559   {
00560     LOGERROR("%s: %d: bad read length.", pClient->m_sClientName, rlen);
00561     return ClientSendFailRsp(pClient, bufCmd, "%d: bad read length.", rlen);
00562   }
00563 
00564   switch( pDev->m_pProxDev->m_eDevClass )
00565   {
00566     case BSPROXY_DEVCLASS_I2C:
00567       nRead = ProxDevI2CRead(pDev->m_pProxDev, i2cAddr, 
00568                             &bufRsp[BSPROXY_RSP_HDR_LEN], rlen);
00569       break;
00570     case BSPROXY_DEVCLASS_RCB3:
00571       nRead = ProxDevRCB3Read(pDev->m_pProxDev,
00572                           &bufRsp[BSPROXY_RSP_HDR_LEN], rlen);
00573       break;
00574     default:
00575       LOGERROR("%s: %s: read operation not implemented.",
00576         pClient->m_sClientName, pDev->m_pProxDev->m_sDevName);
00577       return ClientSendFailRsp(pClient, bufCmd, "operation not implemented");
00578   }
00579 
00580   if( nRead <= 0 )
00581   {
00582     LOGERROR("%s: read operation failed.", pClient->m_sClientName);
00583     return ClientSendFailRsp(pClient, bufCmd, "read operation failed.");
00584   }
00585 
00586   lenRsp = BSPROXY_RSP_HDR_LEN + nRead;
00587 
00588   return ClientSendPassRsp(pClient, bufCmd, bufRsp, lenRsp);
00589 }
00590 
00591 /*!
00592  * \brief Client command to write data to a proxied device.
00593  *
00594  * \par Command Format:
00595  * <table border="0">
00596  * <tr><td>I<sup>2</sup>C:</td><td>cmdhdr handle i2c_addr byte ...</td></tr>
00597  * <tr><td>BrainPack I<sup>2</sup>C:</td><td>cmdhdr handle byte ...</td></tr>
00598  * <tr><td>RS-232:</td><td>cmdhdr handle byte ...td></tr>
00599  * <tr><td>RCB-3:</td><td>cmdhdr handle byte ...td></tr>
00600  * </table>
00601  *
00602  * \par Response Format:
00603  *  rsphdr wlen \n
00604  *  rsphdr errmsg 
00605  *
00606  * \param pServer   BotSense server.
00607  * \param pClient   BotSense client.
00608  * \param bufCmd    Received command buffer.
00609  * \param lenCmd    Received command length (number of bytes).
00610  *
00611  * \return Returns OK on success, RC_ERROR on failure.
00612  */
00613 static int CmdDevWrite(BsProxyServer_T *pServer,
00614                       BsProxyClient_T *pClient,
00615                       byte_t bufCmd[], size_t lenCmd)
00616 {
00617   byte_t              bufRsp[BSPROXY_MSG_MAX_LEN];
00618   size_t              lenRsp;
00619   int                 nHandle;
00620   size_t              n;
00621   BsProxyClientDev_T *pDev;
00622   byte_t              i2cAddr = 0;
00623   size_t              wlen;
00624   int                 nWritten;
00625 
00626   BSPROXY_LOG_CMD(pClient, bufCmd, lenCmd);
00627 
00628   if( (nHandle = ClientGetHandle(pClient, bufCmd)) < 0 )
00629   {
00630     return RC_ERROR;
00631   }
00632 
00633   pDev = &pClient->m_tblClientDev[nHandle];
00634 
00635   n = BSPROXY_CMD_HDR_LEN+1;
00636 
00637   switch( pDev->m_eDevType )
00638   {
00639     case BSPROXY_DEVTYPE_I2C:     // I2C device
00640       chkCmdBLenGE(pClient, bufCmd, 3);
00641       i2cAddr = bufCmd[n++];
00642       break;
00643     case BSPROXY_DEVTYPE_BPFOOT:    // BrainPack I2C foot device
00644     case BSPROXY_DEVTYPE_BPIMU:     // BrainPack I2C IMU device
00645     case BSPROXY_DEVTYPE_BPHAND:    // BrainPack I2C hand device
00646     case BSPROXY_DEVTYPE_BPCOMPASS: // BrainPack I2C compass device
00647       chkCmdBLenGE(pClient, bufCmd, 2);
00648       i2cAddr = pDev->m_i2cAddr;
00649       break;
00650     case BSPROXY_DEVTYPE_RCB3:    // RCB-3 device
00651       chkCmdBLenGE(pClient, bufCmd, 2);
00652       break;
00653     case BSPROXY_DEVTYPE_RS232:   // RS-232 serial device
00654       LOGERROR("%s: %s: read operation not implemented.",
00655         pClient->m_sClientName, pDev->m_pProxDev->m_sDevName);
00656       return ClientSendFailRsp(pClient, bufCmd, "operation not implemented");
00657     default:
00658       LOGERROR("%s: 0x%02x: unknown proxied device type.",
00659             pClient->m_sClientName, bufCmd[0]);
00660       return ClientSendFailRsp(pClient, bufCmd, "bad parameter");
00661   }
00662  
00663   wlen = bufCmd[BSPROXY_CMD_HDR_BLEN_IDX] + BSPROXY_CMD_HDR_LEN - n;
00664 
00665   if(( wlen == 0) || (wlen > BSPROXY_CMD_BODY_LEN_MAX) )
00666   {
00667     LOGERROR("%s: %d: bad write length.", pClient->m_sClientName, wlen);
00668     return ClientSendFailRsp(pClient, bufCmd, "%d: bad write length.", wlen);
00669   }
00670 
00671   switch( pDev->m_pProxDev->m_eDevClass )
00672   {
00673     case BSPROXY_DEVCLASS_I2C:
00674       nWritten = ProxDevI2CWrite(pDev->m_pProxDev, i2cAddr, &bufCmd[n], wlen);
00675       break;
00676     case BSPROXY_DEVCLASS_RCB3:
00677       nWritten = ProxDevRCB3Write(pDev->m_pProxDev, &bufCmd[n], wlen);
00678       break;
00679     default:
00680       LOGERROR("%s: %s: read operation not implemented.",
00681         pClient->m_sClientName, pDev->m_pProxDev->m_sDevName);
00682       return ClientSendFailRsp(pClient, bufCmd, "operation not implemented");
00683   }
00684 
00685   if( nWritten <= 0 )
00686   {
00687     LOGERROR("%s: write operation failed.", pClient->m_sClientName);
00688     return ClientSendFailRsp(pClient, bufCmd, "write operation failed.");
00689   }
00690 
00691   lenRsp            = BSPROXY_RSP_HDR_LEN;
00692   bufRsp[lenRsp++]  = (byte_t)nWritten;
00693 
00694   return ClientSendPassRsp(pClient, bufCmd, bufRsp, lenRsp);
00695 }
00696 
00697 /*!
00698  * \brief Client command to perform a write/read data transaction with
00699  * a proxied device.
00700  *
00701  * \par Command Format:
00702  * <table border="0">
00703  * <tr><td>I<sup>2</sup>C:</td><td>cmdhdr handle i2c_addr byte ...</td></tr>
00704  * <tr><td>BrainPack I<sup>2</sup>C:</td><td>cmdhdr handle byte ...</td></tr>
00705  * <tr><td>RS-232:</td><td>cmdhdr handle byte ...td></tr>
00706  * <tr><td>RCB-3:</td><td>cmdhdr handle byte ...td></tr>
00707  * </table>
00708  *
00709  * \par Response Format:
00710  *  rsphdr wlen \n
00711  *  rsphdr errmsg 
00712  *
00713  * \param pServer   BotSense server.
00714  * \param pClient   BotSense client.
00715  * \param bufCmd    Received command buffer.
00716  * \param lenCmd    Received command length (number of bytes).
00717  *
00718  * \return Returns OK on success, RC_ERROR on failure.
00719  */
00720 static int CmdDevTrans(BsProxyServer_T *pServer,
00721                       BsProxyClient_T *pClient,
00722                       byte_t bufCmd[], size_t lenCmd)
00723 {
00724   byte_t              bufRsp[BSPROXY_MSG_MAX_LEN];
00725   size_t              lenRsp;
00726   int                 nHandle;
00727   size_t              n;
00728   BsProxyClientDev_T *pDev;
00729   byte_t              i2cAddr = 0;
00730   size_t              rlen;
00731   size_t              wlen;
00732   int                 nRead;
00733 
00734   BSPROXY_LOG_CMD(pClient, bufCmd, lenCmd);
00735 
00736   if( (nHandle = ClientGetHandle(pClient, bufCmd)) < 0 )
00737   {
00738     return RC_ERROR;
00739   }
00740 
00741   pDev = &pClient->m_tblClientDev[nHandle];
00742 
00743   n = BSPROXY_CMD_HDR_LEN+1;
00744 
00745   switch( pDev->m_eDevType )
00746   {
00747     case BSPROXY_DEVTYPE_I2C:     // I2C device
00748       chkCmdBLenGE(pClient, bufCmd, 4);
00749       i2cAddr = bufCmd[n++];
00750       rlen    = bufCmd[n++];
00751       break;
00752     case BSPROXY_DEVTYPE_BPFOOT:    // BrainPack I2C foot device
00753     case BSPROXY_DEVTYPE_BPIMU:     // BrainPack I2C IMU device
00754     case BSPROXY_DEVTYPE_BPHAND:    // BrainPack I2C hand device
00755     case BSPROXY_DEVTYPE_BPCOMPASS: // BrainPack I2C compass device
00756       chkCmdBLenGE(pClient, bufCmd, 3);
00757       i2cAddr = pDev->m_i2cAddr;
00758       rlen    = bufCmd[n++];
00759       break;
00760     case BSPROXY_DEVTYPE_RCB3:    // RCB-3 device
00761       chkCmdBLenGE(pClient, bufCmd, 3);
00762       rlen = bufCmd[n++];
00763       break;
00764     case BSPROXY_DEVTYPE_RS232:   // RS-232 serial device
00765       LOGERROR("%s: %s: read operation not implemented.",
00766         pClient->m_sClientName, pDev->m_pProxDev->m_sDevName);
00767       return ClientSendFailRsp(pClient, bufCmd, "operation not implemented");
00768     default:
00769       LOGERROR("%s: 0x%02x: unknown proxied device type.",
00770             pClient->m_sClientName, bufCmd[0]);
00771       return ClientSendFailRsp(pClient, bufCmd, "bad parameter");
00772   }
00773  
00774   if(( rlen == 0) || (rlen > BSPROXY_RSP_BODY_LEN_MAX) )
00775   {
00776     LOGERROR("%s: %d: bad read length.", pClient->m_sClientName, rlen);
00777     return ClientSendFailRsp(pClient, bufCmd, "%d: bad read length.", rlen);
00778   }
00779 
00780   wlen = bufCmd[BSPROXY_CMD_HDR_BLEN_IDX] + BSPROXY_CMD_HDR_LEN - n;
00781 
00782   if(( wlen == 0) || (wlen > BSPROXY_CMD_BODY_LEN_MAX) )
00783   {
00784     LOGERROR("%s: %d: bad write length.", pClient->m_sClientName, wlen);
00785     return ClientSendFailRsp(pClient, bufCmd, "%d: bad write length.", wlen);
00786   }
00787 
00788   switch( pDev->m_pProxDev->m_eDevClass )
00789   {
00790     case BSPROXY_DEVCLASS_I2C:
00791       nRead = ProxDevI2CTrans(pDev->m_pProxDev, i2cAddr,
00792             &bufCmd[n], wlen, &bufRsp[BSPROXY_RSP_HDR_LEN], rlen);
00793       break;
00794     case BSPROXY_DEVCLASS_RCB3:
00795       nRead = ProxDevRCB3Trans(pDev->m_pProxDev,
00796             &bufCmd[n], wlen, &bufRsp[BSPROXY_RSP_HDR_LEN], rlen);
00797       break;
00798     default:
00799       LOGERROR("%s: %s: read operation not implemented.",
00800         pClient->m_sClientName, pDev->m_pProxDev->m_sDevName);
00801       return ClientSendFailRsp(pClient, bufCmd, "operation not implemented");
00802   }
00803 
00804   if( nRead <= 0 )
00805   {
00806     LOGERROR("%s: transaction operation failed.", pClient->m_sClientName);
00807     return ClientSendFailRsp(pClient, bufCmd, "transaction operation failed.");
00808   }
00809 
00810   lenRsp = BSPROXY_RSP_HDR_LEN + nRead;
00811 
00812   return ClientSendPassRsp(pClient, bufCmd, bufRsp, lenRsp);
00813 }
00814 
00815 /*!
00816  * \brief Client command to issue an I/O control to a proxied device.
00817  *
00818  * The semantics for the ioctl operations is dependent on the device class.
00819  * <table border="0">
00820  * <tr><td>I<sup>2</sup>C:</td><td>N/A</td></tr>
00821  * <tr><td>BrainPack I<sup>2</sup>C:</td><td>N/A</td></tr>
00822  * <tr><td>RS-232:</td><td>baudrate ...</td></tr>
00823  * <tr><td>RCB-3:</td><td>TBD</td></tr>
00824  * </table>
00825  *
00826  * \par Command Format:
00827  *  cmdhdr handle [byte ...]\n
00828  *
00829  * \par Response Format:
00830  *  rsphdr [byte ...]\n
00831  *  rsphdr errmsg 
00832  *
00833  * \param pServer   BotSense server.
00834  * \param pClient   BotSense client.
00835  * \param bufCmd    Received command buffer.
00836  * \param lenCmd    Received command length (number of bytes).
00837  *
00838  * \return Returns OK on success, RC_ERROR on failure.
00839  */
00840 static int CmdDevIoctl(BsProxyServer_T *pServer,
00841                       BsProxyClient_T *pClient,
00842                       byte_t bufCmd[], size_t lenCmd)
00843 {
00844   byte_t              bufRsp[BSPROXY_MSG_MAX_LEN];
00845   size_t              lenRsp;
00846   int                 nHandle;
00847   BsProxyClientDev_T *pDev;
00848   byte_t              bufScan[128];
00849   int                 nScanned;
00850   int                 i;
00851 
00852   BSPROXY_LOG_CMD(pClient, bufCmd, lenCmd);
00853 
00854   if( (nHandle = ClientGetHandle(pClient, bufCmd)) < 0 )
00855   {
00856     return RC_ERROR;
00857   }
00858 
00859   pDev = &pClient->m_tblClientDev[nHandle];
00860 
00861   switch( pDev->m_pProxDev->m_eDevClass )
00862   {
00863     case BSPROXY_DEVTYPE_RS232:
00864     case BSPROXY_DEVTYPE_RCB3:
00865       LOGERROR("%s: %s: ioctl operation not implemented.",
00866         pClient->m_sClientName, pDev->m_pProxDev->m_sDevName);
00867       return ClientSendFailRsp(pClient, bufCmd, "operation not implemented");
00868       break;
00869     case BSPROXY_DEVTYPE_I2C:
00870     case BSPROXY_DEVTYPE_BPFOOT:
00871     case BSPROXY_DEVTYPE_BPIMU:
00872     case BSPROXY_DEVTYPE_BPHAND:
00873     case BSPROXY_DEVTYPE_BPCOMPASS:
00874     default:
00875       LOGERROR("%s: %s: scan operation not supported on device.",
00876         pClient->m_sClientName, pDev->m_pProxDev->m_sDevName);
00877       return ClientSendFailRsp(pClient, bufCmd, "operation not supported");
00878   }
00879  
00880   lenRsp            = BSPROXY_RSP_HDR_LEN;
00881   bufRsp[lenRsp++]  = nScanned;
00882 
00883   for(i=0; i<nScanned; ++i)
00884   {
00885     bufRsp[lenRsp++] = bufScan[i];
00886   }
00887 
00888   LOGDIAG2("Found %d I2C devices", nScanned);
00889 
00890   return ClientSendPassRsp(pClient, bufCmd, bufRsp, lenRsp);
00891 }
00892 
00893 /*!
00894  * \brief Client command to scan for devices attached to a proxied device.
00895  *
00896  * The semantics for the scan operations is dependent on the device class.
00897  * <table border="0">
00898  * <tr><td>I<sup>2</sup>C</td><td>Addresses of all attached devices</td></tr>
00899  * <tr><td>RS-232</td><td>N/A </td></tr>
00900  * </table>
00901  *
00902  * \par Command Format:
00903  *  cmdhdr handle \n
00904  *
00905  * \par Response Format:
00906  *  rsphdr num_scanned addr ... \n
00907  *  rsphdr errmsg 
00908  *
00909  * \param pServer   BotSense server.
00910  * \param pClient   BotSense client.
00911  * \param bufCmd    Received command buffer.
00912  * \param lenCmd    Received command length (number of bytes).
00913  *
00914  * \return Returns OK on success, RC_ERROR on failure.
00915  */
00916 static int CmdDevScan(BsProxyServer_T *pServer,
00917                       BsProxyClient_T *pClient,
00918                       byte_t bufCmd[], size_t lenCmd)
00919 {
00920   byte_t              bufRsp[BSPROXY_MSG_MAX_LEN];
00921   size_t              lenRsp;
00922   int                 nHandle;
00923   BsProxyClientDev_T *pDev;
00924   byte_t              bufScan[128];
00925   int                 nScanned;
00926   int                 i;
00927 
00928   BSPROXY_LOG_CMD(pClient, bufCmd, lenCmd);
00929 
00930   if( (nHandle = ClientGetHandle(pClient, bufCmd)) < 0 )
00931   {
00932     return RC_ERROR;
00933   }
00934 
00935   pDev = &pClient->m_tblClientDev[nHandle];
00936 
00937   switch( pDev->m_pProxDev->m_eDevClass )
00938   {
00939     case BSPROXY_DEVCLASS_I2C:
00940       nScanned = ProxDevI2CScan(pDev->m_pProxDev, bufScan, sizeof(bufScan));
00941       break;
00942     default:
00943       LOGERROR("%s: %s: scan operation not supported on device.",
00944         pClient->m_sClientName, pDev->m_pProxDev->m_sDevName);
00945       return ClientSendFailRsp(pClient, bufCmd, "scan operation not supported");
00946   }
00947  
00948   lenRsp            = BSPROXY_RSP_HDR_LEN;
00949   bufRsp[lenRsp++]  = nScanned;
00950 
00951   for(i=0; i<nScanned; ++i)
00952   {
00953     bufRsp[lenRsp++] = bufScan[i];
00954   }
00955 
00956   LOGDIAG2("Found %d I2C devices", nScanned);
00957 
00958   return ClientSendPassRsp(pClient, bufCmd, bufRsp, lenRsp);
00959 }
00960 
00961 /*!
00962  * \brief Client command to dispatch a proxied device specific command.
00963  *
00964  * The specific command sub-dispatcher is determined by the device type.
00965  *
00966  * \par Command Format:
00967  *  cmdhdr handle cmd_id ... \n
00968  *
00969  * \par Response Format:
00970  *  rsphdr \n
00971  *  rsphdr rsp_body \n
00972  *  rsphdr errmsg 
00973  *
00974  * \param pServer   BotSense server.
00975  * \param pClient   BotSense client.
00976  * \param bufCmd    Received command buffer.
00977  * \param lenCmd    Received command length (number of bytes).
00978  *
00979  * \return Returns OK on success, RC_ERROR on failure.
00980  */
00981 static int CmdDevCmd(BsProxyServer_T *pServer,
00982                      BsProxyClient_T *pClient,
00983                      byte_t bufCmd[], size_t lenCmd)
00984 {
00985   int                 nHandle;
00986   BsProxyClientDev_T *pDev;
00987 
00988   // don't log command here, sub-dispatchers will.
00989 
00990   // handle, dev_cmd_id, ...
00991   chkCmdBLenGE(pClient, bufCmd, 2);
00992 
00993   if( (nHandle = ClientGetHandle(pClient, bufCmd)) < 0 )
00994   {
00995     return RC_ERROR;
00996   }
00997 
00998   pDev = &pClient->m_tblClientDev[nHandle];
00999 
01000   //
01001   // Dispatch to specific client device discpatcher.
01002   //
01003   switch( pDev->m_eDevType )
01004   {
01005     // BrainPack Foot
01006     case BSPROXY_DEVTYPE_BPFOOT:
01007       return BPFootDispatch(pServer, pClient, pDev, bufCmd, lenCmd);
01008 
01009     // BrainPack Foot
01010     case BSPROXY_DEVTYPE_BPIMU:
01011       return BPIMUDispatch(pServer, pClient, pDev, bufCmd, lenCmd);
01012 
01013     // RCB-3 Robot Controller
01014     case BSPROXY_DEVTYPE_RCB3:
01015       return RCB3Dispatch(pServer, pClient, pDev, bufCmd, lenCmd);
01016 
01017     default:
01018       LOGERROR("%s: 0x%02x: no built-in specific commands are supported",
01019           pClient->m_sClientName, pDev->m_eDevType);
01020       return ClientSendFailRsp(pClient, bufCmd,
01021           "no commands for proxied device");
01022   }
01023 }
01024 
01025 // ---------------------------------------------------------------------------
01026 // Public Interface 
01027 // ---------------------------------------------------------------------------
01028 
01029 /*!
01030  * \brief Client top-level command dispatcher.
01031  *
01032  * \par Command Format:
01033  *  cmdhdr \n
01034  *  cmdhdr body \n
01035  *
01036  * \par Response Format:
01037  *  rsphdr \n
01038  *  rsphdr body \n
01039  *  rsphdr errmsg 
01040  *
01041  * \param pServer   BotSense server.
01042  * \param pClient   BotSense client.
01043  * \param bufCmd    Received command buffer.
01044  * \param lenCmd    Received command length (number of bytes).
01045  *
01046  * \return Returns OK on success, RC_ERROR on failure.
01047  */
01048 int ClientDispatch(BsProxyServer_T *pServer,
01049                    BsProxyClient_T *pClient,
01050                    byte_t bufCmd[], size_t lenCmd)
01051 {
01052   //
01053   // Validate command header.
01054   //
01055   if( lenCmd < BSPROXY_CMD_HDR_LEN )
01056   {
01057     return ClientSendHdrError(pClient, bufCmd, lenCmd);
01058   }
01059 
01060   //
01061   // Validate length of message body in header matches recieved command length.
01062   //
01063   // Note: For now, report error. But in the future, if recieved a partial
01064   // message (hdr+blen > len), try to read more bytes. If too many bytes,
01065   // flush??
01066   //
01067   if( (size_t)bufCmd[BSPROXY_CMD_HDR_BLEN_IDX]+BSPROXY_CMD_HDR_LEN != lenCmd )
01068   {
01069     LOGERROR("%s: received %u bytes, but blen header field value is %u",
01070         pClient->m_sClientName, (uint_t)lenCmd,
01071         (uint_t)bufCmd[BSPROXY_CMD_HDR_BLEN_IDX]);
01072     return ClientSendFailRsp(pClient, bufCmd,
01073         "received %u bytes, but blen header field value is %u",
01074         (uint_t)lenCmd, (uint_t)bufCmd[BSPROXY_CMD_HDR_BLEN_IDX]);
01075   }
01076 
01077   //
01078   // Dispatch client command.
01079   //
01080   switch( bufCmd[BSPROXY_CMD_HDR_MSGID_IDX] )
01081   {
01082     // loopback client's message
01083     case BSPROXY_MSGID_LOOPBACK:
01084       return CmdLoopback(pServer, pClient, bufCmd, lenCmd);
01085 
01086     // set server's log level
01087     case BSPROXY_MSGID_LOG:
01088       return CmdLog(pServer, pClient, bufCmd, lenCmd);
01089 
01090     // get server's version
01091     case BSPROXY_MSGID_VERSION:
01092       return CmdVersion(pServer, pClient, bufCmd, lenCmd);
01093 
01094     // open proxied device for client
01095     case BSPROXY_MSGID_DEV_OPEN:
01096       return CmdDevOpen(pServer, pClient, bufCmd, lenCmd);
01097 
01098     // close proxied device for client
01099     case BSPROXY_MSGID_DEV_CLOSE:
01100       return CmdDevClose(pServer, pClient, bufCmd, lenCmd);
01101 
01102     // get supported proxied devices
01103     case BSPROXY_MSGID_PROXY_INFO:
01104       return CmdProxyInfo(pServer, pClient, bufCmd, lenCmd);
01105 
01106     // read from proxied device
01107     case BSPROXY_MSGID_DEV_READ:
01108       return CmdDevRead(pServer, pClient, bufCmd, lenCmd);
01109 
01110     // write to proxied device
01111     case BSPROXY_MSGID_DEV_WRITE:
01112       return CmdDevWrite(pServer, pClient, bufCmd, lenCmd);
01113 
01114     // perform a write/read transaction with proxied device
01115     case BSPROXY_MSGID_DEV_TRANS:
01116       return CmdDevTrans(pServer, pClient, bufCmd, lenCmd);
01117 
01118     // issue an ioctl to proxied device
01119     case BSPROXY_MSGID_DEV_IOCTL:
01120       return CmdDevIoctl(pServer, pClient, bufCmd, lenCmd);
01121 
01122     // scan for attached devices on proxied device
01123     case BSPROXY_MSGID_DEV_SCAN:
01124       return CmdDevScan(pServer, pClient, bufCmd, lenCmd);
01125 
01126     // send a specific command to a client's proxied device
01127     case BSPROXY_MSGID_DEV_CMD:
01128       return CmdDevCmd(pServer, pClient, bufCmd, lenCmd);
01129 
01130     default:
01131       LOGERROR("%s: 0x%02x: unknown command",
01132           pClient->m_sClientName, bufCmd[BSPROXY_CMD_HDR_MSGID_IDX]);
01133       return RC_ERROR;
01134   }
01135 
01136   LOGERROR("%s: here?", pClient->m_sClientName);
01137 
01138   return RC_ERROR;
01139 }
01140 
01141 /*!
01142  * \brief Send pass response to the client.
01143  *
01144  * \param pClient   BotSense client.
01145  * \param bufCmd    Received command buffer.
01146  * \param bufRsp    Response buffer.
01147  * \param lenRsp    Response buffer length (number of bytes).
01148  *
01149  * \return Returns OK on success, RC_ERROR on failure.
01150  */
01151 int ClientSendPassRsp(BsProxyClient_T *pClient, byte_t bufCmd[],
01152                       byte_t bufRsp[], size_t lenRsp)
01153 {
01154   ssize_t n;
01155 
01156   // response header
01157   bufRsp[BSPROXY_RSP_HDR_MSGID_IDX] = bufCmd[BSPROXY_CMD_HDR_MSGID_IDX];
01158   bufRsp[BSPROXY_RSP_HDR_TID_IDX]   = bufCmd[BSPROXY_CMD_HDR_TID_IDX];
01159   bufRsp[BSPROXY_RSP_HDR_PF_IDX]    = BSPROXY_RSP_PASS;
01160   bufRsp[BSPROXY_RSP_HDR_BLEN_IDX]  = (byte_t)(lenRsp-BSPROXY_RSP_HDR_LEN);
01161 
01162   // send
01163   n = write(SocketAttrGetSd(pClient->m_pClientSock), bufRsp, lenRsp);
01164 
01165   return n < (ssize_t)lenRsp? RC_ERROR: OK;
01166 }
01167 
01168 /*!
01169  * \brief Send fail response to the client.
01170  *
01171  * \param pClient   BotSense client.
01172  * \param bufCmd    Received command buffer.
01173  * \param sErrFmt   Error format string.
01174  * \param ...       Variable arguments to format string.
01175  *
01176  * \return Returns RC_ERROR.
01177  */
01178 int ClientSendFailRsp(BsProxyClient_T *pClient, byte_t bufCmd[],
01179                       const char *sErrFmt, ...)
01180 {
01181   byte_t    bufRsp[BSPROXY_MSG_MAX_LEN];
01182   size_t    lenBody, lenRsp;
01183   va_list   ap;
01184   char     *sBody;
01185 
01186   // stuff response header
01187   bufRsp[BSPROXY_RSP_HDR_MSGID_IDX] = bufCmd[BSPROXY_CMD_HDR_MSGID_IDX];
01188   bufRsp[BSPROXY_RSP_HDR_TID_IDX]   = bufCmd[BSPROXY_CMD_HDR_TID_IDX];
01189   bufRsp[BSPROXY_RSP_HDR_PF_IDX]    = BSPROXY_RSP_FAIL;
01190 
01191   sBody = (char *)(bufRsp+BSPROXY_RSP_HDR_LEN);
01192 
01193   //
01194   // Fill in formatted error string as the response message body.
01195   //
01196   va_start(ap, sErrFmt);
01197  
01198   vsnprintf(sBody, (size_t)(sizeof(bufRsp)-BSPROXY_RSP_HDR_LEN), sErrFmt, ap);
01199 
01200   va_end(ap);
01201 
01202   // guarantee string is null-terminated
01203   bufRsp[sizeof(bufRsp)-1] = 0;
01204 
01205   lenBody = strlen(sBody);
01206 
01207   // include null
01208   sBody[lenBody++] = 0;
01209 
01210   // body length
01211   bufRsp[BSPROXY_RSP_HDR_BLEN_IDX] = (byte_t)lenBody;
01212 
01213   // total response message length
01214   lenRsp = BSPROXY_RSP_HDR_LEN + lenBody;
01215 
01216   // send
01217   write(SocketAttrGetSd(pClient->m_pClientSock), bufRsp, lenRsp);
01218 
01219   return RC_ERROR;
01220 }
01221 
01222 /*!
01223  * \brief Create new client control structure.
01224  *
01225  * \param pSockClient   Accecpted client socket.
01226  *
01227  * \return Returns a newly allocated and intialized client control block.
01228  */
01229 BsProxyClient_T *ClientNew(Socket_T *pSockClient)
01230 {
01231   BsProxyClient_T  *pClient;
01232   int               i;
01233 
01234   pClient                     = NEW(BsProxyClient_T);
01235   pClient->m_sClientName      = SocketAttrGetRemoteName(pSockClient);
01236   pClient->m_pClientSock      = pSockClient;
01237 
01238   for(i=0; i<BSPROXY_CLIENT_DEV_MAX; ++i)
01239   {
01240     pClient->m_tblClientDev[i].m_eDevType = BSPROXY_DEVTYPE_NONE;
01241     pClient->m_tblClientDev[i].m_pProxDev = NULL;
01242     pClient->m_tblClientDev[i].m_i2cAddr  = 0;
01243   }
01244 
01245   return pClient;
01246 }
01247   
01248 /*!
01249  * \brief Delete a client with the server.
01250  *
01251  * \param pClient   BotSense client.
01252  */
01253 void ClientDelete(BsProxyClient_T *pClient)
01254 {
01255   int   i;
01256 
01257   if( pClient == NULL )
01258   {
01259     return;
01260   }
01261 
01262   for(i=0; i<BSPROXY_CLIENT_DEV_MAX; ++i)
01263   {
01264     if( pClient->m_tblClientDev[i].m_eDevType != BSPROXY_DEVTYPE_NONE )
01265     {
01266       ProxDevClose(pClient->m_tblClientDev[i].m_pProxDev);
01267     }
01268   }
01269 
01270   SocketClose(pClient->m_pClientSock);
01271   SocketDelete(pClient->m_pClientSock);
01272 
01273   delete(pClient);
01274 }

Generated on Wed Nov 28 11:01:08 2007 for botsense by doxygen 1.4.6