TI's CC3100 websocket camera demo with Arducam mini ov5642 and freertos. Should work with other M3's. Work in progress test demo.

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