TI's CC3100. A test demo with very little testing done!

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 
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     if( RetVal != SL_OS_RET_CODE_OK ) {
00388         return RetVal;
00389     }
00390 
00391     RetVal = Msg.Rsp.IpV4.statusOrLen;
00392 
00393     if(RetVal >= 0) {
00394         VERIFY_PROTOCOL(sd == Msg.Rsp.IpV4.sd);
00395 #if 0
00396         _sl_ParseAddress(&Msg.Rsp, from, fromlen);
00397 #else
00398         from->sa_family = Msg.Rsp.IpV4.family;
00399         if(SL_AF_INET == from->sa_family) {
00400             ((SlSockAddrIn_t *)from)->sin_port = Msg.Rsp.IpV4.port;
00401             ((SlSockAddrIn_t *)from)->sin_addr.s_addr = Msg.Rsp.IpV4.address;
00402             *fromlen = sizeof(SlSockAddrIn_t);
00403         } else if (SL_AF_INET6_EUI_48 == from->sa_family ) {
00404             ((SlSockAddrIn6_t *)from)->sin6_port  = Msg.Rsp.IpV6EUI48.port;
00405             memcpy(((SlSockAddrIn6_t *)from)->sin6_addr._S6_un._S6_u8, Msg.Rsp.IpV6EUI48.address, 6);
00406         }
00407 #ifdef SL_SUPPORT_IPV6
00408         else if(AF_INET6 == from->sa_family) {
00409             VERIFY_PROTOCOL(*fromlen >= sizeof(sockaddr_in6));
00410 
00411             ((sockaddr_in6 *)from)->sin6_port = Msg.Rsp.IpV6.port;
00412             memcpy(((sockaddr_in6 *)from)->sin6_addr._S6_un._S6_u32, Msg.Rsp.IpV6.address, 16);
00413             *fromlen = sizeof(sockaddr_in6);
00414         }
00415 #endif
00416 #endif
00417     }
00418 
00419     return (int16_t)RetVal;
00420 }
00421 #endif
00422 
00423 /*******************************************************************************/
00424 /*  sl_Connect */
00425 /*******************************************************************************/
00426 typedef union {
00427     _SocketAddrCommand_u    Cmd;
00428     _SocketResponse_t       Rsp;
00429 } _SlSockConnectMsg_u;
00430 
00431 #if _SL_INCLUDE_FUNC(sl_Connect)
00432 int16_t cc3100_socket::sl_Connect(int16_t sd, const SlSockAddr_t *addr, int16_t addrlen)
00433 {
00434     _SlSockConnectMsg_u  Msg;
00435     _SlReturnVal_t       RetVal;
00436     _SlCmdCtrl_t         CmdCtrl = {0, 0, sizeof(_SocketResponse_t)};
00437     _SocketResponse_t    AsyncRsp;
00438     uint8_t ObjIdx = MAX_CONCURRENT_ACTIONS;
00439 
00440 
00441     switch(addr->sa_family) {
00442         case SL_AF_INET :
00443             CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT;
00444             CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv4Command_t);
00445             /* Do nothing - cmd already initialized to this type */
00446             break;
00447         case  SL_AF_INET6_EUI_48:
00448             CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT_V6;
00449             CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6EUI48Command_t);
00450             break;
00451 #ifdef SL_SUPPORT_IPV6
00452         case AF_INET6:
00453             CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT_V6;
00454             CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6Command_t);
00455             break;
00456 #endif
00457         case SL_AF_RF   :
00458         default:
00459             return SL_RET_CODE_INVALID_INPUT;
00460     }
00461 
00462     Msg.Cmd.IpV4.lenOrPadding = 0;
00463     Msg.Cmd.IpV4.sd = (uint8_t)sd;
00464 
00465     _sl_BuildAddress(addr, &Msg.Cmd);
00466 
00467 
00468     ObjIdx = _driver._SlDrvProtectAsyncRespSetting((uint8_t*)&AsyncRsp, CONNECT_ID, sd  & BSD_SOCKET_ID_MASK);
00469 
00470     if (MAX_CONCURRENT_ACTIONS == ObjIdx)
00471     {
00472         return SL_POOL_IS_EMPTY;
00473     }
00474 
00475     /* send the command */
00476     VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL));
00477     VERIFY_PROTOCOL(Msg.Rsp.sd == sd)
00478 
00479     RetVal = Msg.Rsp.statusOrLen;
00480 
00481     if(SL_RET_CODE_OK == RetVal) {
00482         /*  wait for async and get Data Read parameters */
00483         _driver._SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj);
00484 
00485         VERIFY_PROTOCOL(AsyncRsp.sd == sd);
00486 
00487         RetVal = AsyncRsp.statusOrLen;
00488     }
00489     _driver._SlDrvReleasePoolObj(ObjIdx);
00490     return RetVal;
00491 }
00492 #endif
00493 
00494 /*******************************************************************************/
00495 /*  sl_Send */
00496 /*******************************************************************************/
00497 typedef union {
00498     _sendRecvCommand_t    Cmd;
00499     /*  no response for 'sendto' commands*/
00500 } _SlSendMsg_u;
00501 
00502 const _SlCmdCtrl_t _SlSendCmdCtrl = {
00503     SL_OPCODE_SOCKET_SEND,
00504     sizeof(_sendRecvCommand_t),
00505     0
00506 };
00507 
00508 #if _SL_INCLUDE_FUNC(sl_Send)
00509 int16_t cc3100_socket::sl_Send(int16_t sd, const void *pBuf, int16_t Len, int16_t flags)
00510 {
00511     _SlSendMsg_u   Msg;
00512     _SlCmdExt_t    CmdExt;
00513     uint16_t         ChunkLen;
00514     int16_t            RetVal;
00515     uint32_t         tempVal;
00516     uint8_t  runSingleChunk = FALSE;
00517 
00518     _driver._SlDrvResetCmdExt(&CmdExt);
00519     CmdExt.TxPayloadLen = Len;
00520     CmdExt.pTxPayload = (uint8_t *)pBuf;
00521 
00522     /* Only for RAW transceiver type socket, relay the flags parameter in the 2 bytes (4 byte aligned) before the actual payload */
00523     if ((sd & SL_SOCKET_PAYLOAD_TYPE_MASK) == SL_SOCKET_PAYLOAD_TYPE_RAW_TRANCEIVER) {
00524         tempVal = flags;
00525         CmdExt.pRxPayload = (uint8_t *)&tempVal;
00526         CmdExt.RxPayloadLen = -4; /* mark as Rx data to send */
00527         runSingleChunk = TRUE;
00528     } else {
00529         CmdExt.pRxPayload = NULL;
00530     }
00531 
00532     ChunkLen = _sl_TruncatePayloadByProtocol(sd,Len);
00533     CmdExt.TxPayloadLen = ChunkLen;
00534 
00535     Msg.Cmd.StatusOrLen = ChunkLen;
00536     Msg.Cmd.sd = (uint8_t)sd;
00537     Msg.Cmd.FamilyAndFlags |= flags & 0x0F;
00538 
00539     do {
00540         RetVal = _driver._SlDrvDataWriteOp((uint8_t)sd, (_SlCmdCtrl_t *)&_SlSendCmdCtrl, &Msg, &CmdExt);
00541         if(SL_OS_RET_CODE_OK == RetVal) {
00542             CmdExt.pTxPayload += ChunkLen;
00543             ChunkLen = (uint8_t *)pBuf + Len - CmdExt.pTxPayload;
00544             ChunkLen = _sl_TruncatePayloadByProtocol(sd,ChunkLen);
00545             CmdExt.TxPayloadLen = ChunkLen;
00546             Msg.Cmd.StatusOrLen = ChunkLen;
00547         } else {
00548             return RetVal;
00549         }
00550     } while((ChunkLen > 0) && (runSingleChunk==FALSE));
00551 
00552     return (int16_t)Len;
00553 }
00554 #endif
00555 
00556 /*******************************************************************************/
00557 /*  sl_Listen */
00558 /*******************************************************************************/
00559 typedef union {
00560     _ListenCommand_t    Cmd;
00561     _BasicResponse_t    Rsp;
00562 } _SlListenMsg_u;
00563 
00564 #if _SL_INCLUDE_FUNC(sl_Listen)
00565 const _SlCmdCtrl_t _SlListenCmdCtrl = {
00566     SL_OPCODE_SOCKET_LISTEN,
00567     sizeof(_ListenCommand_t),
00568     sizeof(_BasicResponse_t),
00569 };
00570 
00571 int16_t cc3100_socket::sl_Listen(int16_t sd, int16_t backlog)
00572 {
00573     _SlListenMsg_u  Msg;
00574 
00575     Msg.Cmd.sd = (uint8_t)sd;
00576     Msg.Cmd.backlog = (uint8_t)backlog;
00577 
00578     VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlListenCmdCtrl, &Msg, NULL));
00579 
00580     return (int16_t)Msg.Rsp.status;
00581 }
00582 #endif
00583 
00584 /*******************************************************************************/
00585 /*  sl_Accept */
00586 /*******************************************************************************/
00587 typedef union {
00588     _AcceptCommand_t    Cmd;
00589     _SocketResponse_t   Rsp;
00590 } _SlSockAcceptMsg_u;
00591 
00592 #if _SL_INCLUDE_FUNC(sl_Accept)
00593 const _SlCmdCtrl_t _SlAcceptCmdCtrl = {
00594     SL_OPCODE_SOCKET_ACCEPT,
00595     sizeof(_AcceptCommand_t),
00596     sizeof(_BasicResponse_t),
00597 };
00598 
00599 int16_t cc3100_socket::sl_Accept(int16_t sd, SlSockAddr_t *addr, SlSocklen_t *addrlen)
00600 {
00601     _SlSockAcceptMsg_u      Msg;
00602     _SlReturnVal_t          RetVal;
00603     _SocketAddrResponse_u   AsyncRsp;
00604 
00605     uint8_t ObjIdx = MAX_CONCURRENT_ACTIONS;
00606 
00607 
00608     Msg.Cmd.sd = (uint8_t)sd;
00609     Msg.Cmd.family = (sizeof(SlSockAddrIn_t) == *addrlen) ? SL_AF_INET : SL_AF_INET6;
00610 
00611     ObjIdx = _driver._SlDrvProtectAsyncRespSetting((uint8_t*)&AsyncRsp, ACCEPT_ID, sd  & BSD_SOCKET_ID_MASK );
00612 
00613     if (MAX_CONCURRENT_ACTIONS == ObjIdx)
00614     {
00615         return SL_POOL_IS_EMPTY;
00616     }
00617     
00618     /* send the command */
00619     VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlAcceptCmdCtrl, &Msg, NULL));
00620     VERIFY_PROTOCOL(Msg.Rsp.sd == sd);
00621 
00622     RetVal = Msg.Rsp.statusOrLen;
00623 
00624     if(SL_OS_RET_CODE_OK == RetVal) {
00625         /*  wait for async and get Data Read parameters */
00626         _driver._SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj);
00627 
00628         VERIFY_PROTOCOL(AsyncRsp.IpV4.sd == sd);
00629 
00630         RetVal = AsyncRsp.IpV4.statusOrLen;
00631         if( (NULL != addr) && (NULL != addrlen) ) {
00632 #if 0 /*  Kept for backup */
00633             _sl_ParseAddress(&AsyncRsp, addr, addrlen);
00634 #else
00635             addr->sa_family = AsyncRsp.IpV4.family;
00636 
00637             if(SL_AF_INET == addr->sa_family) {
00638                 if( *addrlen == sizeof( SlSockAddrIn_t ) ) {
00639                     ((SlSockAddrIn_t *)addr)->sin_port         = AsyncRsp.IpV4.port;
00640                     ((SlSockAddrIn_t *)addr)->sin_addr.s_addr  = AsyncRsp.IpV4.address;
00641                 } else {
00642                     *addrlen = 0;
00643                 }
00644             } else if (SL_AF_INET6_EUI_48 == addr->sa_family ) {
00645                 if( *addrlen == sizeof( SlSockAddrIn6_t ) ) {
00646                     ((SlSockAddrIn6_t *)addr)->sin6_port                   = AsyncRsp.IpV6EUI48.port    ;
00647                     /*  will be called from here and from _sl_BuildAddress*/
00648                     memcpy(((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u8, AsyncRsp.IpV6EUI48.address, 6);
00649                 } else {
00650                     *addrlen = 0;
00651                 }
00652             }
00653 #ifdef SL_SUPPORT_IPV6
00654             else {
00655                 if( *addrlen == sizeof( sockaddr_in6 ) ) {
00656                     ((sockaddr_in6 *)addr)->sin6_port                   = AsyncRsp.IpV6.port    ;
00657                     memcpy(((sockaddr_in6 *)addr)->sin6_addr._S6_un._S6_u32, AsyncRsp.IpV6.address, 16);
00658                 } else {
00659                     *addrlen = 0;
00660                 }
00661             }
00662 #endif
00663 #endif
00664         }
00665     }
00666 
00667     _driver._SlDrvReleasePoolObj(ObjIdx);
00668     return (int16_t)RetVal;
00669 }
00670 #endif
00671 
00672 
00673 /*******************************************************************************/
00674 /*  sl_Htonl */
00675 /*******************************************************************************/
00676 uint32_t cc3100_socket::sl_Htonl( uint32_t val )
00677 {
00678     uint32_t i = 1;
00679     int8_t *p = (int8_t *)&i;
00680     if (p[0] == 1) { /* little endian */
00681         p[0] = ((int8_t* )&val)[3];
00682         p[1] = ((int8_t* )&val)[2];
00683         p[2] = ((int8_t* )&val)[1];
00684         p[3] = ((int8_t* )&val)[0];
00685         return i;
00686     } else { /* big endian */
00687         return val;
00688     }
00689 }
00690 
00691 /*******************************************************************************/
00692 /*  sl_Htonl */
00693 /*******************************************************************************/
00694 uint16_t cc3100_socket::sl_Htons( uint16_t val )
00695 {
00696     int16_t i = 1;
00697     int8_t *p = (int8_t *)&i;
00698     if (p[0] == 1) { /* little endian */
00699         p[0] = ((int8_t* )&val)[1];
00700         p[1] = ((int8_t* )&val)[0];
00701         return i;
00702     } else { /* big endian */
00703         return val;
00704     }
00705 }
00706 
00707 /*******************************************************************************/
00708 /*  sl_Recv */
00709 /*******************************************************************************/
00710 typedef union {
00711     _sendRecvCommand_t  Cmd;
00712     _SocketResponse_t   Rsp;
00713 } _SlRecvMsg_u;
00714 
00715 #if _SL_INCLUDE_FUNC(sl_Recv)
00716 const _SlCmdCtrl_t _SlRecvCmdCtrl = {
00717     SL_OPCODE_SOCKET_RECV,
00718     sizeof(_sendRecvCommand_t),
00719     sizeof(_SocketResponse_t)
00720 };
00721 
00722 int16_t cc3100_socket::sl_Recv(int16_t sd, void *pBuf, int16_t Len, int16_t flags)
00723 {
00724     _SlRecvMsg_u    Msg;
00725     _SlCmdExt_t     CmdExt;
00726     _SlReturnVal_t status;
00727 
00728     _driver._SlDrvResetCmdExt(&CmdExt);
00729     CmdExt.RxPayloadLen = Len;
00730     CmdExt.pRxPayload = (uint8_t *)pBuf;
00731 
00732     Msg.Cmd.sd = (uint8_t)sd;
00733     Msg.Cmd.StatusOrLen = Len;
00734 
00735     /*  no size truncation in recv path */
00736     CmdExt.RxPayloadLen = Msg.Cmd.StatusOrLen;
00737 
00738     Msg.Cmd.FamilyAndFlags = flags & 0x0F;
00739 
00740     status = _driver._SlDrvDataReadOp((_SlSd_t)sd, (_SlCmdCtrl_t *)&_SlRecvCmdCtrl, &Msg, &CmdExt);
00741     if( status != SL_OS_RET_CODE_OK ) {
00742         return status;
00743     }
00744 
00745     /*  if the Device side sends less than expected it is not the Driver's role */
00746     /*  the returned value could be smaller than the requested size */
00747     return (int16_t)Msg.Rsp.statusOrLen;
00748 }
00749 #endif
00750 
00751 /*******************************************************************************/
00752 /*  sl_SetSockOpt */
00753 /*******************************************************************************/
00754 typedef union {
00755     _setSockOptCommand_t    Cmd;
00756     _SocketResponse_t       Rsp;
00757 } _SlSetSockOptMsg_u;
00758 
00759 const _SlCmdCtrl_t _SlSetSockOptCmdCtrl = {
00760     SL_OPCODE_SOCKET_SETSOCKOPT,
00761     sizeof(_setSockOptCommand_t),
00762     sizeof(_SocketResponse_t)
00763 };
00764 
00765 #if _SL_INCLUDE_FUNC(sl_SetSockOpt)
00766 int16_t cc3100_socket::sl_SetSockOpt(int16_t sd, int16_t level, int16_t optname, const void *optval, SlSocklen_t optlen)
00767 {
00768     _SlSetSockOptMsg_u    Msg;
00769     _SlCmdExt_t           CmdExt;
00770 
00771      _driver._SlDrvResetCmdExt(&CmdExt);
00772     CmdExt.TxPayloadLen = optlen;
00773     CmdExt.pTxPayload = (uint8_t *)optval;
00774 
00775     Msg.Cmd.sd = (uint8_t)sd;
00776     Msg.Cmd.level = (uint8_t)level;
00777     Msg.Cmd.optionLen = (uint8_t)optlen;
00778     Msg.Cmd.optionName = (uint8_t)optname;
00779 
00780     VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSetSockOptCmdCtrl, &Msg, &CmdExt));
00781 
00782     return (int16_t)Msg.Rsp.statusOrLen;
00783 }
00784 #endif
00785 
00786 /*******************************************************************************/
00787 /*  sl_GetSockOpt */
00788 /*******************************************************************************/
00789 typedef union {
00790     _getSockOptCommand_t    Cmd;
00791     _getSockOptResponse_t   Rsp;
00792 } _SlGetSockOptMsg_u;
00793 
00794 #if _SL_INCLUDE_FUNC(sl_GetSockOpt)
00795 const _SlCmdCtrl_t _SlGetSockOptCmdCtrl = {
00796     SL_OPCODE_SOCKET_GETSOCKOPT,
00797     sizeof(_getSockOptCommand_t),
00798     sizeof(_getSockOptResponse_t)
00799 };
00800 
00801 int16_t cc3100_socket::sl_GetSockOpt(int16_t sd, int16_t level, int16_t optname, void *optval, SlSocklen_t *optlen)
00802 {
00803     _SlGetSockOptMsg_u    Msg;
00804     _SlCmdExt_t           CmdExt;
00805 
00806     if (*optlen == 0) {
00807         return SL_EZEROLEN;
00808     }
00809     
00810     _driver._SlDrvResetCmdExt(&CmdExt);
00811     CmdExt.RxPayloadLen = *optlen;
00812     CmdExt.pRxPayload = (uint8_t*)optval;
00813 
00814     Msg.Cmd.sd = (uint8_t)sd;
00815     Msg.Cmd.level = (uint8_t)level;
00816     Msg.Cmd.optionLen = (uint8_t)(*optlen);
00817     Msg.Cmd.optionName = (uint8_t)optname;
00818 
00819     VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlGetSockOptCmdCtrl, &Msg, &CmdExt));
00820 
00821     if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) {
00822         *optlen = Msg.Rsp.optionLen;
00823         return SL_ESMALLBUF;
00824     } else {
00825         *optlen = (uint8_t)CmdExt.ActualRxPayloadLen;
00826     }
00827     return (int16_t)Msg.Rsp.status;
00828 }
00829 #endif
00830 
00831 /*******************************************************************************/
00832 /*  sl_Select */
00833 /* ******************************************************************************/
00834 typedef union {
00835     _SelectCommand_t   Cmd;
00836     _BasicResponse_t   Rsp;
00837 } _SlSelectMsg_u;
00838 
00839 #ifndef SL_TINY_EXT
00840 #if _SL_INCLUDE_FUNC(sl_Select)
00841 const _SlCmdCtrl_t _SlSelectCmdCtrl = {
00842     SL_OPCODE_SOCKET_SELECT,
00843     sizeof(_SelectCommand_t),
00844     sizeof(_BasicResponse_t)
00845 };
00846 
00847 int16_t cc3100_socket::sl_Select(int16_t nfds, SlFdSet_t *readsds, SlFdSet_t *writesds, SlFdSet_t *exceptsds, SlTimeval_t *timeout)
00848 {
00849     _SlSelectMsg_u          Msg;
00850     _SelectAsyncResponse_t  AsyncRsp;
00851     uint8_t ObjIdx = MAX_CONCURRENT_ACTIONS;
00852 
00853     Msg.Cmd.nfds          = (uint8_t)nfds;
00854     Msg.Cmd.readFdsCount  = 0;
00855     Msg.Cmd.writeFdsCount = 0;
00856 
00857     Msg.Cmd.readFds = 0;
00858     Msg.Cmd.writeFds = 0;
00859 
00860     if( readsds ) {
00861         Msg.Cmd.readFds       = (uint16_t)readsds->fd_array[0];
00862     }
00863     if( writesds ) {
00864         Msg.Cmd.writeFds      = (uint16_t)writesds->fd_array[0];
00865     }
00866     if( NULL == timeout ) {
00867         Msg.Cmd.tv_sec = 0xffff;
00868         Msg.Cmd.tv_usec = 0xffff;
00869     } else {
00870         if( 0xffff <= timeout->tv_sec ) {
00871             Msg.Cmd.tv_sec = 0xffff;
00872         } else {
00873             Msg.Cmd.tv_sec = (uint16_t)timeout->tv_sec;
00874         }
00875         timeout->tv_usec = timeout->tv_usec >> 10;  /*  convert to milliseconds */
00876         if( 0xffff <= timeout->tv_usec ) {
00877             Msg.Cmd.tv_usec = 0xffff;
00878         } else {
00879             Msg.Cmd.tv_usec = (uint16_t)timeout->tv_usec;
00880         }
00881     }
00882 
00883     /* Use Obj to issue the command, if not available try later */
00884     ObjIdx = _driver._SlDrvProtectAsyncRespSetting((uint8_t*)&AsyncRsp, SELECT_ID, SL_MAX_SOCKETS);
00885 
00886     if (MAX_CONCURRENT_ACTIONS == ObjIdx)
00887     {
00888         return SL_POOL_IS_EMPTY;
00889     }
00890     
00891     /* send the command */
00892     VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSelectCmdCtrl, &Msg, NULL));
00893 
00894     if(SL_OS_RET_CODE_OK == (int16_t)Msg.Rsp.status) {
00895         _driver._SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj);
00896         Msg.Rsp.status = AsyncRsp.status;
00897 
00898         if(  ((int16_t)Msg.Rsp.status) >= 0 ) {
00899             if( readsds ) {
00900                 readsds->fd_array[0]  = AsyncRsp.readFds;
00901             }
00902             if( writesds ) {
00903                 writesds->fd_array[0] = AsyncRsp.writeFds;
00904             }
00905         }
00906     }
00907 
00908     _driver._SlDrvReleasePoolObj(ObjIdx);
00909     return (int16_t)Msg.Rsp.status;
00910 }
00911 
00912 /*  Select helper functions */
00913 /*******************************************************************************/
00914 /*  SL_FD_SET */
00915 /* ******************************************************************************/
00916 void cc3100_socket::SL_FD_SET(int16_t fd, SlFdSet_t *fdset)
00917 {
00918     fdset->fd_array[0] |=  (1<< (fd & BSD_SOCKET_ID_MASK));
00919 }
00920 /*******************************************************************************/
00921 /*  SL_FD_CLR */
00922 /*******************************************************************************/
00923 void cc3100_socket::SL_FD_CLR(int16_t fd, SlFdSet_t *fdset)
00924 {
00925     fdset->fd_array[0] &=  ~(1<< (fd & BSD_SOCKET_ID_MASK));
00926 }
00927 /*******************************************************************************/
00928 /*  SL_FD_ISSET */
00929 /*******************************************************************************/
00930 int16_t  cc3100_socket::SL_FD_ISSET(int16_t fd, SlFdSet_t *fdset)
00931 {
00932     if( fdset->fd_array[0] & (1<< (fd & BSD_SOCKET_ID_MASK)) ) {
00933         return 1;
00934     }
00935     return 0;
00936 }
00937 /*******************************************************************************/
00938 /*  SL_FD_ZERO */
00939 /*******************************************************************************/
00940 void cc3100_socket::SL_FD_ZERO(SlFdSet_t *fdset)
00941 {
00942     fdset->fd_array[0] = 0;
00943 }
00944 
00945 #endif
00946 #endif
00947 
00948 }//namespace mbed_cc3100
00949 
00950 
00951