DeepCover Embedded Security in IoT: Public-key Secured Data Paths

Dependencies:   MaximInterface

The MAXREFDES155# is an internet-of-things (IoT) embedded-security reference design, built to authenticate and control a sensing node using elliptic-curve-based public-key cryptography with control and notification from a web server.

The hardware includes an ARM® mbed™ shield and attached sensor endpoint. The shield contains a DS2476 DeepCover® ECDSA/SHA-2 coprocessor, Wifi communication, LCD push-button controls, and status LEDs. The sensor endpoint is attached to the shield using a 300mm cable and contains a DS28C36 DeepCover ECDSA/SHA-2 authenticator, IR-thermal sensor, and aiming laser for the IR sensor. The MAXREFDES155# is equipped with a standard Arduino® form-factor shield connector for immediate testing using an mbed board such as the MAX32600MBED#. The combination of these two devices represent an IoT device. Communication to the web server is accomplished with the shield Wifi circuitry. Communication from the shield to the attached sensor module is accomplished over I2C . The sensor module represents an IoT endpoint that generates small data with a requirement for message authenticity/integrity and secure on/off operational control.

The design is hierarchical with each mbed platform and shield communicating data from the sensor node to a web server that maintains a centralized log and dispatches notifications as necessary. The simplicity of this design enables rapid integration into any star-topology IoT network to provide security with the low overhead and cost provided by the ECDSA-P256 asymmetric-key and SHA-256 symmetric-key algorithms.

More information about the MAXREFDES155# is available on the Maxim Integrated website.

simplelink/source/socket.c

Committer:
IanBenzMaxim
Date:
2018-01-19
Revision:
15:75404fab3615
Parent:
0:33d4e66780c0

File content as of revision 15:75404fab3615:

/*
 * socket.c - CC31xx/CC32xx Host Driver Implementation
 *
 * Copyright (C) 2015 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 "simplelink.h"
#include "protocol.h"
#include "driver.h"


static void    _sl_BuildAddress(const SlSockAddr_t *addr, _SocketAddrCommand_u    *pCmd);
_SlReturnVal_t _sl_HandleAsync_Connect(void *pVoidBuf);

#ifndef SL_TINY_EXT
void   _sl_ParseAddress(_SocketAddrResponse_u *pRsp, SlSockAddr_t *addr, SlSocklen_t *addrlen);
_SlReturnVal_t   _sl_HandleAsync_Accept(void *pVoidBuf);
_SlReturnVal_t   _sl_HandleAsync_Select(void *pVoidBuf);
#endif
static _u16   _sl_TruncatePayloadByProtocol(const _i16 pSd, const _u16 length);  

/*******************************************************************************/
/* Functions                                                                   */
/*******************************************************************************/


    /*  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. */
#define SL_SOCKET_PAYLOAD_BASE (1350)

