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

Dependencies:   MaximInterface

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers socket.c Source File

socket.c

00001 /*
00002  * socket.c - CC31xx/CC32xx Host Driver Implementation
00003  *
00004  * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ 
00005  * 
00006  * 
00007  *  Redistribution and use in source and binary forms, with or without 
00008  *  modification, are permitted provided that the following conditions 
00009  *  are met:
00010  *
00011  *    Redistributions of source code must retain the above copyright 
00012  *    notice, this list of conditions and the following disclaimer.
00013  *
00014  *    Redistributions in binary form must reproduce the above copyright
00015  *    notice, this list of conditions and the following disclaimer in the 
00016  *    documentation and/or other materials provided with the   
00017  *    distribution.
00018  *
00019  *    Neither the name of Texas Instruments Incorporated nor the names of
00020  *    its contributors may be used to endorse or promote products derived
00021  *    from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00026  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
00027  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
00028  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
00029  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00030  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00031  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
00032  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
00033  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034  *
00035 */
00036     
00037 
00038 
00039 
00040 /*****************************************************************************/
00041 /* Include files                                                             */
00042 /*****************************************************************************/
00043 #include "simplelink.h"
00044 #include "protocol.h"
00045 #include "driver.h"
00046 
00047 
00048 static void    _sl_BuildAddress(const SlSockAddr_t *addr, _SocketAddrCommand_u    *pCmd);
00049 _SlReturnVal_t _sl_HandleAsync_Connect(void *pVoidBuf);
00050 
00051 #ifndef SL_TINY_EXT
00052 void   _sl_ParseAddress(_SocketAddrResponse_u *pRsp, SlSockAddr_t *addr, SlSocklen_t *addrlen);
00053 _SlReturnVal_t   _sl_HandleAsync_Accept(void *pVoidBuf);
00054 _SlReturnVal_t   _sl_HandleAsync_Select(void *pVoidBuf);
00055 #endif
00056 static _u16   _sl_TruncatePayloadByProtocol(const _i16 pSd, const _u16 length);  
00057 
00058 /*******************************************************************************/
00059 /* Functions                                                                   */
00060 /*******************************************************************************/
00061 
00062 
00063     /*  Note: parsing of family and port in the generic way for all IPV4, IPV6 and EUI48 */
00064     /*  is possible as _i32 as these parameters are in the same offset and size for these */
00065     /*  three families. */
00066 #define SL_SOCKET_PAYLOAD_BASE (1350)
00067 
00068 static const _u8 _SlPayloadByProtocolLUT[16] = 
00069 {
00070     (1472 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_UDP_IPV4 */
00071     (1460 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_TCP_IPV4 */
00072     (1452 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_UDP_IPV6 */
00073     (1440 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_TCP_IPV6 */
00074     (1386 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_TCP_IPV4_SECURE */
00075     (1386 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_UDP_IPV4_SECURE */
00076     (1396 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_UDP_IPV6_SECURE */
00077     (1396 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_TCP_IPV6_SECURE */
00078     (1476 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_RAW_TRANCEIVER */
00079     (1514 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_RAW_PACKET */
00080     (1480 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_RAW_IP4 */
00081     (1480 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_RAW_IP6 */
00082     (1440 - SL_SOCKET_PAYLOAD_BASE), /* Default */
00083     (1440 - SL_SOCKET_PAYLOAD_BASE), /* Default */
00084     (1440 - SL_SOCKET_PAYLOAD_BASE), /* Default */
00085     (1440 - SL_SOCKET_PAYLOAD_BASE)  /* Default */
00086 };
00087 
00088 
00089 
00090 /* ******************************************************************************/
00091 /*  _sl_BuildAddress */
00092 /* ******************************************************************************/
00093 static void _sl_BuildAddress(const SlSockAddr_t *addr, _SocketAddrCommand_u    *pCmd)
00094 {
00095 
00096     /* Note: parsing of family and port in the generic way for all IPV4, IPV6 and EUI48
00097            is possible as long as these parameters are in the same offset and size for these
00098            three families. */
00099     pCmd->IpV4.FamilyAndFlags = (_u8)((addr->sa_family << 4) & 0xF0);
00100     pCmd->IpV4.port = ((SlSockAddrIn_t *)addr)->sin_port;
00101 
00102     if(SL_AF_INET == addr->sa_family)
00103     {
00104         pCmd->IpV4.address  = ((SlSockAddrIn_t *)addr)->sin_addr.s_addr;
00105     }
00106     else if (SL_AF_INET6_EUI_48 == addr->sa_family )
00107     {
00108         sl_Memcpy( pCmd->IpV6EUI48.address,((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u8, 6);
00109     }
00110 #ifdef SL_SUPPORT_IPV6
00111     else
00112     {
00113         sl_Memcpy(pCmd->IpV6.address, ((sockaddr_in6 *)addr)->sin6_addr._S6_un._S6_u32, 16 );
00114     }
00115 #endif
00116 }
00117 
00118 
00119 /*****************************************************************************
00120  _sl_TruncatePayloadByProtocol 
00121 *****************************************************************************/
00122 static _u16 _sl_TruncatePayloadByProtocol(const _i16 sd, const _u16 length)
00123 {
00124    _u16 maxLength;
00125 
00126 
00127    maxLength = (_u16)(SL_SOCKET_PAYLOAD_BASE + _SlPayloadByProtocolLUT[((sd & SL_SOCKET_PAYLOAD_TYPE_MASK) >> 4)]);
00128 
00129 
00130 
00131    if( length > maxLength )
00132    {
00133       return maxLength;
00134    }
00135    else
00136    {
00137       return length;
00138    }
00139 }
00140 
00141 /*******************************************************************************/
00142 /*  _sl_ParseAddress */
00143 /*******************************************************************************/
00144 
00145 #ifndef SL_TINY_EXT
00146 void _sl_ParseAddress(_SocketAddrResponse_u    *pRsp, SlSockAddr_t *addr, SlSocklen_t *addrlen)
00147 {
00148     /*  Note: parsing of family and port in the generic way for all IPV4, IPV6 and EUI48 */
00149     /*  is possible as long as these parameters are in the same offset and size for these */
00150     /*  three families. */
00151     addr->sa_family                 = pRsp->IpV4.family;
00152     ((SlSockAddrIn_t *)addr)->sin_port = pRsp->IpV4.port;
00153 
00154     *addrlen = (SlSocklen_t)((SL_AF_INET == addr->sa_family) ? sizeof(SlSockAddrIn_t) : sizeof(SlSockAddrIn6_t));
00155 
00156     if(SL_AF_INET == addr->sa_family)
00157     {
00158         ((SlSockAddrIn_t *)addr)->sin_addr.s_addr  = pRsp->IpV4.address;
00159     }
00160     else if (SL_AF_INET6_EUI_48 == addr->sa_family )
00161     {
00162         sl_Memcpy(((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u8, pRsp->IpV6EUI48.address, 6);
00163     }
00164 #ifdef SL_SUPPORT_IPV6
00165     else
00166     {
00167         sl_Memcpy(((sockaddr_in6 *)addr)->sin6_addr._S6_un._S6_u32, pRsp->IpV6.address, 16);
00168     }
00169 #endif
00170 }
00171 
00172 #endif
00173 
00174 /*******************************************************************************/
00175 /* sl_Socket */
00176 /*******************************************************************************/
00177 typedef union
00178 {
00179     _u32                Dummy;
00180     _SocketCommand_t    Cmd;
00181     _SocketResponse_t   Rsp;
00182 }_SlSockSocketMsg_u;
00183 
00184 
00185 
00186 #if _SL_INCLUDE_FUNC(sl_Socket)
00187 
00188 static const _SlCmdCtrl_t _SlSockSocketCmdCtrl =
00189 {
00190     SL_OPCODE_SOCKET_SOCKET,
00191     (_SlArgSize_t)sizeof(_SocketCommand_t),
00192     (_SlArgSize_t)sizeof(_SocketResponse_t)
00193 };
00194 
00195 _i16 sl_Socket(_i16 Domain, _i16 Type, _i16 Protocol)
00196 {
00197     _SlSockSocketMsg_u  Msg;
00198 
00199     Msg.Cmd.Domain      = (_u8)Domain;
00200     Msg.Cmd.Type        = (_u8)Type;
00201     Msg.Cmd.Protocol    = (_u8)Protocol;
00202 
00203     /* verify no erorr handling in progress. if in progress than
00204       ignore the API execution and return immediately with an error */
00205     VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();
00206 
00207     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSockSocketCmdCtrl, &Msg, NULL));
00208 
00209     if( Msg.Rsp.statusOrLen < 0 )
00210     {
00211         return( Msg.Rsp.statusOrLen );
00212     }
00213     else
00214     {
00215     return (_i16)((_u8)Msg.Rsp.sd);
00216 }
00217 }
00218 #endif
00219 
00220 /*******************************************************************************/
00221 /*  sl_Close  */
00222 /*******************************************************************************/
00223 typedef union
00224 {
00225     _CloseCommand_t     Cmd;
00226     _SocketResponse_t   Rsp;
00227 }_SlSockCloseMsg_u;
00228 
00229 
00230 #if _SL_INCLUDE_FUNC(sl_Close)
00231 
00232 static const _SlCmdCtrl_t _SlSockCloseCmdCtrl =
00233 {
00234     SL_OPCODE_SOCKET_CLOSE,
00235     (_SlArgSize_t)sizeof(_CloseCommand_t),
00236     (_SlArgSize_t)sizeof(_SocketResponse_t)
00237 };
00238 
00239 _i16 sl_Close(_i16 sd)
00240 {
00241     _SlSockCloseMsg_u   Msg;
00242 
00243     /* verify no erorr handling in progress. if in progress than
00244      ignore the API execution and return immediately with an error */
00245     VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();
00246 
00247     Msg.Cmd.sd = (_u8)sd;
00248 
00249     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSockCloseCmdCtrl, &Msg, NULL));
00250 
00251     return Msg.Rsp.statusOrLen;
00252 }
00253 #endif
00254 
00255 /*******************************************************************************/
00256 /*  sl_Bind */
00257 /*******************************************************************************/
00258 typedef union
00259 {
00260     _SocketAddrCommand_u    Cmd;
00261     _SocketResponse_t       Rsp;
00262 }_SlSockBindMsg_u;
00263 
00264 #if _SL_INCLUDE_FUNC(sl_Bind)
00265 _i16 sl_Bind(_i16 sd, const SlSockAddr_t *addr, _i16 addrlen)
00266 {
00267     _SlSockBindMsg_u    Msg;
00268     _SlCmdCtrl_t         CmdCtrl = {0, 0, (_SlArgSize_t)sizeof(_SocketResponse_t)};
00269 
00270     /* verify no erorr handling in progress. if in progress than
00271       ignore the API execution and return immediately with an error */
00272     VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();
00273 
00274     switch(addr->sa_family)
00275     {
00276         case SL_AF_INET :
00277             CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND;
00278             CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(_SocketAddrIPv4Command_t);
00279             break;
00280 #ifndef SL_TINY_EXT            
00281         case SL_AF_INET6_EUI_48:
00282             CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND_V6;
00283             CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(_SocketAddrIPv6EUI48Command_t);
00284             break;
00285 
00286 #ifdef SL_SUPPORT_IPV6
00287         case AF_INET6:
00288             CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND_V6;
00289             CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(_SocketAddrIPv6Command_t);
00290             break;
00291 #endif
00292 #endif
00293 
00294 
00295         case SL_AF_RF   :
00296         default:
00297             return SL_RET_CODE_INVALID_INPUT;
00298     }
00299 
00300     Msg.Cmd.IpV4.lenOrPadding = 0;
00301     Msg.Cmd.IpV4.sd = (_u8)sd;
00302 
00303     _sl_BuildAddress(addr, &Msg.Cmd);
00304 
00305     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL));
00306 
00307     return Msg.Rsp.statusOrLen;
00308 }
00309 #endif
00310 
00311 /*******************************************************************************/
00312 /*  sl_Sendto */
00313 /*******************************************************************************/
00314 typedef union
00315 {
00316     _SocketAddrCommand_u    Cmd;
00317     /*  no response for 'sendto' commands*/
00318 }_SlSendtoMsg_u;
00319 
00320 #if _SL_INCLUDE_FUNC(sl_SendTo)
00321 _i16 sl_SendTo(_i16 sd, const void *pBuf, _i16 Len, _i16 flags, const SlSockAddr_t *to, SlSocklen_t tolen)
00322 {
00323     _SlSendtoMsg_u   Msg;
00324     _SlCmdCtrl_t     CmdCtrl = {0, 0, 0};
00325     _SlCmdExt_t      CmdExt;
00326     _u16           ChunkLen;
00327     _i16              RetVal;
00328 
00329     /* verify no erorr handling in progress. if in progress than
00330        ignore the API execution and return immediately with an error */
00331     VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();
00332 
00333     _SlDrvResetCmdExt(&CmdExt);
00334     CmdExt.TxPayloadLen = (_u16)Len;
00335     CmdExt.pTxPayload = (_u8 *)pBuf;
00336 
00337     switch(to->sa_family)
00338     {
00339         case SL_AF_INET:
00340             CmdCtrl.Opcode = SL_OPCODE_SOCKET_SENDTO;
00341             CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(_SocketAddrIPv4Command_t);
00342             break;
00343 #ifndef SL_TINY_EXT            
00344         case SL_AF_INET6_EUI_48:
00345             CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND_V6;
00346             CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(_SocketAddrIPv6EUI48Command_t);
00347             break;        
00348 #ifdef SL_SUPPORT_IPV6
00349         case AF_INET6:
00350             CmdCtrl.Opcode = SL_OPCODE_SOCKET_SENDTO_V6;
00351             CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(_SocketAddrIPv6Command_t);
00352             break;
00353 #endif
00354 #endif
00355         case SL_AF_RF:
00356         default:
00357             return SL_RET_CODE_INVALID_INPUT;
00358     }
00359 
00360     ChunkLen = _sl_TruncatePayloadByProtocol(sd,(_u16)Len);
00361     Msg.Cmd.IpV4.lenOrPadding = (_i16)ChunkLen;
00362     CmdExt.TxPayloadLen = ChunkLen;
00363 
00364     Msg.Cmd.IpV4.sd = (_u8)sd;
00365 
00366     _sl_BuildAddress(to, &Msg.Cmd);
00367 
00368     Msg.Cmd.IpV4.FamilyAndFlags |= flags & 0x0F;
00369 
00370     do
00371     {
00372         RetVal = _SlDrvDataWriteOp((_SlSd_t)sd, &CmdCtrl, &Msg, &CmdExt);
00373 
00374         if(SL_OS_RET_CODE_OK == RetVal)
00375         {
00376             CmdExt.pTxPayload += ChunkLen;
00377             ChunkLen = (_u16)((_u8 *)pBuf + Len - CmdExt.pTxPayload);
00378             ChunkLen = _sl_TruncatePayloadByProtocol(sd,ChunkLen);
00379             CmdExt.TxPayloadLen = ChunkLen;
00380             Msg.Cmd.IpV4.lenOrPadding = (_i16)ChunkLen;
00381         }
00382         else
00383         {
00384             return RetVal;
00385         }
00386     }while(ChunkLen > 0);
00387 
00388     return (_i16)Len;
00389 }
00390 #endif
00391 
00392 /*******************************************************************************/
00393 /*  sl_Recvfrom */
00394 /*******************************************************************************/
00395 typedef union
00396 {
00397     _sendRecvCommand_t      Cmd;
00398     _SocketAddrResponse_u   Rsp;
00399 }_SlRecvfromMsg_u;
00400 
00401 static const _SlCmdCtrl_t _SlRecvfomCmdCtrl =
00402 {
00403     SL_OPCODE_SOCKET_RECVFROM,
00404     (_SlArgSize_t)sizeof(_sendRecvCommand_t),
00405     (_SlArgSize_t)sizeof(_SocketAddrResponse_u)
00406 };
00407 
00408 
00409 
00410 #if _SL_INCLUDE_FUNC(sl_RecvFrom)
00411 _i16 sl_RecvFrom(_i16 sd, void *buf, _i16 Len, _i16 flags, SlSockAddr_t *from, SlSocklen_t *fromlen)
00412 {
00413     _SlRecvfromMsg_u    Msg;
00414     _SlCmdExt_t         CmdExt;
00415     _i16                 RetVal;
00416 
00417     /* verify no erorr handling in progress. if in progress than
00418       ignore the API execution and return immediately with an error */
00419     VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();
00420 
00421     _SlDrvResetCmdExt(&CmdExt);
00422     CmdExt.RxPayloadLen = Len;
00423     CmdExt.pRxPayload = (_u8 *)buf;
00424 
00425     Msg.Cmd.sd = (_u8)sd;
00426     Msg.Cmd.StatusOrLen = (_u16)Len;
00427     
00428     /*  no size truncation in recv path */
00429     CmdExt.RxPayloadLen = (_i16)Msg.Cmd.StatusOrLen;
00430 
00431 
00432     Msg.Cmd.FamilyAndFlags = (_u8)(flags & 0x0F);
00433 
00434 
00435     if(sizeof(SlSockAddrIn_t) == *fromlen)
00436     {
00437         Msg.Cmd.FamilyAndFlags |= (SL_AF_INET << 4);
00438     }
00439     else if (sizeof(SlSockAddrIn6_t) == *fromlen)
00440     {
00441         Msg.Cmd.FamilyAndFlags |= (SL_AF_INET6 << 4);
00442     }
00443     else
00444     {
00445         return SL_RET_CODE_INVALID_INPUT;
00446     }
00447 
00448     RetVal = _SlDrvDataReadOp((_SlSd_t)sd, (_SlCmdCtrl_t *)&_SlRecvfomCmdCtrl, &Msg, &CmdExt);
00449     if( RetVal != SL_OS_RET_CODE_OK )
00450     {
00451     return RetVal;
00452     }
00453 
00454     RetVal = Msg.Rsp.IpV4.statusOrLen;
00455 
00456     if(RetVal >= 0)
00457     {
00458         VERIFY_PROTOCOL(sd == (_i16)Msg.Rsp.IpV4.sd);
00459 #if 0
00460         _sl_ParseAddress(&Msg.Rsp, from, fromlen);
00461 #else
00462         from->sa_family = Msg.Rsp.IpV4.family;
00463         if(SL_AF_INET == from->sa_family)
00464         {
00465             ((SlSockAddrIn_t *)from)->sin_port = Msg.Rsp.IpV4.port;
00466             ((SlSockAddrIn_t *)from)->sin_addr.s_addr = Msg.Rsp.IpV4.address;
00467             *fromlen = (SlSocklen_t)sizeof(SlSockAddrIn_t);
00468         }
00469         else if (SL_AF_INET6_EUI_48 == from->sa_family )
00470          {
00471             ((SlSockAddrIn6_t *)from)->sin6_port  = Msg.Rsp.IpV6EUI48.port;
00472             sl_Memcpy(((SlSockAddrIn6_t *)from)->sin6_addr._S6_un._S6_u8, Msg.Rsp.IpV6EUI48.address, 6);
00473          }
00474 #ifdef SL_SUPPORT_IPV6
00475         else if(AF_INET6 == from->sa_family)
00476         {
00477             VERIFY_PROTOCOL(*fromlen >= sizeof(sockaddr_in6));
00478 
00479             ((sockaddr_in6 *)from)->sin6_port = Msg.Rsp.IpV6.port;
00480             sl_Memcpy(((sockaddr_in6 *)from)->sin6_addr._S6_un._S6_u32, Msg.Rsp.IpV6.address, 16);
00481             *fromlen = sizeof(sockaddr_in6);
00482         }
00483 #endif
00484 #endif
00485     }
00486 
00487     return (_i16)RetVal;
00488 }
00489 #endif
00490 
00491 /*******************************************************************************/
00492 /*  sl_Connect */
00493 /*******************************************************************************/
00494 typedef union
00495 {
00496     _SocketAddrCommand_u    Cmd;
00497     _SocketResponse_t       Rsp;
00498 }_SlSockConnectMsg_u;
00499 
00500 #if _SL_INCLUDE_FUNC(sl_Connect)
00501 _i16 sl_Connect(_i16 sd, const SlSockAddr_t *addr, _i16 addrlen)
00502 {
00503       _SlSockConnectMsg_u  Msg;
00504       _SlReturnVal_t       RetVal;
00505       _SlCmdCtrl_t         CmdCtrl = {0, (_SlArgSize_t)0, (_SlArgSize_t)sizeof(_SocketResponse_t)};
00506       _SocketResponse_t    AsyncRsp;
00507       _u8 ObjIdx = MAX_CONCURRENT_ACTIONS;
00508 
00509     /* verify no erorr handling in progress. if in progress than
00510     ignore the API execution and return immediately with an error */
00511     VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();
00512 
00513 
00514     switch(addr->sa_family)
00515     {
00516         case SL_AF_INET :
00517             CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT;
00518             CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(_SocketAddrIPv4Command_t);
00519             /* Do nothing - cmd already initialized to this type */
00520             break;
00521         case  SL_AF_INET6_EUI_48:
00522             CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT_V6;
00523             CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(_SocketAddrIPv6EUI48Command_t);
00524             break;
00525 #ifdef SL_SUPPORT_IPV6
00526         case AF_INET6:
00527             CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT_V6;
00528             CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(_SocketAddrIPv6Command_t);
00529             break;
00530 #endif
00531         case SL_AF_RF:
00532         default:
00533             return SL_RET_CODE_INVALID_INPUT;
00534     }
00535 
00536     Msg.Cmd.IpV4.lenOrPadding = 0;
00537     Msg.Cmd.IpV4.sd = (_u8)sd;
00538 
00539     _sl_BuildAddress(addr, &Msg.Cmd);
00540 
00541 
00542     ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, CONNECT_ID, (_u8)(sd  & BSD_SOCKET_ID_MASK));
00543 
00544     if (MAX_CONCURRENT_ACTIONS == ObjIdx)
00545     {
00546         return SL_POOL_IS_EMPTY;
00547     }
00548 
00549     /* send the command */
00550     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL));
00551     VERIFY_PROTOCOL(Msg.Rsp.sd == (_u8)sd)
00552 
00553     RetVal = Msg.Rsp.statusOrLen;
00554 
00555     if(SL_RET_CODE_OK == RetVal)
00556     {
00557 #ifndef SL_TINY_EXT    
00558         /*In case socket is non-blocking one, the async event should be received immediately */
00559         if( g_pCB->SocketNonBlocking >> (sd & BSD_SOCKET_ID_MASK))
00560         {
00561             SL_DRV_SYNC_OBJ_WAIT_TIMEOUT(&g_pCB->ObjPool[ObjIdx].SyncObj,
00562                                              SL_DRIVER_TIMEOUT_SHORT,
00563                                              SL_DRIVER_API_SOCKET_CONNECT
00564                                              );
00565         }
00566         else
00567 #endif         
00568         {
00569             /* wait for async and get Data Read parameters */
00570             SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->ObjPool[ObjIdx].SyncObj);
00571         }
00572         
00573         VERIFY_PROTOCOL(AsyncRsp.sd == (_u8)sd);
00574 
00575         RetVal = AsyncRsp.statusOrLen;
00576     }
00577 
00578 
00579 
00580     _SlDrvReleasePoolObj(ObjIdx);
00581     return RetVal;
00582 }
00583 
00584 #endif
00585 
00586 
00587 /*******************************************************************************/
00588 /*   _sl_HandleAsync_Connect */
00589 /*******************************************************************************/
00590 _SlReturnVal_t _sl_HandleAsync_Connect(void *pVoidBuf)
00591 {
00592     _SocketResponse_t          *pMsgArgs   = (_SocketResponse_t *)_SL_RESP_ARGS_START(pVoidBuf);
00593 
00594     SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
00595 
00596     VERIFY_PROTOCOL((pMsgArgs->sd & BSD_SOCKET_ID_MASK) <= SL_MAX_SOCKETS);
00597     VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs);
00598     
00599 
00600     ((_SocketResponse_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->sd = pMsgArgs->sd;
00601     ((_SocketResponse_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->statusOrLen = pMsgArgs->statusOrLen;
00602 
00603 
00604     SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
00605     SL_DRV_PROTECTION_OBJ_UNLOCK();
00606 
00607     return SL_RET_CODE_OK;
00608 }
00609 
00610 /*******************************************************************************/
00611 /*  sl_Send */
00612 /*******************************************************************************/
00613 typedef union
00614 {
00615     _sendRecvCommand_t    Cmd;
00616     /*  no response for 'sendto' commands*/
00617 }_SlSendMsg_u;
00618 
00619 static const _SlCmdCtrl_t _SlSendCmdCtrl =
00620 {
00621     SL_OPCODE_SOCKET_SEND,
00622     (_SlArgSize_t)sizeof(_sendRecvCommand_t),
00623     (_SlArgSize_t)0
00624 };
00625 
00626 #if _SL_INCLUDE_FUNC(sl_Send)
00627 _i16 sl_Send(_i16 sd, const void *pBuf, _i16 Len, _i16 flags)
00628 {
00629     _SlSendMsg_u   Msg;
00630     _SlCmdExt_t    CmdExt;
00631     _u16         ChunkLen;
00632     _i16            RetVal;
00633     _u32         tempVal;
00634     _u8  runSingleChunk = FALSE; 
00635 
00636     /* verify no erorr handling in progress. if in progress than
00637        ignore the API execution and return immediately with an error */
00638     VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();
00639 
00640     _SlDrvResetCmdExt(&CmdExt);
00641     CmdExt.TxPayloadLen = (_u16)Len;
00642     CmdExt.pTxPayload = (_u8 *)pBuf;
00643     
00644     /* Only for RAW transceiver type socket, relay the flags parameter in the 2 bytes (4 byte aligned) before the actual payload */
00645     if ((sd & SL_SOCKET_PAYLOAD_TYPE_MASK) == SL_SOCKET_PAYLOAD_TYPE_RAW_TRANCEIVER)
00646     {
00647         tempVal = (_u32)flags;
00648         CmdExt.pRxPayload = (_u8 *)&tempVal;
00649         CmdExt.RxPayloadLen = -4; /* mark as Rx data to send */
00650         runSingleChunk = TRUE;
00651     }
00652     else
00653     {
00654         CmdExt.pRxPayload = NULL;
00655     }
00656 
00657     ChunkLen = _sl_TruncatePayloadByProtocol(sd,(_u16)Len);
00658     CmdExt.TxPayloadLen = ChunkLen;
00659     Msg.Cmd.StatusOrLen = ChunkLen;
00660     Msg.Cmd.sd = (_u8)sd;
00661     Msg.Cmd.FamilyAndFlags |= flags & 0x0F;
00662 
00663     do
00664     {
00665         RetVal = _SlDrvDataWriteOp((_u8)sd, (_SlCmdCtrl_t *)&_SlSendCmdCtrl, &Msg, &CmdExt);
00666         if(SL_OS_RET_CODE_OK == RetVal)
00667         {
00668             CmdExt.pTxPayload += ChunkLen;
00669             ChunkLen = (_u16)((_u8 *)pBuf + Len - CmdExt.pTxPayload);
00670             ChunkLen = _sl_TruncatePayloadByProtocol(sd, ChunkLen);
00671             CmdExt.TxPayloadLen = ChunkLen;
00672             Msg.Cmd.StatusOrLen = ChunkLen;
00673         }
00674         else
00675         {
00676             return RetVal;
00677         }
00678     }while((ChunkLen > 0) && (runSingleChunk==FALSE));
00679     
00680     return (_i16)Len;
00681 }
00682 #endif
00683 
00684 /*******************************************************************************/
00685 /*  sl_Listen */
00686 /*******************************************************************************/
00687 typedef union
00688 {
00689     _ListenCommand_t    Cmd;
00690     _BasicResponse_t    Rsp;
00691 }_SlListenMsg_u;
00692 
00693 
00694 
00695 #if _SL_INCLUDE_FUNC(sl_Listen)
00696 
00697 static const _SlCmdCtrl_t _SlListenCmdCtrl =
00698 {
00699     SL_OPCODE_SOCKET_LISTEN,
00700     (_SlArgSize_t)sizeof(_ListenCommand_t),
00701     (_SlArgSize_t)sizeof(_BasicResponse_t),
00702 };
00703 
00704 _i16 sl_Listen(_i16 sd, _i16 backlog)
00705 {
00706     _SlListenMsg_u  Msg;
00707 
00708     /* verify no erorr handling in progress. if in progress than
00709        ignore the API execution and return immediately with an error */
00710     VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();
00711 
00712     Msg.Cmd.sd = (_u8)sd;
00713     Msg.Cmd.backlog = (_u8)backlog;
00714 
00715     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlListenCmdCtrl, &Msg, NULL));
00716 
00717     return (_i16)Msg.Rsp.status;
00718 }
00719 #endif
00720 
00721 /*******************************************************************************/
00722 /*  sl_Accept */
00723 /*******************************************************************************/
00724 typedef union
00725 {
00726     _AcceptCommand_t    Cmd;
00727     _SocketResponse_t   Rsp;
00728 }_SlSockAcceptMsg_u;
00729 
00730 
00731 
00732 #if _SL_INCLUDE_FUNC(sl_Accept)
00733 
00734 static const _SlCmdCtrl_t _SlAcceptCmdCtrl =
00735 {
00736     SL_OPCODE_SOCKET_ACCEPT,
00737     (_SlArgSize_t)sizeof(_AcceptCommand_t),
00738     (_SlArgSize_t)sizeof(_BasicResponse_t),
00739 };
00740 
00741 _i16 sl_Accept(_i16 sd, SlSockAddr_t *addr, SlSocklen_t *addrlen)
00742 {
00743     _SlSockAcceptMsg_u      Msg;
00744     _SlReturnVal_t          RetVal;
00745     _SocketAddrResponse_u   AsyncRsp;
00746 
00747     _u8 ObjIdx = MAX_CONCURRENT_ACTIONS;
00748 
00749     /* verify no erorr handling in progress. if in progress than
00750     ignore the API execution and return immediately with an error */
00751     VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();
00752 
00753     
00754 
00755     Msg.Cmd.sd = (_u8)sd;
00756     Msg.Cmd.family = (_u8)((sizeof(SlSockAddrIn_t) == *addrlen) ? SL_AF_INET : SL_AF_INET6);
00757 
00758 
00759     ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, ACCEPT_ID, (_u8)sd  & BSD_SOCKET_ID_MASK );
00760 
00761     if (MAX_CONCURRENT_ACTIONS == ObjIdx)
00762     {
00763         return SL_POOL_IS_EMPTY;
00764     }
00765     
00766     /* send the command */
00767     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlAcceptCmdCtrl, &Msg, NULL));
00768     VERIFY_PROTOCOL(Msg.Rsp.sd == (_u8)sd);
00769 
00770     RetVal = Msg.Rsp.statusOrLen;
00771 
00772     if(SL_OS_RET_CODE_OK == RetVal)
00773     {
00774 #ifndef SL_TINY_EXT    
00775         /* in case socket is non-blocking one, the async event should be received immediately */
00776         if( g_pCB->SocketNonBlocking & (1<<(sd & BSD_SOCKET_ID_MASK) ))
00777         {
00778             SL_DRV_SYNC_OBJ_WAIT_TIMEOUT(&g_pCB->ObjPool[ObjIdx].SyncObj,
00779                                              SL_DRIVER_TIMEOUT_SHORT,
00780                                              SL_DRIVER_API_SOCKET_ACCEPT
00781                                              );
00782         }
00783         else
00784 #endif         
00785         {
00786             /* wait for async and get Data Read parameters */
00787             SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->ObjPool[ObjIdx].SyncObj);
00788         }
00789         
00790         VERIFY_PROTOCOL(AsyncRsp.IpV4.sd == (_u8)sd);
00791 
00792         RetVal = AsyncRsp.IpV4.statusOrLen;
00793         if( (NULL != addr) && (NULL != addrlen) )  
00794         {
00795 #if 0 /*  Kept for backup */
00796             _sl_ParseAddress(&AsyncRsp, addr, addrlen);
00797 #else
00798            addr->sa_family = AsyncRsp.IpV4.family;
00799 
00800             if(SL_AF_INET == addr->sa_family)
00801             {
00802               if( *addrlen == (SlSocklen_t)sizeof( SlSockAddrIn_t ) )
00803               {
00804                 ((SlSockAddrIn_t *)addr)->sin_port         = AsyncRsp.IpV4.port;
00805                 ((SlSockAddrIn_t *)addr)->sin_addr.s_addr  = AsyncRsp.IpV4.address;
00806               }
00807               else
00808               {
00809                 *addrlen = 0;
00810               }
00811             }
00812             else if (SL_AF_INET6_EUI_48 == addr->sa_family )
00813             {
00814                 if( *addrlen == (SlSocklen_t)sizeof( SlSockAddrIn6_t ) )
00815               {
00816                 ((SlSockAddrIn6_t *)addr)->sin6_port                   = AsyncRsp.IpV6EUI48.port    ;
00817                 /*  will be called from here and from _sl_BuildAddress*/
00818                 sl_Memcpy(((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u8, AsyncRsp.IpV6EUI48.address, 6);
00819               }
00820               else
00821               {
00822                 *addrlen = 0;
00823               }
00824             }
00825 #ifdef SL_SUPPORT_IPV6
00826             else
00827             {
00828               if( *addrlen == sizeof( sockaddr_in6 ) )
00829               {
00830                 ((sockaddr_in6 *)addr)->sin6_port                   = AsyncRsp.IpV6.port    ;
00831                 sl_Memcpy(((sockaddr_in6 *)addr)->sin6_addr._S6_un._S6_u32, AsyncRsp.IpV6.address, 16);
00832               }
00833               else
00834               {
00835                 *addrlen = 0;
00836               }
00837             }
00838 #endif
00839 #endif          
00840         }
00841     }
00842 
00843     _SlDrvReleasePoolObj(ObjIdx);
00844     return (_i16)RetVal;
00845 }
00846 #endif
00847 
00848 
00849 /*******************************************************************************/
00850 /*  sl_Htonl */
00851 /*******************************************************************************/
00852 _u32 sl_Htonl( _u32 val )
00853 {
00854   _u32 i = 1; 
00855   _i8 *p = (_i8 *)&i;  
00856   if (p[0] == 1) /* little endian */
00857   {
00858     p[0] = ((_i8* )&val)[3];
00859     p[1] = ((_i8* )&val)[2];
00860     p[2] = ((_i8* )&val)[1];
00861     p[3] = ((_i8* )&val)[0];
00862     return i;
00863   }
00864   else /* big endian */
00865   {
00866     return val; 
00867   }
00868 }
00869 
00870 /*******************************************************************************/
00871 /*  sl_Htonl */
00872 /*******************************************************************************/
00873 _u16 sl_Htons( _u16 val )
00874 {
00875   _i16 i = 1; 
00876   _i8 *p = (_i8 *)&i;  
00877   if (p[0] == 1) /* little endian */
00878   {
00879     p[0] = ((_i8* )&val)[1];
00880     p[1] = ((_i8* )&val)[0];
00881     return (_u16)i;
00882   }
00883   else /* big endian */
00884   {
00885     return val; 
00886   }
00887 }
00888 
00889 /*******************************************************************************/
00890 /*   _sl_HandleAsync_Accept */
00891 /*******************************************************************************/
00892 #ifndef SL_TINY_EXT
00893 _SlReturnVal_t _sl_HandleAsync_Accept(void *pVoidBuf)
00894 {
00895     _SocketAddrResponse_u      *pMsgArgs   = (_SocketAddrResponse_u *)_SL_RESP_ARGS_START(pVoidBuf);
00896 
00897     SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
00898 
00899     VERIFY_PROTOCOL(( pMsgArgs->IpV4.sd & BSD_SOCKET_ID_MASK) <= SL_MAX_SOCKETS);
00900     VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs);
00901 
00902     sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs,sizeof(_SocketAddrResponse_u));
00903     SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
00904 
00905     SL_DRV_PROTECTION_OBJ_UNLOCK();
00906     return SL_RET_CODE_OK;
00907 }
00908 
00909 /*******************************************************************************/
00910 /*   _sl_HandleAsync_Select */
00911 /*******************************************************************************/
00912 _SlReturnVal_t _sl_HandleAsync_Select(void *pVoidBuf)
00913 {
00914     _SelectAsyncResponse_t     *pMsgArgs   = (_SelectAsyncResponse_t *)_SL_RESP_ARGS_START(pVoidBuf);
00915 
00916     SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
00917 
00918     VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs);
00919 
00920     sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(_SelectAsyncResponse_t));
00921 
00922     SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
00923     
00924     SL_DRV_PROTECTION_OBJ_UNLOCK();
00925 
00926     return SL_RET_CODE_OK;
00927 }
00928 
00929 #endif
00930 
00931 /*******************************************************************************/
00932 /*  sl_Recv */
00933 /*******************************************************************************/
00934 typedef union
00935 {
00936     _sendRecvCommand_t  Cmd;
00937     _SocketResponse_t   Rsp;    
00938 }_SlRecvMsg_u;
00939 
00940 
00941 #if _SL_INCLUDE_FUNC(sl_Recv)
00942 
00943 static const _SlCmdCtrl_t _SlRecvCmdCtrl =
00944 {
00945     SL_OPCODE_SOCKET_RECV,
00946     (_SlArgSize_t)sizeof(_sendRecvCommand_t),
00947     (_SlArgSize_t)sizeof(_SocketResponse_t)
00948 };
00949 
00950 
00951 _i16 sl_Recv(_i16 sd, void *pBuf, _i16 Len, _i16 flags)
00952 {
00953     _SlRecvMsg_u    Msg;
00954     _SlCmdExt_t     CmdExt;
00955     _SlReturnVal_t status;
00956 
00957     /* verify no erorr handling in progress. if in progress than
00958       ignore the API execution and return immediately with an error */
00959     VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();
00960 
00961     _SlDrvResetCmdExt(&CmdExt);
00962     CmdExt.RxPayloadLen = Len;
00963     CmdExt.pRxPayload = (_u8 *)pBuf;
00964 
00965     Msg.Cmd.sd = (_u8)sd;
00966     Msg.Cmd.StatusOrLen = (_u16)Len;
00967 
00968     /*  no size truncation in recv path */
00969     CmdExt.RxPayloadLen = (_i16)Msg.Cmd.StatusOrLen;
00970 
00971     Msg.Cmd.FamilyAndFlags = (_u8)(flags & 0x0F);
00972 
00973     status = _SlDrvDataReadOp((_SlSd_t)sd, (_SlCmdCtrl_t *)&_SlRecvCmdCtrl, &Msg, &CmdExt);
00974     if( status != SL_OS_RET_CODE_OK )
00975     {
00976     return status;
00977     }
00978      
00979     /*  if the Device side sends less than expected it is not the Driver's role */
00980     /*  the returned value could be smaller than the requested size */
00981     return (_i16)Msg.Rsp.statusOrLen;
00982 }
00983 #endif
00984 
00985 /*******************************************************************************/
00986 /*  sl_SetSockOpt */
00987 /*******************************************************************************/
00988 typedef union
00989 {
00990     _setSockOptCommand_t    Cmd;
00991     _SocketResponse_t       Rsp;    
00992 }_SlSetSockOptMsg_u;
00993 
00994 static const _SlCmdCtrl_t _SlSetSockOptCmdCtrl =
00995 {
00996     SL_OPCODE_SOCKET_SETSOCKOPT,
00997     (_SlArgSize_t)sizeof(_setSockOptCommand_t),
00998     (_SlArgSize_t)sizeof(_SocketResponse_t)
00999 };
01000 
01001 #if _SL_INCLUDE_FUNC(sl_SetSockOpt)
01002 _i16 sl_SetSockOpt(_i16 sd, _i16 level, _i16 optname, const void *optval, SlSocklen_t optlen)
01003 {
01004     _SlSetSockOptMsg_u    Msg;
01005     _SlCmdExt_t           CmdExt;
01006 
01007     /* verify no erorr handling in progress. if in progress than
01008       ignore the API execution and return immediately with an error */
01009     VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();
01010 
01011     _SlDrvResetCmdExt(&CmdExt);
01012     CmdExt.TxPayloadLen = optlen;
01013     CmdExt.pTxPayload = (_u8 *)optval;
01014 
01015     Msg.Cmd.sd = (_u8)sd;
01016     Msg.Cmd.level = (_u8)level;
01017     Msg.Cmd.optionLen = (_u8)optlen;
01018     Msg.Cmd.optionName = (_u8)optname;
01019 
01020     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSetSockOptCmdCtrl, &Msg, &CmdExt));
01021 
01022     return (_i16)Msg.Rsp.statusOrLen;
01023 }
01024 #endif
01025 
01026 /*******************************************************************************/
01027 /*  sl_GetSockOpt */
01028 /*******************************************************************************/
01029 typedef union
01030 {
01031     _getSockOptCommand_t    Cmd;
01032     _getSockOptResponse_t   Rsp;    
01033 }_SlGetSockOptMsg_u;
01034 
01035 
01036 #if _SL_INCLUDE_FUNC(sl_GetSockOpt)
01037 
01038 static const _SlCmdCtrl_t _SlGetSockOptCmdCtrl =
01039 {
01040     SL_OPCODE_SOCKET_GETSOCKOPT,
01041     (_SlArgSize_t)sizeof(_getSockOptCommand_t),
01042     (_SlArgSize_t)sizeof(_getSockOptResponse_t)
01043 };
01044 
01045 _i16 sl_GetSockOpt(_i16 sd, _i16 level, _i16 optname, void *optval, SlSocklen_t *optlen)
01046 {
01047     _SlGetSockOptMsg_u    Msg;
01048     _SlCmdExt_t           CmdExt;
01049 
01050     /* verify no erorr handling in progress. if in progress than
01051       ignore the API execution and return immediately with an error */
01052     VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();
01053     if (*optlen == 0)
01054     {
01055         return SL_EZEROLEN;
01056     }
01057 
01058     _SlDrvResetCmdExt(&CmdExt);
01059     CmdExt.RxPayloadLen = (_i16)(*optlen);
01060     CmdExt.pRxPayload = optval;
01061 
01062     Msg.Cmd.sd = (_u8)sd;
01063     Msg.Cmd.level = (_u8)level;
01064     Msg.Cmd.optionLen = (_u8)(*optlen);
01065     Msg.Cmd.optionName = (_u8)optname;
01066 
01067     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlGetSockOptCmdCtrl, &Msg, &CmdExt));
01068 
01069     if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) 
01070     {
01071         *optlen = Msg.Rsp.optionLen;
01072        return SL_ESMALLBUF;
01073     }
01074     else
01075     {
01076         *optlen = (_u8)CmdExt.ActualRxPayloadLen;
01077     }
01078     return (_i16)Msg.Rsp.status;
01079 }
01080 #endif
01081 
01082 /*******************************************************************************/
01083 /*  sl_Select */
01084 /* ******************************************************************************/
01085 typedef union
01086 {
01087     _SelectCommand_t   Cmd;
01088     _BasicResponse_t   Rsp;    
01089 }_SlSelectMsg_u;
01090 
01091 
01092 
01093 #ifndef SL_TINY_EXT
01094 #if _SL_INCLUDE_FUNC(sl_Select)
01095 
01096 static const _SlCmdCtrl_t _SlSelectCmdCtrl =
01097 {
01098     SL_OPCODE_SOCKET_SELECT,
01099     (_SlArgSize_t)sizeof(_SelectCommand_t),
01100     (_SlArgSize_t)sizeof(_BasicResponse_t)
01101 };
01102 
01103 
01104 _i16 sl_Select(_i16 nfds, SlFdSet_t *readsds, SlFdSet_t *writesds, SlFdSet_t *exceptsds, struct SlTimeval_t *timeout)
01105 {
01106     _SlSelectMsg_u          Msg;
01107     _SelectAsyncResponse_t  AsyncRsp;
01108     _u8 ObjIdx = MAX_CONCURRENT_ACTIONS;
01109 
01110     /* verify no erorr handling in progress. if in progress than
01111       ignore the API execution and return immediately with an error */
01112     VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();
01113     
01114     Msg.Cmd.nfds          = (_u8)nfds;
01115     Msg.Cmd.readFdsCount  = 0;
01116     Msg.Cmd.writeFdsCount = 0;
01117     
01118     Msg.Cmd.readFds = 0;
01119     Msg.Cmd.writeFds = 0; 
01120 
01121     
01122     if( readsds )
01123     {
01124        Msg.Cmd.readFds       = (_u16)readsds->fd_array[0];  
01125     }
01126     if( writesds )
01127     {
01128        Msg.Cmd.writeFds      = (_u16)writesds->fd_array[0]; 
01129     }
01130     if( NULL == timeout )
01131     {
01132         Msg.Cmd.tv_sec = 0xffff;
01133         Msg.Cmd.tv_usec = 0xffff;
01134     }
01135     else
01136     {
01137         if( 0xffff <= timeout->tv_sec ) 
01138         {
01139             Msg.Cmd.tv_sec = 0xffff;
01140         }
01141         else
01142         {
01143             Msg.Cmd.tv_sec = (_u16)timeout->tv_sec;
01144         }
01145         timeout->tv_usec = timeout->tv_usec >> 10;  /*  convert to milliseconds */
01146         if( 0xffff <= timeout->tv_usec )    
01147         {
01148             Msg.Cmd.tv_usec = 0xffff;
01149         }
01150         else
01151         {
01152             Msg.Cmd.tv_usec = (_u16)timeout->tv_usec;
01153         }
01154     }
01155 
01156     /* Use Obj to issue the command, if not available try later */
01157     ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, SELECT_ID, SL_MAX_SOCKETS);
01158 
01159     if (MAX_CONCURRENT_ACTIONS == ObjIdx)
01160     {
01161         return SL_POOL_IS_EMPTY;
01162     }
01163 
01164     
01165     /* send the command */
01166     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSelectCmdCtrl, &Msg, NULL));
01167 
01168     if(SL_OS_RET_CODE_OK == (_i16)Msg.Rsp.status)
01169     {
01170         SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->ObjPool[ObjIdx].SyncObj);
01171         
01172         Msg.Rsp.status = (_i16)AsyncRsp.status;
01173 
01174         if(  ((_i16)Msg.Rsp.status) >= 0 )
01175         {
01176             if( readsds )
01177             {
01178                readsds->fd_array[0]  = AsyncRsp.readFds;
01179             }
01180             if( writesds )
01181             {
01182                writesds->fd_array[0] = AsyncRsp.writeFds;      
01183             }
01184         }
01185     }
01186 
01187     _SlDrvReleasePoolObj(ObjIdx);
01188     return (_i16)Msg.Rsp.status;
01189 }
01190 
01191 /*  Select helper functions */
01192 /*******************************************************************************/
01193 /*  SL_FD_SET */
01194 /* ******************************************************************************/
01195 void SL_FD_SET(_i16 fd, SlFdSet_t *fdset)
01196 {
01197    fdset->fd_array[0] |=  (1<< (fd & BSD_SOCKET_ID_MASK));
01198 }
01199 /*******************************************************************************/
01200 /*  SL_FD_CLR */
01201 /*******************************************************************************/
01202 void SL_FD_CLR(_i16 fd, SlFdSet_t *fdset)
01203 {
01204   fdset->fd_array[0] &=  ~(1<< (fd & BSD_SOCKET_ID_MASK));
01205 }
01206 /*******************************************************************************/
01207 /*  SL_FD_ISSET */
01208 /*******************************************************************************/
01209 _i16  SL_FD_ISSET(_i16 fd, SlFdSet_t *fdset)
01210 {
01211   if( fdset->fd_array[0] & (1<< (fd & BSD_SOCKET_ID_MASK)) )
01212   {
01213     return 1;
01214   }
01215   return 0;
01216 }
01217 /*******************************************************************************/
01218 /*  SL_FD_ZERO */
01219 /*******************************************************************************/  
01220 void SL_FD_ZERO(SlFdSet_t *fdset)
01221 {
01222   fdset->fd_array[0] = 0;
01223 }
01224 
01225 #endif
01226 #endif
01227 
01228 
01229