Simple LED control project using CC3100 as Access Point and socket

Dependencies:   mbed

Fork of cc3100_Test_Demo by David Fletcher

Revision:
0:e89ba455dbcf
diff -r 000000000000 -r e89ba455dbcf simplelink/cc3100_socket.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simplelink/cc3100_socket.cpp	Tue Feb 10 12:09:29 2015 +0000
@@ -0,0 +1,965 @@
+/*
+ * socket.c - CC31xx/CC32xx Host Driver Implementation
+ *
+ * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *    Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *    Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *    Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+*/
+
+
+
+
+/*****************************************************************************/
+/* Include files                                                             */
+/*****************************************************************************/
+#include "cc3100_simplelink.h"
+#include "cc3100_protocol.h"
+#include "cc3100_driver.h"
+
+#include "cc3100_socket.h"
+
+namespace mbed_cc3100 {
+
+
+cc3100_socket::cc3100_socket(cc3100_driver &driver, cc3100_nonos &nonos)
+    : _driver(driver), _nonos(nonos)
+{
+
+}
+
+cc3100_socket::~cc3100_socket()
+{
+
+}
+
+/*******************************************************************************/
+/* Functions                                                                   */
+/*******************************************************************************/
+
+/* ******************************************************************************/
+/*  _sl_BuildAddress */
+/* ******************************************************************************/
+void cc3100_socket::_sl_BuildAddress(const SlSockAddr_t *addr, int16_t addrlen, _SocketAddrCommand_u *pCmd)
+{
+    /*  Note: parsing of family and port in the generic way for all IPV4, IPV6 and EUI48 */
+    /*  is possible as int32_t as these parameters are in the same offset and size for these */
+    /*  three families. */
+    pCmd->IpV4.FamilyAndFlags = (addr->sa_family << 4) & 0xF0;
+    pCmd->IpV4.port = ((SlSockAddrIn_t *)addr)->sin_port;
+
+    if(SL_AF_INET == addr->sa_family) {
+        pCmd->IpV4.address  = ((SlSockAddrIn_t *)addr)->sin_addr.s_addr;
+    } else if (SL_AF_INET6_EUI_48 == addr->sa_family ) {
+        memcpy( pCmd->IpV6EUI48.address,((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u8, 6);
+    }
+#ifdef SL_SUPPORT_IPV6
+    else {
+        memcpy(pCmd->IpV6.address, ((sockaddr_in6 *)addr)->sin6_addr._S6_un._S6_u32, 16 );
+    }
+#endif
+}
+
+/* ******************************************************************************/
+/*  _sl_TruncatePayloadByProtocol */
+/* ******************************************************************************/
+uint16_t cc3100_socket::_sl_TruncatePayloadByProtocol(const int16_t sd,const uint16_t length)
+{
+    uint16_t maxLength;
+
+    switch(sd & SL_SOCKET_PAYLOAD_TYPE_MASK) {
+        case SL_SOCKET_PAYLOAD_TYPE_UDP_IPV4:
+            maxLength = 1472;
+            break;
+
+        case SL_SOCKET_PAYLOAD_TYPE_TCP_IPV4:
+            maxLength = 1460;
+            break;
+
+        case SL_SOCKET_PAYLOAD_TYPE_UDP_IPV6:
+            maxLength = 1452;
+            break;
+
+        case SL_SOCKET_PAYLOAD_TYPE_TCP_IPV6:
+            maxLength = 1440;
+            break;
+        case SL_SOCKET_PAYLOAD_TYPE_TCP_IPV4_SECURE:
+        case SL_SOCKET_PAYLOAD_TYPE_UDP_IPV4_SECURE:
+            maxLength = 1402;
+            break;
+        case SL_SOCKET_PAYLOAD_TYPE_UDP_IPV6_SECURE:
+        case SL_SOCKET_PAYLOAD_TYPE_TCP_IPV6_SECURE:
+            maxLength = 1396;
+            break;
+        case SL_SOCKET_PAYLOAD_TYPE_RAW_TRANCEIVER:
+            maxLength = 1476;
+            break;
+        case SL_SOCKET_PAYLOAD_TYPE_RAW_PACKET:
+            maxLength = 1514;
+            break;
+        case SL_SOCKET_PAYLOAD_TYPE_RAW_IP4:
+            maxLength = 1480;
+            break;
+        default:
+            maxLength = 1440;
+            break;
+    }
+
+    if( length > maxLength ) {
+        return maxLength;
+    } else {
+        return length;
+    }
+}
+
+/*******************************************************************************/
+/*  _sl_ParseAddress */
+/*******************************************************************************/
+void cc3100_socket::_sl_ParseAddress(_SocketAddrResponse_u    *pRsp, SlSockAddr_t *addr, SlSocklen_t *addrlen)
+{
+    /*  Note: parsing of family and port in the generic way for all IPV4, IPV6 and EUI48 */
+    /*  is possible as long as these parameters are in the same offset and size for these */
+    /*  three families. */
+    addr->sa_family                 = pRsp->IpV4.family;
+    ((SlSockAddrIn_t *)addr)->sin_port = pRsp->IpV4.port;
+
+    *addrlen = (SL_AF_INET == addr->sa_family) ? sizeof(SlSockAddrIn_t) : sizeof(SlSockAddrIn6_t);
+
+    if(SL_AF_INET == addr->sa_family) {
+        ((SlSockAddrIn_t *)addr)->sin_addr.s_addr  = pRsp->IpV4.address;
+    } else if (SL_AF_INET6_EUI_48 == addr->sa_family ) {
+        memcpy(((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u8, pRsp->IpV6EUI48.address, 6);
+    }
+#ifdef SL_SUPPORT_IPV6
+    else {
+        memcpy(((sockaddr_in6 *)addr)->sin6_addr._S6_un._S6_u32, pRsp->IpV6.address, 16);
+    }
+#endif
+}
+
+/*******************************************************************************/
+/* sl_Socket */
+/*******************************************************************************/
+typedef union {
+    uint32_t                Dummy;
+    _SocketCommand_t 	Cmd;
+    _SocketResponse_t	Rsp;
+} _SlSockSocketMsg_u;
+
+const _SlCmdCtrl_t _SlSockSocketCmdCtrl = {
+    SL_OPCODE_SOCKET_SOCKET,
+    sizeof(_SocketCommand_t),
+    sizeof(_SocketResponse_t)
+};
+
+#if _SL_INCLUDE_FUNC(sl_Socket)
+int16_t cc3100_socket::sl_Socket(int16_t Domain, int16_t Type, int16_t Protocol)
+{
+    _SlSockSocketMsg_u  Msg;
+
+    Msg.Cmd.Domain	    = (uint8_t)Domain;
+    Msg.Cmd.Type     	= (uint8_t)Type;
+    Msg.Cmd.Protocol 	= (uint8_t)Protocol;
+
+    VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSockSocketCmdCtrl, &Msg, NULL));
+
+    if( Msg.Rsp.statusOrLen < 0 ) {
+        return( Msg.Rsp.statusOrLen );
+    } else {
+        return (int16_t)((uint8_t)Msg.Rsp.sd);
+    }
+}
+#endif
+
+/*******************************************************************************/
+/*  sl_Close  */
+/*******************************************************************************/
+typedef union {
+    _CloseCommand_t	    Cmd;
+    _SocketResponse_t	Rsp;
+} _SlSockCloseMsg_u;
+
+const _SlCmdCtrl_t _SlSockCloseCmdCtrl = {
+    SL_OPCODE_SOCKET_CLOSE,
+    sizeof(_CloseCommand_t),
+    sizeof(_SocketResponse_t)
+};
+
+#if _SL_INCLUDE_FUNC(sl_Close)
+int16_t cc3100_socket::sl_Close(int16_t sd)
+{
+    _SlSockCloseMsg_u   Msg;
+
+    Msg.Cmd.sd = (uint8_t)sd;
+
+    VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSockCloseCmdCtrl, &Msg, NULL));
+
+    return Msg.Rsp.statusOrLen;
+}
+#endif
+
+/*******************************************************************************/
+/*  sl_Bind */
+/*******************************************************************************/
+typedef union {
+    _SocketAddrCommand_u    Cmd;
+    _SocketResponse_t	    Rsp;
+} _SlSockBindMsg_u;
+
+#if _SL_INCLUDE_FUNC(sl_Bind)
+int16_t cc3100_socket::sl_Bind(int16_t sd, const SlSockAddr_t *addr, int16_t addrlen)
+{
+    _SlSockBindMsg_u    Msg;
+    _SlCmdCtrl_t         CmdCtrl = {0, 0, sizeof(_SocketResponse_t)};
+
+    switch(addr->sa_family) {
+        case SL_AF_INET :
+            CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND;
+            CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv4Command_t);
+            break;
+        case SL_AF_INET6_EUI_48:
+            CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND_V6;
+            CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6EUI48Command_t);
+            break;
+#ifdef SL_SUPPORT_IPV6
+        case AF_INET6:
+            CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND_V6;
+            CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6Command_t);
+            break;
+#endif
+        case SL_AF_RF   :
+        default:
+            return SL_RET_CODE_INVALID_INPUT;
+    }
+
+    Msg.Cmd.IpV4.lenOrPadding = 0;
+    Msg.Cmd.IpV4.sd = (uint8_t)sd;
+
+    _sl_BuildAddress(addr, addrlen, &Msg.Cmd);
+
+    VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL));
+
+    return Msg.Rsp.statusOrLen;
+}
+#endif
+
+/*******************************************************************************/
+/*  sl_Sendto */
+/*******************************************************************************/
+typedef union {
+    _SocketAddrCommand_u    Cmd;
+    /*  no response for 'sendto' commands*/
+} _SlSendtoMsg_u;
+
+#if _SL_INCLUDE_FUNC(sl_SendTo)
+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)
+{
+    _SlSendtoMsg_u   Msg;
+    _SlCmdCtrl_t     CmdCtrl = {0, 0, 0};
+    _SlCmdExt_t      CmdExt;
+    uint16_t         ChunkLen;
+    int16_t          RetVal;
+
+    CmdExt.TxPayloadLen = (uint16_t)Len;
+    CmdExt.RxPayloadLen = 0;
+    CmdExt.pTxPayload = (unsigned char *)pBuf;
+    CmdExt.pRxPayload = NULL;
+
+
+    switch(to->sa_family) {
+        case SL_AF_INET:
+            CmdCtrl.Opcode = SL_OPCODE_SOCKET_SENDTO;
+            CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv4Command_t);
+            break;
+        case SL_AF_INET6_EUI_48:
+            CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND_V6;
+            CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6EUI48Command_t);
+            break;
+#ifdef SL_SUPPORT_IPV6
+        case AF_INET6:
+            CmdCtrl.Opcode = SL_OPCODE_SOCKET_SENDTO_V6;
+            CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6Command_t);
+            break;
+#endif
+        case SL_AF_RF:
+        default:
+            return SL_RET_CODE_INVALID_INPUT;
+    }
+
+    ChunkLen = _sl_TruncatePayloadByProtocol(sd,Len);
+    Msg.Cmd.IpV4.lenOrPadding = ChunkLen;
+    CmdExt.TxPayloadLen = ChunkLen;
+
+    Msg.Cmd.IpV4.sd = (unsigned char)sd;
+
+    _sl_BuildAddress(to, tolen, &Msg.Cmd);
+    
+    Msg.Cmd.IpV4.FamilyAndFlags |= flags & 0x0F;
+    
+    do {
+        RetVal = _driver._SlDrvDataWriteOp((_SlSd_t)sd, &CmdCtrl, &Msg, &CmdExt);
+        
+        if(SL_OS_RET_CODE_OK == RetVal) {
+            CmdExt.pTxPayload += ChunkLen;
+            ChunkLen = (uint16_t)((unsigned char *)pBuf + Len - CmdExt.pTxPayload);
+            ChunkLen = _sl_TruncatePayloadByProtocol(sd,ChunkLen);
+            CmdExt.TxPayloadLen = ChunkLen;
+            Msg.Cmd.IpV4.lenOrPadding = ChunkLen;
+        } else {
+            return RetVal;
+        }
+    } while(ChunkLen > 0);
+
+    return (int16_t)Len;
+}
+#endif
+
+/*******************************************************************************/
+/*  sl_Recvfrom */
+/*******************************************************************************/
+typedef union {
+    _sendRecvCommand_t	    Cmd;
+    _SocketAddrResponse_u	Rsp;
+} _SlRecvfromMsg_u;
+
+const _SlCmdCtrl_t _SlRecvfomCmdCtrl = {
+    SL_OPCODE_SOCKET_RECVFROM,
+    sizeof(_sendRecvCommand_t),
+    sizeof(_SocketAddrResponse_u)
+};
+
+#if _SL_INCLUDE_FUNC(sl_RecvFrom)
+int16_t cc3100_socket::sl_RecvFrom(int16_t sd, void *buf, int16_t Len, int16_t flags, SlSockAddr_t *from, SlSocklen_t *fromlen)
+{
+    _SlRecvfromMsg_u    Msg;
+    _SlCmdExt_t         CmdExt;
+    int16_t                 RetVal;
+
+    CmdExt.TxPayloadLen = 0;
+    CmdExt.RxPayloadLen = Len;
+    CmdExt.pTxPayload = NULL;
+    CmdExt.pRxPayload = (uint8_t *)buf;
+
+
+    Msg.Cmd.sd = (uint8_t)sd;
+    Msg.Cmd.StatusOrLen = Len;
+    /*  no size truncation in recv path */
+    CmdExt.RxPayloadLen = Msg.Cmd.StatusOrLen;
+
+    if(sizeof(SlSockAddrIn_t) == *fromlen) {
+        Msg.Cmd.FamilyAndFlags = SL_AF_INET;
+    } else if (sizeof(SlSockAddrIn6_t) == *fromlen) {
+        Msg.Cmd.FamilyAndFlags = SL_AF_INET6;
+    } else {
+        return SL_RET_CODE_INVALID_INPUT;
+    }
+
+    Msg.Cmd.FamilyAndFlags = (Msg.Cmd.FamilyAndFlags << 4) & 0xF0;
+    Msg.Cmd.FamilyAndFlags |= flags & 0x0F;
+
+    RetVal = _driver._SlDrvDataReadOp((_SlSd_t)sd, (_SlCmdCtrl_t *)&_SlRecvfomCmdCtrl, &Msg, &CmdExt);
+    if( RetVal != SL_OS_RET_CODE_OK ) {
+        return RetVal;
+    }
+
+    RetVal = Msg.Rsp.IpV4.statusOrLen;
+
+    if(RetVal >= 0) {
+        VERIFY_PROTOCOL(sd == Msg.Rsp.IpV4.sd);
+#if 0
+        _sl_ParseAddress(&Msg.Rsp, from, fromlen);
+#else
+        from->sa_family = Msg.Rsp.IpV4.family;
+        if(SL_AF_INET == from->sa_family) {
+            ((SlSockAddrIn_t *)from)->sin_port = Msg.Rsp.IpV4.port;
+            ((SlSockAddrIn_t *)from)->sin_addr.s_addr = Msg.Rsp.IpV4.address;
+            *fromlen = sizeof(SlSockAddrIn_t);
+        } else if (SL_AF_INET6_EUI_48 == from->sa_family ) {
+            ((SlSockAddrIn6_t *)from)->sin6_port  = Msg.Rsp.IpV6EUI48.port;
+            memcpy(((SlSockAddrIn6_t *)from)->sin6_addr._S6_un._S6_u8, Msg.Rsp.IpV6EUI48.address, 6);
+        }
+#ifdef SL_SUPPORT_IPV6
+        else if(AF_INET6 == from->sa_family) {
+            VERIFY_PROTOCOL(*fromlen >= sizeof(sockaddr_in6));
+
+            ((sockaddr_in6 *)from)->sin6_port = Msg.Rsp.IpV6.port;
+            memcpy(((sockaddr_in6 *)from)->sin6_addr._S6_un._S6_u32, Msg.Rsp.IpV6.address, 16);
+            *fromlen = sizeof(sockaddr_in6);
+        }
+#endif
+#endif
+    }
+
+    return (int16_t)RetVal;
+}
+#endif
+
+/*******************************************************************************/
+/*  sl_Connect */
+/*******************************************************************************/
+typedef union {
+    _SocketAddrCommand_u    Cmd;
+    _SocketResponse_t	    Rsp;
+} _SlSockConnectMsg_u;
+
+#if _SL_INCLUDE_FUNC(sl_Connect)
+int16_t cc3100_socket::sl_Connect(int16_t sd, const SlSockAddr_t *addr, int16_t addrlen)
+{
+    _SlSockConnectMsg_u  Msg;
+    _SlReturnVal_t       RetVal;
+    _SlCmdCtrl_t         CmdCtrl = {0, 0, sizeof(_SocketResponse_t)};
+    _SocketResponse_t    AsyncRsp;
+    uint8_t ObjIdx = MAX_CONCURRENT_ACTIONS;
+
+
+    switch(addr->sa_family) {
+        case SL_AF_INET :
+            CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT;
+            CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv4Command_t);
+            break;
+        case  SL_AF_INET6_EUI_48:
+            CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT_V6;
+            CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6EUI48Command_t);
+            break;
+#ifdef SL_SUPPORT_IPV6
+        case AF_INET6:
+            CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT_V6;
+            CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6Command_t);
+            break;
+#endif
+        case SL_AF_RF   :
+        default:
+            return SL_RET_CODE_INVALID_INPUT;
+    }
+
+    Msg.Cmd.IpV4.lenOrPadding = 0;
+    Msg.Cmd.IpV4.sd = (uint8_t)sd;
+
+    _sl_BuildAddress(addr, addrlen, &Msg.Cmd);
+
+    /* Use Obj to issue the command, if not available try later */
+    ObjIdx = (uint8_t)_driver._SlDrvWaitForPoolObj(CONNECT_ID, (uint8_t)(sd  & BSD_SOCKET_ID_MASK));
+
+    if (MAX_CONCURRENT_ACTIONS == ObjIdx) {
+        return SL_POOL_IS_EMPTY;
+    }
+    OSI_RET_OK_CHECK(_nonos.sl_LockObjLock(&g_pCB->ProtectionLockObj, NON_OS_LOCK_OBJ_UNLOCK_VALUE, NON_OS_LOCK_OBJ_LOCK_VALUE, SL_OS_WAIT_FOREVER));
+
+    g_pCB->ObjPool[ObjIdx].pRespArgs =  (uint8_t *)&AsyncRsp;
+
+    OSI_RET_OK_CHECK(_nonos.sl_LockObjUnlock(&g_pCB->ProtectionLockObj, NON_OS_LOCK_OBJ_UNLOCK_VALUE));
+
+    /* send the command */
+    VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL));
+    VERIFY_PROTOCOL(Msg.Rsp.sd == sd)
+
+    RetVal = Msg.Rsp.statusOrLen;
+
+    if(SL_RET_CODE_OK == RetVal) {
+        /*  wait for async and get Data Read parameters */
+        OSI_RET_OK_CHECK(_nonos.sl_SyncObjWait(&g_pCB->ObjPool[ObjIdx].SyncObj, NON_OS_SYNC_OBJ_SIGNAL_VALUE, NON_OS_SYNC_OBJ_CLEAR_VALUE, SL_OS_WAIT_FOREVER));
+
+        VERIFY_PROTOCOL(AsyncRsp.sd == sd);
+
+        RetVal = AsyncRsp.statusOrLen;
+    }
+    _driver._SlDrvReleasePoolObj(ObjIdx);
+    return RetVal;
+}
+#endif
+
+/*******************************************************************************/
+/*  sl_Send */
+/*******************************************************************************/
+typedef union {
+    _sendRecvCommand_t    Cmd;
+    /*  no response for 'sendto' commands*/
+} _SlSendMsg_u;
+
+const _SlCmdCtrl_t _SlSendCmdCtrl = {
+    SL_OPCODE_SOCKET_SEND,
+    sizeof(_sendRecvCommand_t),
+    0
+};
+
+#if _SL_INCLUDE_FUNC(sl_Send)
+int16_t cc3100_socket::sl_Send(int16_t sd, const void *pBuf, int16_t Len, int16_t flags)
+{
+    _SlSendMsg_u   Msg;
+    _SlCmdExt_t    CmdExt;
+    uint16_t         ChunkLen;
+    int16_t            RetVal;
+    uint32_t         tempVal;
+    uint8_t  runSingleChunk = FALSE;
+
+    CmdExt.TxPayloadLen = Len;
+    CmdExt.RxPayloadLen = 0;
+    CmdExt.pTxPayload = (uint8_t *)pBuf;
+
+    /* Only for RAW transceiver type socket, relay the flags parameter in the 2 bytes (4 byte aligned) before the actual payload */
+    if ((sd & SL_SOCKET_PAYLOAD_TYPE_MASK) == SL_SOCKET_PAYLOAD_TYPE_RAW_TRANCEIVER) {
+        tempVal = flags;
+        CmdExt.pRxPayload = (uint8_t *)&tempVal;
+        CmdExt.RxPayloadLen = 4;
+        g_pCB->RelayFlagsViaRxPayload = TRUE;
+        runSingleChunk = TRUE;
+    } else {
+        CmdExt.pRxPayload = NULL;
+    }
+
+    ChunkLen = _sl_TruncatePayloadByProtocol(sd,Len);
+    CmdExt.TxPayloadLen = ChunkLen;
+
+    Msg.Cmd.StatusOrLen = ChunkLen;
+    Msg.Cmd.sd = (uint8_t)sd;
+    Msg.Cmd.FamilyAndFlags |= flags & 0x0F;
+
+    do {
+        RetVal = _driver._SlDrvDataWriteOp((uint8_t)sd, (_SlCmdCtrl_t *)&_SlSendCmdCtrl, &Msg, &CmdExt);
+        if(SL_OS_RET_CODE_OK == RetVal) {
+            CmdExt.pTxPayload += ChunkLen;
+            ChunkLen = (uint8_t *)pBuf + Len - CmdExt.pTxPayload;
+            ChunkLen = _sl_TruncatePayloadByProtocol(sd,ChunkLen);
+            CmdExt.TxPayloadLen = ChunkLen;
+            Msg.Cmd.StatusOrLen = ChunkLen;
+        } else {
+            return RetVal;
+        }
+    } while((ChunkLen > 0) && (runSingleChunk==FALSE));
+
+    return (int16_t)Len;
+}
+#endif
+
+/*******************************************************************************/
+/*  sl_Listen */
+/*******************************************************************************/
+typedef union {
+    _ListenCommand_t    Cmd;
+    _BasicResponse_t    Rsp;
+} _SlListenMsg_u;
+
+const _SlCmdCtrl_t _SlListenCmdCtrl = {
+    SL_OPCODE_SOCKET_LISTEN,
+    sizeof(_ListenCommand_t),
+    sizeof(_BasicResponse_t),
+};
+
+#if _SL_INCLUDE_FUNC(sl_Listen)
+int16_t cc3100_socket::sl_Listen(int16_t sd, int16_t backlog)
+{
+    _SlListenMsg_u  Msg;
+
+    Msg.Cmd.sd = (uint8_t)sd;
+    Msg.Cmd.backlog = (uint8_t)backlog;
+
+    VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlListenCmdCtrl, &Msg, NULL));
+
+    return (int16_t)Msg.Rsp.status;
+}
+#endif
+
+/*******************************************************************************/
+/*  sl_Accept */
+/*******************************************************************************/
+typedef union {
+    _AcceptCommand_t    Cmd;
+    _SocketResponse_t   Rsp;
+} _SlSockAcceptMsg_u;
+
+const _SlCmdCtrl_t _SlAcceptCmdCtrl = {
+    SL_OPCODE_SOCKET_ACCEPT,
+    sizeof(_AcceptCommand_t),
+    sizeof(_BasicResponse_t),
+};
+
+#if _SL_INCLUDE_FUNC(sl_Accept)
+int16_t cc3100_socket::sl_Accept(int16_t sd, SlSockAddr_t *addr, SlSocklen_t *addrlen)
+{
+    _SlSockAcceptMsg_u      Msg;
+    _SlReturnVal_t          RetVal;
+    _SocketAddrResponse_u   AsyncRsp;
+
+    uint8_t ObjIdx = MAX_CONCURRENT_ACTIONS;
+
+
+    Msg.Cmd.sd = (uint8_t)sd;
+    Msg.Cmd.family = (sizeof(SlSockAddrIn_t) == *addrlen) ? SL_AF_INET : SL_AF_INET6;
+
+    /* Use Obj to issue the command, if not available try later */
+    ObjIdx = (uint8_t)_driver._SlDrvWaitForPoolObj(ACCEPT_ID, (uint8_t)(sd  & BSD_SOCKET_ID_MASK));
+
+    if (MAX_CONCURRENT_ACTIONS == ObjIdx) {
+        return SL_POOL_IS_EMPTY;
+    }
+
+    OSI_RET_OK_CHECK(_nonos.sl_LockObjLock(&g_pCB->ProtectionLockObj, NON_OS_LOCK_OBJ_UNLOCK_VALUE, NON_OS_LOCK_OBJ_LOCK_VALUE, SL_OS_WAIT_FOREVER));
+
+    g_pCB->ObjPool[ObjIdx].pRespArgs = (uint8_t *)&AsyncRsp;
+
+    OSI_RET_OK_CHECK(_nonos.sl_LockObjUnlock(&g_pCB->ProtectionLockObj, NON_OS_LOCK_OBJ_UNLOCK_VALUE));
+    /* send the command */
+    VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlAcceptCmdCtrl, &Msg, NULL));
+    VERIFY_PROTOCOL(Msg.Rsp.sd == sd);
+
+    RetVal = Msg.Rsp.statusOrLen;
+
+    if(SL_OS_RET_CODE_OK == RetVal) {
+        /*  wait for async and get Data Read parameters */
+        OSI_RET_OK_CHECK(_nonos.sl_SyncObjWait(&g_pCB->ObjPool[ObjIdx].SyncObj, NON_OS_SYNC_OBJ_SIGNAL_VALUE, NON_OS_SYNC_OBJ_CLEAR_VALUE, SL_OS_WAIT_FOREVER));
+
+        VERIFY_PROTOCOL(AsyncRsp.IpV4.sd == sd);
+
+        RetVal = AsyncRsp.IpV4.statusOrLen;
+        if( (NULL != addr) && (NULL != addrlen) ) {
+#if 0 /*  Kept for backup */
+            _sl_ParseAddress(&AsyncRsp, addr, addrlen);
+#else
+            addr->sa_family = AsyncRsp.IpV4.family;
+
+            if(SL_AF_INET == addr->sa_family) {
+                if( *addrlen == sizeof( SlSockAddrIn_t ) ) {
+                    ((SlSockAddrIn_t *)addr)->sin_port         = AsyncRsp.IpV4.port;
+                    ((SlSockAddrIn_t *)addr)->sin_addr.s_addr  = AsyncRsp.IpV4.address;
+                } else {
+                    *addrlen = 0;
+                }
+            } else if (SL_AF_INET6_EUI_48 == addr->sa_family ) {
+                if( *addrlen == sizeof( SlSockAddrIn6_t ) ) {
+                    ((SlSockAddrIn6_t *)addr)->sin6_port                   = AsyncRsp.IpV6EUI48.port    ;
+                    /*  will be called from here and from _sl_BuildAddress*/
+                    memcpy(((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u8, AsyncRsp.IpV6EUI48.address, 6);
+                } else {
+                    *addrlen = 0;
+                }
+            }
+#ifdef SL_SUPPORT_IPV6
+            else {
+                if( *addrlen == sizeof( sockaddr_in6 ) ) {
+                    ((sockaddr_in6 *)addr)->sin6_port                   = AsyncRsp.IpV6.port    ;
+                    memcpy(((sockaddr_in6 *)addr)->sin6_addr._S6_un._S6_u32, AsyncRsp.IpV6.address, 16);
+                } else {
+                    *addrlen = 0;
+                }
+            }
+#endif
+#endif
+        }
+    }
+
+    _driver._SlDrvReleasePoolObj(ObjIdx);
+    return (int16_t)RetVal;
+}
+#endif
+
+
+/*******************************************************************************/
+/*  sl_Htonl */
+/*******************************************************************************/
+uint32_t cc3100_socket::sl_Htonl( uint32_t val )
+{
+    uint32_t i = 1;
+    int8_t *p = (int8_t *)&i;
+    if (p[0] == 1) { /* little endian */
+        p[0] = ((int8_t* )&val)[3];
+        p[1] = ((int8_t* )&val)[2];
+        p[2] = ((int8_t* )&val)[1];
+        p[3] = ((int8_t* )&val)[0];
+        return i;
+    } else { /* big endian */
+        return val;
+    }
+}
+
+/*******************************************************************************/
+/*  sl_Htonl */
+/*******************************************************************************/
+uint16_t cc3100_socket::sl_Htons( uint16_t val )
+{
+    int16_t i = 1;
+    int8_t *p = (int8_t *)&i;
+    if (p[0] == 1) { /* little endian */
+        p[0] = ((int8_t* )&val)[1];
+        p[1] = ((int8_t* )&val)[0];
+        return i;
+    } else { /* big endian */
+        return val;
+    }
+}
+
+/*******************************************************************************/
+/*  sl_Recv */
+/*******************************************************************************/
+typedef union {
+    _sendRecvCommand_t  Cmd;
+    _SocketResponse_t   Rsp;
+} _SlRecvMsg_u;
+
+const _SlCmdCtrl_t _SlRecvCmdCtrl = {
+    SL_OPCODE_SOCKET_RECV,
+    sizeof(_sendRecvCommand_t),
+    sizeof(_SocketResponse_t)
+};
+
+#if _SL_INCLUDE_FUNC(sl_Recv)
+int16_t cc3100_socket::sl_Recv(int16_t sd, void *pBuf, int16_t Len, int16_t flags)
+{
+    _SlRecvMsg_u    Msg;
+    _SlCmdExt_t     CmdExt;
+    _SlReturnVal_t status;
+
+    CmdExt.TxPayloadLen = 0;
+    CmdExt.RxPayloadLen = Len;
+    CmdExt.pTxPayload = NULL;
+    CmdExt.pRxPayload = (uint8_t *)pBuf;
+
+    Msg.Cmd.sd = (uint8_t)sd;
+    Msg.Cmd.StatusOrLen = Len;
+
+    /*  no size truncation in recv path */
+    CmdExt.RxPayloadLen = Msg.Cmd.StatusOrLen;
+
+    Msg.Cmd.FamilyAndFlags = flags & 0x0F;
+
+    status = _driver._SlDrvDataReadOp((_SlSd_t)sd, (_SlCmdCtrl_t *)&_SlRecvCmdCtrl, &Msg, &CmdExt);
+    if( status != SL_OS_RET_CODE_OK ) {
+        return status;
+    }
+
+    /*  if the Device side sends less than expected it is not the Driver's role */
+    /*  the returned value could be smaller than the requested size */
+    return (int16_t)Msg.Rsp.statusOrLen;
+}
+#endif
+
+/*******************************************************************************/
+/*  sl_SetSockOpt */
+/*******************************************************************************/
+typedef union {
+    _setSockOptCommand_t    Cmd;
+    _SocketResponse_t       Rsp;
+} _SlSetSockOptMsg_u;
+
+const _SlCmdCtrl_t _SlSetSockOptCmdCtrl = {
+    SL_OPCODE_SOCKET_SETSOCKOPT,
+    sizeof(_setSockOptCommand_t),
+    sizeof(_SocketResponse_t)
+};
+
+#if _SL_INCLUDE_FUNC(sl_SetSockOpt)
+int16_t cc3100_socket::sl_SetSockOpt(int16_t sd, int16_t level, int16_t optname, const void *optval, SlSocklen_t optlen)
+{
+    _SlSetSockOptMsg_u    Msg;
+    _SlCmdExt_t           CmdExt;
+
+    CmdExt.TxPayloadLen = optlen;
+    CmdExt.RxPayloadLen = 0;
+    CmdExt.pTxPayload = (uint8_t *)optval;
+    CmdExt.pRxPayload = NULL;
+
+    Msg.Cmd.sd = (uint8_t)sd;
+    Msg.Cmd.level = (uint8_t)level;
+    Msg.Cmd.optionLen = (uint8_t)optlen;
+    Msg.Cmd.optionName = (uint8_t)optname;
+
+    VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSetSockOptCmdCtrl, &Msg, &CmdExt));
+
+    return (int16_t)Msg.Rsp.statusOrLen;
+}
+#endif
+
+/*******************************************************************************/
+/*  sl_GetSockOpt */
+/*******************************************************************************/
+typedef union {
+    _getSockOptCommand_t    Cmd;
+    _getSockOptResponse_t   Rsp;
+} _SlGetSockOptMsg_u;
+
+const _SlCmdCtrl_t _SlGetSockOptCmdCtrl = {
+    SL_OPCODE_SOCKET_GETSOCKOPT,
+    sizeof(_getSockOptCommand_t),
+    sizeof(_getSockOptResponse_t)
+};
+
+#if _SL_INCLUDE_FUNC(sl_GetSockOpt)
+int16_t cc3100_socket::sl_GetSockOpt(int16_t sd, int16_t level, int16_t optname, void *optval, SlSocklen_t *optlen)
+{
+    _SlGetSockOptMsg_u    Msg;
+    _SlCmdExt_t           CmdExt;
+
+    if (*optlen == 0) {
+        return SL_EZEROLEN;
+    }
+    CmdExt.TxPayloadLen = 0;
+    CmdExt.RxPayloadLen = *optlen;
+    CmdExt.pTxPayload = NULL;
+    CmdExt.pRxPayload = (uint8_t*)optval;
+    CmdExt.ActualRxPayloadLen = 0;
+
+    Msg.Cmd.sd = (uint8_t)sd;
+    Msg.Cmd.level = (uint8_t)level;
+    Msg.Cmd.optionLen = (uint8_t)(*optlen);
+    Msg.Cmd.optionName = (uint8_t)optname;
+
+    VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlGetSockOptCmdCtrl, &Msg, &CmdExt));
+
+    if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) {
+        *optlen = Msg.Rsp.optionLen;
+        return SL_ESMALLBUF;
+    } else {
+        *optlen = (uint8_t)CmdExt.ActualRxPayloadLen;
+    }
+    return (int16_t)Msg.Rsp.status;
+}
+#endif
+
+/*******************************************************************************/
+/*  sl_Select */
+/* ******************************************************************************/
+typedef union {
+    _SelectCommand_t   Cmd;
+    _BasicResponse_t   Rsp;
+} _SlSelectMsg_u;
+
+const _SlCmdCtrl_t _SlSelectCmdCtrl = {
+    SL_OPCODE_SOCKET_SELECT,
+    sizeof(_SelectCommand_t),
+    sizeof(_BasicResponse_t)
+};
+
+#if _SL_INCLUDE_FUNC(sl_Select)
+int16_t cc3100_socket::sl_Select(int16_t nfds, SlFdSet_t *readsds, SlFdSet_t *writesds, SlFdSet_t *exceptsds, SlTimeval_t *timeout)
+{
+    _SlSelectMsg_u          Msg;
+    _SelectAsyncResponse_t  AsyncRsp;
+    uint8_t ObjIdx = MAX_CONCURRENT_ACTIONS;
+
+    Msg.Cmd.nfds          = (uint8_t)nfds;
+    Msg.Cmd.readFdsCount  = 0;
+    Msg.Cmd.writeFdsCount = 0;
+
+    Msg.Cmd.readFds = 0;
+    Msg.Cmd.writeFds = 0;
+
+    if( readsds ) {
+        Msg.Cmd.readFds       = (uint16_t)readsds->fd_array[0];
+    }
+    if( writesds ) {
+        Msg.Cmd.writeFds      = (uint16_t)writesds->fd_array[0];
+    }
+    if( NULL == timeout ) {
+        Msg.Cmd.tv_sec = 0xffff;
+        Msg.Cmd.tv_usec = 0xffff;
+    } else {
+        if( 0xffff <= timeout->tv_sec ) {
+            Msg.Cmd.tv_sec = 0xffff;
+        } else {
+            Msg.Cmd.tv_sec = (uint16_t)timeout->tv_sec;
+        }
+        timeout->tv_usec = timeout->tv_usec >> 10;  /*  convert to milliseconds */
+        if( 0xffff <= timeout->tv_usec ) {
+            Msg.Cmd.tv_usec = 0xffff;
+        } else {
+            Msg.Cmd.tv_usec = (uint16_t)timeout->tv_usec;
+        }
+    }
+
+    /* Use Obj to issue the command, if not available try later */
+    ObjIdx = (uint8_t)_driver._SlDrvWaitForPoolObj(SELECT_ID, SL_MAX_SOCKETS);
+
+    if (MAX_CONCURRENT_ACTIONS == ObjIdx) {
+        return SL_POOL_IS_EMPTY;
+    }
+    OSI_RET_OK_CHECK(_nonos.sl_LockObjLock(&g_pCB->ProtectionLockObj, NON_OS_LOCK_OBJ_UNLOCK_VALUE, NON_OS_LOCK_OBJ_LOCK_VALUE, SL_OS_WAIT_FOREVER));
+
+    g_pCB->ObjPool[ObjIdx].pRespArgs =  (uint8_t *)&AsyncRsp;
+
+    OSI_RET_OK_CHECK(_nonos.sl_LockObjUnlock(&g_pCB->ProtectionLockObj, NON_OS_LOCK_OBJ_UNLOCK_VALUE));
+    /* send the command */
+    VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSelectCmdCtrl, &Msg, NULL));
+
+    if(SL_OS_RET_CODE_OK == (int16_t)Msg.Rsp.status) {
+        OSI_RET_OK_CHECK(_nonos.sl_SyncObjWait(&g_pCB->ObjPool[ObjIdx].SyncObj, NON_OS_SYNC_OBJ_SIGNAL_VALUE, NON_OS_SYNC_OBJ_CLEAR_VALUE, SL_OS_WAIT_FOREVER));
+        Msg.Rsp.status = AsyncRsp.status;
+
+        if(  ((int16_t)Msg.Rsp.status) >= 0 ) {
+            if( readsds ) {
+                readsds->fd_array[0]  = AsyncRsp.readFds;
+            }
+            if( writesds ) {
+                writesds->fd_array[0] = AsyncRsp.writeFds;
+            }
+        }
+    }
+
+    _driver._SlDrvReleasePoolObj(ObjIdx);
+    return (int16_t)Msg.Rsp.status;
+}
+
+/*  Select helper functions */
+/*******************************************************************************/
+/*  SL_FD_SET */
+/* ******************************************************************************/
+void cc3100_socket::SL_FD_SET(int16_t fd, SlFdSet_t *fdset)
+{
+    fdset->fd_array[0] |=  (1<< (fd & BSD_SOCKET_ID_MASK));
+}
+/*******************************************************************************/
+/*  SL_FD_CLR */
+/*******************************************************************************/
+void cc3100_socket::SL_FD_CLR(int16_t fd, SlFdSet_t *fdset)
+{
+    fdset->fd_array[0] &=  ~(1<< (fd & BSD_SOCKET_ID_MASK));
+}
+/*******************************************************************************/
+/*  SL_FD_ISSET */
+/*******************************************************************************/
+int16_t  cc3100_socket::SL_FD_ISSET(int16_t fd, SlFdSet_t *fdset)
+{
+    if( fdset->fd_array[0] & (1<< (fd & BSD_SOCKET_ID_MASK)) ) {
+        return 1;
+    }
+    return 0;
+}
+/*******************************************************************************/
+/*  SL_FD_ZERO */
+/*******************************************************************************/
+void cc3100_socket::SL_FD_ZERO(SlFdSet_t *fdset)
+{
+    fdset->fd_array[0] = 0;
+}
+
+#endif
+
+}//namespace mbed_cc3100
+
+
+