TI's CC3100 websocket camera demo with Arducam mini ov5642 and freertos. Should work with other M3's. Work in progress test demo.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers cc3100_driver.cpp Source File

cc3100_driver.cpp

00001 /*
00002 * driver.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 /* Include files                                                             */
00039 /*****************************************************************************/
00040 #include "cc3100_simplelink.h"
00041 #include "cc3100_protocol.h"
00042 #include "cc3100_driver.h"
00043 
00044 #include "fPtr_func.h"
00045 #include "cli_uart.h"
00046 
00047 #if (defined (SL_PLATFORM_MULTI_THREADED)) || (defined (SL_PLATFORM_EXTERNAL_SPAWN))
00048 #include "osi.h"
00049 #endif
00050 
00051 /*****************************************************************************/
00052 /* Macro declarations                                                        */
00053 /*****************************************************************************/
00054 
00055 namespace mbed_cc3100 {
00056 
00057 #ifndef SL_MEMORY_MGMT_DYNAMIC
00058 typedef struct {
00059     uint32_t      Align;
00060     _SlDriverCb_t DriverCB;
00061     uint8_t AsyncRespBuf[SL_ASYNC_MAX_MSG_LEN];
00062 } _SlStatMem_t;
00063 
00064 _SlStatMem_t g_StatMem;
00065 #endif
00066 
00067 
00068 _SlDriverCb_t* g_pCB = NULL;
00069 
00070 uint8_t gFirstCmdMode = 0;
00071 
00072 const _SlSyncPattern_t g_H2NSyncPattern = H2N_SYNC_PATTERN;
00073 const _SlSyncPattern_t g_H2NCnysPattern = H2N_CNYS_PATTERN;
00074 volatile uint8_t RxIrqCnt;
00075 
00076 #ifndef SL_TINY_EXT
00077 const _SlActionLookup_t _SlActionLookupTable[] = {
00078     {ACCEPT_ID, SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE, (_SlSpawnEntryFunc_t) &_sl_HandleAsync_Accept},
00079     {CONNECT_ID, SL_OPCODE_SOCKET_CONNECTASYNCRESPONSE,(_SlSpawnEntryFunc_t) &_sl_HandleAsync_Connect},
00080     {SELECT_ID, SL_OPCODE_SOCKET_SELECTASYNCRESPONSE,(_SlSpawnEntryFunc_t) &_sl_HandleAsync_Select},
00081     {GETHOSYBYNAME_ID, SL_OPCODE_NETAPP_DNSGETHOSTBYNAMEASYNCRESPONSE,(_SlSpawnEntryFunc_t) &_sl_HandleAsync_DnsGetHostByName},
00082     {GETHOSYBYSERVICE_ID, SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICEASYNCRESPONSE,(_SlSpawnEntryFunc_t) &_sl_HandleAsync_DnsGetHostByService},
00083     {PING_ID, SL_OPCODE_NETAPP_PINGREPORTREQUESTRESPONSE, (_SlSpawnEntryFunc_t) &_sl_HandleAsync_PingResponse},
00084     {START_STOP_ID, SL_OPCODE_DEVICE_STOP_ASYNC_RESPONSE,(_SlSpawnEntryFunc_t) &_sl_HandleAsync_Stop}
00085 
00086 };
00087 #else
00088 const _SlActionLookup_t _SlActionLookupTable[] = 
00089 {
00090     {CONNECT_ID, SL_OPCODE_SOCKET_CONNECTASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_Connect},
00091     {GETHOSYBYNAME_ID, SL_OPCODE_NETAPP_DNSGETHOSTBYNAMEASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_DnsGetHostByName},  
00092     {START_STOP_ID, SL_OPCODE_DEVICE_STOP_ASYNC_RESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_Stop}
00093 };
00094 #endif
00095 
00096 typedef struct
00097 {
00098     uint16_t opcode;
00099     uint8_t  event;
00100 } OpcodeKeyVal_t;
00101 
00102 /* The table translates opcode to user's event type */
00103 const OpcodeKeyVal_t OpcodeTranslateTable[] = 
00104 {
00105 {SL_OPCODE_WLAN_SMART_CONFIG_START_ASYNC_RESPONSE, SL_WLAN_SMART_CONFIG_COMPLETE_EVENT},
00106 {SL_OPCODE_WLAN_SMART_CONFIG_STOP_ASYNC_RESPONSE,SL_WLAN_SMART_CONFIG_STOP_EVENT},
00107 {SL_OPCODE_WLAN_STA_CONNECTED, SL_WLAN_STA_CONNECTED_EVENT},
00108 {SL_OPCODE_WLAN_STA_DISCONNECTED,SL_WLAN_STA_DISCONNECTED_EVENT},
00109 {SL_OPCODE_WLAN_P2P_DEV_FOUND,SL_WLAN_P2P_DEV_FOUND_EVENT},    
00110 {SL_OPCODE_WLAN_P2P_NEG_REQ_RECEIVED, SL_WLAN_P2P_NEG_REQ_RECEIVED_EVENT},
00111 {SL_OPCODE_WLAN_CONNECTION_FAILED, SL_WLAN_CONNECTION_FAILED_EVENT},
00112 {SL_OPCODE_WLAN_WLANASYNCCONNECTEDRESPONSE, SL_WLAN_CONNECT_EVENT},
00113 {SL_OPCODE_WLAN_WLANASYNCDISCONNECTEDRESPONSE, SL_WLAN_DISCONNECT_EVENT},
00114 {SL_OPCODE_NETAPP_IPACQUIRED, SL_NETAPP_IPV4_IPACQUIRED_EVENT},
00115 {SL_OPCODE_NETAPP_IPACQUIRED_V6, SL_NETAPP_IPV6_IPACQUIRED_EVENT},
00116 {SL_OPCODE_NETAPP_IP_LEASED, SL_NETAPP_IP_LEASED_EVENT},
00117 {SL_OPCODE_NETAPP_IP_RELEASED, SL_NETAPP_IP_RELEASED_EVENT},
00118 {SL_OPCODE_SOCKET_TXFAILEDASYNCRESPONSE, SL_SOCKET_TX_FAILED_EVENT},
00119 {SL_OPCODE_SOCKET_SOCKETASYNCEVENT, SL_SOCKET_ASYNC_EVENT}
00120 };
00121 
00122 /*
00123 
00124 #define SL_OPCODE_SILO_DEVICE                           ( 0x0 << SL_OPCODE_SILO_OFFSET )
00125 #define SL_OPCODE_SILO_WLAN                             ( 0x1 << SL_OPCODE_SILO_OFFSET )
00126 #define SL_OPCODE_SILO_SOCKET                           ( 0x2 << SL_OPCODE_SILO_OFFSET )
00127 #define SL_OPCODE_SILO_NETAPP                           ( 0x3 << SL_OPCODE_SILO_OFFSET )
00128 #define SL_OPCODE_SILO_NVMEM                            ( 0x4 << SL_OPCODE_SILO_OFFSET )
00129 #define SL_OPCODE_SILO_NETCFG                           ( 0x5 << SL_OPCODE_SILO_OFFSET )
00130 
00131 
00132 */
00133 
00134 /* The Lookup table below holds the event handlers to be called according to the incoming
00135     RX message SILO type */
00136 const _SlSpawnEntryFunc_t RxMsgClassLUT[] = {
00137     (_SlSpawnEntryFunc_t)_SlDrvDeviceEventHandler, /* SL_OPCODE_SILO_DEVICE */
00138 #if defined(sl_WlanEvtHdlr) || defined(EXT_LIB_REGISTERED_WLAN_EVENTS)
00139     (_SlSpawnEntryFunc_t)_SlDrvHandleWlanEvents,           /* SL_OPCODE_SILO_WLAN */
00140 #else
00141     NULL,
00142 #endif
00143 #if defined (sl_SockEvtHdlr) || defined(EXT_LIB_REGISTERED_SOCK_EVENTS)
00144     (_SlSpawnEntryFunc_t)_SlDrvHandleSockEvents,   /* SL_OPCODE_SILO_SOCKET */
00145 #else
00146     NULL,
00147 #endif
00148 
00149 #if defined(sl_NetAppEvtHdlr) || defined(EXT_LIB_REGISTERED_NETAPP_EVENTS)
00150     (_SlSpawnEntryFunc_t)_SlDrvHandleNetAppEvents, /* SL_OPCODE_SILO_NETAPP */
00151 #else
00152     NULL,  
00153 #endif
00154     NULL,                                          /* SL_OPCODE_SILO_NVMEM */
00155     NULL,                                          /* SL_OPCODE_SILO_NETCFG */
00156     NULL,
00157     NULL
00158 };
00159 
00160 #ifndef SL_PLATFORM_MULTI_THREADED
00161 cc3100_driver::cc3100_driver(cc3100_spi &spi, cc3100_nonos &nonos, cc3100_netapp &netapp, cc3100_flowcont &flowcont)
00162     :  _spi(spi), _nonos(nonos), _netapp(netapp), _flowcont(flowcont)
00163 {
00164 }
00165 #else
00166 
00167 cc3100_driver::cc3100_driver(cc3100_spi &spi, cc3100_netapp &netapp, cc3100_flowcont &flowcont)
00168     :  _spi(spi), _netapp(netapp), _flowcont(flowcont)
00169 {
00170 }
00171 #endif
00172 
00173 cc3100_driver::~cc3100_driver()
00174 {
00175 
00176 }
00177 
00178 /*****************************************************************************/
00179 /* Variables                                                                 */
00180 /*****************************************************************************/
00181 
00182 /********************************************************************************/
00183 
00184 uint8_t cc3100_driver::_SlDrvProtectAsyncRespSetting(uint8_t *pAsyncRsp, uint8_t ActionID, uint8_t SocketID)
00185 {
00186     uint8_t ObjIdx;
00187 
00188 
00189     /* Use Obj to issue the command, if not available try later */
00190     ObjIdx = _SlDrvWaitForPoolObj(ActionID, SocketID);
00191 
00192     if (MAX_CONCURRENT_ACTIONS != ObjIdx)
00193     {
00194         _SlDrvProtectionObjLockWaitForever();
00195         g_pCB->ObjPool[ObjIdx].pRespArgs = pAsyncRsp;
00196         _SlDrvProtectionObjUnLock();
00197     }
00198 
00199     return ObjIdx;
00200 }
00201 
00202 
00203 /*****************************************************************************/
00204 /* Internal functions                                                        */
00205 /*****************************************************************************/
00206 bool cc3100_driver::_SL_PENDING_RX_MSG(pDriver* pDriverCB){
00207     
00208     if(RxIrqCnt != (pDriverCB)->RxDoneCnt){
00209         return TRUE;
00210     }else{
00211         return FALSE;
00212     }
00213 }
00214 
00215 /*****************************************************************************
00216 _SlDrvDriverCBInit - init Driver Control Block
00217 *****************************************************************************/
00218 void cc3100_driver::_SlDrvDriverCBInit(void)
00219 {
00220     
00221     uint8_t Idx = 0;
00222 
00223 #ifdef SL_MEMORY_MGMT_DYNAMIC
00224 
00225     g_pCB = sl_Malloc(sizeof(_SlDriverCb_t));
00226 #else
00227     g_pCB = &(g_StatMem.DriverCB);
00228 #endif
00229    
00230     MALLOC_OK_CHECK(g_pCB);
00231     _SlDrvMemZero(g_pCB, sizeof(_SlDriverCb_t));
00232     RxIrqCnt = 0;
00233 #ifndef SL_PLATFORM_MULTI_THREADED
00234     OSI_RET_OK_CHECK( _nonos.sl_SyncObjCreate(&g_pCB->CmdSyncObj, "CmdSyncObj") );
00235     _nonos.sl_SyncObjClear(&g_pCB->CmdSyncObj);
00236     OSI_RET_OK_CHECK( _nonos.sl_LockObjCreate(&g_pCB->GlobalLockObj, "GlobalLockObj") );
00237     OSI_RET_OK_CHECK( _nonos.sl_LockObjCreate(&g_pCB->ProtectionLockObj, "ProtectionLockObj") );
00238 #else    
00239     OSI_RET_OK_CHECK( sl_SyncObjCreate(&g_pCB->CmdSyncObj, "CmdSyncObj") );
00240     sl_SyncObjClear(&g_pCB->CmdSyncObj);
00241     OSI_RET_OK_CHECK( sl_LockObjCreate(&g_pCB->GlobalLockObj, "GlobalLockObj") );
00242     OSI_RET_OK_CHECK( sl_LockObjCreate(&g_pCB->ProtectionLockObj, "ProtectionLockObj") );
00243 #endif    
00244     /* Init Drv object */
00245     _SlDrvMemZero(&g_pCB->ObjPool[0], MAX_CONCURRENT_ACTIONS*sizeof(_SlPoolObj_t));
00246 
00247     /* place all Obj in the free list*/
00248     g_pCB->FreePoolIdx = 0;
00249 
00250     for (Idx = 0 ; Idx < MAX_CONCURRENT_ACTIONS ; Idx++)
00251     {
00252         g_pCB->ObjPool[Idx].NextIndex = Idx + 1;
00253         g_pCB->ObjPool[Idx].AdditionalData = SL_MAX_SOCKETS;
00254 #ifndef SL_PLATFORM_MULTI_THREADED
00255         OSI_RET_OK_CHECK( _nonos.sl_SyncObjCreate(&g_pCB->ObjPool[Idx].SyncObj, "SyncObj"));
00256         _nonos.sl_SyncObjClear(&g_pCB->ObjPool[Idx].SyncObj);
00257 #else
00258         OSI_RET_OK_CHECK( sl_SyncObjCreate(&g_pCB->ObjPool[Idx].SyncObj, "SyncObj"));
00259         sl_SyncObjClear(&g_pCB->ObjPool[Idx].SyncObj);
00260 #endif               
00261     }
00262 
00263      g_pCB->ActivePoolIdx = MAX_CONCURRENT_ACTIONS;
00264      g_pCB->PendingPoolIdx = MAX_CONCURRENT_ACTIONS;
00265 
00266     /* Flow control init */
00267     g_pCB->FlowContCB.TxPoolCnt = FLOW_CONT_MIN;
00268 #ifndef SL_PLATFORM_MULTI_THREADED   
00269     OSI_RET_OK_CHECK(_nonos.sl_LockObjCreate(&g_pCB->FlowContCB.TxLockObj, "TxLockObj"));
00270     OSI_RET_OK_CHECK(_nonos.sl_SyncObjCreate(&g_pCB->FlowContCB.TxSyncObj, "TxSyncObj"));
00271 #else
00272     OSI_RET_OK_CHECK(sl_LockObjCreate(&g_pCB->FlowContCB.TxLockObj, "TxLockObj"));
00273     OSI_RET_OK_CHECK(sl_SyncObjCreate(&g_pCB->FlowContCB.TxSyncObj, "TxSyncObj"));
00274 #endif  
00275     gFirstCmdMode = 0;  
00276 }
00277 
00278 /*****************************************************************************
00279 _SlDrvDriverCBDeinit - De init Driver Control Block
00280 *****************************************************************************/
00281 void cc3100_driver::_SlDrvDriverCBDeinit()
00282 {
00283     uint8_t        Idx = 0;
00284     
00285     /* Flow control de-init */
00286     g_pCB->FlowContCB.TxPoolCnt = 0;
00287 #ifndef SL_PLATFORM_MULTI_THREADED    
00288     OSI_RET_OK_CHECK(_nonos.sl_LockObjDelete(&g_pCB->FlowContCB.TxLockObj));
00289     OSI_RET_OK_CHECK(_nonos.sl_SyncObjDelete(&g_pCB->FlowContCB.TxSyncObj));
00290     
00291     OSI_RET_OK_CHECK( _nonos.sl_SyncObjDelete(&g_pCB->CmdSyncObj) );
00292     OSI_RET_OK_CHECK( _nonos.sl_LockObjDelete(&g_pCB->GlobalLockObj) );
00293     OSI_RET_OK_CHECK( _nonos.sl_LockObjDelete(&g_pCB->ProtectionLockObj) );
00294 #else    
00295     OSI_RET_OK_CHECK(sl_LockObjDelete(&g_pCB->FlowContCB.TxLockObj));
00296     OSI_RET_OK_CHECK(sl_SyncObjDelete(&g_pCB->FlowContCB.TxSyncObj));
00297     
00298     OSI_RET_OK_CHECK( sl_SyncObjDelete(&g_pCB->CmdSyncObj) );
00299     OSI_RET_OK_CHECK( sl_LockObjDelete(&g_pCB->GlobalLockObj) );
00300     OSI_RET_OK_CHECK( sl_LockObjDelete(&g_pCB->ProtectionLockObj) );   
00301 #endif
00302     
00303 #ifndef SL_TINY_EXT
00304     for (Idx = 0; Idx < MAX_CONCURRENT_ACTIONS; Idx++)
00305 #endif
00306 
00307     g_pCB->FreePoolIdx = 0;
00308     g_pCB->PendingPoolIdx = MAX_CONCURRENT_ACTIONS;
00309     g_pCB->ActivePoolIdx = MAX_CONCURRENT_ACTIONS;
00310 
00311 #ifdef SL_MEMORY_MGMT_DYNAMIC
00312     sl_Free(g_pCB);
00313 #else
00314     g_pCB = NULL;
00315 #endif
00316 
00317     g_pCB = NULL;
00318 }
00319 
00320 /*****************************************************************************
00321 _SlDrvRxIrqHandler - Interrupt handler
00322 *****************************************************************************/
00323 
00324 void cc3100_driver::_SlDrvRxIrqHandler(void *pValue)
00325 {
00326     
00327     int32_t rv = 0;
00328     _spi.MaskIntHdlr();
00329     
00330     RxIrqCnt++;
00331     
00332     if (TRUE == g_pCB->IsCmdRespWaited) {
00333 #ifndef SL_PLATFORM_MULTI_THREADED      
00334         OSI_RET_OK_CHECK( _nonos.sl_SyncObjSignalFromIRQ(&g_pCB->CmdSyncObj) );
00335 #else        
00336         OSI_RET_OK_CHECK( sl_SyncObjSignalFromIRQ(&g_pCB->CmdSyncObj) );
00337 #endif       
00338     } else {
00339 #if (defined (SL_PLATFORM_MULTI_THREADED)) || (defined (SL_PLATFORM_EXTERNAL_SPAWN))               
00340         rv = sl_Spawn((_SlSpawnEntryFunc_t)_SlDrvMsgReadSpawnCtx, NULL, 0);
00341 
00342         if(rv <0){
00343            Uart_Write((uint8_t*)"\n\r OSI_OPERATION_FAILED \n\r");
00344         }   
00345 #else        
00346         _nonos._SlNonOsSpawn((_SlSpawnEntryFunc_t)&_SlDrvMsgReadSpawnCtx, NULL, 0);
00347 #endif      
00348        
00349     }
00350 }
00351 
00352 /*****************************************************************************
00353 _SlDrvCmdOp
00354 *****************************************************************************/
00355 _SlReturnVal_t cc3100_driver::_SlDrvCmdOp(_SlCmdCtrl_t *pCmdCtrl,void* pTxRxDescBuff, _SlCmdExt_t *pCmdExt)
00356 {
00357     _SlReturnVal_t RetVal;
00358     
00359     _SlDrvObjLockWaitForever(&g_pCB->GlobalLockObj);
00360     
00361     g_pCB->IsCmdRespWaited = TRUE;
00362     SL_TRACE0(DBG_MSG, MSG_312, "_SlDrvCmdOp: call _SlDrvMsgWrite");
00363     
00364     /* send the message */
00365     RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, (uint8_t*)pTxRxDescBuff);
00366     
00367     if(SL_OS_RET_CODE_OK == RetVal) {
00368 
00369 #ifndef SL_IF_TYPE_UART
00370         /* Waiting for SPI to stabilize after first command */
00371         if( 0 == gFirstCmdMode ) {           
00372             gFirstCmdMode = 1;
00373             wait_ms(2);
00374         }
00375 #endif
00376         
00377         /* wait for respond */
00378         RetVal = _SlDrvMsgReadCmdCtx(); /* will free global lock */
00379         SL_TRACE0(DBG_MSG, MSG_314, "_SlDrvCmdOp: exited _SlDrvMsgReadCmdCtx");
00380         
00381     } else 
00382     {
00383         _SlDrvObjUnLock(&g_pCB->GlobalLockObj);
00384     }
00385     return RetVal;
00386 }
00387 
00388 /*****************************************************************************
00389 _SlDrvDataReadOp
00390 *****************************************************************************/
00391 _SlReturnVal_t cc3100_driver::_SlDrvDataReadOp(_SlSd_t Sd, _SlCmdCtrl_t *pCmdCtrl, void* pTxRxDescBuff, _SlCmdExt_t *pCmdExt)
00392 {
00393     _SlReturnVal_t RetVal;
00394     uint8_t ObjIdx = MAX_CONCURRENT_ACTIONS;
00395     _SlArgsData_t pArgsData;
00396 
00397     /* Validate input arguments */
00398     VERIFY_PROTOCOL(NULL != pCmdExt->pRxPayload);
00399 
00400     /* If zero bytes is requested, return error. */
00401     /*  This allows us not to fill remote socket's IP address in return arguments */
00402     VERIFY_PROTOCOL(0 != pCmdExt->RxPayloadLen);
00403 
00404     /* Validate socket */
00405     if((Sd & BSD_SOCKET_ID_MASK) >= SL_MAX_SOCKETS) {
00406         return SL_EBADF;
00407     }
00408 
00409     /*Use Obj to issue the command, if not available try later*/
00410     ObjIdx = (uint8_t)_SlDrvWaitForPoolObj(RECV_ID, Sd & BSD_SOCKET_ID_MASK);
00411 
00412     if (MAX_CONCURRENT_ACTIONS == ObjIdx) {
00413         return SL_POOL_IS_EMPTY;
00414     }
00415     
00416     _SlDrvProtectionObjLockWaitForever();
00417     
00418     pArgsData.pData = pCmdExt->pRxPayload;
00419     pArgsData.pArgs =  (uint8_t *)pTxRxDescBuff;
00420     g_pCB->ObjPool[ObjIdx].pRespArgs =  (uint8_t *)&pArgsData;
00421     _SlDrvProtectionObjUnLock();
00422 
00423     /* Do Flow Control check/update for DataWrite operation */
00424     _SlDrvObjLockWaitForever(&g_pCB->FlowContCB.TxLockObj);
00425     
00426     /* Clear SyncObj for the case it was signalled before TxPoolCnt */
00427     /* dropped below '1' (last Data buffer was taken)  */
00428     /* OSI_RET_OK_CHECK( sl_SyncObjClear(&g_pCB->FlowContCB.TxSyncObj) ); */
00429 #ifndef SL_PLATFORM_MULTI_THREADED       
00430     _nonos.sl_SyncObjClear(&g_pCB->FlowContCB.TxSyncObj);
00431 #else    
00432     sl_SyncObjClear(&g_pCB->FlowContCB.TxSyncObj);
00433 #endif
00434     if(g_pCB->FlowContCB.TxPoolCnt <= FLOW_CONT_MIN) {
00435 
00436         /* If TxPoolCnt was increased by other thread at this moment,
00437         TxSyncObj won't wait here */
00438     _SlDrvSyncObjWaitForever(&g_pCB->FlowContCB.TxSyncObj);
00439        
00440     }
00441 
00442     _SlDrvObjLockWaitForever(&g_pCB->GlobalLockObj);
00443 
00444     VERIFY_PROTOCOL(g_pCB->FlowContCB.TxPoolCnt > FLOW_CONT_MIN);
00445     g_pCB->FlowContCB.TxPoolCnt--;
00446 
00447     _SlDrvObjUnLock(&g_pCB->FlowContCB.TxLockObj);
00448 
00449     /* send the message */
00450     RetVal =  _SlDrvMsgWrite(pCmdCtrl, pCmdExt, (uint8_t *)pTxRxDescBuff);
00451 
00452     _SlDrvObjUnLock(&g_pCB->GlobalLockObj);
00453 
00454     if(SL_OS_RET_CODE_OK == RetVal) {
00455         /* Wait for response message. Will be signaled by _SlDrvMsgRead. */
00456         _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj);
00457     }
00458 
00459     _SlDrvReleasePoolObj(ObjIdx);
00460     return RetVal;
00461 }
00462 
00463 /* ******************************************************************************/
00464 /*   _SlDrvDataWriteOp                                                          */
00465 /* ******************************************************************************/
00466 _SlReturnVal_t cc3100_driver::_SlDrvDataWriteOp(_SlSd_t Sd, _SlCmdCtrl_t *pCmdCtrl, void* pTxRxDescBuff, _SlCmdExt_t *pCmdExt)
00467 {
00468     _SlReturnVal_t  RetVal = SL_EAGAIN; /*  initiated as SL_EAGAIN for the non blocking mode */
00469     while( 1 ) {
00470         /*  Do Flow Control check/update for DataWrite operation */        
00471         _SlDrvObjLockWaitForever(&g_pCB->FlowContCB.TxLockObj);
00472 
00473         /*  Clear SyncObj for the case it was signalled before TxPoolCnt */
00474         /*  dropped below '1' (last Data buffer was taken) */
00475         /* OSI_RET_OK_CHECK( sl_SyncObjClear(&g_pCB->FlowContCB.TxSyncObj) ); */
00476 #ifndef SL_PLATFORM_MULTI_THREADED               
00477         _nonos.sl_SyncObjClear(&g_pCB->FlowContCB.TxSyncObj);
00478 #else        
00479         sl_SyncObjClear(&g_pCB->FlowContCB.TxSyncObj);
00480 #endif               
00481         /*  we have indication that the last send has failed - socket is no longer valid for operations  */
00482         if(g_pCB->SocketTXFailure & (1<<(Sd & BSD_SOCKET_ID_MASK))) {
00483             _SlDrvObjUnLock(&g_pCB->FlowContCB.TxLockObj);
00484             return SL_SOC_ERROR;
00485         }
00486         
00487         if(g_pCB->FlowContCB.TxPoolCnt <= FLOW_CONT_MIN + 1) {
00488             /*  we have indication that this socket is set as blocking and we try to  */
00489             /*  unblock it - return an error */
00490             if( g_pCB->SocketNonBlocking & (1<< (Sd & BSD_SOCKET_ID_MASK)))
00491             {
00492             _SlDrvObjUnLock(&g_pCB->FlowContCB.TxLockObj);
00493                 return RetVal;
00494             }
00495             /*  If TxPoolCnt was increased by other thread at this moment, */
00496             /*  TxSyncObj won't wait here */
00497             _SlDrvSyncObjWaitForever(&g_pCB->FlowContCB.TxSyncObj);
00498         }
00499 
00500         if(g_pCB->FlowContCB.TxPoolCnt > FLOW_CONT_MIN + 1 ) {
00501             break;
00502         } 
00503         else 
00504         {
00505         _SlDrvObjUnLock(&g_pCB->FlowContCB.TxLockObj);
00506         }
00507     }
00508 
00509     _SlDrvObjLockWaitForever(&g_pCB->GlobalLockObj);
00510 
00511 
00512     VERIFY_PROTOCOL(g_pCB->FlowContCB.TxPoolCnt > FLOW_CONT_MIN + 1 );
00513     g_pCB->FlowContCB.TxPoolCnt--;
00514 
00515     _SlDrvObjUnLock(&g_pCB->FlowContCB.TxLockObj);
00516     
00517     /* send the message */
00518     RetVal =  _SlDrvMsgWrite(pCmdCtrl, pCmdExt, (uint8_t*)pTxRxDescBuff);
00519 
00520     _SlDrvObjUnLock(&g_pCB->GlobalLockObj);
00521 
00522     return RetVal;
00523 }
00524 
00525 /* ******************************************************************************/
00526 /*  _SlDrvMsgWrite */
00527 /* ******************************************************************************/
00528 _SlReturnVal_t cc3100_driver::_SlDrvMsgWrite(_SlCmdCtrl_t  *pCmdCtrl, _SlCmdExt_t  *pCmdExt, uint8_t *pTxRxDescBuff)
00529 {
00530     uint8_t sendRxPayload = FALSE;
00531     VERIFY_PROTOCOL(NULL != pCmdCtrl);
00532 
00533     g_pCB->FunctionParams.pCmdCtrl = pCmdCtrl;
00534     g_pCB->FunctionParams.pTxRxDescBuff = pTxRxDescBuff;
00535     g_pCB->FunctionParams.pCmdExt = pCmdExt;
00536     
00537     g_pCB->TempProtocolHeader.Opcode   = pCmdCtrl->Opcode;
00538     g_pCB->TempProtocolHeader.Len   = _SL_PROTOCOL_CALC_LEN(pCmdCtrl, pCmdExt);
00539 
00540     if (pCmdExt && pCmdExt->RxPayloadLen < 0 && pCmdExt->TxPayloadLen)
00541     {
00542         pCmdExt->RxPayloadLen = pCmdExt->RxPayloadLen * (-1); /* change sign */
00543         sendRxPayload = TRUE;
00544         g_pCB->TempProtocolHeader.Len = g_pCB->TempProtocolHeader.Len + pCmdExt->RxPayloadLen;
00545     }
00546     
00547 #ifdef SL_START_WRITE_STAT
00548     sl_IfStartWriteSequence(g_pCB->FD);
00549 #endif
00550 
00551 #ifdef SL_IF_TYPE_UART
00552     /*  Write long sync pattern */
00553     _spi.spi_Write(g_pCB->FD, (uint8_t *)&g_H2NSyncPattern.Long, 2*SYNC_PATTERN_LEN);
00554 #else
00555     /*  Write short sync pattern */
00556     _spi.spi_Write(g_pCB->FD, (uint8_t *)&g_H2NSyncPattern.Short, SYNC_PATTERN_LEN);
00557 #endif
00558     /*  Header */
00559     _spi.spi_Write(g_pCB->FD, (uint8_t *)&g_pCB->TempProtocolHeader, _SL_CMD_HDR_SIZE);
00560 
00561     /*  Descriptors */
00562     if (pTxRxDescBuff && pCmdCtrl->TxDescLen > 0)
00563     {
00564         _spi.spi_Write(g_pCB->FD, pTxRxDescBuff, 
00565                            _SL_PROTOCOL_ALIGN_SIZE(pCmdCtrl->TxDescLen));
00566     }
00567 
00568     /*  A special mode where Rx payload and Rx length are used as Tx as well */
00569     /*  This mode requires no Rx payload on the response and currently used by fs_Close and sl_Send on */
00570     /*  transceiver mode */
00571     if (sendRxPayload == TRUE )
00572     {
00573         _spi.spi_Write(g_pCB->FD, pCmdExt->pRxPayload, _SL_PROTOCOL_ALIGN_SIZE(pCmdExt->RxPayloadLen));
00574     }
00575 
00576     /*  Payload */
00577     if (pCmdExt && pCmdExt->TxPayloadLen > 0)
00578     {
00579         /*  If the message has payload, it is mandatory that the message's arguments are protocol aligned. */
00580         /*  Otherwise the aligning of arguments will create a gap between arguments and payload. */
00581         VERIFY_PROTOCOL(_SL_IS_PROTOCOL_ALIGNED_SIZE(pCmdCtrl->TxDescLen));
00582 
00583         _spi.spi_Write(g_pCB->FD, pCmdExt->pTxPayload, _SL_PROTOCOL_ALIGN_SIZE(pCmdExt->TxPayloadLen));
00584     }
00585 
00586     _SL_DBG_CNT_INC(MsgCnt.Write);
00587 
00588 #ifdef SL_START_WRITE_STAT
00589     sl_IfEndWriteSequence(g_pCB->FD);
00590 #endif
00591 
00592     return SL_OS_RET_CODE_OK;
00593 }
00594 
00595 /* ******************************************************************************/
00596 /*  _SlDrvMsgRead  */
00597 /* ******************************************************************************/
00598 _SlReturnVal_t cc3100_driver::_SlDrvMsgRead(void)
00599 {
00600     /*  alignment for small memory models */
00601     union {
00602       uint8_t             TempBuf[_SL_RESP_HDR_SIZE];
00603       uint32_t            DummyBuf[2];
00604     } uBuf;
00605     uint8_t               TailBuffer[4];
00606     uint16_t              LengthToCopy;
00607     uint16_t              AlignedLengthRecv;
00608     uint8_t               AlignSize;
00609     uint8_t               *pAsyncBuf = NULL;
00610     uint16_t              OpCode;
00611     uint16_t              RespPayloadLen;
00612     uint8_t               sd = SL_MAX_SOCKETS;
00613     _SlRxMsgClass_e   RxMsgClass;
00614     
00615 
00616     /* save params in global CB */
00617     g_pCB->FunctionParams.AsyncExt.pAsyncBuf      = NULL;
00618     g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler= NULL;
00619 
00620     
00621     VERIFY_RET_OK(_SlDrvRxHdrRead((uint8_t*)(uBuf.TempBuf), &AlignSize));
00622 
00623     OpCode = OPCODE(uBuf.TempBuf);
00624     RespPayloadLen = RSP_PAYLOAD_LEN(uBuf.TempBuf);
00625 
00626 
00627     /* 'Init Compelete' message bears no valid FlowControl info */
00628     if(SL_OPCODE_DEVICE_INITCOMPLETE != OpCode) {
00629         g_pCB->FlowContCB.TxPoolCnt = ((_SlResponseHeader_t *)uBuf.TempBuf)->TxPoolCnt;
00630         g_pCB->SocketNonBlocking = ((_SlResponseHeader_t *)uBuf.TempBuf)->SocketNonBlocking;
00631         g_pCB->SocketTXFailure = ((_SlResponseHeader_t *)uBuf.TempBuf)->SocketTXFailure;
00632 
00633         if(g_pCB->FlowContCB.TxPoolCnt > FLOW_CONT_MIN) {
00634             _SlDrvSyncObjSignal(&g_pCB->FlowContCB.TxSyncObj);
00635         }
00636     }
00637 
00638     /* Find the RX messaage class and set its async event handler */
00639     _SlDrvClassifyRxMsg(OpCode);
00640     
00641     RxMsgClass = g_pCB->FunctionParams.AsyncExt.RxMsgClass;
00642 
00643 
00644     switch(RxMsgClass)
00645     {
00646     case ASYNC_EVT_CLASS:
00647 
00648             VERIFY_PROTOCOL(NULL == pAsyncBuf);
00649 
00650 #ifdef SL_MEMORY_MGMT_DYNAMIC
00651         g_pCB->FunctionParams.AsyncExt.pAsyncBuf = sl_Malloc(SL_ASYNC_MAX_MSG_LEN);
00652 #else
00653         g_pCB->FunctionParams.AsyncExt.pAsyncBuf = g_StatMem.AsyncRespBuf;
00654 #endif
00655             /* set the local pointer to the allocated one */
00656             pAsyncBuf = g_pCB->FunctionParams.AsyncExt.pAsyncBuf;
00657 
00658             /* clear the async buffer */
00659             _SlDrvMemZero(pAsyncBuf, SL_ASYNC_MAX_MSG_LEN);
00660             
00661             MALLOC_OK_CHECK(pAsyncBuf);
00662 
00663             memcpy(pAsyncBuf, uBuf.TempBuf, _SL_RESP_HDR_SIZE);
00664             if (_SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen) <= SL_ASYNC_MAX_PAYLOAD_LEN)
00665             {
00666                 AlignedLengthRecv = _SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen);
00667             }
00668             else
00669             {
00670                 AlignedLengthRecv = _SL_PROTOCOL_ALIGN_SIZE(SL_ASYNC_MAX_PAYLOAD_LEN);
00671             }
00672             if (RespPayloadLen > 0)
00673             {
00674                 _spi.spi_Read(g_pCB->FD, pAsyncBuf + _SL_RESP_HDR_SIZE, AlignedLengthRecv);
00675             }
00676         /* In case ASYNC RX buffer length is smaller then the received data length, dump the rest */
00677             if ((_SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen) > SL_ASYNC_MAX_PAYLOAD_LEN))
00678             {
00679                 AlignedLengthRecv = _SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen) - SL_ASYNC_MAX_PAYLOAD_LEN;
00680                 while (AlignedLengthRecv > 0)
00681                 {
00682                 _spi.spi_Read(g_pCB->FD,TailBuffer,4);
00683                 AlignedLengthRecv = AlignedLengthRecv - 4;
00684                 }
00685             }
00686             
00687             _SlDrvProtectionObjLockWaitForever();
00688           
00689             if (
00690 #ifndef SL_TINY_EXT               
00691                 (SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE == OpCode) || (SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE_V6 == OpCode) || 
00692 #endif                
00693                 (SL_OPCODE_SOCKET_CONNECTASYNCRESPONSE == OpCode)
00694                )
00695             {
00696                 /* go over the active list if exist to find obj waiting for this Async event */
00697                 sd = ((((_SocketResponse_t *)(pAsyncBuf + _SL_RESP_HDR_SIZE))->sd) & BSD_SOCKET_ID_MASK);
00698             }
00699             _SlFindAndSetActiveObj(OpCode, sd);
00700             _SlDrvProtectionObjUnLock();
00701 
00702             break;
00703     case RECV_RESP_CLASS:
00704         {
00705             uint8_t ExpArgSize; /*  Expected size of Recv/Recvfrom arguments */
00706 
00707             switch(OpCode)
00708             {
00709             case SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE:
00710                 ExpArgSize = RECVFROM_IPV4_ARGS_SIZE;
00711                 break;
00712 #ifndef SL_TINY_EXT                        
00713             case SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE_V6:
00714                 ExpArgSize = RECVFROM_IPV6_ARGS_SIZE;
00715                 break;
00716 #endif                        
00717             default:
00718                 /* SL_OPCODE_SOCKET_RECVASYNCRESPONSE: */
00719                 ExpArgSize = RECV_ARGS_SIZE;
00720             }              
00721 
00722             /*  Read first 4 bytes of Recv/Recvfrom response to get SocketId and actual  */
00723             /*  response data length */
00724             _spi.spi_Read(g_pCB->FD, &uBuf.TempBuf[4], RECV_ARGS_SIZE);
00725 
00726             /*  Validate Socket ID and Received Length value.  */
00727             VERIFY_PROTOCOL((SD(&uBuf.TempBuf[4])& BSD_SOCKET_ID_MASK) < SL_MAX_SOCKETS);
00728 
00729             _SlDrvProtectionObjLockWaitForever();
00730 
00731             /* go over the active list if exist to find obj waiting for this Async event */
00732                 VERIFY_RET_OK(_SlFindAndSetActiveObj(OpCode,SD(&uBuf.TempBuf[4]) & BSD_SOCKET_ID_MASK));
00733 
00734             /*  Verify data is waited on this socket. The pArgs should have been set by _SlDrvDataReadOp(). */
00735             VERIFY_SOCKET_CB(NULL !=  ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pData))->pArgs);    
00736 
00737             memcpy( ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pArgs, &uBuf.TempBuf[4], RECV_ARGS_SIZE);
00738 
00739             if(ExpArgSize > RECV_ARGS_SIZE)
00740             {
00741                 _spi.spi_Read(g_pCB->FD,
00742                     ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pArgs + RECV_ARGS_SIZE,
00743                     ExpArgSize - RECV_ARGS_SIZE);
00744             }
00745 
00746             /*  Here g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pData contains requested(expected) Recv/Recvfrom DataSize. */
00747             /*  Overwrite requested DataSize with actual one. */
00748             /*  If error is received, this information will be read from arguments. */
00749             if(ACT_DATA_SIZE(&uBuf.TempBuf[4]) > 0)
00750             {       
00751                 VERIFY_SOCKET_CB(NULL != ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pData);
00752 
00753                 /*  Read 4 bytes aligned from interface */
00754                 /*  therefore check the requested length and read only  */
00755                 /*  4 bytes aligned data. The rest unaligned (if any) will be read */
00756                 /*  and copied to a TailBuffer  */
00757                 LengthToCopy = ACT_DATA_SIZE(&uBuf.TempBuf[4]) & (3);
00758                 AlignedLengthRecv = ACT_DATA_SIZE(&uBuf.TempBuf[4]) & (~3);
00759                 if( AlignedLengthRecv >= 4)
00760                 {
00761                     _spi.spi_Read(g_pCB->FD,((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pData,AlignedLengthRecv );                      
00762                 }
00763                 /*  copy the unaligned part, if any */
00764                 if( LengthToCopy > 0) 
00765                 {
00766                     _spi.spi_Read(g_pCB->FD,TailBuffer,4);
00767                     /*  copy TailBuffer unaligned part (1/2/3 bytes) */
00768                     memcpy(((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pData + AlignedLengthRecv,TailBuffer,LengthToCopy);                    
00769                 }                  
00770             }
00771                  _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
00772                  _SlDrvProtectionObjUnLock();
00773         }
00774         break;
00775 
00776         case CMD_RESP_CLASS:
00777 
00778             /*  Some commands pass a maximum arguments size. */
00779             /*  In this case Driver will send extra dummy patterns to NWP if */
00780             /*  the response message is smaller than maximum. */
00781             /*  When RxDescLen is not exact, using RxPayloadLen is forbidden! */
00782             /*  If such case cannot be avoided - parse message here to detect */
00783             /*  arguments/payload border. */
00784             _spi.spi_Read(g_pCB->FD, g_pCB->FunctionParams.pTxRxDescBuff, _SL_PROTOCOL_ALIGN_SIZE(g_pCB->FunctionParams.pCmdCtrl->RxDescLen));
00785 
00786             if((NULL != g_pCB->FunctionParams.pCmdExt) && (0 != g_pCB->FunctionParams.pCmdExt->RxPayloadLen)) {
00787                 /*  Actual size of command's response payload: <msg_payload_len> - <rsp_args_len> */
00788                 int16_t    ActDataSize = RSP_PAYLOAD_LEN(uBuf.TempBuf) - g_pCB->FunctionParams.pCmdCtrl->RxDescLen;
00789 
00790                 g_pCB->FunctionParams.pCmdExt->ActualRxPayloadLen = ActDataSize;
00791 
00792                 /* Check that the space prepared by user for the response data is sufficient. */
00793                 if(ActDataSize <= 0) {
00794                     g_pCB->FunctionParams.pCmdExt->RxPayloadLen = 0;
00795                 } else {
00796                     /* In case the user supplied Rx buffer length which is smaller then the received data length, copy according to user length */
00797                     if (ActDataSize > g_pCB->FunctionParams.pCmdExt->RxPayloadLen) {
00798                         LengthToCopy = g_pCB->FunctionParams.pCmdExt->RxPayloadLen & (3);
00799                         AlignedLengthRecv = g_pCB->FunctionParams.pCmdExt->RxPayloadLen & (~3);
00800                     } else {
00801                         LengthToCopy = ActDataSize & (3);
00802                         AlignedLengthRecv = ActDataSize & (~3);
00803                     }
00804                     /*  Read 4 bytes aligned from interface */
00805                     /*  therefore check the requested length and read only  */
00806                     /*  4 bytes aligned data. The rest unaligned (if any) will be read */
00807                     /*  and copied to a TailBuffer  */
00808 
00809                     if( AlignedLengthRecv >= 4) {
00810                         _spi.spi_Read(g_pCB->FD,
00811                                           g_pCB->FunctionParams.pCmdExt->pRxPayload,
00812                                           AlignedLengthRecv );
00813 
00814                     }
00815                     /*  copy the unaligned part, if any */
00816                     if( LengthToCopy > 0) {
00817                         _spi.spi_Read(g_pCB->FD,TailBuffer,4);
00818                         /*  copy TailBuffer unaligned part (1/2/3 bytes) */
00819                         memcpy(g_pCB->FunctionParams.pCmdExt->pRxPayload + AlignedLengthRecv,
00820                                   TailBuffer,
00821                                   LengthToCopy);
00822                         ActDataSize = ActDataSize-4;
00823                     }
00824                     /* In case the user supplied Rx buffer length which is smaller then the received data length, dump the rest */
00825                     if (ActDataSize > g_pCB->FunctionParams.pCmdExt->RxPayloadLen) {
00826                         /* calculate the rest of the data size to dump */
00827                         AlignedLengthRecv = ActDataSize - (g_pCB->FunctionParams.pCmdExt->RxPayloadLen & (~3));
00828                         while( AlignedLengthRecv > 0) {
00829                             _spi.spi_Read(g_pCB->FD,TailBuffer, 4 );
00830                             AlignedLengthRecv = AlignedLengthRecv - 4;
00831                         }
00832                     }
00833                 }
00834             }
00835             break;
00836 
00837         default:
00838             /*  DUMMY_MSG_CLASS: Flow control message has no payload. */
00839             break;
00840     }
00841 
00842     if(AlignSize > 0) {
00843         _spi.spi_Read(g_pCB->FD, uBuf.TempBuf, AlignSize);
00844     }
00845 
00846     _SL_DBG_CNT_INC(MsgCnt.Read);
00847 
00848     /*  Unmask Interrupt call */
00849     _spi.UnMaskIntHdlr();
00850     
00851     return SL_OS_RET_CODE_OK;
00852 }
00853 
00854 /* ******************************************************************************/
00855 /*  _SlAsyncEventGenericHandler */
00856 /* ******************************************************************************/
00857 void cc3100_driver::_SlAsyncEventGenericHandler(void)
00858 {
00859     uint32_t SlAsyncEvent = 0;
00860     uint8_t  OpcodeFound = FALSE; 
00861     uint8_t  i;
00862     
00863     uint32_t* pEventLocation  = NULL; /* This pointer will override the async buffer with the translated event type */
00864     _SlResponseHeader_t  *pHdr       = (_SlResponseHeader_t *)g_pCB->FunctionParams.AsyncExt.pAsyncBuf;
00865 
00866 
00867     /* if no async event registered nothing to do..*/
00868     if (g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler == NULL)
00869         return;
00870 
00871     /* Iterate through all the opcode in the table */
00872     for (i=0; i< (sizeof(OpcodeTranslateTable) / sizeof(OpcodeKeyVal_t)); i++)
00873     {
00874         if (OpcodeTranslateTable[i].opcode == pHdr->GenHeader.Opcode)
00875         {
00876             SlAsyncEvent = OpcodeTranslateTable[i].event;
00877             OpcodeFound = TRUE;
00878             break;
00879         }
00880     }
00881 
00882     /* No Async event found in the table */
00883     if (OpcodeFound == FALSE)
00884     {
00885         /* This case handles all the async events handlers of the DEVICE & SOCK Silos which are handled internally.
00886                  For these cases we send the async even buffer as is */
00887         g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler(g_pCB->FunctionParams.AsyncExt.pAsyncBuf);
00888     }
00889     else
00890     {
00891        /* calculate the event type location to be filled in the async buffer */
00892        pEventLocation = (uint32_t*)(g_pCB->FunctionParams.AsyncExt.pAsyncBuf + sizeof (_SlResponseHeader_t) - sizeof(SlAsyncEvent) );
00893 
00894        /* Override the async buffer (before the data starts ) with our event type  */
00895        *pEventLocation = SlAsyncEvent;
00896 
00897        /* call the event handler registered by the user with our async buffer which now holds
00898                 the User's event type and its related data */
00899        g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler(pEventLocation);
00900     }
00901     
00902 }
00903 
00904 
00905 /* ******************************************************************************/
00906 /*  _SlDrvMsgReadCmdCtx  */
00907 /* ******************************************************************************/
00908 _SlReturnVal_t cc3100_driver::_SlDrvMsgReadCmdCtx(void)
00909 {
00910 
00911     /*  after command response is received and isCmdRespWaited */
00912     /*  flag is set FALSE, it is necessary to read out all */
00913     /*  Async messages in Commands context, because ssiDma_IsrHandleSignalFromSlave */
00914     /*  could have dispatched some Async messages to g_NwpIf.CmdSyncObj */
00915     /*  after command response but before this response has been processed */
00916     /*  by spi_singleRead and isCmdRespWaited was set FALSE. */
00917     
00918     while (TRUE == g_pCB->IsCmdRespWaited) {
00919         
00920         if(_SL_PENDING_RX_MSG(g_pCB)) {
00921                        
00922             VERIFY_RET_OK(_SlDrvMsgRead());
00923             g_pCB->RxDoneCnt++;
00924            
00925             if (CMD_RESP_CLASS == g_pCB->FunctionParams.AsyncExt.RxMsgClass) {
00926                 g_pCB->IsCmdRespWaited = FALSE;
00927 
00928                 /*  In case CmdResp has been read without  waiting on CmdSyncObj -  that */
00929                 /*  Sync object. That to prevent old signal to be processed. */
00930 #ifndef SL_PLATFORM_MULTI_THREADED               
00931                 _nonos.sl_SyncObjClear(&g_pCB->CmdSyncObj);
00932 #else                
00933                 sl_SyncObjClear(&g_pCB->CmdSyncObj);
00934 #endif                
00935             } else if (ASYNC_EVT_CLASS == g_pCB->FunctionParams.AsyncExt.RxMsgClass) {
00936                 /*  If Async event has been read in CmdResp context, check whether */
00937                 /*  there is a handler for this event. If there is, spawn specific */
00938                 /*  handler. Otherwise free the event's buffer. */
00939                 /*  This way there will be no "dry shots" from CmdResp context to */
00940                 /*  temporary context, i.e less waste of CPU and faster buffer */
00941                 /*  release. */
00942                 _SlAsyncEventGenericHandler();
00943 
00944 #ifdef SL_MEMORY_MGMT_DYNAMIC
00945                 sl_Free(g_pCB->FunctionParams.AsyncExt.pAsyncBuf);
00946 #else
00947                 g_pCB->FunctionParams.AsyncExt.pAsyncBuf = NULL;
00948 #endif
00949             }
00950         } else {
00951             /* CmdSyncObj will be signaled by IRQ */
00952             _SlDrvSyncObjWaitForever(&g_pCB->CmdSyncObj);
00953         }
00954     }
00955     
00956     /*  If there are more pending Rx Msgs after CmdResp is received, */
00957     /*  that means that these are Async, Dummy or Read Data Msgs. */
00958     /*  Spawn _SlDrvMsgReadSpawnCtx to trigger reading these messages from */
00959     /*  Temporary context. */
00960     /* sl_Spawn is activated, using a different context */
00961     _SlDrvObjUnLock(&g_pCB->GlobalLockObj);
00962     
00963     if(_SL_PENDING_RX_MSG(g_pCB)) {
00964 #ifndef SL_PLATFORM_MULTI_THREADED      
00965       _nonos._SlNonOsSpawn((_SlSpawnEntryFunc_t)&_SlDrvMsgReadSpawnCtx, NULL, 0);
00966 #else
00967       sl_Spawn((_SlSpawnEntryFunc_t)&_SlDrvMsgReadSpawnCtx, NULL, 0);
00968 #endif      
00969     }
00970     
00971     return SL_OS_RET_CODE_OK;
00972 }
00973 
00974 /* ******************************************************************************/
00975 /*  _SlDrvClassifyRxMsg */
00976 /* ******************************************************************************/
00977 void cc3100_driver::_SlDrvClassifyRxMsg(_SlOpcode_t Opcode)
00978 {
00979     _SlSpawnEntryFunc_t AsyncEvtHandler = NULL;
00980     _SlRxMsgClass_e     RxMsgClass  = CMD_RESP_CLASS;
00981     uint8_t             Silo;
00982     
00983 
00984     if (0 == (SL_OPCODE_SYNC & Opcode))
00985     {   /* Async event has received */
00986         
00987         if (SL_OPCODE_DEVICE_DEVICEASYNCDUMMY == Opcode)
00988         { 
00989             RxMsgClass = DUMMY_MSG_CLASS;
00990         }
00991         else if ( (SL_OPCODE_SOCKET_RECVASYNCRESPONSE == Opcode) || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE == Opcode) 
00992 #ifndef SL_TINY_EXT                      
00993                     || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE_V6 == Opcode) 
00994 #endif                    
00995                  ) 
00996         {
00997             RxMsgClass = RECV_RESP_CLASS;
00998         }
00999         else
01000         {
01001             /* This is Async Event class message */
01002             RxMsgClass = ASYNC_EVT_CLASS;
01003         
01004             /* Despite the fact that 4 bits are allocated in the SILO field, we actually have only 6 SILOs
01005               So we can use the 8 options of SILO in look up table */
01006             Silo = ((Opcode >> SL_OPCODE_SILO_OFFSET) & 0x7);
01007 
01008             VERIFY_PROTOCOL(Silo < (sizeof(RxMsgClassLUT)/sizeof(_SlSpawnEntryFunc_t)));
01009 
01010             /* Set the async event hander according to the LUT */
01011             AsyncEvtHandler = RxMsgClassLUT[Silo];
01012             
01013             if ((SL_OPCODE_NETAPP_HTTPGETTOKENVALUE == Opcode) || (SL_OPCODE_NETAPP_HTTPPOSTTOKENVALUE == Opcode))
01014             {
01015                 AsyncEvtHandler = _SlDrvNetAppEventHandler;
01016             }
01017 #ifndef SL_TINY_EXT            
01018             else if (SL_OPCODE_NETAPP_PINGREPORTREQUESTRESPONSE == Opcode)
01019             {
01020                 AsyncEvtHandler = (_SlSpawnEntryFunc_t)_sl_HandleAsync_PingResponse;
01021             }
01022 #endif
01023         }
01024     }
01025 
01026     g_pCB->FunctionParams.AsyncExt.RxMsgClass = RxMsgClass; 
01027     g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler = AsyncEvtHandler;
01028 
01029 }
01030 
01031 /* ******************************************************************************/
01032 /*  _SlDrvRxHdrRead  */
01033 /* ******************************************************************************/
01034 _SlReturnVal_t  cc3100_driver::_SlDrvRxHdrRead(uint8_t *pBuf, uint8_t *pAlignSize)
01035 {
01036     uint32_t       SyncCnt  = 0;
01037     uint8_t        ShiftIdx;      
01038     
01039 #ifndef SL_IF_TYPE_UART
01040     /*  1. Write CNYS pattern to NWP when working in SPI mode only  */
01041     _spi.spi_Write(g_pCB->FD, (uint8_t *)&g_H2NCnysPattern.Short, SYNC_PATTERN_LEN);
01042 #endif
01043 
01044     /*  2. Read 4 bytes (protocol aligned) */
01045     _spi.spi_Read(g_pCB->FD, &pBuf[0], 4);
01046     _SL_DBG_SYNC_LOG(SyncCnt,pBuf);
01047 
01048     /* Wait for SYNC_PATTERN_LEN from the device */
01049     while ( ! N2H_SYNC_PATTERN_MATCH(pBuf, g_pCB->TxSeqNum) ) {
01050         /*  3. Debug limit of scan */
01051         VERIFY_PROTOCOL(SyncCnt < SL_SYNC_SCAN_THRESHOLD);
01052 
01053         /*  4. Read next 4 bytes to Low 4 bytes of buffer */
01054         if(0 == (SyncCnt % (uint32_t)SYNC_PATTERN_LEN)) {
01055             _spi.spi_Read(g_pCB->FD, &pBuf[4], 4);
01056             _SL_DBG_SYNC_LOG(SyncCnt,pBuf);
01057         }
01058 
01059         /*  5. Shift Buffer Up for checking if the sync is shifted */
01060         for(ShiftIdx = 0; ShiftIdx< 7; ShiftIdx++)
01061         {
01062             pBuf[ShiftIdx] = pBuf[ShiftIdx+1];
01063         }             
01064         pBuf[7] = 0;
01065 
01066         SyncCnt++;
01067     }
01068 
01069     /*  5. Sync pattern found. If needed, complete number of read bytes to multiple of 4 (protocol align) */
01070     SyncCnt %= SYNC_PATTERN_LEN;
01071 
01072     if(SyncCnt > 0) {
01073         *(uint32_t *)&pBuf[0] = *(uint32_t *)&pBuf[4];
01074         _spi.spi_Read(g_pCB->FD, &pBuf[SYNC_PATTERN_LEN - SyncCnt], (uint16_t)SyncCnt);
01075     } else {
01076         _spi.spi_Read(g_pCB->FD, &pBuf[0], 4);
01077     }
01078 
01079     /*  6. Scan for Double pattern. */
01080     while ( N2H_SYNC_PATTERN_MATCH(pBuf, g_pCB->TxSeqNum) ) {
01081         _SL_DBG_CNT_INC(Work.DoubleSyncPattern);
01082         _spi.spi_Read(g_pCB->FD, &pBuf[0], SYNC_PATTERN_LEN);
01083     }
01084     g_pCB->TxSeqNum++;
01085 
01086     /*  7. Here we've read Generic Header (4 bytes). Read the Resp Specific header (4 more bytes). */
01087     _spi.spi_Read(g_pCB->FD, &pBuf[SYNC_PATTERN_LEN], _SL_RESP_SPEC_HDR_SIZE);
01088 
01089     /*  8. Here we've read the entire Resp Header. */
01090     /*     Return number bytes needed to be sent after read for NWP Rx 4-byte alignment (protocol alignment) */
01091     *pAlignSize = (uint8_t)((SyncCnt > 0) ? (SYNC_PATTERN_LEN - SyncCnt) : 0);
01092 
01093     return SL_RET_CODE_OK;
01094 }
01095 
01096 /* ***************************************************************************** */
01097 /*  _SlDrvBasicCmd */
01098 /* ***************************************************************************** */
01099 typedef union {
01100     _BasicResponse_t    Rsp;
01101 } _SlBasicCmdMsg_u;
01102 
01103 #ifndef SL_TINY_EXT
01104 int16_t cc3100_driver::_SlDrvBasicCmd(_SlOpcode_t Opcode)
01105 {
01106     _SlBasicCmdMsg_u       Msg = {0};
01107     _SlCmdCtrl_t           CmdCtrl;
01108 
01109     CmdCtrl.Opcode = Opcode;
01110     CmdCtrl.TxDescLen = 0;
01111     CmdCtrl.RxDescLen = sizeof(_BasicResponse_t);
01112 
01113 
01114     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL));
01115 
01116     return (int16_t)Msg.Rsp.status;
01117 }
01118 
01119 /*****************************************************************************
01120   _SlDrvCmdSend 
01121   Send SL command without waiting for command response 
01122   This function is unprotected and the caller should make 
01123   sure global lock is active
01124 *****************************************************************************/
01125 _SlReturnVal_t cc3100_driver::_SlDrvCmdSend(_SlCmdCtrl_t *pCmdCtrl, void *pTxRxDescBuff, _SlCmdExt_t *pCmdExt)
01126 {
01127     _SlReturnVal_t RetVal;
01128     uint8_t        IsCmdRespWaitedOriginalVal;
01129 
01130     _SlFunctionParams_t originalFuncParms;
01131 
01132     /* save the current RespWait flag before clearing it */
01133     IsCmdRespWaitedOriginalVal = g_pCB->IsCmdRespWaited;
01134 
01135     /* save the current command parameters */
01136     memcpy(&originalFuncParms,  &g_pCB->FunctionParams, sizeof(_SlFunctionParams_t));
01137 
01138     g_pCB->IsCmdRespWaited = FALSE;
01139   
01140     SL_TRACE0(DBG_MSG, MSG_312, "_SlDrvCmdSend: call _SlDrvMsgWrite");
01141 
01142     /* send the message */
01143     RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, (uint8_t*)pTxRxDescBuff);
01144 
01145     /* restore the original RespWait flag */
01146     g_pCB->IsCmdRespWaited = IsCmdRespWaitedOriginalVal;
01147 
01148     /* restore the original command parameters  */
01149     memcpy(&g_pCB->FunctionParams, &originalFuncParms, sizeof(_SlFunctionParams_t));
01150 
01151     return RetVal;
01152 
01153 
01154 }
01155 #endif
01156 
01157 /* ***************************************************************************** */
01158 /*  _SlDrvWaitForPoolObj */
01159 /* ***************************************************************************** */
01160 uint8_t cc3100_driver::_SlDrvWaitForPoolObj(uint8_t ActionID, uint8_t SocketID)
01161 {
01162     uint8_t CurrObjIndex = MAX_CONCURRENT_ACTIONS;
01163     
01164     /* Get free object  */
01165     _SlDrvProtectionObjLockWaitForever();
01166     if (MAX_CONCURRENT_ACTIONS > g_pCB->FreePoolIdx) {
01167         /* save the current obj index */
01168         CurrObjIndex = g_pCB->FreePoolIdx;
01169         /* set the new free index */
01170 #ifndef SL_TINY_EXT        
01171         if (MAX_CONCURRENT_ACTIONS > g_pCB->ObjPool[CurrObjIndex].NextIndex) {
01172             g_pCB->FreePoolIdx = g_pCB->ObjPool[CurrObjIndex].NextIndex;
01173         } 
01174         else
01175 #endif         
01176         {            
01177             /* No further free actions available */
01178             g_pCB->FreePoolIdx = MAX_CONCURRENT_ACTIONS;
01179         }
01180     } else {
01181         _SlDrvProtectionObjUnLock();
01182         return CurrObjIndex;
01183     }
01184     g_pCB->ObjPool[CurrObjIndex].ActionID = (uint8_t)ActionID;
01185     if (SL_MAX_SOCKETS > SocketID) {
01186         g_pCB->ObjPool[CurrObjIndex].AdditionalData = SocketID;
01187     }
01188 #ifndef SL_TINY_EXT    
01189     /*In case this action is socket related, SocketID bit will be on
01190     In case SocketID is set to SL_MAX_SOCKETS, the socket is not relevant to the action. In that case ActionID bit will be on */
01191         while ( ( (SL_MAX_SOCKETS > SocketID) && (g_pCB->ActiveActionsBitmap & (1<<SocketID)) ) || 
01192             ( (g_pCB->ActiveActionsBitmap & (1<<ActionID)) && (SL_MAX_SOCKETS == SocketID) ) )
01193     {
01194         /* action in progress - move to pending list */
01195         g_pCB->ObjPool[CurrObjIndex].NextIndex = g_pCB->PendingPoolIdx;
01196         g_pCB->PendingPoolIdx = CurrObjIndex;
01197         _SlDrvProtectionObjUnLock();
01198         
01199         /* wait for action to be free */
01200         _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[CurrObjIndex].SyncObj);
01201         
01202         /* set params and move to active (remove from pending list at _SlDrvReleasePoolObj) */
01203         _SlDrvProtectionObjLockWaitForever();
01204     }
01205 #endif
01206     /* mark as active. Set socket as active if action is on socket, otherwise mark action as active */
01207     if (SL_MAX_SOCKETS > SocketID) {
01208         g_pCB->ActiveActionsBitmap |= (1<<SocketID);
01209     } else {
01210         g_pCB->ActiveActionsBitmap |= (1<<ActionID);
01211     }
01212     /* move to active list  */
01213     g_pCB->ObjPool[CurrObjIndex].NextIndex = g_pCB->ActivePoolIdx;
01214     g_pCB->ActivePoolIdx = CurrObjIndex;
01215     /* unlock */
01216     _SlDrvProtectionObjUnLock();
01217     return CurrObjIndex;
01218 }
01219 
01220 /* ******************************************************************************/
01221 /*  _SlDrvReleasePoolObj */
01222 /* ******************************************************************************/
01223 void cc3100_driver::_SlDrvReleasePoolObj(uint8_t ObjIdx)
01224 {
01225 #ifndef SL_TINY_EXT        
01226     uint8_t PendingIndex;
01227 #endif
01228 
01229      _SlDrvProtectionObjLockWaitForever();
01230 
01231       /* In Tiny mode, there is only one object pool so no pending actions are available */
01232 #ifndef SL_TINY_EXT
01233     /* go over the pending list and release other pending action if needed */
01234     PendingIndex = g_pCB->PendingPoolIdx;
01235         
01236     while(MAX_CONCURRENT_ACTIONS > PendingIndex)
01237     {
01238         /* In case this action is socket related, SocketID is in use, otherwise will be set to SL_MAX_SOCKETS */
01239         if ( (g_pCB->ObjPool[PendingIndex].ActionID == g_pCB->ObjPool[ObjIdx].ActionID) && 
01240             ( (SL_MAX_SOCKETS == (g_pCB->ObjPool[PendingIndex].AdditionalData & BSD_SOCKET_ID_MASK)) || 
01241             ((SL_MAX_SOCKETS > (g_pCB->ObjPool[ObjIdx].AdditionalData & BSD_SOCKET_ID_MASK)) && ( (g_pCB->ObjPool[PendingIndex].AdditionalData & BSD_SOCKET_ID_MASK) == (g_pCB->ObjPool[ObjIdx].AdditionalData & BSD_SOCKET_ID_MASK) ))) )
01242         {
01243             /* remove from pending list */
01244             _SlRemoveFromList(&g_pCB->PendingPoolIdx, PendingIndex);
01245              _SlDrvSyncObjSignal(&g_pCB->ObjPool[PendingIndex].SyncObj);
01246              break;
01247         }
01248         PendingIndex = g_pCB->ObjPool[PendingIndex].NextIndex;
01249     }
01250 #endif
01251 
01252         if (SL_MAX_SOCKETS > (g_pCB->ObjPool[ObjIdx].AdditionalData & BSD_SOCKET_ID_MASK))
01253         {
01254         /* unset socketID  */
01255             g_pCB->ActiveActionsBitmap &= ~(1<<(g_pCB->ObjPool[ObjIdx].AdditionalData & BSD_SOCKET_ID_MASK));
01256         }
01257         else
01258         {
01259         /* unset actionID  */
01260             g_pCB->ActiveActionsBitmap &= ~(1<<g_pCB->ObjPool[ObjIdx].ActionID);
01261         }
01262 
01263     /* delete old data */
01264     g_pCB->ObjPool[ObjIdx].pRespArgs = NULL;
01265     g_pCB->ObjPool[ObjIdx].ActionID = 0;
01266     g_pCB->ObjPool[ObjIdx].AdditionalData = SL_MAX_SOCKETS;
01267 
01268     /* remove from active list */
01269     _SlRemoveFromList(&g_pCB->ActivePoolIdx, ObjIdx);
01270     /* move to free list */
01271     g_pCB->ObjPool[ObjIdx].NextIndex = g_pCB->FreePoolIdx;
01272     g_pCB->FreePoolIdx = ObjIdx;
01273 
01274     _SlDrvProtectionObjUnLock();
01275 }
01276 
01277 /* ******************************************************************************/
01278 /* _SlRemoveFromList  */
01279 /* ******************************************************************************/
01280 void cc3100_driver::_SlRemoveFromList(uint8_t *ListIndex, uint8_t ItemIndex)
01281 {
01282 #ifndef SL_TINY_EXT  
01283     uint8_t Idx;
01284 #endif        
01285         
01286     if (MAX_CONCURRENT_ACTIONS == g_pCB->ObjPool[*ListIndex].NextIndex)
01287     {
01288         *ListIndex = MAX_CONCURRENT_ACTIONS;
01289     }
01290     /* As MAX_CONCURRENT_ACTIONS is equal to 1 in Tiny mode */
01291 #ifndef SL_TINY_EXT
01292     /* need to remove the first item in the list and therefore update the global which holds this index */
01293     else if (*ListIndex == ItemIndex)
01294     {
01295         *ListIndex = g_pCB->ObjPool[ItemIndex].NextIndex;
01296     }
01297     else
01298     {
01299               Idx = *ListIndex;
01300       
01301               while(MAX_CONCURRENT_ACTIONS > Idx)
01302               {
01303                   /* remove from list */
01304                   if (g_pCB->ObjPool[Idx].NextIndex == ItemIndex)
01305                   {
01306                           g_pCB->ObjPool[Idx].NextIndex = g_pCB->ObjPool[ItemIndex].NextIndex;
01307                           break;
01308                   }
01309 
01310                   Idx = g_pCB->ObjPool[Idx].NextIndex;
01311               }
01312     }
01313 #endif    
01314 }
01315 
01316 /* ******************************************************************************/
01317 /*  _SlFindAndSetActiveObj                                                     */
01318 /* ******************************************************************************/
01319 _SlReturnVal_t cc3100_driver::_SlFindAndSetActiveObj(_SlOpcode_t  Opcode, uint8_t Sd)
01320 {
01321     uint8_t ActiveIndex;
01322 
01323     ActiveIndex = g_pCB->ActivePoolIdx;
01324     /* go over the active list if exist to find obj waiting for this Async event */
01325     #ifndef SL_TINY_EXT    
01326         while (MAX_CONCURRENT_ACTIONS > ActiveIndex){
01327 #else
01328         /* Only one Active action is availabe in tiny mode, so we can replace the loop with if condition */
01329         if (MAX_CONCURRENT_ACTIONS > ActiveIndex)
01330 #endif
01331         /* unset the Ipv4\IPv6 bit in the opcode if family bit was set  */
01332         if (g_pCB->ObjPool[ActiveIndex].AdditionalData & SL_NETAPP_FAMILY_MASK) {
01333             Opcode &= ~SL_OPCODE_IPV6;
01334         }
01335 
01336         if ((g_pCB->ObjPool[ActiveIndex].ActionID == RECV_ID) && (Sd == g_pCB->ObjPool[ActiveIndex].AdditionalData) &&
01337                                         ( (SL_OPCODE_SOCKET_RECVASYNCRESPONSE == Opcode) || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE == Opcode)
01338 #ifndef SL_TINY_EXT
01339                         || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE_V6 == Opcode) 
01340 #endif
01341                           ) 
01342 
01343                )
01344         {       
01345             g_pCB->FunctionParams.AsyncExt.ActionIndex = ActiveIndex;
01346             return SL_RET_CODE_OK;
01347         }
01348         /* In case this action is socket related, SocketID is in use, otherwise will be set to SL_MAX_SOCKETS */
01349         if ( (_SlActionLookupTable[ g_pCB->ObjPool[ActiveIndex].ActionID - MAX_SOCKET_ENUM_IDX].ActionAsyncOpcode == Opcode) &&
01350                 ( ((Sd == (g_pCB->ObjPool[ActiveIndex].AdditionalData & BSD_SOCKET_ID_MASK) ) && (SL_MAX_SOCKETS > Sd)) || (SL_MAX_SOCKETS == (g_pCB->ObjPool[ActiveIndex].AdditionalData & BSD_SOCKET_ID_MASK)) ) ) {
01351             /* set handler */
01352             g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler = _SlActionLookupTable[ g_pCB->ObjPool[ActiveIndex].ActionID - MAX_SOCKET_ENUM_IDX].AsyncEventHandler;
01353             g_pCB->FunctionParams.AsyncExt.ActionIndex = ActiveIndex;
01354             return SL_RET_CODE_OK;
01355         }
01356         ActiveIndex = g_pCB->ObjPool[ActiveIndex].NextIndex;
01357     }
01358 
01359     return SL_RET_CODE_SELF_ERROR;
01360 
01361 }
01362 
01363 /* Wrappers for the object functions */
01364 
01365 void  cc3100_driver::_SlDrvSyncObjWaitForever(_SlSyncObj_t *pSyncObj)
01366 {
01367 #ifndef SL_PLATFORM_MULTI_THREADED   
01368     OSI_RET_OK_CHECK(_nonos.sl_SyncObjWait(pSyncObj, SL_OS_WAIT_FOREVER));
01369 #else    
01370     OSI_RET_OK_CHECK(sl_SyncObjWait(pSyncObj, SL_OS_WAIT_FOREVER));
01371 #endif   
01372 }
01373 
01374 void  cc3100_driver::_SlDrvSyncObjSignal(_SlSyncObj_t *pSyncObj)
01375 {
01376 #ifndef SL_PLATFORM_MULTI_THREADED   
01377     OSI_RET_OK_CHECK(_nonos.sl_SyncObjSignal(pSyncObj));
01378 #else    
01379     OSI_RET_OK_CHECK(sl_SyncObjSignal(pSyncObj));
01380 #endif   
01381 }
01382 
01383 void cc3100_driver::_SlDrvObjLockWaitForever(_SlLockObj_t *pLockObj)
01384 {
01385 #ifndef SL_PLATFORM_MULTI_THREADED  
01386     OSI_RET_OK_CHECK(_nonos.sl_LockObjLock(pLockObj, SL_OS_WAIT_FOREVER));
01387 #else    
01388     OSI_RET_OK_CHECK(sl_LockObjLock(pLockObj, SL_OS_WAIT_FOREVER));
01389 #endif    
01390 }
01391 
01392 void cc3100_driver::_SlDrvProtectionObjLockWaitForever()
01393 {
01394 #ifndef SL_PLATFORM_MULTI_THREADED    
01395     OSI_RET_OK_CHECK(_nonos.sl_LockObjLock(&g_pCB->ProtectionLockObj, SL_OS_WAIT_FOREVER));
01396 #else
01397     OSI_RET_OK_CHECK(sl_LockObjLock(&g_pCB->ProtectionLockObj, SL_OS_WAIT_FOREVER));
01398 #endif
01399 }
01400 
01401 void cc3100_driver::_SlDrvObjUnLock(_SlLockObj_t *pLockObj)
01402 {
01403 #ifndef SL_PLATFORM_MULTI_THREADED    
01404     OSI_RET_OK_CHECK(_nonos.sl_LockObjUnlock(pLockObj));
01405 #else    
01406     OSI_RET_OK_CHECK(sl_LockObjUnlock(pLockObj));
01407 #endif
01408 }
01409 
01410 void cc3100_driver::_SlDrvProtectionObjUnLock()
01411 {
01412 #ifndef SL_PLATFORM_MULTI_THREADED   
01413     OSI_RET_OK_CHECK(_nonos.sl_LockObjUnlock(&g_pCB->ProtectionLockObj));
01414 #else    
01415     OSI_RET_OK_CHECK(sl_LockObjUnlock(&g_pCB->ProtectionLockObj));
01416 #endif    
01417 }
01418 
01419 
01420 void cc3100_driver::_SlDrvMemZero(void* Addr, uint16_t size)
01421 {
01422     memset(Addr, 0, size);
01423 }
01424 
01425 
01426 void cc3100_driver::_SlDrvResetCmdExt(_SlCmdExt_t* pCmdExt)
01427 {
01428     _SlDrvMemZero(pCmdExt, sizeof (_SlCmdExt_t));
01429 }
01430 
01431 }//namespace mbed_cc3100
01432 
01433