Port of TI's CC3100 Websock camera demo. Using FreeRTOS, mbedTLS, also parts of Arducam for cams ov5642 and 0v2640. Can also use MT9D111. Work in progress. Be warned some parts maybe a bit flacky. This is for Seeed Arch max only, for an M3, see the demo for CM3 using the 0v5642 aducam mini.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers cc3100_socket.cpp Source File

cc3100_socket.cpp

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