Update revision to use TI's mqtt and Freertos.

Dependencies:   mbed client server

Fork of cc3100_Test_mqtt_CM3 by David Fletcher

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