TI's MQTT Demo with freertos CM4F

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers cc3100_socket.cpp Source File

cc3100_socket.cpp

00001 /*
00002  * socket.c - CC31xx/CC32xx Host Driver Implementation
00003  *
00004  * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
00005  *
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *    Redistributions of source code must retain the above copyright
00012  *    notice, this list of conditions and the following disclaimer.
00013  *
00014  *    Redistributions in binary form must reproduce the above copyright
00015  *    notice, this list of conditions and the following disclaimer in the
00016  *    documentation and/or other materials provided with the
00017  *    distribution.
00018  *
00019  *    Neither the name of Texas Instruments Incorporated nor the names of
00020  *    its contributors may be used to endorse or promote products derived
00021  *    from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00026  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00027  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00028  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00029  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00030  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00031  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00032  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00033  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034  *
00035 */
00036 
00037 
00038 
00039 
00040 /*****************************************************************************/
00041 /* Include files                                                             */
00042 /*****************************************************************************/
00043 #include "cc3100_simplelink.h"
00044 #include "cc3100_protocol.h"
00045 #include "cc3100_driver.h"
00046 
00047 #include "cc3100_socket.h"
00048 
00049 namespace mbed_cc3100 {
00050     
00051 /*  Note: parsing of family and port in the generic way for all IPV4, IPV6 and EUI48 */
00052     /*  is possible as _i32 as these parameters are in the same offset and size for these */
00053     /*  three families. */
00054 #define SL_SOCKET_PAYLOAD_BASE (1350)
00055 
00056 const uint8_t _SlPayloadByProtocolLUT[16] = 
00057 {
00058     (1472 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_UDP_IPV4 */
00059     (1460 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_TCP_IPV4 */
00060     (1452 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_UDP_IPV6 */
00061     (1440 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_TCP_IPV6 */
00062     (1386 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_TCP_IPV4_SECURE */
00063     (1386 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_UDP_IPV4_SECURE */
00064     (1396 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_UDP_IPV6_SECURE */
00065     (1396 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_TCP_IPV6_SECURE */
00066     (1476 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_RAW_TRANCEIVER */
00067     (1514 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_RAW_PACKET */
00068     (1480 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_RAW_IP4 */
00069     (1480 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_RAW_IP6 */
00070     (1440 - SL_SOCKET_PAYLOAD_BASE), /* Default */
00071     (1440 - SL_SOCKET_PAYLOAD_BASE), /* Default */
00072     (1440 - SL_SOCKET_PAYLOAD_BASE), /* Default */
00073     (1440 - SL_SOCKET_PAYLOAD_BASE)  /* Default */
00074 };  
00075 
00076 #ifndef SL_PLATFORM_MULTI_THREADED
00077 cc3100_socket::cc3100_socket(cc3100_driver &driver, cc3100_nonos &nonos)
00078     : _driver(driver), _nonos(nonos)
00079 {
00080 }
00081 #else
00082 cc3100_socket::cc3100_socket(cc3100_driver &driver)
00083     : _driver(driver)
00084 {
00085 }
00086 #endif
00087 cc3100_socket::~cc3100_socket()
00088 {
00089 
00090 }
00091 
00092 /*******************************************************************************/
00093 /* Functions                                                                   */
00094 /*******************************************************************************/
00095 
00096 /* ******************************************************************************/
00097 /*  _sl_BuildAddress */
00098 /* ******************************************************************************/
00099 void cc3100_socket::_sl_BuildAddress(const SlSockAddr_t *addr, _SocketAddrCommand_u *pCmd)
00100 {
00101     /* Note: parsing of family and port in the generic way for all IPV4, IPV6 and EUI48
00102            is possible as long as these parameters are in the same offset and size for these
00103            three families. */
00104     pCmd->IpV4.FamilyAndFlags = (addr->sa_family << 4) & 0xF0;
00105     pCmd->IpV4.port = ((SlSockAddrIn_t *)addr)->sin_port;
00106 
00107     if(SL_AF_INET == addr->sa_family) {
00108         pCmd->IpV4.address  = ((SlSockAddrIn_t *)addr)->sin_addr.s_addr;
00109     } else if (SL_AF_INET6_EUI_48 == addr->sa_family ) {
00110         memcpy( pCmd->IpV6EUI48.address,((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u8, 6);
00111     }
00112 #ifdef SL_SUPPORT_IPV6
00113     else {
00114         memcpy(pCmd->IpV6.address, ((sockaddr_in6 *)addr)->sin6_addr._S6_un._S6_u32, 16 );
00115     }
00116 #endif
00117 }
00118 
00119 /* ******************************************************************************/
00120 /*  _sl_TruncatePayloadByProtocol */
00121 /* ******************************************************************************/
00122 uint16_t cc3100_socket::_sl_TruncatePayloadByProtocol(const int16_t sd,const uint16_t length)
00123 {
00124 
00125     uint32_t maxLength;
00126 
00127    maxLength = SL_SOCKET_PAYLOAD_BASE + _SlPayloadByProtocolLUT[((sd & SL_SOCKET_PAYLOAD_TYPE_MASK) >> 4)];
00128    
00129    if( length > maxLength )
00130    {
00131       return maxLength;
00132    }
00133    else
00134    {
00135       return length;
00136    }
00137 
00138 }
00139 
00140 /*******************************************************************************/
00141 /*  _sl_ParseAddress */
00142 /*******************************************************************************/
00143 #ifndef SL_TINY_EXT
00144 void cc3100_socket::_sl_ParseAddress(_SocketAddrResponse_u    *pRsp, SlSockAddr_t *addr, SlSocklen_t *addrlen)
00145 {
00146     /*  Note: parsing of family and port in the generic way for all IPV4, IPV6 and EUI48 */
00147     /*  is possible as long as these parameters are in the same offset and size for these */
00148     /*  three families. */
00149     addr->sa_family                 = pRsp->IpV4.family;
00150     ((SlSockAddrIn_t *)addr)->sin_port = pRsp->IpV4.port;
00151 
00152     *addrlen = (SL_AF_INET == addr->sa_family) ? sizeof(SlSockAddrIn_t) : sizeof(SlSockAddrIn6_t);
00153 
00154     if(SL_AF_INET == addr->sa_family) {
00155         ((SlSockAddrIn_t *)addr)->sin_addr.s_addr  = pRsp->IpV4.address;
00156     } else if (SL_AF_INET6_EUI_48 == addr->sa_family ) {
00157         memcpy(((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u8, pRsp->IpV6EUI48.address, 6);
00158     }
00159 #ifdef SL_SUPPORT_IPV6
00160     else {
00161         memcpy(((sockaddr_in6 *)addr)->sin6_addr._S6_un._S6_u32, pRsp->IpV6.address, 16);
00162     }
00163 #endif
00164 }
00165 #endif
00166 
00167 /*******************************************************************************/
00168 /* sl_Socket */
00169 /*******************************************************************************/
00170 typedef union {
00171     uint32_t                Dummy;
00172     _SocketCommand_t    Cmd;
00173     _SocketResponse_t   Rsp;
00174 } _SlSockSocketMsg_u;
00175 
00176 #if _SL_INCLUDE_FUNC(sl_Socket)
00177 const _SlCmdCtrl_t _SlSockSocketCmdCtrl = {
00178     SL_OPCODE_SOCKET_SOCKET,
00179     sizeof(_SocketCommand_t),
00180     sizeof(_SocketResponse_t)
00181 };
00182 
00183 int16_t cc3100_socket::sl_Socket(int16_t Domain, int16_t Type, int16_t Protocol)
00184 {
00185     _SlSockSocketMsg_u  Msg;
00186 
00187     Msg.Cmd.Domain      = (uint8_t)Domain;
00188     Msg.Cmd.Type        = (uint8_t)Type;
00189     Msg.Cmd.Protocol    = (uint8_t)Protocol;
00190 
00191     VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSockSocketCmdCtrl, &Msg, NULL));
00192 
00193     if( Msg.Rsp.statusOrLen < 0 ) {
00194         return( Msg.Rsp.statusOrLen );
00195     } else {
00196         return (int16_t)((uint8_t)Msg.Rsp.sd);
00197     }
00198 }
00199 #endif
00200 
00201 /*******************************************************************************/
00202 /*  sl_Close  */
00203 /*******************************************************************************/
00204 typedef union {
00205     _CloseCommand_t     Cmd;
00206     _SocketResponse_t   Rsp;
00207 } _SlSockCloseMsg_u;
00208 
00209 #if _SL_INCLUDE_FUNC(sl_Close)
00210 const _SlCmdCtrl_t _SlSockCloseCmdCtrl = {
00211     SL_OPCODE_SOCKET_CLOSE,
00212     sizeof(_CloseCommand_t),
00213     sizeof(_SocketResponse_t)
00214 };
00215 
00216 int16_t cc3100_socket::sl_Close(int16_t sd)
00217 {
00218     _SlSockCloseMsg_u   Msg;
00219 
00220     Msg.Cmd.sd = (uint8_t)sd;
00221 
00222     VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSockCloseCmdCtrl, &Msg, NULL));
00223 
00224     return Msg.Rsp.statusOrLen;
00225 }
00226 #endif
00227 
00228 /*******************************************************************************/
00229 /*  sl_Bind */
00230 /*******************************************************************************/
00231 typedef union {
00232     _SocketAddrCommand_u    Cmd;
00233     _SocketResponse_t       Rsp;
00234 } _SlSockBindMsg_u;
00235 
00236 #if _SL_INCLUDE_FUNC(sl_Bind)
00237 int16_t cc3100_socket::sl_Bind(int16_t sd, const SlSockAddr_t *addr, int16_t addrlen)
00238 {
00239     _SlSockBindMsg_u    Msg;
00240     _SlCmdCtrl_t         CmdCtrl = {0, 0, sizeof(_SocketResponse_t)};
00241 
00242     switch(addr->sa_family) {
00243         case SL_AF_INET :
00244             CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND;
00245             CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv4Command_t);
00246             break;
00247 #ifndef SL_TINY_EXT             
00248         case SL_AF_INET6_EUI_48:
00249             CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND_V6;
00250             CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6EUI48Command_t);
00251             break;
00252 #ifdef SL_SUPPORT_IPV6
00253         case AF_INET6:
00254             CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND_V6;
00255             CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6Command_t);
00256             break;
00257 #endif
00258 #endif
00259         case SL_AF_RF   :
00260         default:
00261             return SL_RET_CODE_INVALID_INPUT;
00262     }
00263 
00264     Msg.Cmd.IpV4.lenOrPadding = 0;
00265     Msg.Cmd.IpV4.sd = (uint8_t)sd;
00266 
00267     _sl_BuildAddress(addr, &Msg.Cmd);
00268 
00269     VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL));
00270 
00271     return Msg.Rsp.statusOrLen;
00272 }
00273 #endif
00274 
00275 /*******************************************************************************/
00276 /*  sl_Sendto */
00277 /*******************************************************************************/
00278 typedef union {
00279     _SocketAddrCommand_u    Cmd;
00280     /*  no response for 'sendto' commands*/
00281 } _SlSendtoMsg_u;
00282 
00283 #if _SL_INCLUDE_FUNC(sl_SendTo)
00284 int16_t cc3100_socket::sl_SendTo(int16_t sd, const void *pBuf, int16_t Len, int16_t flags, const SlSockAddr_t *to, SlSocklen_t tolen)
00285 {
00286     _SlSendtoMsg_u   Msg;
00287     _SlCmdCtrl_t     CmdCtrl = {0, 0, 0};
00288     _SlCmdExt_t      CmdExt;
00289     uint16_t         ChunkLen;
00290     int16_t          RetVal;
00291 
00292     _driver._SlDrvResetCmdExt(&CmdExt);
00293     CmdExt.TxPayloadLen = (uint16_t)Len;
00294     CmdExt.pTxPayload = (uint8_t *)pBuf;
00295 
00296     switch(to->sa_family) {
00297         case SL_AF_INET:
00298             CmdCtrl.Opcode = SL_OPCODE_SOCKET_SENDTO;
00299             CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv4Command_t);
00300             break;
00301 #ifndef SL_TINY_EXT            
00302         case SL_AF_INET6_EUI_48:
00303             CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND_V6;
00304             CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6EUI48Command_t);
00305             break;
00306 #ifdef SL_SUPPORT_IPV6
00307         case AF_INET6:
00308             CmdCtrl.Opcode = SL_OPCODE_SOCKET_SENDTO_V6;
00309             CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6Command_t);
00310             break;
00311 #endif
00312 #endif
00313         case SL_AF_RF:
00314         default:
00315             return SL_RET_CODE_INVALID_INPUT;
00316     }
00317 
00318     ChunkLen = _sl_TruncatePayloadByProtocol(sd,Len);
00319     Msg.Cmd.IpV4.lenOrPadding = ChunkLen;
00320     CmdExt.TxPayloadLen = ChunkLen;
00321 
00322     Msg.Cmd.IpV4.sd = (unsigned char)sd;
00323 
00324     _sl_BuildAddress(to, &Msg.Cmd);
00325     
00326     Msg.Cmd.IpV4.FamilyAndFlags |= flags & 0x0F;
00327     
00328     do {
00329         RetVal = _driver._SlDrvDataWriteOp((_SlSd_t)sd, &CmdCtrl, &Msg, &CmdExt);
00330         
00331         if(SL_OS_RET_CODE_OK == RetVal) {
00332             CmdExt.pTxPayload += ChunkLen;
00333             ChunkLen = (uint16_t)((unsigned char *)pBuf + Len - CmdExt.pTxPayload);
00334             ChunkLen = _sl_TruncatePayloadByProtocol(sd,ChunkLen);
00335             CmdExt.TxPayloadLen = ChunkLen;
00336             Msg.Cmd.IpV4.lenOrPadding = ChunkLen;
00337         } else {
00338             return RetVal;
00339         }
00340     } while(ChunkLen > 0);
00341 
00342     return (int16_t)Len;
00343 }
00344 #endif
00345 
00346 /*******************************************************************************/
00347 /*  sl_Recvfrom */
00348 /*******************************************************************************/
00349 typedef union {
00350     _sendRecvCommand_t      Cmd;
00351     _SocketAddrResponse_u   Rsp;
00352 } _SlRecvfromMsg_u;
00353 
00354 const _SlCmdCtrl_t _SlRecvfomCmdCtrl = {
00355     SL_OPCODE_SOCKET_RECVFROM,
00356     sizeof(_sendRecvCommand_t),
00357     sizeof(_SocketAddrResponse_u)
00358 };
00359 
00360 #if _SL_INCLUDE_FUNC(sl_RecvFrom)
00361 int16_t cc3100_socket::sl_RecvFrom(int16_t sd, void *buf, int16_t Len, int16_t flags, SlSockAddr_t *from, SlSocklen_t *fromlen)
00362 {
00363     _SlRecvfromMsg_u    Msg;
00364     _SlCmdExt_t         CmdExt;
00365     int16_t                 RetVal;
00366 
00367     _driver._SlDrvResetCmdExt(&CmdExt);
00368     CmdExt.RxPayloadLen = Len;
00369     CmdExt.pRxPayload = (uint8_t *)buf;
00370 
00371     Msg.Cmd.sd = (uint8_t)sd;
00372     Msg.Cmd.StatusOrLen = Len;
00373     /*  no size truncation in recv path */
00374     CmdExt.RxPayloadLen = Msg.Cmd.StatusOrLen;
00375     
00376     Msg.Cmd.FamilyAndFlags = flags & 0x0F;
00377 
00378     if(sizeof(SlSockAddrIn_t) == *fromlen) {
00379         Msg.Cmd.FamilyAndFlags |= (SL_AF_INET << 4);
00380     }
00381     else if (sizeof(SlSockAddrIn6_t) == *fromlen)
00382     {
00383         Msg.Cmd.FamilyAndFlags |= (SL_AF_INET6 << 4);
00384     } 
00385     else 
00386     {
00387         return SL_RET_CODE_INVALID_INPUT;
00388     }
00389 
00390     RetVal = _driver._SlDrvDataReadOp((_SlSd_t)sd, (_SlCmdCtrl_t *)&_SlRecvfomCmdCtrl, &Msg, &CmdExt);
00391     
00392     if( RetVal != SL_OS_RET_CODE_OK ) {
00393         return RetVal;
00394     }
00395     
00396     RetVal = Msg.Rsp.IpV4.statusOrLen;
00397 
00398     if(RetVal >= 0) {
00399         VERIFY_PROTOCOL(sd == Msg.Rsp.IpV4.sd);
00400 #if 0
00401         _sl_ParseAddress(&Msg.Rsp, from, fromlen);
00402 #else
00403         from->sa_family = Msg.Rsp.IpV4.family;
00404         if(SL_AF_INET == from->sa_family) {
00405             ((SlSockAddrIn_t *)from)->sin_port = Msg.Rsp.IpV4.port;
00406             ((SlSockAddrIn_t *)from)->sin_addr.s_addr = Msg.Rsp.IpV4.address;
00407             *fromlen = sizeof(SlSockAddrIn_t);
00408         } else if (SL_AF_INET6_EUI_48 == from->sa_family ) {
00409             ((SlSockAddrIn6_t *)from)->sin6_port  = Msg.Rsp.IpV6EUI48.port;
00410             memcpy(((SlSockAddrIn6_t *)from)->sin6_addr._S6_un._S6_u8, Msg.Rsp.IpV6EUI48.address, 6);
00411         }
00412 #ifdef SL_SUPPORT_IPV6
00413         else if(AF_INET6 == from->sa_family) {
00414             VERIFY_PROTOCOL(*fromlen >= sizeof(sockaddr_in6));
00415 
00416             ((sockaddr_in6 *)from)->sin6_port = Msg.Rsp.IpV6.port;
00417             memcpy(((sockaddr_in6 *)from)->sin6_addr._S6_un._S6_u32, Msg.Rsp.IpV6.address, 16);
00418             *fromlen = sizeof(sockaddr_in6);
00419         }
00420 #endif
00421 #endif
00422     }
00423 
00424     return (int16_t)RetVal;
00425 }
00426 #endif
00427 
00428 /*******************************************************************************/
00429 /*  sl_Connect */
00430 /*******************************************************************************/
00431 typedef union {
00432     _SocketAddrCommand_u    Cmd;
00433     _SocketResponse_t       Rsp;
00434 } _SlSockConnectMsg_u;
00435 
00436 #if _SL_INCLUDE_FUNC(sl_Connect)
00437 int16_t cc3100_socket::sl_Connect(int16_t sd, const SlSockAddr_t *addr, int16_t addrlen)
00438 {
00439     _SlSockConnectMsg_u  Msg;
00440     _SlReturnVal_t       RetVal;
00441     _SlCmdCtrl_t         CmdCtrl = {0, 0, sizeof(_SocketResponse_t)};
00442     _SocketResponse_t    AsyncRsp;
00443     uint8_t ObjIdx = MAX_CONCURRENT_ACTIONS;
00444 
00445 
00446     switch(addr->sa_family) {
00447         case SL_AF_INET :
00448             CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT;
00449             CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv4Command_t);
00450             /* Do nothing - cmd already initialized to this type */
00451             break;
00452         case  SL_AF_INET6_EUI_48:
00453             CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT_V6;
00454             CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6EUI48Command_t);
00455             break;
00456 #ifdef SL_SUPPORT_IPV6
00457         case AF_INET6:
00458             CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT_V6;
00459             CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6Command_t);
00460             break;
00461 #endif
00462         case SL_AF_RF   :
00463         default:
00464             return SL_RET_CODE_INVALID_INPUT;
00465     }
00466 
00467     Msg.Cmd.IpV4.lenOrPadding = 0;
00468     Msg.Cmd.IpV4.sd = (uint8_t)sd;
00469 
00470     _sl_BuildAddress(addr, &Msg.Cmd);
00471 
00472 
00473     ObjIdx = _driver._SlDrvProtectAsyncRespSetting((uint8_t*)&AsyncRsp, CONNECT_ID, sd  & BSD_SOCKET_ID_MASK);
00474 
00475     if (MAX_CONCURRENT_ACTIONS == ObjIdx)
00476     {
00477         return SL_POOL_IS_EMPTY;
00478     }
00479 
00480     /* send the command */
00481     VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL));
00482     VERIFY_PROTOCOL(Msg.Rsp.sd == sd)
00483 
00484     RetVal = Msg.Rsp.statusOrLen;
00485 
00486     if(SL_RET_CODE_OK == RetVal) {
00487         /*  wait for async and get Data Read parameters */
00488         _driver._SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj);
00489 
00490         VERIFY_PROTOCOL(AsyncRsp.sd == sd);
00491 
00492         RetVal = AsyncRsp.statusOrLen;
00493     }
00494     _driver._SlDrvReleasePoolObj(ObjIdx);
00495     return RetVal;
00496 }
00497 #endif
00498 
00499 /*******************************************************************************/
00500 /*  sl_Send */
00501 /*******************************************************************************/
00502 typedef union {
00503     _sendRecvCommand_t    Cmd;
00504     /*  no response for 'sendto' commands*/
00505 } _SlSendMsg_u;
00506 
00507 const _SlCmdCtrl_t _SlSendCmdCtrl = {
00508     SL_OPCODE_SOCKET_SEND,
00509     sizeof(_sendRecvCommand_t),
00510     0
00511 };
00512 
00513 #if _SL_INCLUDE_FUNC(sl_Send)
00514 int16_t cc3100_socket::sl_Send(int16_t sd, const void *pBuf, int16_t Len, int16_t flags)
00515 {
00516     _SlSendMsg_u   Msg;
00517     _SlCmdExt_t    CmdExt;
00518     uint16_t         ChunkLen;
00519     int16_t            RetVal;
00520     uint32_t         tempVal;
00521     uint8_t  runSingleChunk = FALSE;
00522 
00523     _driver._SlDrvResetCmdExt(&CmdExt);
00524     CmdExt.TxPayloadLen = Len;
00525     CmdExt.pTxPayload = (uint8_t *)pBuf;
00526 
00527     /* Only for RAW transceiver type socket, relay the flags parameter in the 2 bytes (4 byte aligned) before the actual payload */
00528     if ((sd & SL_SOCKET_PAYLOAD_TYPE_MASK) == SL_SOCKET_PAYLOAD_TYPE_RAW_TRANCEIVER) {
00529         tempVal = flags;
00530         CmdExt.pRxPayload = (uint8_t *)&tempVal;
00531         CmdExt.RxPayloadLen = -4; /* mark as Rx data to send */
00532         runSingleChunk = TRUE;
00533     } else {
00534         CmdExt.pRxPayload = NULL;
00535     }
00536 
00537     ChunkLen = _sl_TruncatePayloadByProtocol(sd,Len);
00538     CmdExt.TxPayloadLen = ChunkLen;
00539 
00540     Msg.Cmd.StatusOrLen = ChunkLen;
00541     Msg.Cmd.sd = (uint8_t)sd;
00542     Msg.Cmd.FamilyAndFlags |= flags & 0x0F;
00543 
00544     do {
00545         RetVal = _driver._SlDrvDataWriteOp((uint8_t)sd, (_SlCmdCtrl_t *)&_SlSendCmdCtrl, &Msg, &CmdExt);
00546         if(SL_OS_RET_CODE_OK == RetVal) {
00547             CmdExt.pTxPayload += ChunkLen;
00548             ChunkLen = (uint8_t *)pBuf + Len - CmdExt.pTxPayload;
00549             ChunkLen = _sl_TruncatePayloadByProtocol(sd,ChunkLen);
00550             CmdExt.TxPayloadLen = ChunkLen;
00551             Msg.Cmd.StatusOrLen = ChunkLen;
00552         } else {
00553             return RetVal;
00554         }
00555     } while((ChunkLen > 0) && (runSingleChunk==FALSE));
00556 
00557     return (int16_t)Len;
00558 }
00559 #endif
00560 
00561 /*******************************************************************************/
00562 /*  sl_Listen */
00563 /*******************************************************************************/
00564 typedef union {
00565     _ListenCommand_t    Cmd;
00566     _BasicResponse_t    Rsp;
00567 } _SlListenMsg_u;
00568 
00569 #if _SL_INCLUDE_FUNC(sl_Listen)
00570 const _SlCmdCtrl_t _SlListenCmdCtrl = {
00571     SL_OPCODE_SOCKET_LISTEN,
00572     sizeof(_ListenCommand_t),
00573     sizeof(_BasicResponse_t),
00574 };
00575 
00576 int16_t cc3100_socket::sl_Listen(int16_t sd, int16_t backlog)
00577 {
00578     _SlListenMsg_u  Msg;
00579 
00580     Msg.Cmd.sd = (uint8_t)sd;
00581     Msg.Cmd.backlog = (uint8_t)backlog;
00582 
00583     VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlListenCmdCtrl, &Msg, NULL));
00584 
00585     return (int16_t)Msg.Rsp.status;
00586 }
00587 #endif
00588 
00589 /*******************************************************************************/
00590 /*  sl_Accept */
00591 /*******************************************************************************/
00592 typedef union {
00593     _AcceptCommand_t    Cmd;
00594     _SocketResponse_t   Rsp;
00595 } _SlSockAcceptMsg_u;
00596 
00597 #if _SL_INCLUDE_FUNC(sl_Accept)
00598 const _SlCmdCtrl_t _SlAcceptCmdCtrl = {
00599     SL_OPCODE_SOCKET_ACCEPT,
00600     sizeof(_AcceptCommand_t),
00601     sizeof(_BasicResponse_t),
00602 };
00603 
00604 int16_t cc3100_socket::sl_Accept(int16_t sd, SlSockAddr_t *addr, SlSocklen_t *addrlen)
00605 {
00606     _SlSockAcceptMsg_u      Msg;
00607     _SlReturnVal_t          RetVal;
00608     _SocketAddrResponse_u   AsyncRsp;
00609 
00610     uint8_t ObjIdx = MAX_CONCURRENT_ACTIONS;
00611 
00612 
00613     Msg.Cmd.sd = (uint8_t)sd;
00614     Msg.Cmd.family = (sizeof(SlSockAddrIn_t) == *addrlen) ? SL_AF_INET : SL_AF_INET6;
00615 
00616     ObjIdx = _driver._SlDrvProtectAsyncRespSetting((uint8_t*)&AsyncRsp, ACCEPT_ID, sd  & BSD_SOCKET_ID_MASK );
00617 
00618     if (MAX_CONCURRENT_ACTIONS == ObjIdx)
00619     {
00620         return SL_POOL_IS_EMPTY;
00621     }
00622     
00623     /* send the command */
00624     VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlAcceptCmdCtrl, &Msg, NULL));
00625     VERIFY_PROTOCOL(Msg.Rsp.sd == sd);
00626 
00627     RetVal = Msg.Rsp.statusOrLen;
00628 
00629     if(SL_OS_RET_CODE_OK == RetVal) {
00630         /*  wait for async and get Data Read parameters */
00631         _driver._SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj);
00632 
00633         VERIFY_PROTOCOL(AsyncRsp.IpV4.sd == sd);
00634 
00635         RetVal = AsyncRsp.IpV4.statusOrLen;
00636         if( (NULL != addr) && (NULL != addrlen) ) {
00637 #if 0 /*  Kept for backup */
00638             _sl_ParseAddress(&AsyncRsp, addr, addrlen);
00639 #else
00640             addr->sa_family = AsyncRsp.IpV4.family;
00641 
00642             if(SL_AF_INET == addr->sa_family) {
00643                 if( *addrlen == sizeof( SlSockAddrIn_t ) ) {
00644                     ((SlSockAddrIn_t *)addr)->sin_port         = AsyncRsp.IpV4.port;
00645                     ((SlSockAddrIn_t *)addr)->sin_addr.s_addr  = AsyncRsp.IpV4.address;
00646                 } else {
00647                     *addrlen = 0;
00648                 }
00649             } else if (SL_AF_INET6_EUI_48 == addr->sa_family ) {
00650                 if( *addrlen == sizeof( SlSockAddrIn6_t ) ) {
00651                     ((SlSockAddrIn6_t *)addr)->sin6_port                   = AsyncRsp.IpV6EUI48.port    ;
00652                     /*  will be called from here and from _sl_BuildAddress*/
00653                     memcpy(((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u8, AsyncRsp.IpV6EUI48.address, 6);
00654                 } else {
00655                     *addrlen = 0;
00656                 }
00657             }
00658 #ifdef SL_SUPPORT_IPV6
00659             else {
00660                 if( *addrlen == sizeof( sockaddr_in6 ) ) {
00661                     ((sockaddr_in6 *)addr)->sin6_port                   = AsyncRsp.IpV6.port    ;
00662                     memcpy(((sockaddr_in6 *)addr)->sin6_addr._S6_un._S6_u32, AsyncRsp.IpV6.address, 16);
00663                 } else {
00664                     *addrlen = 0;
00665                 }
00666             }
00667 #endif
00668 #endif
00669         }
00670     }
00671 
00672     _driver._SlDrvReleasePoolObj(ObjIdx);
00673     return (int16_t)RetVal;
00674 }
00675 #endif
00676 
00677 
00678 /*******************************************************************************/
00679 /*  sl_Htonl */
00680 /*******************************************************************************/
00681 uint32_t cc3100_socket::sl_Htonl( uint32_t val )
00682 {
00683     uint32_t i = 1;
00684     int8_t *p = (int8_t *)&i;
00685     if (p[0] == 1) { /* little endian */
00686         p[0] = ((int8_t* )&val)[3];
00687         p[1] = ((int8_t* )&val)[2];
00688         p[2] = ((int8_t* )&val)[1];
00689         p[3] = ((int8_t* )&val)[0];
00690         return i;
00691     } else { /* big endian */
00692         return val;
00693     }
00694 }
00695 
00696 /*******************************************************************************/
00697 /*  sl_Htonl */
00698 /*******************************************************************************/
00699 uint16_t cc3100_socket::sl_Htons( uint16_t val )
00700 {
00701     int16_t i = 1;
00702     int8_t *p = (int8_t *)&i;
00703     if (p[0] == 1) { /* little endian */
00704         p[0] = ((int8_t* )&val)[1];
00705         p[1] = ((int8_t* )&val)[0];
00706         return i;
00707     } else { /* big endian */
00708         return val;
00709     }
00710 }
00711 
00712 /*******************************************************************************/
00713 /*  sl_Recv */
00714 /*******************************************************************************/
00715 typedef union {
00716     _sendRecvCommand_t  Cmd;
00717     _SocketResponse_t   Rsp;
00718 } _SlRecvMsg_u;
00719 
00720 #if _SL_INCLUDE_FUNC(sl_Recv)
00721 const _SlCmdCtrl_t _SlRecvCmdCtrl = {
00722     SL_OPCODE_SOCKET_RECV,
00723     sizeof(_sendRecvCommand_t),
00724     sizeof(_SocketResponse_t)
00725 };
00726 
00727 int16_t cc3100_socket::sl_Recv(int16_t sd, void *pBuf, int16_t Len, int16_t flags)
00728 {
00729     _SlRecvMsg_u    Msg;
00730     _SlCmdExt_t     CmdExt;
00731     _SlReturnVal_t status;
00732 
00733     _driver._SlDrvResetCmdExt(&CmdExt);
00734     CmdExt.RxPayloadLen = Len;
00735     CmdExt.pRxPayload = (uint8_t *)pBuf;
00736 
00737     Msg.Cmd.sd = (uint8_t)sd;
00738     Msg.Cmd.StatusOrLen = Len;
00739 
00740     /*  no size truncation in recv path */
00741     CmdExt.RxPayloadLen = Msg.Cmd.StatusOrLen;
00742 
00743     Msg.Cmd.FamilyAndFlags = flags & 0x0F;
00744 
00745     status = _driver._SlDrvDataReadOp((_SlSd_t)sd, (_SlCmdCtrl_t *)&_SlRecvCmdCtrl, &Msg, &CmdExt);
00746     if( status != SL_OS_RET_CODE_OK ) {
00747         return status;
00748     }
00749 
00750     /*  if the Device side sends less than expected it is not the Driver's role */
00751     /*  the returned value could be smaller than the requested size */
00752     return (int16_t)Msg.Rsp.statusOrLen;
00753 }
00754 #endif
00755 
00756 /*******************************************************************************/
00757 /*  sl_SetSockOpt */
00758 /*******************************************************************************/
00759 typedef union {
00760     _setSockOptCommand_t    Cmd;
00761     _SocketResponse_t       Rsp;
00762 } _SlSetSockOptMsg_u;
00763 
00764 const _SlCmdCtrl_t _SlSetSockOptCmdCtrl = {
00765     SL_OPCODE_SOCKET_SETSOCKOPT,
00766     sizeof(_setSockOptCommand_t),
00767     sizeof(_SocketResponse_t)
00768 };
00769 
00770 #if _SL_INCLUDE_FUNC(sl_SetSockOpt)
00771 int16_t cc3100_socket::sl_SetSockOpt(int16_t sd, int16_t level, int16_t optname, const void *optval, SlSocklen_t optlen)
00772 {
00773     _SlSetSockOptMsg_u    Msg;
00774     _SlCmdExt_t           CmdExt;
00775 
00776      _driver._SlDrvResetCmdExt(&CmdExt);
00777     CmdExt.TxPayloadLen = optlen;
00778     CmdExt.pTxPayload = (uint8_t *)optval;
00779 
00780     Msg.Cmd.sd = (uint8_t)sd;
00781     Msg.Cmd.level = (uint8_t)level;
00782     Msg.Cmd.optionLen = (uint8_t)optlen;
00783     Msg.Cmd.optionName = (uint8_t)optname;
00784 
00785     VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSetSockOptCmdCtrl, &Msg, &CmdExt));
00786 
00787     return (int16_t)Msg.Rsp.statusOrLen;
00788 }
00789 #endif
00790 
00791 /*******************************************************************************/
00792 /*  sl_GetSockOpt */
00793 /*******************************************************************************/
00794 typedef union {
00795     _getSockOptCommand_t    Cmd;
00796     _getSockOptResponse_t   Rsp;
00797 } _SlGetSockOptMsg_u;
00798 
00799 #if _SL_INCLUDE_FUNC(sl_GetSockOpt)
00800 const _SlCmdCtrl_t _SlGetSockOptCmdCtrl = {
00801     SL_OPCODE_SOCKET_GETSOCKOPT,
00802     sizeof(_getSockOptCommand_t),
00803     sizeof(_getSockOptResponse_t)
00804 };
00805 
00806 int16_t cc3100_socket::sl_GetSockOpt(int16_t sd, int16_t level, int16_t optname, void *optval, SlSocklen_t *optlen)
00807 {
00808     _SlGetSockOptMsg_u    Msg;
00809     _SlCmdExt_t           CmdExt;
00810 
00811     if (*optlen == 0) {
00812         return SL_EZEROLEN;
00813     }
00814     
00815     _driver._SlDrvResetCmdExt(&CmdExt);
00816     CmdExt.RxPayloadLen = *optlen;
00817     CmdExt.pRxPayload = (uint8_t*)optval;
00818 
00819     Msg.Cmd.sd = (uint8_t)sd;
00820     Msg.Cmd.level = (uint8_t)level;
00821     Msg.Cmd.optionLen = (uint8_t)(*optlen);
00822     Msg.Cmd.optionName = (uint8_t)optname;
00823 
00824     VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlGetSockOptCmdCtrl, &Msg, &CmdExt));
00825 
00826     if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) {
00827         *optlen = Msg.Rsp.optionLen;
00828         return SL_ESMALLBUF;
00829     } else {
00830         *optlen = (uint8_t)CmdExt.ActualRxPayloadLen;
00831     }
00832     return (int16_t)Msg.Rsp.status;
00833 }
00834 #endif
00835 
00836 /*******************************************************************************/
00837 /*  sl_Select */
00838 /* ******************************************************************************/
00839 typedef union {
00840     _SelectCommand_t   Cmd;
00841     _BasicResponse_t   Rsp;
00842 } _SlSelectMsg_u;
00843 
00844 #ifndef SL_TINY_EXT
00845 #if _SL_INCLUDE_FUNC(sl_Select)
00846 const _SlCmdCtrl_t _SlSelectCmdCtrl = {
00847     SL_OPCODE_SOCKET_SELECT,
00848     sizeof(_SelectCommand_t),
00849     sizeof(_BasicResponse_t)
00850 };
00851 
00852 int16_t cc3100_socket::sl_Select(int16_t nfds, SlFdSet_t *readsds, SlFdSet_t *writesds, SlFdSet_t *exceptsds, SlTimeval_t *timeout)
00853 {
00854     _SlSelectMsg_u          Msg;
00855     _SelectAsyncResponse_t  AsyncRsp;
00856     uint8_t ObjIdx = MAX_CONCURRENT_ACTIONS;
00857 
00858     Msg.Cmd.nfds          = (uint8_t)nfds;
00859     Msg.Cmd.readFdsCount  = 0;
00860     Msg.Cmd.writeFdsCount = 0;
00861 
00862     Msg.Cmd.readFds = 0;
00863     Msg.Cmd.writeFds = 0;
00864 
00865     if( readsds ) {
00866         Msg.Cmd.readFds       = (uint16_t)readsds->fd_array[0];
00867     }
00868     if( writesds ) {
00869         Msg.Cmd.writeFds      = (uint16_t)writesds->fd_array[0];
00870     }
00871     if( NULL == timeout ) {
00872         Msg.Cmd.tv_sec = 0xffff;
00873         Msg.Cmd.tv_usec = 0xffff;
00874     } else {
00875         if( 0xffff <= timeout->tv_sec ) {
00876             Msg.Cmd.tv_sec = 0xffff;
00877         } else {
00878             Msg.Cmd.tv_sec = (uint16_t)timeout->tv_sec;
00879         }
00880         timeout->tv_usec = timeout->tv_usec >> 10;  /*  convert to milliseconds */
00881         if( 0xffff <= timeout->tv_usec ) {
00882             Msg.Cmd.tv_usec = 0xffff;
00883         } else {
00884             Msg.Cmd.tv_usec = (uint16_t)timeout->tv_usec;
00885         }
00886     }
00887 
00888     /* Use Obj to issue the command, if not available try later */
00889     ObjIdx = _driver._SlDrvProtectAsyncRespSetting((uint8_t*)&AsyncRsp, SELECT_ID, SL_MAX_SOCKETS);
00890 
00891     if (MAX_CONCURRENT_ACTIONS == ObjIdx)
00892     {
00893         return SL_POOL_IS_EMPTY;
00894     }
00895     
00896     /* send the command */
00897     VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSelectCmdCtrl, &Msg, NULL));
00898 
00899     if(SL_OS_RET_CODE_OK == (int16_t)Msg.Rsp.status) {
00900         _driver._SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj);
00901         Msg.Rsp.status = AsyncRsp.status;
00902 
00903         if(  ((int16_t)Msg.Rsp.status) >= 0 ) {
00904             if( readsds ) {
00905                 readsds->fd_array[0]  = AsyncRsp.readFds;
00906             }
00907             if( writesds ) {
00908                 writesds->fd_array[0] = AsyncRsp.writeFds;
00909             }
00910         }
00911     }
00912     
00913     _driver._SlDrvReleasePoolObj(ObjIdx);
00914     return (int16_t)Msg.Rsp.status;
00915 }
00916 
00917 /*  Select helper functions */
00918 /*******************************************************************************/
00919 /*  SL_FD_SET */
00920 /* ******************************************************************************/
00921 void cc3100_socket::SL_FD_SET(int16_t fd, SlFdSet_t *fdset)
00922 {
00923     fdset->fd_array[0] |=  (1<< (fd & BSD_SOCKET_ID_MASK));
00924 }
00925 /*******************************************************************************/
00926 /*  SL_FD_CLR */
00927 /*******************************************************************************/
00928 void cc3100_socket::SL_FD_CLR(int16_t fd, SlFdSet_t *fdset)
00929 {
00930     fdset->fd_array[0] &=  ~(1<< (fd & BSD_SOCKET_ID_MASK));
00931 }
00932 /*******************************************************************************/
00933 /*  SL_FD_ISSET */
00934 /*******************************************************************************/
00935 int16_t  cc3100_socket::SL_FD_ISSET(int16_t fd, SlFdSet_t *fdset)
00936 {
00937     if( fdset->fd_array[0] & (1<< (fd & BSD_SOCKET_ID_MASK)) ) {
00938         return 1;
00939     }
00940     return 0;
00941 }
00942 /*******************************************************************************/
00943 /*  SL_FD_ZERO */
00944 /*******************************************************************************/
00945 void cc3100_socket::SL_FD_ZERO(SlFdSet_t *fdset)
00946 {
00947     fdset->fd_array[0] = 0;
00948 }
00949 
00950 #endif
00951 #endif
00952 
00953 }//namespace mbed_cc3100
00954 
00955 
00956