static const _u8 _SlPayloadByProtocolLUT[16] = 
{
    (1472 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_UDP_IPV4 */
    (1460 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_TCP_IPV4 */
    (1452 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_UDP_IPV6 */
    (1440 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_TCP_IPV6 */
    (1386 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_TCP_IPV4_SECURE */
    (1386 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_UDP_IPV4_SECURE */
    (1396 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_UDP_IPV6_SECURE */
    (1396 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_TCP_IPV6_SECURE */
    (1476 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_RAW_TRANCEIVER */
    (1514 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_RAW_PACKET */
    (1480 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_RAW_IP4 */
    (1480 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_RAW_IP6 */
    (1440 - SL_SOCKET_PAYLOAD_BASE), /* Default */
    (1440 - SL_SOCKET_PAYLOAD_BASE), /* Default */
    (1440 - SL_SOCKET_PAYLOAD_BASE), /* Default */
    (1440 - SL_SOCKET_PAYLOAD_BASE)  /* Default */
};



/* ******************************************************************************/
/*  _sl_BuildAddress */
/* ******************************************************************************/
static void _sl_BuildAddress(const SlSockAddr_t *addr, _SocketAddrCommand_u    *pCmd)
{

    /* 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. */
    pCmd->IpV4.FamilyAndFlags = (_u8)((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 
*****************************************************************************/
static _u16 _sl_TruncatePayloadByProtocol(const _i16 sd, const _u16 length)
{
   _u16 maxLength;


   maxLength = (_u16)(SL_SOCKET_PAYLOAD_BASE + _SlPayloadByProtocolLUT[((sd & SL_SOCKET_PAYLOAD_TYPE_MASK) >> 4)]);



   if( length > maxLength )
   {
      return maxLength;
   }
   else
   {
      return length;
   }
}

/*******************************************************************************/
/*  _sl_ParseAddress */
/*******************************************************************************/

#ifndef SL_TINY_EXT
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 = (SlSocklen_t)((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
}

#endif

/*******************************************************************************/
/* sl_Socket */
/*******************************************************************************/
typedef union
{
    _u32                Dummy;
	_SocketCommand_t 	Cmd;
	_SocketResponse_t	Rsp;
}_SlSockSocketMsg_u;



#if _SL_INCLUDE_FUNC(sl_Socket)

static const _SlCmdCtrl_t _SlSockSocketCmdCtrl =
{
    SL_OPCODE_SOCKET_SOCKET,
    (_SlArgSize_t)sizeof(_SocketCommand_t),
    (_SlArgSize_t)sizeof(_SocketResponse_t)
};

_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 no erorr handling in progress. if in progress than
      ignore the API execution and return immediately with an error */
    VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();

    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;


#if _SL_INCLUDE_FUNC(sl_Close)

static const _SlCmdCtrl_t _SlSockCloseCmdCtrl =
{
	SL_OPCODE_SOCKET_CLOSE,
    (_SlArgSize_t)sizeof(_CloseCommand_t),
    (_SlArgSize_t)sizeof(_SocketResponse_t)
};

_i16 sl_Close(_i16 sd)
{
	_SlSockCloseMsg_u   Msg;

    /* verify no erorr handling in progress. if in progress than
     ignore the API execution and return immediately with an error */
    VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();

    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, (_SlArgSize_t)sizeof(_SocketResponse_t)};

    /* verify no erorr handling in progress. if in progress than
      ignore the API execution and return immediately with an error */
    VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();

    switch(addr->sa_family)
    {
        case SL_AF_INET :
            CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND;
            CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(_SocketAddrIPv4Command_t);
            break;
#ifndef SL_TINY_EXT            
        case SL_AF_INET6_EUI_48:
            CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND_V6;
            CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(_SocketAddrIPv6EUI48Command_t);
        	break;

#ifdef SL_SUPPORT_IPV6
        case AF_INET6:
            CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND_V6;
            CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(_SocketAddrIPv6Command_t);
            break;
#endif
#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, &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;

    /* verify no erorr handling in progress. if in progress than
       ignore the API execution and return immediately with an error */
    VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();

    _SlDrvResetCmdExt(&CmdExt);
    CmdExt.TxPayloadLen = (_u16)Len;
    CmdExt.pTxPayload = (_u8 *)pBuf;

    switch(to->sa_family)
    {
        case SL_AF_INET:
            CmdCtrl.Opcode = SL_OPCODE_SOCKET_SENDTO;
            CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(_SocketAddrIPv4Command_t);
            break;
#ifndef SL_TINY_EXT            
        case SL_AF_INET6_EUI_48:
            CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND_V6;
            CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(_SocketAddrIPv6EUI48Command_t);
        	break;        
#ifdef SL_SUPPORT_IPV6
        case AF_INET6:
            CmdCtrl.Opcode = SL_OPCODE_SOCKET_SENDTO_V6;
            CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(_SocketAddrIPv6Command_t);
            break;
#endif
#endif
        case SL_AF_RF:
        default:
            return SL_RET_CODE_INVALID_INPUT;
    }

    ChunkLen = _sl_TruncatePayloadByProtocol(sd,(_u16)Len);
    Msg.Cmd.IpV4.lenOrPadding = (_i16)ChunkLen;
    CmdExt.TxPayloadLen = ChunkLen;

    Msg.Cmd.IpV4.sd = (_u8)sd;

    _sl_BuildAddress(to, &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 = (_i16)ChunkLen;
        }
        else
        {
            return RetVal;
        }
    }while(ChunkLen > 0);

    return (_i16)Len;
}
#endif

/*******************************************************************************/
/*  sl_Recvfrom */
/*******************************************************************************/
typedef union
{
    _sendRecvCommand_t	    Cmd;
    _SocketAddrResponse_u	Rsp;
}_SlRecvfromMsg_u;

static const _SlCmdCtrl_t _SlRecvfomCmdCtrl =
{
	SL_OPCODE_SOCKET_RECVFROM,
    (_SlArgSize_t)sizeof(_sendRecvCommand_t),
    (_SlArgSize_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;

    /* verify no erorr handling in progress. if in progress than
      ignore the API execution and return immediately with an error */
    VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();

    _SlDrvResetCmdExt(&CmdExt);
    CmdExt.RxPayloadLen = Len;
    CmdExt.pRxPayload = (_u8 *)buf;

    Msg.Cmd.sd = (_u8)sd;
    Msg.Cmd.StatusOrLen = (_u16)Len;
    
    /*  no size truncation in recv path */
    CmdExt.RxPayloadLen = (_i16)Msg.Cmd.StatusOrLen;


    Msg.Cmd.FamilyAndFlags = (_u8)(flags & 0x0F);


    if(sizeof(SlSockAddrIn_t) == *fromlen)
    {
        Msg.Cmd.FamilyAndFlags |= (SL_AF_INET << 4);
    }
    else if (sizeof(SlSockAddrIn6_t) == *fromlen)
    {
        Msg.Cmd.FamilyAndFlags |= (SL_AF_INET6 << 4);
    }
    else
    {
        return SL_RET_CODE_INVALID_INPUT;
    }

    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 == (_i16)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 = (SlSocklen_t)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, (_SlArgSize_t)0, (_SlArgSize_t)sizeof(_SocketResponse_t)};
      _SocketResponse_t    AsyncRsp;
      _u8 ObjIdx = MAX_CONCURRENT_ACTIONS;

	/* verify no erorr handling in progress. if in progress than
	ignore the API execution and return immediately with an error */
	VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();


    switch(addr->sa_family)
    {
        case SL_AF_INET :
            CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT;
            CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(_SocketAddrIPv4Command_t);
            /* Do nothing - cmd already initialized to this type */
            break;
        case  SL_AF_INET6_EUI_48:
            CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT_V6;
            CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(_SocketAddrIPv6EUI48Command_t);
        	break;
#ifdef SL_SUPPORT_IPV6
        case AF_INET6:
            CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT_V6;
            CmdCtrl.TxDescLen = (_SlArgSize_t)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, &Msg.Cmd);


    ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, CONNECT_ID, (_u8)(sd  & BSD_SOCKET_ID_MASK));

    if (MAX_CONCURRENT_ACTIONS == ObjIdx)
    {
        return SL_POOL_IS_EMPTY;
    }

    /* send the command */
    VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL));
    VERIFY_PROTOCOL(Msg.Rsp.sd == (_u8)sd)

	RetVal = Msg.Rsp.statusOrLen;

    if(SL_RET_CODE_OK == RetVal)
    {
#ifndef SL_TINY_EXT    
    	/*In case socket is non-blocking one, the async event should be received immediately */
    	if( g_pCB->SocketNonBlocking >> (sd & BSD_SOCKET_ID_MASK))
		{
    		SL_DRV_SYNC_OBJ_WAIT_TIMEOUT(&g_pCB->ObjPool[ObjIdx].SyncObj,
                                             SL_DRIVER_TIMEOUT_SHORT,
                                             SL_DRIVER_API_SOCKET_CONNECT
                                             );
		}
    	else
#endif         
    	{
    		/* wait for async and get Data Read parameters */
    		SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->ObjPool[ObjIdx].SyncObj);
    	}
        
        VERIFY_PROTOCOL(AsyncRsp.sd == (_u8)sd);

        RetVal = AsyncRsp.statusOrLen;
    }



    _SlDrvReleasePoolObj(ObjIdx);
    return RetVal;
}

#endif


/*******************************************************************************/
/*   _sl_HandleAsync_Connect */
/*******************************************************************************/
_SlReturnVal_t _sl_HandleAsync_Connect(void *pVoidBuf)
{
    _SocketResponse_t          *pMsgArgs   = (_SocketResponse_t *)_SL_RESP_ARGS_START(pVoidBuf);

    SL_DRV_PROTECTION_OBJ_LOCK_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;


    SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
    SL_DRV_PROTECTION_OBJ_UNLOCK();

	return SL_RET_CODE_OK;
}

/*******************************************************************************/
/*  sl_Send */
/*******************************************************************************/
typedef union
{
	_sendRecvCommand_t    Cmd;
    /*  no response for 'sendto' commands*/
}_SlSendMsg_u;

static const _SlCmdCtrl_t _SlSendCmdCtrl =
{
    SL_OPCODE_SOCKET_SEND,
    (_SlArgSize_t)sizeof(_sendRecvCommand_t),
    (_SlArgSize_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; 

    /* verify no erorr handling in progress. if in progress than
       ignore the API execution and return immediately with an error */
    VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();

    _SlDrvResetCmdExt(&CmdExt);
    CmdExt.TxPayloadLen = (_u16)Len;
    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 = (_u32)flags;
        CmdExt.pRxPayload = (_u8 *)&tempVal;
		CmdExt.RxPayloadLen = -4; /* mark as Rx data to send */
		runSingleChunk = TRUE;
    }
    else
    {
        CmdExt.pRxPayload = NULL;
    }

    ChunkLen = _sl_TruncatePayloadByProtocol(sd,(_u16)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 = (_u16)((_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;



#if _SL_INCLUDE_FUNC(sl_Listen)

static const _SlCmdCtrl_t _SlListenCmdCtrl =
{
    SL_OPCODE_SOCKET_LISTEN,
    (_SlArgSize_t)sizeof(_ListenCommand_t),
    (_SlArgSize_t)sizeof(_BasicResponse_t),
};

_i16 sl_Listen(_i16 sd, _i16 backlog)
{
    _SlListenMsg_u  Msg;

    /* verify no erorr handling in progress. if in progress than
       ignore the API execution and return immediately with an error */
    VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();

    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;



#if _SL_INCLUDE_FUNC(sl_Accept)

static const _SlCmdCtrl_t _SlAcceptCmdCtrl =
{
    SL_OPCODE_SOCKET_ACCEPT,
    (_SlArgSize_t)sizeof(_AcceptCommand_t),
    (_SlArgSize_t)sizeof(_BasicResponse_t),
};

_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;

    /* verify no erorr handling in progress. if in progress than
    ignore the API execution and return immediately with an error */
    VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();

	

    Msg.Cmd.sd = (_u8)sd;
    Msg.Cmd.family = (_u8)((sizeof(SlSockAddrIn_t) == *addrlen) ? SL_AF_INET : SL_AF_INET6);


    ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, ACCEPT_ID, (_u8)sd  & BSD_SOCKET_ID_MASK );

    if (MAX_CONCURRENT_ACTIONS == ObjIdx)
    {
        return SL_POOL_IS_EMPTY;
    }
    
	/* send the command */
    VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlAcceptCmdCtrl, &Msg, NULL));
    VERIFY_PROTOCOL(Msg.Rsp.sd == (_u8)sd);

    RetVal = Msg.Rsp.statusOrLen;

    if(SL_OS_RET_CODE_OK == RetVal)
    {
#ifndef SL_TINY_EXT    
    	/* in case socket is non-blocking one, the async event should be received immediately */
    	if( g_pCB->SocketNonBlocking & (1<<(sd & BSD_SOCKET_ID_MASK) ))
    	{
    		SL_DRV_SYNC_OBJ_WAIT_TIMEOUT(&g_pCB->ObjPool[ObjIdx].SyncObj,
                                             SL_DRIVER_TIMEOUT_SHORT,
                                             SL_DRIVER_API_SOCKET_ACCEPT
                                             );
    	}
    	else
#endif         
    	{
    		/* wait for async and get Data Read parameters */
    		SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->ObjPool[ObjIdx].SyncObj);
    	}
        
        VERIFY_PROTOCOL(AsyncRsp.IpV4.sd == (_u8)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 == (SlSocklen_t)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 == (SlSocklen_t)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 (_u16)i;
  }
  else /* big endian */
  {
    return val; 
  }
}

/*******************************************************************************/
/*   _sl_HandleAsync_Accept */
/*******************************************************************************/
#ifndef SL_TINY_EXT
_SlReturnVal_t _sl_HandleAsync_Accept(void *pVoidBuf)
{
    _SocketAddrResponse_u      *pMsgArgs   = (_SocketAddrResponse_u *)_SL_RESP_ARGS_START(pVoidBuf);

    SL_DRV_PROTECTION_OBJ_LOCK_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));
	SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);

    SL_DRV_PROTECTION_OBJ_UNLOCK();
    return SL_RET_CODE_OK;
}

/*******************************************************************************/
/*   _sl_HandleAsync_Select */
/*******************************************************************************/
_SlReturnVal_t _sl_HandleAsync_Select(void *pVoidBuf)
{
    _SelectAsyncResponse_t     *pMsgArgs   = (_SelectAsyncResponse_t *)_SL_RESP_ARGS_START(pVoidBuf);

    SL_DRV_PROTECTION_OBJ_LOCK_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));

    SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
    
    SL_DRV_PROTECTION_OBJ_UNLOCK();

    return SL_RET_CODE_OK;
}

#endif

/*******************************************************************************/
/*  sl_Recv */
/*******************************************************************************/
typedef union
{
	_sendRecvCommand_t  Cmd;
	_SocketResponse_t   Rsp;    
}_SlRecvMsg_u;


#if _SL_INCLUDE_FUNC(sl_Recv)

static const _SlCmdCtrl_t _SlRecvCmdCtrl =
{
    SL_OPCODE_SOCKET_RECV,
    (_SlArgSize_t)sizeof(_sendRecvCommand_t),
    (_SlArgSize_t)sizeof(_SocketResponse_t)
};


_i16 sl_Recv(_i16 sd, void *pBuf, _i16 Len, _i16 flags)
{
    _SlRecvMsg_u    Msg;
    _SlCmdExt_t     CmdExt;
    _SlReturnVal_t status;

    /* verify no erorr handling in progress. if in progress than
      ignore the API execution and return immediately with an error */
    VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();

    _SlDrvResetCmdExt(&CmdExt);
    CmdExt.RxPayloadLen = Len;
    CmdExt.pRxPayload = (_u8 *)pBuf;

    Msg.Cmd.sd = (_u8)sd;
    Msg.Cmd.StatusOrLen = (_u16)Len;

    /*  no size truncation in recv path */
    CmdExt.RxPayloadLen = (_i16)Msg.Cmd.StatusOrLen;

    Msg.Cmd.FamilyAndFlags = (_u8)(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;

static const _SlCmdCtrl_t _SlSetSockOptCmdCtrl =
{
    SL_OPCODE_SOCKET_SETSOCKOPT,
    (_SlArgSize_t)sizeof(_setSockOptCommand_t),
    (_SlArgSize_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;

    /* verify no erorr handling in progress. if in progress than
      ignore the API execution and return immediately with an error */
    VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();

    _SlDrvResetCmdExt(&CmdExt);
    CmdExt.TxPayloadLen = optlen;
    CmdExt.pTxPayload = (_u8 *)optval;

    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;


#if _SL_INCLUDE_FUNC(sl_GetSockOpt)

static const _SlCmdCtrl_t _SlGetSockOptCmdCtrl =
{
    SL_OPCODE_SOCKET_GETSOCKOPT,
    (_SlArgSize_t)sizeof(_getSockOptCommand_t),
    (_SlArgSize_t)sizeof(_getSockOptResponse_t)
};

_i16 sl_GetSockOpt(_i16 sd, _i16 level, _i16 optname, void *optval, SlSocklen_t *optlen)
{
    _SlGetSockOptMsg_u    Msg;
    _SlCmdExt_t           CmdExt;

    /* verify no erorr handling in progress. if in progress than
      ignore the API execution and return immediately with an error */
    VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();
	if (*optlen == 0)
	{
		return SL_EZEROLEN;
	}

    _SlDrvResetCmdExt(&CmdExt);
    CmdExt.RxPayloadLen = (_i16)(*optlen);
    CmdExt.pRxPayload = optval;

    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;



#ifndef SL_TINY_EXT
#if _SL_INCLUDE_FUNC(sl_Select)

static const _SlCmdCtrl_t _SlSelectCmdCtrl =
{
    SL_OPCODE_SOCKET_SELECT,
    (_SlArgSize_t)sizeof(_SelectCommand_t),
    (_SlArgSize_t)sizeof(_BasicResponse_t)
};


_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;

    /* verify no erorr handling in progress. if in progress than
      ignore the API execution and return immediately with an error */
    VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();
    
    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 = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, SELECT_ID, SL_MAX_SOCKETS);

    if (MAX_CONCURRENT_ACTIONS == ObjIdx)
    {
        return SL_POOL_IS_EMPTY;
    }

    
	/* send the command */
    VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSelectCmdCtrl, &Msg, NULL));

    if(SL_OS_RET_CODE_OK == (_i16)Msg.Rsp.status)
    {
    	SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->ObjPool[ObjIdx].SyncObj);
        
        Msg.Rsp.status = (_i16)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
#endif