TI's CC3100 host driver and demo. Experimental and a work in progress.

Dependencies:   mbed

Revision:
0:bbe98578d4c0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simplelink/cc3100_socket.cpp	Mon Nov 17 19:38:34 2014 +0000
@@ -0,0 +1,1124 @@
+/*
+ * 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"
+
+
+/*******************************************************************************/
+/* Functions prototypes                                                        */
+/*******************************************************************************/
+void   _sl_BuildAddress(const SlSockAddr_t *addr, _i16 addrlen, _SocketAddrCommand_u    *pCmd);
+void   _sl_ParseAddress(_SocketAddrResponse_u *pRsp, SlSockAddr_t *addr, SlSocklen_t *addrlen);
+void   _sl_HandleAsync_Connect(void *pVoidBuf);
+void   _sl_HandleAsync_Accept(void *pVoidBuf);
+void   _sl_HandleAsync_Select(void *pVoidBuf);
+_u16   _sl_TruncatePayloadByProtocol(const _i16 pSd,const _u16 length);  
+
+/*******************************************************************************/
+/* Functions                                                                   */
+/*******************************************************************************/
+
+/* ******************************************************************************/
+/*  _sl_BuildAddress */
+/* ******************************************************************************/
+void _sl_BuildAddress(const SlSockAddr_t *addr, _i16 addrlen, _SocketAddrCommand_u    *pCmd)
+{
+
+    /*  Note: parsing of family and port in the generic way for all IPV4, IPV6 and EUI48 */
+    /*  is possible as _i32 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 )
+    {
+        sl_Memcpy( pCmd->IpV6EUI48.address,((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u8, 6);
+    }
+#ifdef SL_SUPPORT_IPV6
+    else
+    {
+        sl_Memcpy(pCmd->IpV6.address, ((sockaddr_in6 *)addr)->sin6_addr._S6_un._S6_u32, 16 );
+    }
+#endif
+}
+
+/* ******************************************************************************/
+/*  _sl_TruncatePayloadByProtocol */
+/* ******************************************************************************/
+_u16 _sl_TruncatePayloadByProtocol(const _i16 sd,const _u16 length)
+{
+   _u16 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 _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 )
+    {
+        sl_Memcpy(((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u8, pRsp->IpV6EUI48.address, 6);
+    }
+#ifdef SL_SUPPORT_IPV6
+    else
+    {
+        sl_Memcpy(((sockaddr_in6 *)addr)->sin6_addr._S6_un._S6_u32, pRsp->IpV6.address, 16);
+    }
+#endif
+}
+
+/*******************************************************************************/
+/* sl_Socket */
+/*******************************************************************************/
+typedef union
+{
+    _u32                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)
+_i16 sl_Socket(_i16 Domain, _i16 Type, _i16 Protocol)
+{
+    _SlSockSocketMsg_u  Msg;
+
+    Msg.Cmd.Domain	    = (_u8)Domain;
+    Msg.Cmd.Type     	= (_u8)Type;
+    Msg.Cmd.Protocol 	= (_u8)Protocol;
+
+    VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSockSocketCmdCtrl, &Msg, NULL));
+
+    if( Msg.Rsp.statusOrLen < 0 )
+	{
+		return( Msg.Rsp.statusOrLen );
+	}
+	else
+	{
+    return (_i16)((_u8)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)
+_i16 sl_Close(_i16 sd)
+{
+	_SlSockCloseMsg_u   Msg;
+
+    Msg.Cmd.sd = (_u8)sd;
+
+    VERIFY_RET_OK(_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)
+_i16 sl_Bind(_i16 sd, const SlSockAddr_t *addr, _i16 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 = (_u8)sd;
+
+    _sl_BuildAddress(addr, addrlen, &Msg.Cmd);
+
+    VERIFY_RET_OK(_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)
+_i16 sl_SendTo(_i16 sd, const void *pBuf, _i16 Len, _i16 flags, const SlSockAddr_t *to, SlSocklen_t tolen)
+{
+    _SlSendtoMsg_u   Msg;
+    _SlCmdCtrl_t     CmdCtrl = {0, 0, 0};
+    _SlCmdExt_t      CmdExt;
+    _u16           ChunkLen;
+    _i16              RetVal;
+
+    CmdExt.TxPayloadLen = (_u16)Len;
+    CmdExt.RxPayloadLen = 0;
+    CmdExt.pTxPayload = (_u8 *)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 = (_u8)sd;
+
+    _sl_BuildAddress(to, tolen, &Msg.Cmd);
+
+    Msg.Cmd.IpV4.FamilyAndFlags |= flags & 0x0F;
+
+    do
+    {
+        RetVal = _SlDrvDataWriteOp((_SlSd_t)sd, &CmdCtrl, &Msg, &CmdExt);
+
+        if(SL_OS_RET_CODE_OK == RetVal)
+        {
+            CmdExt.pTxPayload += ChunkLen;
+            ChunkLen = (_u16)((_u8 *)pBuf + Len - CmdExt.pTxPayload);
+            ChunkLen = _sl_TruncatePayloadByProtocol(sd,ChunkLen);
+            CmdExt.TxPayloadLen = ChunkLen;
+            Msg.Cmd.IpV4.lenOrPadding = ChunkLen;
+        }
+        else
+        {
+            return RetVal;
+        }
+    }while(ChunkLen > 0);
+
+    return (_i16)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)
+_i16 sl_RecvFrom(_i16 sd, void *buf, _i16 Len, _i16 flags, SlSockAddr_t *from, SlSocklen_t *fromlen)
+{
+    _SlRecvfromMsg_u    Msg;
+    _SlCmdExt_t         CmdExt;
+    _i16                 RetVal;
+
+    CmdExt.TxPayloadLen = 0;
+    CmdExt.RxPayloadLen = Len;
+    CmdExt.pTxPayload = NULL;
+    CmdExt.pRxPayload = (_u8 *)buf;
+
+
+    Msg.Cmd.sd = (_u8)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 = _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;
+            sl_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;
+            sl_Memcpy(((sockaddr_in6 *)from)->sin6_addr._S6_un._S6_u32, Msg.Rsp.IpV6.address, 16);
+            *fromlen = sizeof(sockaddr_in6);
+        }
+#endif
+#endif
+    }
+
+    return (_i16)RetVal;
+}
+#endif
+
+/*******************************************************************************/
+/*  sl_Connect */
+/*******************************************************************************/
+typedef union
+{
+	_SocketAddrCommand_u    Cmd;
+	_SocketResponse_t	    Rsp;
+}_SlSockConnectMsg_u;
+
+#if _SL_INCLUDE_FUNC(sl_Connect)
+_i16 sl_Connect(_i16 sd, const SlSockAddr_t *addr, _i16 addrlen)
+{
+	_SlSockConnectMsg_u  Msg;
+	_SlReturnVal_t       RetVal;
+    _SlCmdCtrl_t         CmdCtrl = {0, 0, sizeof(_SocketResponse_t)};
+    _SocketResponse_t    AsyncRsp;
+	_u8 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 = (_u8)sd;
+
+    _sl_BuildAddress(addr, addrlen, &Msg.Cmd);
+
+	/* Use Obj to issue the command, if not available try later */
+	ObjIdx = (_u8)_SlDrvWaitForPoolObj(CONNECT_ID, (_u8)(sd  & BSD_SOCKET_ID_MASK));
+
+	if (MAX_CONCURRENT_ACTIONS == ObjIdx)
+	{
+		return SL_POOL_IS_EMPTY;
+	}
+	OSI_RET_OK_CHECK(sl_LockObjLock(&g_pCB->ProtectionLockObj, SL_OS_WAIT_FOREVER));
+
+	g_pCB->ObjPool[ObjIdx].pRespArgs =  (_u8 *)&AsyncRsp;
+
+    OSI_RET_OK_CHECK(sl_LockObjUnlock(&g_pCB->ProtectionLockObj));
+	
+	/* send the command */
+    VERIFY_RET_OK(_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(sl_SyncObjWait(&g_pCB->ObjPool[ObjIdx].SyncObj, SL_OS_WAIT_FOREVER));
+
+        VERIFY_PROTOCOL(AsyncRsp.sd == sd);
+
+        RetVal = AsyncRsp.statusOrLen;
+    }
+    _SlDrvReleasePoolObj(ObjIdx);
+    return RetVal;
+}
+#endif
+
+/*******************************************************************************/
+/*   _sl_HandleAsync_Connect */
+/*******************************************************************************/
+void _sl_HandleAsync_Connect(void *pVoidBuf)
+{
+    _SocketResponse_t          *pMsgArgs   = (_SocketResponse_t *)_SL_RESP_ARGS_START(pVoidBuf);
+
+    OSI_RET_OK_CHECK(sl_LockObjLock(&g_pCB->ProtectionLockObj, SL_OS_WAIT_FOREVER));
+
+    VERIFY_PROTOCOL((pMsgArgs->sd & BSD_SOCKET_ID_MASK) <= SL_MAX_SOCKETS);
+    VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs);
+
+    ((_SocketResponse_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->sd = pMsgArgs->sd;
+    ((_SocketResponse_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->statusOrLen = pMsgArgs->statusOrLen;
+
+    OSI_RET_OK_CHECK(sl_SyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj));
+    OSI_RET_OK_CHECK(sl_LockObjUnlock(&g_pCB->ProtectionLockObj));
+    return;
+}
+
+/*******************************************************************************/
+/*  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)
+_i16 sl_Send(_i16 sd, const void *pBuf, _i16 Len, _i16 flags)
+{
+    _SlSendMsg_u   Msg;
+    _SlCmdExt_t    CmdExt;
+    _u16         ChunkLen;
+    _i16            RetVal;
+	_u32         tempVal;
+	_u8  runSingleChunk = FALSE; 
+
+    CmdExt.TxPayloadLen = Len;
+    CmdExt.RxPayloadLen = 0;
+    CmdExt.pTxPayload = (_u8 *)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 = (_u8 *)&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 = (_u8)sd;
+    Msg.Cmd.FamilyAndFlags |= flags & 0x0F;
+
+    do
+    {
+        RetVal = _SlDrvDataWriteOp((_u8)sd, (_SlCmdCtrl_t *)&_SlSendCmdCtrl, &Msg, &CmdExt);
+        if(SL_OS_RET_CODE_OK == RetVal)
+        {
+            CmdExt.pTxPayload += ChunkLen;
+            ChunkLen = (_u8 *)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 (_i16)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)
+_i16 sl_Listen(_i16 sd, _i16 backlog)
+{
+    _SlListenMsg_u  Msg;
+
+    Msg.Cmd.sd = (_u8)sd;
+    Msg.Cmd.backlog = (_u8)backlog;
+
+    VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlListenCmdCtrl, &Msg, NULL));
+
+    return (_i16)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)
+_i16 sl_Accept(_i16 sd, SlSockAddr_t *addr, SlSocklen_t *addrlen)
+{
+	_SlSockAcceptMsg_u      Msg;
+    _SlReturnVal_t          RetVal;
+    _SocketAddrResponse_u   AsyncRsp;
+
+	_u8 ObjIdx = MAX_CONCURRENT_ACTIONS;
+
+
+    Msg.Cmd.sd = (_u8)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 = (_u8)_SlDrvWaitForPoolObj(ACCEPT_ID, (_u8)(sd  & BSD_SOCKET_ID_MASK));
+	
+	if (MAX_CONCURRENT_ACTIONS == ObjIdx)
+	{
+		return SL_POOL_IS_EMPTY;
+	}
+	
+    OSI_RET_OK_CHECK(sl_LockObjLock(&g_pCB->ProtectionLockObj, SL_OS_WAIT_FOREVER));
+
+	g_pCB->ObjPool[ObjIdx].pRespArgs = (_u8 *)&AsyncRsp;
+
+    OSI_RET_OK_CHECK(sl_LockObjUnlock(&g_pCB->ProtectionLockObj));
+	/* send the command */
+    VERIFY_RET_OK(_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(sl_SyncObjWait(&g_pCB->ObjPool[ObjIdx].SyncObj, 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*/
+                sl_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    ;
+    	        sl_Memcpy(((sockaddr_in6 *)addr)->sin6_addr._S6_un._S6_u32, AsyncRsp.IpV6.address, 16);
+              }
+              else
+              {
+                *addrlen = 0;
+              }
+    	    }
+#endif
+#endif			
+        }
+    }
+
+    _SlDrvReleasePoolObj(ObjIdx);
+    return (_i16)RetVal;
+}
+#endif
+
+
+/*******************************************************************************/
+/*  sl_Htonl */
+/*******************************************************************************/
+_u32 sl_Htonl( _u32 val )
+{
+  _u32 i = 1; 
+  _i8 *p = (_i8 *)&i;  
+  if (p[0] == 1) /* little endian */
+  {
+    p[0] = ((_i8* )&val)[3];
+    p[1] = ((_i8* )&val)[2];
+    p[2] = ((_i8* )&val)[1];
+    p[3] = ((_i8* )&val)[0];
+    return i;
+  }
+  else /* big endian */
+  {
+    return val; 
+  }
+}
+
+/*******************************************************************************/
+/*  sl_Htonl */
+/*******************************************************************************/
+_u16 sl_Htons( _u16 val )
+{
+  _i16 i = 1; 
+  _i8 *p = (_i8 *)&i;  
+  if (p[0] == 1) /* little endian */
+  {
+    p[0] = ((_i8* )&val)[1];
+    p[1] = ((_i8* )&val)[0];
+    return i;
+  }
+  else /* big endian */
+  {
+    return val; 
+  }
+}
+
+/*******************************************************************************/
+/*   _sl_HandleAsync_Accept */
+/*******************************************************************************/
+void _sl_HandleAsync_Accept(void *pVoidBuf)
+{
+    _SocketAddrResponse_u      *pMsgArgs   = (_SocketAddrResponse_u *)_SL_RESP_ARGS_START(pVoidBuf);
+
+    OSI_RET_OK_CHECK(sl_LockObjLock(&g_pCB->ProtectionLockObj, SL_OS_WAIT_FOREVER));
+
+    VERIFY_PROTOCOL(( pMsgArgs->IpV4.sd & BSD_SOCKET_ID_MASK) <= SL_MAX_SOCKETS);
+    VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs);
+
+	sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs,sizeof(_SocketAddrResponse_u));
+	OSI_RET_OK_CHECK(sl_SyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj));
+
+    OSI_RET_OK_CHECK(sl_LockObjUnlock(&g_pCB->ProtectionLockObj));
+    return;
+}
+
+/*******************************************************************************/
+/*  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)
+_i16 sl_Recv(_i16 sd, void *pBuf, _i16 Len, _i16 flags)
+{
+    _SlRecvMsg_u    Msg;
+    _SlCmdExt_t     CmdExt;
+    _SlReturnVal_t status;
+
+    CmdExt.TxPayloadLen = 0;
+    CmdExt.RxPayloadLen = Len;
+    CmdExt.pTxPayload = NULL;
+    CmdExt.pRxPayload = (_u8 *)pBuf;
+
+    Msg.Cmd.sd = (_u8)sd;
+    Msg.Cmd.StatusOrLen = Len;
+
+    /*  no size truncation in recv path */
+    CmdExt.RxPayloadLen = Msg.Cmd.StatusOrLen;
+
+    Msg.Cmd.FamilyAndFlags = flags & 0x0F;
+
+    status = _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 (_i16)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)
+_i16 sl_SetSockOpt(_i16 sd, _i16 level, _i16 optname, const void *optval, SlSocklen_t optlen)
+{
+    _SlSetSockOptMsg_u    Msg;
+    _SlCmdExt_t           CmdExt;
+
+    CmdExt.TxPayloadLen = optlen;
+    CmdExt.RxPayloadLen = 0;
+    CmdExt.pTxPayload = (_u8 *)optval;
+    CmdExt.pRxPayload = NULL;
+
+    Msg.Cmd.sd = (_u8)sd;
+    Msg.Cmd.level = (_u8)level;
+    Msg.Cmd.optionLen = (_u8)optlen;
+    Msg.Cmd.optionName = (_u8)optname;
+
+    VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSetSockOptCmdCtrl, &Msg, &CmdExt));
+
+    return (_i16)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)
+_i16 sl_GetSockOpt(_i16 sd, _i16 level, _i16 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 = (unsigned char*)optval;//(unsigned char*) added
+	CmdExt.ActualRxPayloadLen = 0;
+
+    Msg.Cmd.sd = (_u8)sd;
+    Msg.Cmd.level = (_u8)level;
+    Msg.Cmd.optionLen = (_u8)(*optlen);
+    Msg.Cmd.optionName = (_u8)optname;
+
+    VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlGetSockOptCmdCtrl, &Msg, &CmdExt));
+
+	if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) 
+	{
+	    *optlen = Msg.Rsp.optionLen;
+	   return SL_ESMALLBUF;
+	}
+	else
+	{
+		*optlen = (_u8)CmdExt.ActualRxPayloadLen;
+	}
+    return (_i16)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)
+_i16 sl_Select(_i16 nfds, SlFdSet_t *readsds, SlFdSet_t *writesds, SlFdSet_t *exceptsds, struct SlTimeval_t *timeout)
+{
+    _SlSelectMsg_u          Msg;
+    _SelectAsyncResponse_t  AsyncRsp;
+	_u8 ObjIdx = MAX_CONCURRENT_ACTIONS;
+
+    Msg.Cmd.nfds          = (_u8)nfds;
+    Msg.Cmd.readFdsCount  = 0;
+    Msg.Cmd.writeFdsCount = 0;
+    
+    Msg.Cmd.readFds = 0;
+    Msg.Cmd.writeFds = 0; 
+    
+    if( readsds )
+    {
+       Msg.Cmd.readFds       = (_u16)readsds->fd_array[0];  
+    }
+    if( writesds )
+    {
+       Msg.Cmd.writeFds      = (_u16)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 = (_u16)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 = (_u16)timeout->tv_usec;
+		}
+	}
+
+	/* Use Obj to issue the command, if not available try later */
+	ObjIdx = (_u8)_SlDrvWaitForPoolObj(SELECT_ID, SL_MAX_SOCKETS);
+
+	if (MAX_CONCURRENT_ACTIONS == ObjIdx)
+	{
+		return SL_POOL_IS_EMPTY;
+	}
+	OSI_RET_OK_CHECK(sl_LockObjLock(&g_pCB->ProtectionLockObj, SL_OS_WAIT_FOREVER));
+
+	g_pCB->ObjPool[ObjIdx].pRespArgs =  (_u8 *)&AsyncRsp;
+
+    OSI_RET_OK_CHECK(sl_LockObjUnlock(&g_pCB->ProtectionLockObj));
+	/* send the command */
+    VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSelectCmdCtrl, &Msg, NULL));
+
+    if(SL_OS_RET_CODE_OK == (_i16)Msg.Rsp.status)
+    {
+        OSI_RET_OK_CHECK(sl_SyncObjWait(&g_pCB->ObjPool[ObjIdx].SyncObj, SL_OS_WAIT_FOREVER));
+        Msg.Rsp.status = AsyncRsp.status;
+
+        if(  ((_i16)Msg.Rsp.status) >= 0 )
+        {
+            if( readsds )
+            {
+               readsds->fd_array[0]  = AsyncRsp.readFds;
+            }
+            if( writesds )
+            {
+               writesds->fd_array[0] = AsyncRsp.writeFds;      
+            }
+        }
+    }
+
+    _SlDrvReleasePoolObj(ObjIdx);
+    return (_i16)Msg.Rsp.status;
+}
+
+/*  Select helper functions */
+/*******************************************************************************/
+/*  SL_FD_SET */
+/* ******************************************************************************/
+void SL_FD_SET(_i16 fd, SlFdSet_t *fdset)
+{
+   fdset->fd_array[0] |=  (1<< (fd & BSD_SOCKET_ID_MASK));
+}
+/*******************************************************************************/
+/*  SL_FD_CLR */
+/*******************************************************************************/
+void SL_FD_CLR(_i16 fd, SlFdSet_t *fdset)
+{
+  fdset->fd_array[0] &=  ~(1<< (fd & BSD_SOCKET_ID_MASK));
+}
+/*******************************************************************************/
+/*  SL_FD_ISSET */
+/*******************************************************************************/
+_i16  SL_FD_ISSET(_i16 fd, SlFdSet_t *fdset)
+{
+  if( fdset->fd_array[0] & (1<< (fd & BSD_SOCKET_ID_MASK)) )
+  {
+    return 1;
+  }
+  return 0;
+}
+/*******************************************************************************/
+/*  SL_FD_ZERO */
+/*******************************************************************************/  
+void SL_FD_ZERO(SlFdSet_t *fdset)
+{
+  fdset->fd_array[0] = 0;
+}
+
+#endif
+
+/*******************************************************************************/
+/*   _sl_HandleAsync_Select */
+/*******************************************************************************/
+void _sl_HandleAsync_Select(void *pVoidBuf)
+{
+    _SelectAsyncResponse_t     *pMsgArgs   = (_SelectAsyncResponse_t *)_SL_RESP_ARGS_START(pVoidBuf);
+
+    OSI_RET_OK_CHECK(sl_LockObjLock(&g_pCB->ProtectionLockObj, SL_OS_WAIT_FOREVER));
+
+    VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs);
+
+    sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(_SelectAsyncResponse_t));
+    OSI_RET_OK_CHECK(sl_SyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj));
+
+    OSI_RET_OK_CHECK(sl_LockObjUnlock(&g_pCB->ProtectionLockObj));
+    return;
+}
+
+