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

Dependencies:   MaximInterface

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers driver.c Source File

driver.c

00001 /*
00002  * driver.c - CC31xx/CC32xx Host Driver Implementation
00003  *
00004  * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ 
00005  * 
00006  * 
00007  *  Redistribution and use in source and binary forms, with or without 
00008  *  modification, are permitted provided that the following conditions 
00009  *  are met:
00010  *
00011  *    Redistributions of source code must retain the above copyright 
00012  *    notice, this list of conditions and the following disclaimer.
00013  *
00014  *    Redistributions in binary form must reproduce the above copyright
00015  *    notice, this list of conditions and the following disclaimer in the 
00016  *    documentation and/or other materials provided with the   
00017  *    distribution.
00018  *
00019  *    Neither the name of Texas Instruments Incorporated nor the names of
00020  *    its contributors may be used to endorse or promote products derived
00021  *    from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00026  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
00027  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
00028  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
00029  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00030  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00031  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
00032  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
00033  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034  *
00035 */
00036 
00037 /*****************************************************************************/
00038 /* Include files                                                             */
00039 /*****************************************************************************/
00040 #include "simplelink.h"
00041 #include "protocol.h"
00042 #include "driver.h"
00043 #include "flowcont.h"
00044 
00045 /*****************************************************************************/
00046 /* Macro declarations                                                        */
00047 /*****************************************************************************/
00048 
00049 #define          _SL_PENDING_RX_MSG(pDriverCB)   (RxIrqCnt != (pDriverCB)->RxDoneCnt)
00050 
00051 /*  2 LSB of the N2H_SYNC_PATTERN are for sequence number 
00052 only in SPI interface
00053 support backward sync pattern */
00054 #define N2H_SYNC_PATTERN_SEQ_NUM_BITS            ((_u32)0x00000003) /* Bits 0..1    - use the 2 LBS for seq num */
00055 #define N2H_SYNC_PATTERN_SEQ_NUM_EXISTS          ((_u32)0x00000004) /* Bit  2       - sign that sequence number exists in the sync pattern */
00056 #define N2H_SYNC_PATTERN_MASK                    ((_u32)0xFFFFFFF8) /* Bits 3..31   - constant SYNC PATTERN */
00057 #define N2H_SYNC_SPI_BUGS_MASK                   ((_u32)0x7FFF7F7F) /* Bits 7,15,31 - ignore the SPI (8,16,32 bites bus) error bits  */
00058 #define BUF_SYNC_SPIM(pBuf)                      ((*(_u32 *)(pBuf)) & N2H_SYNC_SPI_BUGS_MASK)
00059 
00060 #define N2H_SYNC_SPIM                            (N2H_SYNC_PATTERN    & N2H_SYNC_SPI_BUGS_MASK)
00061 #define N2H_SYNC_SPIM_WITH_SEQ(TxSeqNum)         ((N2H_SYNC_SPIM & N2H_SYNC_PATTERN_MASK) | N2H_SYNC_PATTERN_SEQ_NUM_EXISTS | ((TxSeqNum) & (N2H_SYNC_PATTERN_SEQ_NUM_BITS)))
00062 #define MATCH_WOUT_SEQ_NUM(pBuf)                 ( BUF_SYNC_SPIM(pBuf) ==  N2H_SYNC_SPIM )
00063 #define MATCH_WITH_SEQ_NUM(pBuf, TxSeqNum)       ( BUF_SYNC_SPIM(pBuf) == (N2H_SYNC_SPIM_WITH_SEQ(TxSeqNum)) )
00064 #define N2H_SYNC_PATTERN_MATCH(pBuf, TxSeqNum) \
00065     ( \
00066     (  (*((_u32 *)pBuf) & N2H_SYNC_PATTERN_SEQ_NUM_EXISTS) && ( MATCH_WITH_SEQ_NUM(pBuf, TxSeqNum) ) )  || \
00067     ( !(*((_u32 *)pBuf) & N2H_SYNC_PATTERN_SEQ_NUM_EXISTS) && ( MATCH_WOUT_SEQ_NUM(pBuf          ) ) )     \
00068     )
00069 
00070 #define OPCODE(_ptr)          (((_SlResponseHeader_t *)(_ptr))->GenHeader.Opcode)         
00071 #define RSP_PAYLOAD_LEN(_ptr) (((_SlResponseHeader_t *)(_ptr))->GenHeader.Len - _SL_RESP_SPEC_HDR_SIZE)         
00072 #define SD(_ptr)              (((_SocketAddrResponse_u *)(_ptr))->IpV4.sd)
00073 /*  Actual size of Recv/Recvfrom response data  */
00074 #define ACT_DATA_SIZE(_ptr)   (((_SocketAddrResponse_u *)(_ptr))->IpV4.statusOrLen)
00075 
00076 
00077 /* Internal function prototype declaration */
00078 
00079       
00080 /* General Events handling*/
00081 #if defined (EXT_LIB_REGISTERED_GENERAL_EVENTS)
00082 
00083 typedef _SlEventPropogationStatus_e (*general_callback) (SlDeviceEvent_t *);
00084 
00085 static const general_callback  general_callbacks[] =
00086 {
00087 #ifdef SlExtLib1GeneralEventHandler
00088     SlExtLib1GeneralEventHandler,
00089 #endif
00090 
00091 #ifdef SlExtLib2GeneralEventHandler
00092     SlExtLib2GeneralEventHandler,
00093 #endif
00094 
00095 #ifdef SlExtLib3GeneralEventHandler
00096     SlExtLib3GeneralEventHandler,
00097 #endif
00098 
00099 #ifdef SlExtLib4GeneralEventHandler
00100     SlExtLib4GeneralEventHandler,
00101 #endif
00102 
00103 #ifdef SlExtLib5GeneralEventHandler
00104     SlExtLib5GeneralEventHandler,
00105 #endif
00106 };
00107 
00108 #undef _SlDrvHandleGeneralEvents
00109 
00110 /********************************************************************
00111   _SlDrvHandleGeneralEvents
00112   Iterates through all the general(device) event handlers which are
00113   registered by   the external libs/user application.
00114 *********************************************************************/
00115 void _SlDrvHandleGeneralEvents(SlDeviceEvent_t *slGeneralEvent)
00116 {
00117     _u8 i;
00118 
00119     /* Iterate over all the extenal libs handlers */
00120     for ( i = 0 ; i < sizeof(general_callbacks)/sizeof(general_callbacks[0]) ; i++ )
00121     {
00122         if (EVENT_PROPAGATION_BLOCK == general_callbacks[i](slGeneralEvent) )
00123         {
00124             /* exit immediately and do not call the user specific handler as well */
00125             return;
00126         }
00127     }
00128 
00129 /* At last call the Application specific handler if registered */
00130 #ifdef sl_GeneralEvtHdlr
00131     sl_GeneralEvtHdlr(slGeneralEvent);
00132 #endif
00133 
00134 }
00135 #endif
00136 
00137 
00138 
00139 /* WLAN Events handling*/
00140 
00141 #if defined (EXT_LIB_REGISTERED_WLAN_EVENTS)
00142 
00143 typedef _SlEventPropogationStatus_e (*wlan_callback) (SlWlanEvent_t *);
00144 
00145 static wlan_callback  wlan_callbacks[] =
00146 {
00147 #ifdef SlExtLib1WlanEventHandler
00148         SlExtLib1WlanEventHandler,
00149 #endif
00150 
00151 #ifdef SlExtLib2WlanEventHandler
00152         SlExtLib2WlanEventHandler,
00153 #endif
00154 
00155 #ifdef SlExtLib3WlanEventHandler
00156         SlExtLib3WlanEventHandler,
00157 #endif
00158 
00159 #ifdef SlExtLib4WlanEventHandler
00160         SlExtLib4WlanEventHandler,
00161 #endif
00162 
00163 #ifdef SlExtLib5WlanEventHandler
00164         SlExtLib5WlanEventHandler,
00165 #endif
00166 };
00167 
00168 #undef _SlDrvHandleWlanEvents
00169 
00170 /***********************************************************
00171   _SlDrvHandleWlanEvents
00172   Iterates through all the wlan event handlers which are
00173   registered by the external libs/user application.
00174 ************************************************************/
00175 void _SlDrvHandleWlanEvents(SlWlanEvent_t *slWlanEvent)
00176 {
00177     _u8 i;
00178 
00179     /* Iterate over all the extenal libs handlers */
00180     for ( i = 0 ; i < sizeof(wlan_callbacks)/sizeof(wlan_callbacks[0]) ; i++ )
00181     {
00182         if ( EVENT_PROPAGATION_BLOCK == wlan_callbacks[i](slWlanEvent) )
00183         {
00184             /* exit immediately and do not call the user specific handler as well */
00185             return;
00186         }
00187     }
00188 
00189 /* At last call the Application specific handler if registered */
00190 #ifdef sl_WlanEvtHdlr
00191     sl_WlanEvtHdlr(slWlanEvent);
00192 #endif
00193 
00194 }
00195 #endif
00196 
00197 
00198 /* NetApp Events handling */
00199 #if defined (EXT_LIB_REGISTERED_NETAPP_EVENTS)
00200 
00201 typedef _SlEventPropogationStatus_e (*netApp_callback) (SlNetAppEvent_t *);
00202 
00203 static const netApp_callback  netApp_callbacks[] =
00204 {
00205 #ifdef SlExtLib1NetAppEventHandler
00206      SlExtLib1NetAppEventHandler,
00207 #endif
00208 
00209 #ifdef SlExtLib2NetAppEventHandler
00210      SlExtLib2NetAppEventHandler,
00211 #endif
00212 
00213 #ifdef SlExtLib3NetAppEventHandler
00214      SlExtLib3NetAppEventHandler,
00215 #endif
00216 
00217 #ifdef SlExtLib4NetAppEventHandler
00218      SlExtLib4NetAppEventHandler,
00219 #endif
00220 
00221 #ifdef SlExtLib5NetAppEventHandler
00222      SlExtLib5NetAppEventHandler,
00223 #endif
00224 };
00225 
00226 #undef _SlDrvHandleNetAppEvents
00227 
00228 /************************************************************
00229   _SlDrvHandleNetAppEvents
00230   Iterates through all the net app event handlers which are
00231   registered by   the external libs/user application.
00232 ************************************************************/
00233 void _SlDrvHandleNetAppEvents(SlNetAppEvent_t *slNetAppEvent)
00234 {
00235     _u8 i;
00236 
00237     /* Iterate over all the extenal libs handlers */
00238     for ( i = 0 ; i < sizeof(netApp_callbacks)/sizeof(netApp_callbacks[0]) ; i++ )
00239     {
00240         if (EVENT_PROPAGATION_BLOCK == netApp_callbacks[i](slNetAppEvent) )
00241         {
00242             /* exit immediately and do not call the user specific handler as well */
00243             return;
00244         }
00245     }
00246 
00247 /* At last call the Application specific handler if registered */
00248 #ifdef sl_NetAppEvtHdlr
00249     sl_NetAppEvtHdlr(slNetAppEvent);
00250 #endif
00251 
00252 }
00253 #endif
00254 
00255 
00256 /* Http Server Events handling */
00257 #if defined (EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS)
00258 
00259 typedef _SlEventPropogationStatus_e (*httpServer_callback) (SlHttpServerEvent_t*, SlHttpServerResponse_t*);
00260 
00261 static const httpServer_callback  httpServer_callbacks[] =
00262 {
00263 #ifdef SlExtLib1HttpServerEventHandler
00264         SlExtLib1HttpServerEventHandler,
00265 #endif
00266 
00267 #ifdef SlExtLib2HttpServerEventHandler
00268         SlExtLib2HttpServerEventHandler,
00269 #endif
00270 
00271 #ifdef SlExtLib3HttpServerEventHandler
00272         SlExtLib3HttpServerEventHandler,
00273 #endif
00274 
00275 #ifdef SlExtLib4HttpServerEventHandler
00276         SlExtLib4HttpServerEventHandler,
00277 #endif
00278 
00279 #ifdef SlExtLib5HttpServerEventHandler
00280       SlExtLib5HttpServerEventHandler,
00281 #endif
00282 };
00283 
00284 #undef _SlDrvHandleHttpServerEvents
00285 
00286 /*******************************************************************
00287   _SlDrvHandleHttpServerEvents
00288   Iterates through all the http server event handlers which are
00289   registered by the external libs/user application.
00290 ********************************************************************/
00291 void _SlDrvHandleHttpServerEvents(SlHttpServerEvent_t *slHttpServerEvent, SlHttpServerResponse_t *slHttpServerResponse)
00292 {
00293     _u8 i;
00294 
00295     /* Iterate over all the external libs handlers */
00296     for ( i = 0 ; i < sizeof(httpServer_callbacks)/sizeof(httpServer_callbacks[0]) ; i++ )
00297     {
00298         if ( EVENT_PROPAGATION_BLOCK == httpServer_callbacks[i](slHttpServerEvent, slHttpServerResponse) )
00299         {
00300             /* exit immediately and do not call the user specific handler as well */
00301             return;
00302         }
00303     }
00304 
00305 /* At last call the Application specific handler if registered */
00306 #ifdef sl_HttpServerCallback
00307     sl_HttpServerCallback(slHttpServerEvent, slHttpServerResponse);
00308 #endif
00309 
00310 }
00311 #endif
00312 
00313 
00314 /* Socket Events */
00315 #if defined (EXT_LIB_REGISTERED_SOCK_EVENTS)
00316 
00317 typedef _SlEventPropogationStatus_e (*sock_callback) (SlSockEvent_t *);
00318 
00319 static const sock_callback  sock_callbacks[] =
00320 {
00321 #ifdef SlExtLib1SockEventHandler
00322         SlExtLib1SockEventHandler,
00323 #endif
00324 
00325 #ifdef SlExtLib2SockEventHandler
00326         SlExtLib2SockEventHandler,
00327 #endif
00328 
00329 #ifdef SlExtLib3SockEventHandler
00330         SlExtLib3SockEventHandler,
00331 #endif
00332 
00333 #ifdef SlExtLib4SockEventHandler
00334         SlExtLib4SockEventHandler,
00335 #endif
00336 
00337 #ifdef SlExtLib5SockEventHandler
00338         SlExtLib5SockEventHandler,
00339 #endif
00340 };
00341 
00342 /*************************************************************
00343   _SlDrvHandleSockEvents
00344   Iterates through all the socket event handlers which are
00345   registered by the external libs/user application.
00346 **************************************************************/
00347 void _SlDrvHandleSockEvents(SlSockEvent_t *slSockEvent)
00348 {
00349     _u8 i;
00350 
00351     /* Iterate over all the external libs handlers */
00352     for ( i = 0 ; i < sizeof(sock_callbacks)/sizeof(sock_callbacks[0]) ; i++ )
00353     {
00354         if ( EVENT_PROPAGATION_BLOCK == sock_callbacks[i](slSockEvent) )
00355         {
00356             /* exit immediately and do not call the user specific handler as well */
00357             return;
00358         }
00359     }
00360 
00361 /* At last call the Application specific handler if registered */
00362 #ifdef sl_SockEvtHdlr
00363     sl_SockEvtHdlr(slSockEvent);
00364 #endif
00365 
00366 }
00367 
00368 #endif
00369 
00370 
00371 #ifndef SL_MEMORY_MGMT_DYNAMIC
00372 typedef struct
00373 {
00374     _u32 Align;
00375     _SlDriverCb_t DriverCB;
00376     _u8 AsyncRespBuf[SL_ASYNC_MAX_MSG_LEN];
00377 }_SlStatMem_t;
00378 
00379 static _SlStatMem_t g_StatMem;
00380 #endif
00381 
00382 _u8 _SlDrvProtectAsyncRespSetting(_u8 *pAsyncRsp, _SlActionID_e ActionID, _u8 SocketID)
00383 {
00384     _u8 ObjIdx;
00385 
00386 
00387     /* Use Obj to issue the command, if not available try later */
00388     ObjIdx = (_u8)_SlDrvWaitForPoolObj(ActionID, SocketID);
00389 
00390     if (MAX_CONCURRENT_ACTIONS != ObjIdx)
00391     {
00392         SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
00393         g_pCB->ObjPool[ObjIdx].pRespArgs = pAsyncRsp;
00394         SL_DRV_PROTECTION_OBJ_UNLOCK();
00395     }
00396 
00397     return ObjIdx;
00398 }
00399 
00400 
00401 /*****************************************************************************/
00402 /* Variables                                                                 */
00403 /*****************************************************************************/
00404 static const _SlSyncPattern_t g_H2NSyncPattern = H2N_SYNC_PATTERN;
00405 
00406 #ifndef SL_IF_TYPE_UART
00407 static const _SlSyncPattern_t g_H2NCnysPattern = H2N_CNYS_PATTERN;
00408 #endif
00409 
00410 
00411 _volatile _u8           RxIrqCnt;
00412 
00413 #ifndef SL_TINY_EXT
00414 
00415 _volatile _u8  g_bDeviceRestartIsRequired;
00416 
00417 const _SlActionLookup_t _SlActionLookupTable[] = 
00418 {
00419     {ACCEPT_ID, SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE, (_SlSpawnEntryFunc_t)_sl_HandleAsync_Accept},
00420     {CONNECT_ID, SL_OPCODE_SOCKET_CONNECTASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_Connect},
00421     {SELECT_ID, SL_OPCODE_SOCKET_SELECTASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_Select},
00422     {GETHOSYBYNAME_ID, SL_OPCODE_NETAPP_DNSGETHOSTBYNAMEASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_DnsGetHostByName},
00423     {GETHOSYBYSERVICE_ID, SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICEASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_DnsGetHostByService}, 
00424     {PING_ID, SL_OPCODE_NETAPP_PINGREPORTREQUESTRESPONSE, (_SlSpawnEntryFunc_t)_sl_HandleAsync_PingResponse},
00425     {START_STOP_ID, SL_OPCODE_DEVICE_STOP_ASYNC_RESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_Stop}
00426 };
00427 #else
00428 const _SlActionLookup_t _SlActionLookupTable[] = 
00429 {
00430     {CONNECT_ID, SL_OPCODE_SOCKET_CONNECTASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_Connect},
00431     {GETHOSYBYNAME_ID, SL_OPCODE_NETAPP_DNSGETHOSTBYNAMEASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_DnsGetHostByName},  
00432     {START_STOP_ID, SL_OPCODE_DEVICE_STOP_ASYNC_RESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_Stop}
00433 };
00434 #endif
00435 
00436 
00437 
00438 typedef struct
00439 {
00440     _u16 opcode;
00441     _u8  event;
00442 } OpcodeKeyVal_t;
00443 
00444 /* The table translates opcode to user's event type */
00445 const OpcodeKeyVal_t OpcodeTranslateTable[] = 
00446 {
00447 {SL_OPCODE_WLAN_SMART_CONFIG_START_ASYNC_RESPONSE, SL_WLAN_SMART_CONFIG_COMPLETE_EVENT},
00448 {SL_OPCODE_WLAN_SMART_CONFIG_STOP_ASYNC_RESPONSE,SL_WLAN_SMART_CONFIG_STOP_EVENT},
00449 {SL_OPCODE_WLAN_STA_CONNECTED, SL_WLAN_STA_CONNECTED_EVENT},
00450 {SL_OPCODE_WLAN_STA_DISCONNECTED,SL_WLAN_STA_DISCONNECTED_EVENT},
00451 {SL_OPCODE_WLAN_P2P_DEV_FOUND,SL_WLAN_P2P_DEV_FOUND_EVENT},    
00452 {SL_OPCODE_WLAN_P2P_NEG_REQ_RECEIVED, SL_WLAN_P2P_NEG_REQ_RECEIVED_EVENT},
00453 {SL_OPCODE_WLAN_CONNECTION_FAILED, SL_WLAN_CONNECTION_FAILED_EVENT},
00454 {SL_OPCODE_WLAN_WLANASYNCCONNECTEDRESPONSE, SL_WLAN_CONNECT_EVENT},
00455 {SL_OPCODE_WLAN_WLANASYNCDISCONNECTEDRESPONSE, SL_WLAN_DISCONNECT_EVENT},
00456 {SL_OPCODE_NETAPP_IPACQUIRED, SL_NETAPP_IPV4_IPACQUIRED_EVENT},
00457 {SL_OPCODE_NETAPP_IPACQUIRED_V6, SL_NETAPP_IPV6_IPACQUIRED_EVENT},
00458 {SL_OPCODE_NETAPP_IP_LEASED, SL_NETAPP_IP_LEASED_EVENT},
00459 {SL_OPCODE_NETAPP_IP_RELEASED, SL_NETAPP_IP_RELEASED_EVENT},
00460 {SL_OPCODE_SOCKET_TXFAILEDASYNCRESPONSE, SL_SOCKET_TX_FAILED_EVENT},
00461 {SL_OPCODE_SOCKET_SOCKETASYNCEVENT, SL_SOCKET_ASYNC_EVENT}
00462 };
00463 
00464 
00465 
00466 _SlDriverCb_t* g_pCB = NULL;
00467 P_SL_DEV_PING_CALLBACK  pPingCallBackFunc = NULL;
00468 
00469 #ifndef SL_IF_TYPE_UART
00470 static _u8 gFirstCmdMode = 0;
00471 #endif
00472 
00473 /*****************************************************************************/
00474 /* Function prototypes                                                       */
00475 /*****************************************************************************/
00476 static _SlReturnVal_t _SlDrvMsgRead(void);
00477 static _SlReturnVal_t _SlDrvMsgWrite(_SlCmdCtrl_t  *pCmdCtrl,_SlCmdExt_t  *pCmdExt, _u8 *pTxRxDescBuff);
00478 static _SlReturnVal_t _SlDrvMsgReadCmdCtx(_u16 cmdOpcode);
00479 static _SlReturnVal_t _SlDrvClassifyRxMsg(_SlOpcode_t Opcode );
00480 static _SlReturnVal_t _SlDrvRxHdrRead(_u8 *pBuf, _u8 *pAlignSize);
00481 static void           _SlAsyncEventGenericHandler(_u8 bInCmdContext);
00482 static void           _SlRemoveFromList(_u8* ListIndex, _u8 ItemIndex);
00483 static _SlReturnVal_t _SlFindAndSetActiveObj(_SlOpcode_t  Opcode, _u8 Sd);
00484 static _SlReturnVal_t _SlDrvObjGlobalLockWaitForever(void);
00485 
00486 /*****************************************************************************/
00487 /* Internal functions                                                        */
00488 /*****************************************************************************/
00489 
00490 
00491 /*****************************************************************************
00492 _SlDrvDriverCBInit - init Driver Control Block
00493 *****************************************************************************/
00494 
00495 _SlReturnVal_t _SlDrvDriverCBInit(void)
00496 {
00497     _u8          Idx =0;
00498 
00499 #ifdef SL_MEMORY_MGMT_DYNAMIC
00500     g_pCB = (_SlDriverCb_t*)sl_Malloc(sizeof(_SlDriverCb_t));
00501 #else
00502     g_pCB = &(g_StatMem.DriverCB);
00503 #endif
00504     MALLOC_OK_CHECK(g_pCB);
00505 
00506 #ifndef SL_PLATFORM_MULTI_THREADED
00507     {
00508         extern _SlNonOsCB_t g__SlNonOsCB;
00509         sl_Memset(&g__SlNonOsCB, 0, sizeof(g__SlNonOsCB));
00510     }
00511 #endif
00512 
00513     _SlDrvMemZero(g_pCB, (_u16)sizeof(_SlDriverCb_t));
00514     RxIrqCnt = 0;
00515     OSI_RET_OK_CHECK( sl_SyncObjCreate(&g_pCB->CmdSyncObj, "CmdSyncObj") );
00516     SL_DRV_SYNC_OBJ_CLEAR(&g_pCB->CmdSyncObj);
00517 
00518     OSI_RET_OK_CHECK( sl_LockObjCreate(&g_pCB->GlobalLockObj, "GlobalLockObj") );
00519     OSI_RET_OK_CHECK( sl_LockObjCreate(&g_pCB->ProtectionLockObj, "ProtectionLockObj") );
00520 
00521     /* Init Drv object */
00522     _SlDrvMemZero(&g_pCB->ObjPool[0], (_u16)(MAX_CONCURRENT_ACTIONS*sizeof(_SlPoolObj_t)));
00523 
00524     /* place all Obj in the free list*/
00525     g_pCB->FreePoolIdx = 0;
00526 
00527     for (Idx = 0 ; Idx < MAX_CONCURRENT_ACTIONS ; Idx++)
00528     {
00529         g_pCB->ObjPool[Idx].NextIndex = Idx + 1;
00530         g_pCB->ObjPool[Idx].AdditionalData = SL_MAX_SOCKETS;
00531 
00532         OSI_RET_OK_CHECK( sl_SyncObjCreate(&g_pCB->ObjPool[Idx].SyncObj, "SyncObj"));
00533         SL_DRV_SYNC_OBJ_CLEAR(&g_pCB->ObjPool[Idx].SyncObj);
00534     }
00535 
00536      g_pCB->ActivePoolIdx = MAX_CONCURRENT_ACTIONS;
00537      g_pCB->PendingPoolIdx = MAX_CONCURRENT_ACTIONS;
00538 
00539     /* Flow control init */
00540     g_pCB->FlowContCB.TxPoolCnt = FLOW_CONT_MIN;
00541     OSI_RET_OK_CHECK(sl_LockObjCreate(&g_pCB->FlowContCB.TxLockObj, "TxLockObj"));
00542     OSI_RET_OK_CHECK(sl_SyncObjCreate(&g_pCB->FlowContCB.TxSyncObj, "TxSyncObj"));
00543     
00544 #ifndef SL_IF_TYPE_UART   
00545     gFirstCmdMode = 0;  
00546 #endif
00547     
00548     return SL_OS_RET_CODE_OK;
00549 }
00550 
00551 /*****************************************************************************
00552 _SlDrvDriverCBDeinit - De init Driver Control Block
00553 *****************************************************************************/
00554 _SlReturnVal_t _SlDrvDriverCBDeinit(void)
00555 {
00556     _u8  Idx =0;
00557 
00558     /* Flow control de-init */
00559     g_pCB->FlowContCB.TxPoolCnt = 0;
00560     OSI_RET_OK_CHECK(sl_LockObjDelete(&g_pCB->FlowContCB.TxLockObj));
00561     OSI_RET_OK_CHECK(sl_SyncObjDelete(&g_pCB->FlowContCB.TxSyncObj));
00562     
00563     OSI_RET_OK_CHECK( sl_SyncObjDelete(&g_pCB->CmdSyncObj) );
00564 
00565 #ifndef SL_TINY_EXT    
00566     if (g_bDeviceRestartIsRequired == 0)
00567 #endif      
00568     {
00569         OSI_RET_OK_CHECK( sl_LockObjDelete(&g_pCB->GlobalLockObj) );
00570     }
00571     
00572     OSI_RET_OK_CHECK( sl_LockObjDelete(&g_pCB->ProtectionLockObj) );
00573         
00574  #ifndef SL_TINY_EXT
00575     for (Idx = 0; Idx < MAX_CONCURRENT_ACTIONS; Idx++)
00576  #endif
00577     {
00578     OSI_RET_OK_CHECK( sl_SyncObjDelete(&g_pCB->ObjPool[Idx].SyncObj) );   
00579     }
00580 
00581     g_pCB->FreePoolIdx = 0;
00582     g_pCB->PendingPoolIdx = MAX_CONCURRENT_ACTIONS;
00583     g_pCB->ActivePoolIdx = MAX_CONCURRENT_ACTIONS;
00584 
00585 #ifdef SL_MEMORY_MGMT_DYNAMIC
00586     sl_Free(g_pCB);
00587 #else
00588     g_pCB = NULL;
00589 #endif
00590 
00591 
00592     g_pCB = NULL;
00593     return SL_OS_RET_CODE_OK;
00594 }
00595 
00596 /*****************************************************************************
00597 _SlDrvRxIrqHandler - Interrupt handler 
00598 *****************************************************************************/
00599 _SlReturnVal_t _SlDrvRxIrqHandler(void *pValue)
00600 {
00601     (void)pValue;
00602 
00603     sl_IfMaskIntHdlr();
00604 
00605     RxIrqCnt++;
00606 
00607     if (TRUE == g_pCB->IsCmdRespWaited)
00608     {
00609         OSI_RET_OK_CHECK( sl_SyncObjSignalFromIRQ(&g_pCB->CmdSyncObj) );
00610     }
00611     else
00612     {
00613         (void)sl_Spawn((_SlSpawnEntryFunc_t)_SlDrvMsgReadSpawnCtx, NULL, SL_SPAWN_FLAG_FROM_SL_IRQ_HANDLER);
00614     }
00615     return SL_OS_RET_CODE_OK;
00616 }
00617 
00618 /*****************************************************************************
00619 _SlDrvCmdOp
00620 *****************************************************************************/
00621 _SlReturnVal_t _SlDrvCmdOp(
00622     _SlCmdCtrl_t  *pCmdCtrl ,
00623     void          *pTxRxDescBuff ,
00624     _SlCmdExt_t   *pCmdExt)
00625 {
00626     _SlReturnVal_t RetVal;
00627 
00628     SL_DRV_LOCK_GLOBAL_LOCK_FOREVER();
00629 
00630 #ifndef SL_TINY_EXT 
00631     /* In case the global was succesffully taken but error in progress
00632     it means it has been released as part of an error handling and we should abort immediately */
00633     if (TRUE == g_bDeviceRestartIsRequired)
00634     {
00635           SL_DRV_LOCK_GLOBAL_UNLOCK();
00636           return SL_API_ABORTED;
00637     }
00638 #endif
00639     
00640     g_pCB->IsCmdRespWaited = TRUE;
00641 
00642     SL_TRACE0(DBG_MSG, MSG_312, "_SlDrvCmdOp: call _SlDrvMsgWrite");
00643 
00644 
00645     /* send the message */
00646     RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, pTxRxDescBuff);
00647 
00648     if(SL_OS_RET_CODE_OK == RetVal)
00649     {
00650 
00651 #ifndef SL_IF_TYPE_UART    
00652         /* Waiting for SPI to stabilize after first command */
00653         if( 0 == gFirstCmdMode )
00654         {
00655             volatile _u32 CountVal = 0;
00656             gFirstCmdMode = 1;
00657             CountVal = CPU_FREQ_IN_MHZ*USEC_DELAY;
00658             while( CountVal-- );
00659         }   
00660 #endif 
00661         /* wait for respond */
00662         RetVal = _SlDrvMsgReadCmdCtx(pCmdCtrl->Opcode); /* will free global lock */
00663         SL_TRACE0(DBG_MSG, MSG_314, "_SlDrvCmdOp: exited _SlDrvMsgReadCmdCtx");
00664     }
00665     else
00666     {
00667         SL_DRV_LOCK_GLOBAL_UNLOCK();
00668     }
00669     
00670     return RetVal;
00671 }
00672 
00673 
00674 
00675 /*****************************************************************************
00676 _SlDrvDataReadOp
00677 *****************************************************************************/
00678 _SlReturnVal_t _SlDrvDataReadOp(
00679     _SlSd_t             Sd,
00680     _SlCmdCtrl_t        *pCmdCtrl ,
00681     void                *pTxRxDescBuff ,
00682     _SlCmdExt_t         *pCmdExt)
00683 {
00684     _SlReturnVal_t RetVal;
00685     _u8 ObjIdx = MAX_CONCURRENT_ACTIONS;
00686     _SlArgsData_t pArgsData;
00687 
00688     /* Validate input arguments */
00689     VERIFY_PROTOCOL(NULL != pCmdExt->pRxPayload);
00690 
00691     /* If zero bytes is requested, return error. */
00692     /*  This allows us not to fill remote socket's IP address in return arguments */
00693     VERIFY_PROTOCOL(0 != pCmdExt->RxPayloadLen);
00694 
00695     /* Validate socket */
00696     if((Sd & BSD_SOCKET_ID_MASK) >= SL_MAX_SOCKETS)
00697     {
00698         return SL_EBADF;
00699     }
00700 
00701     /*Use Obj to issue the command, if not available try later*/
00702     ObjIdx = (_u8)_SlDrvWaitForPoolObj(RECV_ID, Sd & BSD_SOCKET_ID_MASK);
00703 
00704     if (MAX_CONCURRENT_ACTIONS == ObjIdx)
00705     {
00706         return SL_POOL_IS_EMPTY;
00707     }
00708 
00709     SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
00710 
00711     pArgsData.pData = pCmdExt->pRxPayload;
00712     pArgsData.pArgs =  (_u8 *)pTxRxDescBuff;
00713     g_pCB->ObjPool[ObjIdx].pRespArgs =  (_u8 *)&pArgsData;
00714 
00715     SL_DRV_PROTECTION_OBJ_UNLOCK();
00716 
00717 
00718     /* Do Flow Control check/update for DataWrite operation */
00719     SL_DRV_OBJ_LOCK_FOREVER(&g_pCB->FlowContCB.TxLockObj);
00720 
00721 
00722     /* Clear SyncObj for the case it was signalled before TxPoolCnt */
00723     /* dropped below '1' (last Data buffer was taken)  */
00724     /* OSI_RET_OK_CHECK( sl_SyncObjClear(&g_pCB->FlowContCB.TxSyncObj) ); */
00725     SL_DRV_SYNC_OBJ_CLEAR(&g_pCB->FlowContCB.TxSyncObj);
00726 
00727     if(g_pCB->FlowContCB.TxPoolCnt <= FLOW_CONT_MIN)
00728     {
00729 
00730         /* If TxPoolCnt was increased by other thread at this moment,
00731                  TxSyncObj won't wait here */
00732         SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->FlowContCB.TxSyncObj);
00733        
00734     }
00735 
00736     SL_DRV_LOCK_GLOBAL_LOCK_FOREVER();
00737 
00738 #ifndef SL_TINY_EXT    
00739     /* In case the global was succesffully taken but error in progress
00740     it means it has been released as part of an error handling and we should abort immediately */
00741     if (TRUE == g_bDeviceRestartIsRequired)
00742     {
00743         SL_DRV_LOCK_GLOBAL_UNLOCK();
00744         return SL_API_ABORTED;
00745     }
00746 #endif
00747 
00748     VERIFY_PROTOCOL(g_pCB->FlowContCB.TxPoolCnt > FLOW_CONT_MIN);
00749     g_pCB->FlowContCB.TxPoolCnt--;
00750 
00751     SL_DRV_OBJ_UNLOCK(&g_pCB->FlowContCB.TxLockObj);
00752 
00753     /* send the message */
00754     RetVal =  _SlDrvMsgWrite(pCmdCtrl, pCmdExt, (_u8 *)pTxRxDescBuff);
00755 
00756     SL_DRV_LOCK_GLOBAL_UNLOCK();
00757     
00758 
00759     if(SL_OS_RET_CODE_OK == RetVal)
00760     {
00761 #ifndef SL_TINY_EXT    
00762         /* in case socket is non-blocking one, the async event should be received immediately */
00763         if( g_pCB->SocketNonBlocking & (1<<(Sd & BSD_SOCKET_ID_MASK) ))
00764         {
00765              SlDriverAPIWithTimeout_e api = (pCmdCtrl->Opcode ==  SL_OPCODE_SOCKET_RECV) ? SL_DRIVER_API_SOCKET_RECV : SL_DRIVER_API_SOCKET_RECVFROM; 
00766              
00767              SL_DRV_SYNC_OBJ_WAIT_TIMEOUT(&g_pCB->ObjPool[ObjIdx].SyncObj,
00768                                            SL_DRIVER_TIMEOUT_SHORT,
00769                                            api
00770                                            );
00771         }
00772         else
00773 #endif         
00774         {
00775             /* Wait for response message. Will be signaled by _SlDrvMsgRead. */
00776             SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->ObjPool[ObjIdx].SyncObj);
00777         }
00778           
00779     }
00780 
00781     _SlDrvReleasePoolObj(ObjIdx);
00782     return RetVal;
00783 }
00784 
00785 /* ******************************************************************************/
00786 /*   _SlDrvDataWriteOp                                                          */
00787 /* ******************************************************************************/
00788 _SlReturnVal_t _SlDrvDataWriteOp(
00789     _SlSd_t             Sd,
00790     _SlCmdCtrl_t  *pCmdCtrl ,
00791     void                *pTxRxDescBuff ,
00792     _SlCmdExt_t         *pCmdExt)
00793 {
00794     _SlReturnVal_t  RetVal = SL_EAGAIN; /*  initiated as SL_EAGAIN for the non blocking mode */
00795     while( 1 )
00796     {
00797         /*  Do Flow Control check/update for DataWrite operation */
00798         SL_DRV_OBJ_LOCK_FOREVER(&g_pCB->FlowContCB.TxLockObj);
00799 
00800         /*  Clear SyncObj for the case it was signalled before TxPoolCnt */
00801         /*  dropped below '1' (last Data buffer was taken) */
00802         /* OSI_RET_OK_CHECK( sl_SyncObjClear(&g_pCB->FlowContCB.TxSyncObj) ); */
00803         SL_DRV_SYNC_OBJ_CLEAR(&g_pCB->FlowContCB.TxSyncObj);
00804 
00805         /*  we have indication that the last send has failed - socket is no longer valid for operations  */
00806         if(g_pCB->SocketTXFailure & (1<<(Sd & BSD_SOCKET_ID_MASK)))
00807         {
00808             SL_DRV_OBJ_UNLOCK(&g_pCB->FlowContCB.TxLockObj);
00809             return SL_SOC_ERROR;
00810         }
00811         if(g_pCB->FlowContCB.TxPoolCnt <= FLOW_CONT_MIN + 1)
00812         {
00813             /*  we have indication that this socket is set as blocking and we try to  */
00814             /*  unblock it - return an error */
00815             if( g_pCB->SocketNonBlocking & (1<<(Sd & BSD_SOCKET_ID_MASK) ))
00816             {
00817                 SL_DRV_OBJ_UNLOCK(&g_pCB->FlowContCB.TxLockObj);
00818                 return RetVal;
00819             }
00820             /*  If TxPoolCnt was increased by other thread at this moment, */
00821             /*  TxSyncObj won't wait here */
00822 
00823             SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->FlowContCB.TxSyncObj);
00824         }
00825         if(g_pCB->FlowContCB.TxPoolCnt > FLOW_CONT_MIN + 1 )
00826         {
00827             break;
00828         }
00829         else
00830         {
00831             SL_DRV_OBJ_UNLOCK(&g_pCB->FlowContCB.TxLockObj);
00832         }
00833     }
00834 
00835     SL_DRV_LOCK_GLOBAL_LOCK_FOREVER();
00836 
00837 #ifndef SL_TINY_EXT    
00838     /* In case the global was succesffully taken but error in progress
00839     it means it has been released as part of an error handling and we should abort immediately */
00840     if (TRUE == g_bDeviceRestartIsRequired)
00841     {
00842         SL_DRV_LOCK_GLOBAL_UNLOCK();
00843         return SL_API_ABORTED;
00844     }
00845 #endif
00846 
00847 
00848     VERIFY_PROTOCOL(g_pCB->FlowContCB.TxPoolCnt > FLOW_CONT_MIN + 1 );
00849     g_pCB->FlowContCB.TxPoolCnt--;
00850 
00851     SL_DRV_OBJ_UNLOCK(&g_pCB->FlowContCB.TxLockObj);
00852     
00853     /* send the message */
00854     RetVal =  _SlDrvMsgWrite(pCmdCtrl, pCmdExt, pTxRxDescBuff);
00855 
00856     SL_DRV_LOCK_GLOBAL_UNLOCK();
00857 
00858     return RetVal;
00859 }
00860 
00861 /* ******************************************************************************/
00862 /*  _SlDrvMsgWrite */
00863 /* ******************************************************************************/
00864 static _SlReturnVal_t _SlDrvMsgWrite(_SlCmdCtrl_t  *pCmdCtrl,_SlCmdExt_t  *pCmdExt, _u8 *pTxRxDescBuff)
00865 {
00866     _u8 sendRxPayload = FALSE;
00867     VERIFY_PROTOCOL(NULL != pCmdCtrl);
00868 
00869     g_pCB->FunctionParams.pCmdCtrl = pCmdCtrl;
00870     g_pCB->FunctionParams.pTxRxDescBuff = pTxRxDescBuff;
00871     g_pCB->FunctionParams.pCmdExt = pCmdExt;
00872     
00873     g_pCB->TempProtocolHeader.Opcode   = pCmdCtrl->Opcode;
00874     g_pCB->TempProtocolHeader.Len   = (_u16)(_SL_PROTOCOL_CALC_LEN(pCmdCtrl, pCmdExt));
00875 
00876     if (pCmdExt && pCmdExt->RxPayloadLen < 0 )
00877     {
00878         pCmdExt->RxPayloadLen = pCmdExt->RxPayloadLen * (-1); /* change sign */
00879         sendRxPayload = TRUE;
00880         g_pCB->TempProtocolHeader.Len = g_pCB->TempProtocolHeader.Len + pCmdExt->RxPayloadLen;
00881     }
00882 
00883 #ifdef SL_START_WRITE_STAT
00884     sl_IfStartWriteSequence(g_pCB->FD);
00885 #endif
00886 
00887 #ifdef SL_IF_TYPE_UART
00888     /*  Write long sync pattern */
00889     NWP_IF_WRITE_CHECK(g_pCB->FD, (_u8 *)&g_H2NSyncPattern.Long, 2*SYNC_PATTERN_LEN);
00890 #else
00891     /*  Write short sync pattern */
00892     NWP_IF_WRITE_CHECK(g_pCB->FD, (_u8 *)&g_H2NSyncPattern.Short, SYNC_PATTERN_LEN);
00893 #endif
00894 
00895     /*  Header */
00896     NWP_IF_WRITE_CHECK(g_pCB->FD, (_u8 *)&g_pCB->TempProtocolHeader, _SL_CMD_HDR_SIZE);
00897 
00898     /*  Descriptors */
00899     if (pTxRxDescBuff && pCmdCtrl->TxDescLen > 0)
00900     {
00901         NWP_IF_WRITE_CHECK(g_pCB->FD, pTxRxDescBuff, 
00902                            _SL_PROTOCOL_ALIGN_SIZE(pCmdCtrl->TxDescLen));
00903     }
00904 
00905     /*  A special mode where Rx payload and Rx length are used as Tx as well */
00906     /*  This mode requires no Rx payload on the response and currently used by fs_Close and sl_Send on */
00907     /*  transceiver mode */
00908     if (sendRxPayload == TRUE )
00909     {
00910         NWP_IF_WRITE_CHECK(g_pCB->FD, pCmdExt->pRxPayload, 
00911                            _SL_PROTOCOL_ALIGN_SIZE(pCmdExt->RxPayloadLen));
00912     }
00913 
00914     /*  Payload */
00915     if (pCmdExt && pCmdExt->TxPayloadLen > 0)
00916     {
00917         /*  If the message has payload, it is mandatory that the message's arguments are protocol aligned. */
00918         /*  Otherwise the aligning of arguments will create a gap between arguments and payload. */
00919         VERIFY_PROTOCOL(_SL_IS_PROTOCOL_ALIGNED_SIZE(pCmdCtrl->TxDescLen));
00920 
00921         NWP_IF_WRITE_CHECK(g_pCB->FD, pCmdExt->pTxPayload, 
00922                            _SL_PROTOCOL_ALIGN_SIZE(pCmdExt->TxPayloadLen));
00923     }
00924 
00925 
00926     _SL_DBG_CNT_INC(MsgCnt.Write);
00927 
00928 #ifdef SL_START_WRITE_STAT
00929     sl_IfEndWriteSequence(g_pCB->FD);
00930 #endif
00931 
00932     return SL_OS_RET_CODE_OK;
00933 }
00934 
00935 /* ******************************************************************************/
00936 /*  _SlDrvMsgRead  */
00937 /* ******************************************************************************/
00938 static _SlReturnVal_t _SlDrvMsgRead(void)
00939 {
00940     /*  alignment for small memory models */
00941     union
00942     {      
00943       _u8             TempBuf[_SL_RESP_HDR_SIZE];
00944       _u32            DummyBuf[2];
00945     } uBuf;
00946     _u8               TailBuffer[4];
00947     _u16              LengthToCopy;
00948     _u16              AlignedLengthRecv;
00949     _u8               AlignSize;
00950     _u8               *pAsyncBuf = NULL;
00951     _u16              OpCode;
00952     _u16              RespPayloadLen;
00953     _u8               sd = SL_MAX_SOCKETS;
00954     _SlRxMsgClass_e   RxMsgClass;
00955     
00956 
00957     /* save params in global CB */
00958     g_pCB->FunctionParams.AsyncExt.pAsyncBuf      = NULL;
00959     g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler= NULL;
00960 
00961 #ifdef SL_TINY_EXT
00962     VERIFY_RET_OK(_SlDrvRxHdrRead((_u8*)(uBuf.TempBuf), &AlignSize));
00963 #else   
00964     if (_SlDrvRxHdrRead((_u8*)(uBuf.TempBuf), &AlignSize) == SL_API_ABORTED)
00965     {
00966         SL_DRV_LOCK_GLOBAL_UNLOCK();
00967 
00968         _SlDriverHandleError(SL_DEVICE_DRIVER_TIMEOUT_SYNC_PATTERN, 0, 0);
00969         return SL_API_ABORTED;
00970     }
00971 #endif
00972     OpCode = OPCODE(uBuf.TempBuf);
00973     RespPayloadLen = (_u16)(RSP_PAYLOAD_LEN(uBuf.TempBuf));
00974 
00975 
00976     /* 'Init Compelete' message bears no valid FlowControl info */
00977     if(SL_OPCODE_DEVICE_INITCOMPLETE != OpCode)
00978     {
00979         g_pCB->FlowContCB.TxPoolCnt = ((_SlResponseHeader_t *)uBuf.TempBuf)->TxPoolCnt;
00980         g_pCB->SocketNonBlocking = ((_SlResponseHeader_t *)uBuf.TempBuf)->SocketNonBlocking;
00981         g_pCB->SocketTXFailure = ((_SlResponseHeader_t *)uBuf.TempBuf)->SocketTXFailure;
00982 
00983         if(g_pCB->FlowContCB.TxPoolCnt > FLOW_CONT_MIN)
00984         {
00985             SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->FlowContCB.TxSyncObj);
00986         }
00987     }
00988 
00989     /* Find the RX messaage class and set its async event handler */
00990     _SlDrvClassifyRxMsg(OpCode);
00991     
00992     RxMsgClass = g_pCB->FunctionParams.AsyncExt.RxMsgClass;
00993 
00994 
00995     switch(RxMsgClass)
00996     {
00997     case ASYNC_EVT_CLASS:
00998 
00999             VERIFY_PROTOCOL(NULL == pAsyncBuf);
01000 
01001 #ifdef SL_MEMORY_MGMT_DYNAMIC
01002         g_pCB->FunctionParams.AsyncExt.pAsyncBuf = (_u8*)sl_Malloc(SL_ASYNC_MAX_MSG_LEN);
01003 #else
01004         g_pCB->FunctionParams.AsyncExt.pAsyncBuf = g_StatMem.AsyncRespBuf;
01005 #endif
01006             /* set the local pointer to the allocated one */
01007             pAsyncBuf = g_pCB->FunctionParams.AsyncExt.pAsyncBuf;
01008 
01009             /* clear the async buffer */
01010             _SlDrvMemZero(pAsyncBuf, (_u16)SL_ASYNC_MAX_MSG_LEN);
01011             
01012             MALLOC_OK_CHECK(pAsyncBuf);
01013 
01014             sl_Memcpy(pAsyncBuf, uBuf.TempBuf, _SL_RESP_HDR_SIZE);
01015             if (_SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen) <= SL_ASYNC_MAX_PAYLOAD_LEN)
01016             {
01017                 AlignedLengthRecv = (_u16)_SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen);
01018             }
01019             else
01020             {
01021                 AlignedLengthRecv = (_u16)_SL_PROTOCOL_ALIGN_SIZE(SL_ASYNC_MAX_PAYLOAD_LEN);
01022             }
01023             if (RespPayloadLen > 0)
01024             {
01025                 NWP_IF_READ_CHECK(g_pCB->FD,
01026                                   pAsyncBuf + _SL_RESP_HDR_SIZE,
01027                                   AlignedLengthRecv);
01028         }
01029         /* In case ASYNC RX buffer length is smaller then the received data length, dump the rest */
01030             if ((_SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen) > SL_ASYNC_MAX_PAYLOAD_LEN))
01031         {
01032                 AlignedLengthRecv = (_u16)(_SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen) - SL_ASYNC_MAX_PAYLOAD_LEN);
01033             while (AlignedLengthRecv > 0)
01034             {
01035                 NWP_IF_READ_CHECK(g_pCB->FD,TailBuffer,4);
01036                 AlignedLengthRecv = AlignedLengthRecv - 4;
01037             }
01038         }
01039             
01040             SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
01041           
01042             if (
01043 #ifndef SL_TINY_EXT               
01044                 (SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE == OpCode) || 
01045                 (SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE_V6 == OpCode) || 
01046 #endif                
01047                 (SL_OPCODE_SOCKET_CONNECTASYNCRESPONSE == OpCode)
01048                )
01049             {
01050                 /* go over the active list if exist to find obj waiting for this Async event */
01051                 sd = ((((_SocketResponse_t *)(pAsyncBuf + _SL_RESP_HDR_SIZE))->sd) & BSD_SOCKET_ID_MASK);
01052             }
01053             
01054              (void)_SlFindAndSetActiveObj(OpCode, sd);
01055 
01056              SL_DRV_PROTECTION_OBJ_UNLOCK();
01057 
01058             break;
01059     case RECV_RESP_CLASS:
01060         {
01061             _u8   ExpArgSize; /*  Expected size of Recv/Recvfrom arguments */
01062 
01063                 switch(OpCode)
01064             {
01065             case SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE:
01066                 ExpArgSize = (_u8)RECVFROM_IPV4_ARGS_SIZE;
01067                 break;
01068 #ifndef SL_TINY_EXT                        
01069             case SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE_V6:
01070                 ExpArgSize = (_u8)RECVFROM_IPV6_ARGS_SIZE;
01071                 break;
01072 #endif                        
01073             default:
01074                 /* SL_OPCODE_SOCKET_RECVASYNCRESPONSE: */
01075                 ExpArgSize = (_u8)RECV_ARGS_SIZE;
01076             }              
01077 
01078             /*  Read first 4 bytes of Recv/Recvfrom response to get SocketId and actual  */
01079             /*  response data length */
01080             NWP_IF_READ_CHECK(g_pCB->FD, &uBuf.TempBuf[4], RECV_ARGS_SIZE);
01081 
01082             /*  Validate Socket ID and Received Length value.  */
01083             VERIFY_PROTOCOL((SD(&uBuf.TempBuf[4])& BSD_SOCKET_ID_MASK) < SL_MAX_SOCKETS);
01084 
01085             SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
01086 
01087             /* go over the active list if exist to find obj waiting for this Async event */
01088                 VERIFY_RET_OK(_SlFindAndSetActiveObj(OpCode,SD(&uBuf.TempBuf[4]) & BSD_SOCKET_ID_MASK));
01089 
01090             /*  Verify data is waited on this socket. The pArgs should have been set by _SlDrvDataReadOp(). */
01091             VERIFY_SOCKET_CB(NULL !=  ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pData))->pArgs);    
01092 
01093             sl_Memcpy( ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pArgs, &uBuf.TempBuf[4], RECV_ARGS_SIZE);
01094 
01095             if(ExpArgSize > (_u8)RECV_ARGS_SIZE)
01096             {
01097                 NWP_IF_READ_CHECK(g_pCB->FD,
01098                     ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pArgs + RECV_ARGS_SIZE,
01099                     ExpArgSize - RECV_ARGS_SIZE);
01100             }
01101 
01102             /*  Here g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pData contains requested(expected) Recv/Recvfrom DataSize. */
01103             /*  Overwrite requested DataSize with actual one. */
01104             /*  If error is received, this information will be read from arguments. */
01105             if(ACT_DATA_SIZE(&uBuf.TempBuf[4]) > 0)
01106             {       
01107                 VERIFY_SOCKET_CB(NULL != ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pData);
01108 
01109                 /*  Read 4 bytes aligned from interface */
01110                 /*  therefore check the requested length and read only  */
01111                 /*  4 bytes aligned data. The rest unaligned (if any) will be read */
01112                 /*  and copied to a TailBuffer  */
01113                 LengthToCopy = (_u16)(ACT_DATA_SIZE(&uBuf.TempBuf[4]) & (3));
01114                 AlignedLengthRecv = (_u16)(ACT_DATA_SIZE(&uBuf.TempBuf[4]) & (~3));
01115                 if( AlignedLengthRecv >= 4)
01116                 {
01117                     NWP_IF_READ_CHECK(g_pCB->FD,((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pData,AlignedLengthRecv );                      
01118                 }
01119                 /*  copy the unaligned part, if any */
01120                 if( LengthToCopy > 0) 
01121                 {
01122                     NWP_IF_READ_CHECK(g_pCB->FD,TailBuffer,4);
01123                     /*  copy TailBuffer unaligned part (1/2/3 bytes) */
01124                     sl_Memcpy(((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pData + AlignedLengthRecv,TailBuffer,LengthToCopy);                    
01125                 }                  
01126             }
01127                  SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
01128                  SL_DRV_PROTECTION_OBJ_UNLOCK();
01129         }
01130         break;
01131 
01132     case CMD_RESP_CLASS:
01133 
01134         /*  Some commands pass a maximum arguments size. */
01135         /*  In this case Driver will send extra dummy patterns to NWP if */
01136         /*  the response message is smaller than maximum. */
01137         /*  When RxDescLen is not exact, using RxPayloadLen is forbidden! */
01138         /*  If such case cannot be avoided - parse message here to detect */
01139         /*  arguments/payload border. */
01140         NWP_IF_READ_CHECK(g_pCB->FD,
01141             g_pCB->FunctionParams.pTxRxDescBuff,
01142             _SL_PROTOCOL_ALIGN_SIZE(g_pCB->FunctionParams.pCmdCtrl->RxDescLen));
01143 
01144         if((NULL != g_pCB->FunctionParams.pCmdExt) && (0 != g_pCB->FunctionParams.pCmdExt->RxPayloadLen))
01145         {
01146             /*  Actual size of command's response payload: <msg_payload_len> - <rsp_args_len> */
01147             _i16    ActDataSize = (_i16)(RSP_PAYLOAD_LEN(uBuf.TempBuf) - g_pCB->FunctionParams.pCmdCtrl->RxDescLen);
01148 
01149             g_pCB->FunctionParams.pCmdExt->ActualRxPayloadLen = ActDataSize;
01150 
01151             /* Check that the space prepared by user for the response data is sufficient. */
01152             if(ActDataSize <= 0)
01153             {
01154                 g_pCB->FunctionParams.pCmdExt->RxPayloadLen = 0;
01155             }
01156             else
01157             {
01158                 /* In case the user supplied Rx buffer length which is smaller then the received data length, copy according to user length */
01159                 if (ActDataSize > g_pCB->FunctionParams.pCmdExt->RxPayloadLen)
01160                 {
01161                     LengthToCopy = (_u16)(g_pCB->FunctionParams.pCmdExt->RxPayloadLen & (3));
01162                     AlignedLengthRecv = (_u16)(g_pCB->FunctionParams.pCmdExt->RxPayloadLen & (~3));
01163                 }
01164                 else
01165                 {
01166                     LengthToCopy = (_u16)(ActDataSize & (3));
01167                     AlignedLengthRecv = (_u16)(ActDataSize & (~3));
01168                 }
01169                 /*  Read 4 bytes aligned from interface */
01170                 /*  therefore check the requested length and read only  */
01171                 /*  4 bytes aligned data. The rest unaligned (if any) will be read */
01172                 /*  and copied to a TailBuffer  */
01173 
01174                 if( AlignedLengthRecv >= 4)
01175                 {
01176                     NWP_IF_READ_CHECK(g_pCB->FD,
01177                         g_pCB->FunctionParams.pCmdExt->pRxPayload,
01178                         AlignedLengthRecv );
01179 
01180                 }
01181                 /*  copy the unaligned part, if any */
01182                 if( LengthToCopy > 0) 
01183                 {
01184                     NWP_IF_READ_CHECK(g_pCB->FD,TailBuffer,4);
01185                     /*  copy TailBuffer unaligned part (1/2/3 bytes) */
01186                     sl_Memcpy(g_pCB->FunctionParams.pCmdExt->pRxPayload + AlignedLengthRecv,
01187                         TailBuffer,
01188                         LengthToCopy);
01189                     ActDataSize = ActDataSize-4;
01190                 }
01191                 /* In case the user supplied Rx buffer length which is smaller then the received data length, dump the rest */
01192                 if (ActDataSize > g_pCB->FunctionParams.pCmdExt->RxPayloadLen)
01193                 {
01194                     /* calculate the rest of the data size to dump */
01195                     AlignedLengthRecv = (_u16)( (ActDataSize + 3 - g_pCB->FunctionParams.pCmdExt->RxPayloadLen) & (~3) );
01196                     while( AlignedLengthRecv > 0)
01197                     {
01198                         NWP_IF_READ_CHECK(g_pCB->FD,TailBuffer, 4 );
01199                         AlignedLengthRecv = AlignedLengthRecv - 4;
01200                     }
01201                 }
01202             }
01203         }
01204         break;
01205 
01206     default:
01207         /*  DUMMY_MSG_CLASS: Flow control message has no payload. */
01208         break;
01209     }
01210 
01211     if(AlignSize > 0)
01212     {
01213         NWP_IF_READ_CHECK(g_pCB->FD, uBuf.TempBuf, AlignSize);
01214     }
01215 
01216     _SL_DBG_CNT_INC(MsgCnt.Read);
01217 
01218     /*  Unmask Interrupt call */
01219     sl_IfUnMaskIntHdlr();
01220 
01221     return SL_OS_RET_CODE_OK;
01222 }
01223 
01224 
01225 /* ******************************************************************************/
01226 /*  _SlAsyncEventGenericHandler */
01227 /* ******************************************************************************/
01228 static void _SlAsyncEventGenericHandler(_u8 bInCmdContext)
01229 {
01230     _u32 SlAsyncEvent = 0;
01231     _u8  OpcodeFound = FALSE; 
01232     _u8  i;
01233     
01234     _u32* pEventLocation  = NULL; /* This pointer will override the async buffer with the translated event type */
01235     _SlResponseHeader_t  *pHdr       = (_SlResponseHeader_t *)g_pCB->FunctionParams.AsyncExt.pAsyncBuf;
01236 
01237 
01238     /* if no async event registered nothing to do..*/
01239     if (g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler == NULL)
01240         return;
01241 
01242     /* Iterate through all the opcode in the table */
01243     for (i=0; i< (_u8)(sizeof(OpcodeTranslateTable) / sizeof(OpcodeKeyVal_t)); i++)
01244     {
01245         if (OpcodeTranslateTable[i].opcode == pHdr->GenHeader.Opcode)
01246         {
01247             SlAsyncEvent = OpcodeTranslateTable[i].event;
01248             OpcodeFound = TRUE;
01249             break;
01250         }
01251     }
01252 
01253     /* No Async event found in the table */
01254     if (OpcodeFound == FALSE)
01255     {
01256         if ((pHdr->GenHeader.Opcode & SL_OPCODE_SILO_MASK) == SL_OPCODE_SILO_DEVICE)
01257         {
01258             DeviceEventInfo_t deviceEvent;
01259 
01260             deviceEvent.pAsyncMsgBuff = g_pCB->FunctionParams.AsyncExt.pAsyncBuf;
01261             deviceEvent.bInCmdContext = bInCmdContext;
01262 
01263             g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler(&deviceEvent);
01264         }
01265         else
01266         {
01267         /* This case handles all the async events handlers of the DEVICE & SOCK Silos which are handled internally.
01268                  For these cases we send the async even buffer as is */
01269         g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler(g_pCB->FunctionParams.AsyncExt.pAsyncBuf);
01270         }
01271     }
01272     else
01273     {
01274        /* calculate the event type location to be filled in the async buffer */
01275        pEventLocation = (_u32*)(g_pCB->FunctionParams.AsyncExt.pAsyncBuf + sizeof (_SlResponseHeader_t) - sizeof(SlAsyncEvent) );
01276 
01277        /* Override the async buffer (before the data starts ) with our event type  */
01278        *pEventLocation = SlAsyncEvent;
01279 
01280        /* call the event handler registered by the user with our async buffer which now holds
01281                 the User's event type and its related data */
01282        g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler(pEventLocation);
01283     }
01284 
01285      
01286 }
01287 
01288 
01289 /* ******************************************************************************/
01290 /*  _SlDrvMsgReadCmdCtx  */
01291 /* ******************************************************************************/
01292 static _SlReturnVal_t _SlDrvMsgReadCmdCtx(_u16 cmdOpcode)
01293 {
01294 #ifndef SL_TINY_EXT
01295     _u16 CmdCmpltTimeout;
01296 
01297     /* For any FS command, the timeout will be the long one as the commnad response holds the full response data */
01298     CmdCmpltTimeout = (SL_OPCODE_SILO_NVMEM & cmdOpcode)? (_u16)(SL_DRIVER_TIMEOUT_LONG) : (_u16)SL_DRIVER_TIMEOUT_SHORT;
01299 #endif
01300 
01301     /*  after command response is received and isCmdRespWaited */
01302     /*  flag is set FALSE, it is necessary to read out all */
01303     /*  Async messages in Commands context, because ssiDma_IsrHandleSignalFromSlave */
01304     /*  could have dispatched some Async messages to g_NwpIf.CmdSyncObj */
01305     /*  after command response but before this response has been processed */
01306     /*  by spi_singleRead and isCmdRespWaited was set FALSE. */
01307     while (TRUE == g_pCB->IsCmdRespWaited)
01308     {
01309         if(_SL_PENDING_RX_MSG(g_pCB))
01310         {
01311 #ifdef SL_TINY_EXT        
01312             VERIFY_RET_OK(_SlDrvMsgRead());
01313 #else
01314             if (_SlDrvMsgRead() != SL_OS_RET_CODE_OK)
01315             {
01316                 SL_DRV_LOCK_GLOBAL_UNLOCK();
01317                 return SL_API_ABORTED;
01318             }
01319 #endif            
01320             g_pCB->RxDoneCnt++;
01321 
01322             if (CMD_RESP_CLASS == g_pCB->FunctionParams.AsyncExt.RxMsgClass)
01323             {
01324                 g_pCB->IsCmdRespWaited = FALSE;
01325 
01326                 /*  In case CmdResp has been read without  waiting on CmdSyncObj -  that */
01327                 /*  Sync object. That to prevent old signal to be processed. */
01328                 SL_DRV_SYNC_OBJ_CLEAR(&g_pCB->CmdSyncObj);
01329             }
01330             else if (ASYNC_EVT_CLASS == g_pCB->FunctionParams.AsyncExt.RxMsgClass)
01331             {
01332                 /*  If Async event has been read in CmdResp context, check whether */
01333                 /*  there is a handler for this event. If there is, spawn specific */
01334                 /*  handler. Otherwise free the event's buffer. */
01335                 /*  This way there will be no "dry shots" from CmdResp context to */
01336                 /*  temporary context, i.e less waste of CPU and faster buffer */
01337                 /*  release. */
01338                 _SlAsyncEventGenericHandler(TRUE);
01339                 
01340                 
01341 #ifdef SL_MEMORY_MGMT_DYNAMIC
01342                 sl_Free(g_pCB->FunctionParams.AsyncExt.pAsyncBuf);
01343 #else
01344                 g_pCB->FunctionParams.AsyncExt.pAsyncBuf = NULL;
01345 #endif
01346             }
01347         }
01348         else
01349         {
01350 #ifdef SL_TINY_EXT          
01351             /* CmdSyncObj will be signaled by IRQ */
01352              _SlDrvSyncObjWaitForever(&g_pCB->CmdSyncObj);
01353 #else
01354 
01355 
01356             if (sl_SyncObjWait(&g_pCB->CmdSyncObj, CmdCmpltTimeout))
01357             {
01358                 SL_DRV_LOCK_GLOBAL_UNLOCK();
01359                 _SlDriverHandleError(SL_DEVICE_DRIVER_TIMEOUT_CMD_COMPLETE, cmdOpcode, CmdCmpltTimeout);
01360                 return SL_API_ABORTED;
01361             }
01362 #endif                        
01363         }
01364     }
01365 
01366     /*  If there are more pending Rx Msgs after CmdResp is received, */
01367     /*  that means that these are Async, Dummy or Read Data Msgs. */
01368     /*  Spawn _SlDrvMsgReadSpawnCtx to trigger reading these messages from */
01369     /*  Temporary context. */
01370     /* sl_Spawn is activated, using a different context */
01371 
01372     SL_DRV_LOCK_GLOBAL_UNLOCK();
01373     
01374     if(_SL_PENDING_RX_MSG(g_pCB))
01375     {
01376         (void)sl_Spawn((_SlSpawnEntryFunc_t)_SlDrvMsgReadSpawnCtx, NULL, 0);
01377     }
01378 
01379     return SL_OS_RET_CODE_OK;
01380 }
01381 
01382 /* ******************************************************************************/
01383 /*  _SlDrvMsgReadSpawnCtx                                                       */
01384 /* ******************************************************************************/
01385 _SlReturnVal_t _SlDrvMsgReadSpawnCtx(void *pValue)
01386 {
01387 #ifdef SL_POLLING_MODE_USED
01388     _i16 retCode = OSI_OK;
01389     /*  for polling based systems */
01390     do
01391     {
01392         retCode = sl_LockObjLock(&g_pCB->GlobalLockObj, 0);
01393         if ( OSI_OK != retCode )
01394         {
01395             if (TRUE == g_pCB->IsCmdRespWaited)
01396             {
01397                 SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->CmdSyncObj);
01398                 return SL_RET_CODE_OK;
01399             }
01400         }
01401 
01402     }
01403     while (OSI_OK != retCode);
01404 
01405 #else
01406     SL_DRV_LOCK_GLOBAL_LOCK_FOREVER();
01407 #endif
01408 
01409     /* pValue paramater is currently not in use */
01410     (void)pValue;
01411 
01412     /*  Messages might have been read by CmdResp context. Therefore after */
01413     /*  getting LockObj, check again where the Pending Rx Msg is still present. */
01414     if(FALSE == (_SL_PENDING_RX_MSG(g_pCB)))
01415     {
01416         SL_DRV_LOCK_GLOBAL_UNLOCK();
01417         
01418         return SL_RET_CODE_OK;
01419     }
01420 
01421 #ifdef SL_TINY_EXT
01422     VERIFY_RET_OK(_SlDrvMsgRead());
01423 #else
01424     if (_SlDrvMsgRead() != SL_OS_RET_CODE_OK)
01425     {
01426         SL_DRV_LOCK_GLOBAL_UNLOCK();
01427         return SL_API_ABORTED;
01428     }
01429 #endif
01430 
01431     g_pCB->RxDoneCnt++;
01432 
01433     switch(g_pCB->FunctionParams.AsyncExt.RxMsgClass)
01434     {
01435     case ASYNC_EVT_CLASS:
01436         /*  If got here and protected by LockObj a message is waiting  */
01437         /*  to be read */
01438         VERIFY_PROTOCOL(NULL != g_pCB->FunctionParams.AsyncExt.pAsyncBuf);
01439    
01440         _SlAsyncEventGenericHandler(FALSE);        
01441         
01442 #ifdef SL_MEMORY_MGMT_DYNAMIC
01443         sl_Free(g_pCB->FunctionParams.AsyncExt.pAsyncBuf);
01444 #else
01445         g_pCB->FunctionParams.AsyncExt.pAsyncBuf = NULL;
01446 #endif
01447         break;
01448     case DUMMY_MSG_CLASS:
01449     case RECV_RESP_CLASS:
01450         /* These types are legal in this context. Do nothing */
01451         break;
01452     case CMD_RESP_CLASS:
01453         /* Command response is illegal in this context. */
01454         /* No 'break' here: Assert! */
01455     default:
01456         VERIFY_PROTOCOL(0);
01457     }
01458 
01459     SL_DRV_LOCK_GLOBAL_UNLOCK();
01460 
01461     return(SL_RET_CODE_OK);
01462 }
01463 
01464 
01465 
01466 /*
01467 
01468 #define SL_OPCODE_SILO_DEVICE                           ( 0x0 << SL_OPCODE_SILO_OFFSET )
01469 #define SL_OPCODE_SILO_WLAN                             ( 0x1 << SL_OPCODE_SILO_OFFSET )
01470 #define SL_OPCODE_SILO_SOCKET                           ( 0x2 << SL_OPCODE_SILO_OFFSET )
01471 #define SL_OPCODE_SILO_NETAPP                           ( 0x3 << SL_OPCODE_SILO_OFFSET )
01472 #define SL_OPCODE_SILO_NVMEM                            ( 0x4 << SL_OPCODE_SILO_OFFSET )
01473 #define SL_OPCODE_SILO_NETCFG                           ( 0x5 << SL_OPCODE_SILO_OFFSET )
01474 
01475 
01476 */
01477 
01478 /* The Lookup table below holds the event handlers to be called according to the incoming
01479     RX message SILO type */
01480 static const _SlSpawnEntryFunc_t RxMsgClassLUT[] = {
01481     (_SlSpawnEntryFunc_t)_SlDrvDeviceEventHandler, /* SL_OPCODE_SILO_DEVICE */
01482 #if defined(sl_WlanEvtHdlr) || defined(EXT_LIB_REGISTERED_WLAN_EVENTS)
01483     (_SlSpawnEntryFunc_t)_SlDrvHandleWlanEvents,           /* SL_OPCODE_SILO_WLAN */
01484 #else
01485     NULL,
01486 #endif
01487 #if defined (sl_SockEvtHdlr) || defined(EXT_LIB_REGISTERED_SOCK_EVENTS)
01488     (_SlSpawnEntryFunc_t)_SlDrvHandleSockEvents,   /* SL_OPCODE_SILO_SOCKET */
01489 #else
01490     NULL,
01491 #endif
01492 
01493 #if defined(sl_NetAppEvtHdlr) || defined(EXT_LIB_REGISTERED_NETAPP_EVENTS)
01494     (_SlSpawnEntryFunc_t)_SlDrvHandleNetAppEvents, /* SL_OPCODE_SILO_NETAPP */
01495 #else
01496     NULL,  
01497 #endif
01498     NULL,                                          /* SL_OPCODE_SILO_NVMEM */
01499     NULL,                                          /* SL_OPCODE_SILO_NETCFG */
01500     NULL,
01501     NULL
01502 };
01503 
01504 
01505 /* ******************************************************************************/
01506 /*  _SlDrvClassifyRxMsg */
01507 /* ******************************************************************************/
01508 static _SlReturnVal_t _SlDrvClassifyRxMsg(
01509     _SlOpcode_t         Opcode)
01510 {
01511     _SlSpawnEntryFunc_t AsyncEvtHandler = NULL;
01512     _SlRxMsgClass_e     RxMsgClass  = CMD_RESP_CLASS;
01513     _u8               Silo;
01514     
01515 
01516     if (0 == (SL_OPCODE_SYNC & Opcode))
01517     {   /* Async event has received */
01518         
01519         if (SL_OPCODE_DEVICE_DEVICEASYNCDUMMY == Opcode)
01520         { 
01521             RxMsgClass = DUMMY_MSG_CLASS;
01522         }
01523         else if ( (SL_OPCODE_SOCKET_RECVASYNCRESPONSE == Opcode) || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE == Opcode) 
01524 #ifndef SL_TINY_EXT                      
01525                     || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE_V6 == Opcode) 
01526 #endif                    
01527                  ) 
01528         {
01529             RxMsgClass = RECV_RESP_CLASS;
01530         }
01531         else
01532         {
01533             /* This is Async Event class message */
01534             RxMsgClass = ASYNC_EVT_CLASS;
01535         
01536             /* Despite the fact that 4 bits are allocated in the SILO field, we actually have only 6 SILOs
01537               So we can use the 8 options of SILO in look up table */
01538             Silo = (_u8)((Opcode >> SL_OPCODE_SILO_OFFSET) & 0x7);
01539 
01540             VERIFY_PROTOCOL(Silo < (_u8)(sizeof(RxMsgClassLUT)/sizeof(_SlSpawnEntryFunc_t)));
01541 
01542             /* Set the async event hander according to the LUT */
01543             AsyncEvtHandler = RxMsgClassLUT[Silo];
01544             
01545             if ((SL_OPCODE_NETAPP_HTTPGETTOKENVALUE == Opcode) || (SL_OPCODE_NETAPP_HTTPPOSTTOKENVALUE == Opcode))
01546             {
01547                 AsyncEvtHandler = _SlDrvNetAppEventHandler;
01548             }
01549 #ifndef SL_TINY_EXT            
01550             else if (SL_OPCODE_NETAPP_PINGREPORTREQUESTRESPONSE == Opcode)
01551             {
01552                 AsyncEvtHandler = (_SlSpawnEntryFunc_t)_sl_HandleAsync_PingResponse;
01553             }
01554 #endif
01555         }
01556     }
01557 
01558     g_pCB->FunctionParams.AsyncExt.RxMsgClass = RxMsgClass; 
01559     g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler = AsyncEvtHandler;
01560          
01561 
01562     return SL_RET_CODE_OK;
01563 }
01564 
01565 
01566 /* ******************************************************************************/
01567 /*  _SlDrvRxHdrRead  */
01568 /* ******************************************************************************/
01569 static _SlReturnVal_t _SlDrvRxHdrRead(_u8 *pBuf, _u8 *pAlignSize)
01570 {
01571      _u32       SyncCnt  = 0;
01572     _u8         ShiftIdx;
01573     _u8         TimeoutState = TIMEOUT_STATE_INIT_VAL;
01574     _u8         SearchSync = TRUE;
01575 
01576 
01577 #if (!defined (SL_TINY_EXT)) && (defined(sl_GetTimestamp))
01578      _SlTimeoutParams_t      TimeoutInfo={0};
01579 #endif
01580 
01581 #ifndef SL_IF_TYPE_UART
01582     /*  1. Write CNYS pattern to NWP when working in SPI mode only  */
01583     NWP_IF_WRITE_CHECK(g_pCB->FD, (_u8 *)&g_H2NCnysPattern.Short, SYNC_PATTERN_LEN);
01584 #endif
01585 
01586 #if (!defined (SL_TINY)) && (defined(sl_GetTimestamp))
01587     _SlDrvStartMeasureTimeout(&TimeoutInfo, SYNC_PATTERN_TIMEOUT_IN_MSEC);
01588 #endif
01589 
01590     /*  2. Read 8 bytes (protocol aligned) - expected to be the sync pattern */
01591     NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[0], 8);
01592     _SL_DBG_SYNC_LOG(SyncCnt,pBuf);
01593 
01594     /* read while first 4 bytes are different than last 4 bytes */
01595     while ( *(_u32 *)&pBuf[0] == *(_u32 *)&pBuf[4])
01596     {
01597          NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[4], 4);
01598     }
01599 
01600 
01601     /* scan for the sync pattern till found or timeout elapsed (if configured) */
01602     while (SearchSync && TimeoutState)
01603     {
01604         /* scan till we get the real sync pattern */
01605         for (ShiftIdx =0; ShiftIdx <=4 ; ShiftIdx++)
01606         {
01607            /* sync pattern found so complete the read to  4 bytes aligned */
01608            if (N2H_SYNC_PATTERN_MATCH(&pBuf[ShiftIdx], g_pCB->TxSeqNum))
01609            {
01610                    /* copy the bytes following the sync pattern to the buffer start */
01611                    *(_u32 *)&pBuf[0] = *(_u32 *)&pBuf[ShiftIdx + SYNC_PATTERN_LEN];
01612 
01613                   /* read the rest of the byte */
01614                   NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[SYNC_PATTERN_LEN - ShiftIdx], ShiftIdx);
01615 
01616                   /* here we except to get the opcode + length or false doubled sync..*/
01617                   SearchSync = FALSE;
01618                   break;
01619            }
01620 
01621         }
01622 
01623         if (SearchSync == TRUE)
01624         {
01625             /* sync not found move top 4 bytes to bottom */
01626             *(_u32 *)&pBuf[0] = *(_u32 *)&pBuf[4];
01627 
01628             /* read 4 more bytes to the buffer top */
01629             NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[4], 4);
01630         }
01631 
01632 
01633 #if (defined (sl_GetTimestamp)) &&  (!defined (SL_TINY))
01634 
01635        /* if we got here after first timeout detection, it means that we gave
01636            one more chance, and we can now exit the loop with timeout expiry  */
01637        if (TIMEOUT_ONE_MORE_SHOT == TimeoutState)
01638        {
01639            TimeoutState =  TIMEOUT_STATE_EXPIRY;
01640            break;
01641        }
01642 
01643        /* Timeout occured. do not break now as we want to give one more chance in case
01644            the timeout occured due to some external context switch */
01645        if (_SlDrvIsTimeoutExpired(&TimeoutInfo))
01646        {
01647         TimeoutState = TIMEOUT_ONE_MORE_SHOT;
01648        }
01649 
01650 #endif
01651 
01652     } /* end of while*/
01653 
01654 
01655 #if (defined (sl_GetTimestamp)) &&  (!defined (SL_TINY))
01656     if (TIMEOUT_STATE_EXPIRY  == TimeoutState)
01657     {
01658         return SL_API_ABORTED;
01659     }
01660 #endif
01661 
01662 
01663 
01664     /*  6. Scan for Double pattern. */
01665     while ( N2H_SYNC_PATTERN_MATCH(pBuf, g_pCB->TxSeqNum) )
01666     {
01667         _SL_DBG_CNT_INC(Work.DoubleSyncPattern);
01668         NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[0], SYNC_PATTERN_LEN);
01669     }
01670     g_pCB->TxSeqNum++;
01671 
01672     /*  7. Here we've read Generic Header (4 bytes opcode+length).
01673      * Now Read the Resp Specific header (4 more bytes). */
01674     NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[SYNC_PATTERN_LEN], _SL_RESP_SPEC_HDR_SIZE);
01675 
01676     /*  8. Here we've read the entire Resp Header. */
01677     /*     Return number bytes needed to be sent after read for NWP Rx 4-byte alignment (protocol alignment) */
01678     *pAlignSize = (_u8)((SyncCnt > 0) ? (SYNC_PATTERN_LEN - SyncCnt) : 0);
01679 
01680     return SL_RET_CODE_OK;
01681 }
01682 
01683 /* ***************************************************************************** */
01684 /*  _SlDrvBasicCmd */
01685 /* ***************************************************************************** */
01686 typedef union
01687 {
01688     _BasicResponse_t    Rsp;
01689 }_SlBasicCmdMsg_u;
01690 
01691 
01692 #ifndef SL_TINY_EXT
01693 _i16 _SlDrvBasicCmd(_SlOpcode_t Opcode)
01694 {
01695     _SlBasicCmdMsg_u       Msg;
01696     _SlCmdCtrl_t           CmdCtrl;
01697 
01698     _SlDrvMemZero(&Msg, (_u16)sizeof(_SlBasicCmdMsg_u));
01699     
01700     CmdCtrl.Opcode = Opcode;
01701     CmdCtrl.TxDescLen = 0;
01702     CmdCtrl.RxDescLen = (_SlArgSize_t)sizeof(_BasicResponse_t);
01703 
01704 
01705     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL));
01706 
01707     return (_i16)Msg.Rsp.status;
01708 }
01709 
01710 /*****************************************************************************
01711   _SlDrvCmdSend 
01712   Send SL command without waiting for command response 
01713   This function is unprotected and the caller should make 
01714   sure global lock is active
01715 *****************************************************************************/
01716 _SlReturnVal_t _SlDrvCmdSend(
01717     _SlCmdCtrl_t  *pCmdCtrl ,
01718     void          *pTxRxDescBuff ,
01719     _SlCmdExt_t   *pCmdExt)
01720 {
01721     _SlReturnVal_t RetVal;
01722     _u8            IsCmdRespWaitedOriginalVal;
01723 
01724        _SlFunctionParams_t originalFuncParms;
01725 
01726     /* save the current RespWait flag before clearing it */
01727     IsCmdRespWaitedOriginalVal = g_pCB->IsCmdRespWaited;
01728 
01729     /* save the current command paramaters */
01730     sl_Memcpy(&originalFuncParms,  &g_pCB->FunctionParams, sizeof(_SlFunctionParams_t));
01731 
01732     g_pCB->IsCmdRespWaited = FALSE;
01733   
01734     SL_TRACE0(DBG_MSG, MSG_312, "_SlDrvCmdSend: call _SlDrvMsgWrite");
01735 
01736     /* send the message */
01737     RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, pTxRxDescBuff);
01738 
01739     /* restore the original RespWait flag */
01740     g_pCB->IsCmdRespWaited = IsCmdRespWaitedOriginalVal;
01741 
01742     /* restore the original command paramaters  */
01743     sl_Memcpy(&g_pCB->FunctionParams, &originalFuncParms, sizeof(_SlFunctionParams_t));
01744 
01745     return RetVal;
01746 
01747 
01748 }
01749 #endif
01750 
01751 /* ***************************************************************************** */
01752 /*  _SlDrvWaitForPoolObj */
01753 /* ***************************************************************************** */
01754 _u8 _SlDrvWaitForPoolObj(_u8 ActionID, _u8 SocketID)
01755 {
01756     _u8 CurrObjIndex = MAX_CONCURRENT_ACTIONS;
01757 
01758     /* Get free object  */
01759     SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
01760     
01761     if (MAX_CONCURRENT_ACTIONS > g_pCB->FreePoolIdx)
01762     {
01763         /* save the current obj index */
01764         CurrObjIndex = g_pCB->FreePoolIdx;
01765         /* set the new free index */
01766 #ifndef SL_TINY_EXT
01767         if (MAX_CONCURRENT_ACTIONS > g_pCB->ObjPool[CurrObjIndex].NextIndex)
01768         {
01769             g_pCB->FreePoolIdx = g_pCB->ObjPool[CurrObjIndex].NextIndex;
01770         }
01771         else
01772 #endif           
01773         {
01774             /* No further free actions available */
01775             g_pCB->FreePoolIdx = MAX_CONCURRENT_ACTIONS;
01776         }
01777     }
01778     else
01779     {
01780         SL_DRV_PROTECTION_OBJ_UNLOCK();
01781         return CurrObjIndex;
01782     }
01783     g_pCB->ObjPool[CurrObjIndex].ActionID = (_u8)ActionID;
01784     if (SL_MAX_SOCKETS > SocketID)
01785     {
01786         g_pCB->ObjPool[CurrObjIndex].AdditionalData = SocketID;
01787     }
01788 #ifndef SL_TINY_EXT
01789     /*In case this action is socket related, SocketID bit will be on
01790     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 */
01791     while ( ( (SL_MAX_SOCKETS > SocketID) && (g_pCB->ActiveActionsBitmap & (1<<SocketID)) ) || 
01792             ( (g_pCB->ActiveActionsBitmap & (1<<ActionID)) && (SL_MAX_SOCKETS == SocketID) ) )
01793     {
01794         /* action in progress - move to pending list */
01795         g_pCB->ObjPool[CurrObjIndex].NextIndex = g_pCB->PendingPoolIdx;
01796         g_pCB->PendingPoolIdx = CurrObjIndex;
01797         SL_DRV_PROTECTION_OBJ_UNLOCK();
01798         
01799         /* wait for action to be free */
01800     (void)_SlDrvSyncObjWaitForever(&g_pCB->ObjPool[CurrObjIndex].SyncObj);
01801         
01802         /* set params and move to active (remove from pending list at _SlDrvReleasePoolObj) */
01803         SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
01804     }
01805 #endif
01806     /* mark as active. Set socket as active if action is on socket, otherwise mark action as active */
01807     if (SL_MAX_SOCKETS > SocketID)
01808     {
01809         g_pCB->ActiveActionsBitmap |= (1<<SocketID);
01810     }
01811     else
01812     {
01813         g_pCB->ActiveActionsBitmap |= (1<<ActionID);
01814     }
01815     /* move to active list  */
01816     g_pCB->ObjPool[CurrObjIndex].NextIndex = g_pCB->ActivePoolIdx;
01817     g_pCB->ActivePoolIdx = CurrObjIndex;    
01818     /* unlock */
01819     SL_DRV_PROTECTION_OBJ_UNLOCK();
01820     return CurrObjIndex;
01821 }
01822 
01823 /* ******************************************************************************/
01824 /*  _SlDrvReleasePoolObj */
01825 /* ******************************************************************************/
01826 void _SlDrvReleasePoolObj(_u8 ObjIdx)
01827 {
01828 #ifndef SL_TINY_EXT        
01829     _u8 PendingIndex;
01830 #endif
01831 
01832      SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
01833 
01834       /* In Tiny mode, there is only one object pool so no pending actions are available */
01835 #ifndef SL_TINY_EXT
01836     /* go over the pending list and release other pending action if needed */
01837     PendingIndex = g_pCB->PendingPoolIdx;
01838         
01839     while(MAX_CONCURRENT_ACTIONS > PendingIndex)
01840     {
01841         /* In case this action is socket related, SocketID is in use, otherwise will be set to SL_MAX_SOCKETS */
01842         if ( (g_pCB->ObjPool[PendingIndex].ActionID == g_pCB->ObjPool[ObjIdx].ActionID) && 
01843             ( (SL_MAX_SOCKETS == (g_pCB->ObjPool[PendingIndex].AdditionalData & BSD_SOCKET_ID_MASK)) || 
01844             ((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) ))) )
01845         {
01846             /* remove from pending list */
01847             _SlRemoveFromList(&g_pCB->PendingPoolIdx, PendingIndex);
01848              SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[PendingIndex].SyncObj);
01849              break;
01850         }
01851         PendingIndex = g_pCB->ObjPool[PendingIndex].NextIndex;
01852     }
01853 #endif
01854 
01855         if (SL_MAX_SOCKETS > (g_pCB->ObjPool[ObjIdx].AdditionalData & BSD_SOCKET_ID_MASK))
01856         {
01857         /* unset socketID  */
01858             g_pCB->ActiveActionsBitmap &= ~(1<<(g_pCB->ObjPool[ObjIdx].AdditionalData & BSD_SOCKET_ID_MASK));
01859         }
01860         else
01861         {
01862         /* unset actionID  */
01863             g_pCB->ActiveActionsBitmap &= ~(1<<g_pCB->ObjPool[ObjIdx].ActionID);
01864         }   
01865 
01866     /* delete old data */
01867     g_pCB->ObjPool[ObjIdx].pRespArgs = NULL;
01868     g_pCB->ObjPool[ObjIdx].ActionID = 0;
01869     g_pCB->ObjPool[ObjIdx].AdditionalData = SL_MAX_SOCKETS;
01870 
01871     /* remove from active list */
01872     _SlRemoveFromList(&g_pCB->ActivePoolIdx, ObjIdx);
01873     /* move to free list */
01874     g_pCB->ObjPool[ObjIdx].NextIndex = g_pCB->FreePoolIdx;
01875     g_pCB->FreePoolIdx = ObjIdx;
01876     SL_DRV_PROTECTION_OBJ_UNLOCK();
01877 }
01878 
01879 
01880 /* ******************************************************************************/
01881 /* _SlRemoveFromList  */
01882 /* ******************************************************************************/
01883 static void _SlRemoveFromList(_u8 *ListIndex, _u8 ItemIndex)
01884 {
01885 #ifndef SL_TINY_EXT  
01886     _u8 Idx;
01887 #endif        
01888         
01889     if (MAX_CONCURRENT_ACTIONS == g_pCB->ObjPool[*ListIndex].NextIndex)
01890     {
01891         *ListIndex = MAX_CONCURRENT_ACTIONS;
01892     }
01893     /* As MAX_CONCURRENT_ACTIONS is equal to 1 in Tiny mode */
01894 #ifndef SL_TINY_EXT
01895     /* need to remove the first item in the list and therefore update the global which holds this index */
01896     else if (*ListIndex == ItemIndex)
01897     {
01898         *ListIndex = g_pCB->ObjPool[ItemIndex].NextIndex;
01899     }
01900     else
01901     {
01902               Idx = *ListIndex;
01903       
01904               while(MAX_CONCURRENT_ACTIONS > Idx)
01905               {
01906                   /* remove from list */
01907                   if (g_pCB->ObjPool[Idx].NextIndex == ItemIndex)
01908                   {
01909                           g_pCB->ObjPool[Idx].NextIndex = g_pCB->ObjPool[ItemIndex].NextIndex;
01910                           break;
01911                   }
01912 
01913                   Idx = g_pCB->ObjPool[Idx].NextIndex;
01914               }
01915     }
01916 #endif    
01917 }
01918 
01919 
01920 /* ******************************************************************************/
01921 /*  _SlFindAndSetActiveObj                                                     */
01922 /* ******************************************************************************/
01923 static _SlReturnVal_t _SlFindAndSetActiveObj(_SlOpcode_t  Opcode, _u8 Sd)
01924 {
01925     _u8 ActiveIndex;
01926 
01927     ActiveIndex = g_pCB->ActivePoolIdx;
01928     /* go over the active list if exist to find obj waiting for this Async event */
01929 #ifndef SL_TINY_EXT    
01930         while (MAX_CONCURRENT_ACTIONS > ActiveIndex)
01931 #else
01932         /* Only one Active action is availabe in tiny mode, so we can replace the loop with if condition */
01933         if (MAX_CONCURRENT_ACTIONS > ActiveIndex)
01934 #endif
01935     {
01936         /* unset the Ipv4\IPv6 bit in the opcode if family bit was set  */
01937         if (g_pCB->ObjPool[ActiveIndex].AdditionalData & SL_NETAPP_FAMILY_MASK)
01938         {
01939             Opcode &= ~SL_OPCODE_IPV6;
01940         }
01941 
01942         if ((g_pCB->ObjPool[ActiveIndex].ActionID == RECV_ID) && (Sd == g_pCB->ObjPool[ActiveIndex].AdditionalData) && 
01943                         ( (SL_OPCODE_SOCKET_RECVASYNCRESPONSE == Opcode) || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE == Opcode)
01944 #ifndef SL_TINY_EXT
01945                         || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE_V6 == Opcode) 
01946 #endif
01947                           ) 
01948 
01949                )
01950         {
01951             g_pCB->FunctionParams.AsyncExt.ActionIndex = ActiveIndex;
01952             return SL_RET_CODE_OK;
01953         }
01954         /* In case this action is socket related, SocketID is in use, otherwise will be set to SL_MAX_SOCKETS */
01955         if ( (_SlActionLookupTable[ g_pCB->ObjPool[ActiveIndex].ActionID - MAX_SOCKET_ENUM_IDX].ActionAsyncOpcode == Opcode) && 
01956             ( ((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)) ) )
01957         {
01958             /* set handler */
01959             g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler = _SlActionLookupTable[ g_pCB->ObjPool[ActiveIndex].ActionID - MAX_SOCKET_ENUM_IDX].AsyncEventHandler;
01960             g_pCB->FunctionParams.AsyncExt.ActionIndex = ActiveIndex;
01961             return SL_RET_CODE_OK;
01962         }
01963         ActiveIndex = g_pCB->ObjPool[ActiveIndex].NextIndex;
01964     }
01965 
01966     return SL_RET_CODE_SELF_ERROR;
01967 
01968 }
01969 
01970 
01971 #if defined(sl_HttpServerCallback) || defined(EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS)
01972 void _SlDrvDispatchHttpServerEvents(SlHttpServerEvent_t *slHttpServerEvent, SlHttpServerResponse_t *slHttpServerResponse)
01973 {
01974     _SlDrvHandleHttpServerEvents (slHttpServerEvent, slHttpServerResponse);
01975 }
01976 #endif
01977 
01978 
01979 /* Wrappers for the object functions */
01980 
01981 
01982 _SlReturnVal_t _SlDrvSyncObjSignal(_SlSyncObj_t *pSyncObj)
01983 {
01984     OSI_RET_OK_CHECK(sl_SyncObjSignal(pSyncObj));
01985     return SL_OS_RET_CODE_OK;
01986 }
01987 
01988 _SlReturnVal_t _SlDrvObjLockWaitForever(_SlLockObj_t *pLockObj)
01989 {
01990     OSI_RET_OK_CHECK(sl_LockObjLock(pLockObj, SL_OS_WAIT_FOREVER));
01991     return SL_OS_RET_CODE_OK;
01992 }
01993 
01994 _SlReturnVal_t _SlDrvProtectionObjLockWaitForever(void)
01995 {
01996     OSI_RET_OK_CHECK(sl_LockObjLock(&g_pCB->ProtectionLockObj, SL_OS_WAIT_FOREVER));
01997 
01998     return SL_OS_RET_CODE_OK;
01999 }
02000 
02001 _SlReturnVal_t _SlDrvObjUnLock(_SlLockObj_t *pLockObj)
02002 {
02003     OSI_RET_OK_CHECK(sl_LockObjUnlock(pLockObj));
02004 
02005     return SL_OS_RET_CODE_OK;
02006 }
02007 
02008 _SlReturnVal_t _SlDrvProtectionObjUnLock(void)
02009 {
02010     OSI_RET_OK_CHECK(sl_LockObjUnlock(&g_pCB->ProtectionLockObj));
02011     return SL_OS_RET_CODE_OK;
02012 }
02013 
02014 static _SlReturnVal_t _SlDrvObjGlobalLockWaitForever(void)
02015 {
02016 #ifndef SL_TINY_EXT  
02017     if (g_bDeviceRestartIsRequired == TRUE)
02018     {
02019          return SL_API_ABORTED;
02020     }
02021 #endif        
02022     return sl_LockObjLock(&g_pCB->GlobalLockObj, SL_OS_WAIT_FOREVER);
02023 }
02024 _SlReturnVal_t _SlDrvGlobalObjUnLock(void)
02025 {
02026 
02027     OSI_RET_OK_CHECK(sl_LockObjUnlock(&g_pCB->GlobalLockObj));
02028 
02029     return SL_OS_RET_CODE_OK;
02030 }
02031 
02032 void _SlDrvMemZero(void* Addr, _u16 size)
02033 {
02034     sl_Memset(Addr, 0, size);
02035 }
02036 
02037 
02038 void _SlDrvResetCmdExt(_SlCmdExt_t* pCmdExt)
02039 {
02040     _SlDrvMemZero(pCmdExt, (_u16)sizeof (_SlCmdExt_t));
02041 }
02042 
02043 
02044 #ifdef SL_TINY_EXT
02045 
02046 _SlReturnVal_t  _SlDrvSyncObjWaitForever(_SlSyncObj_t *pSyncObj)
02047 {
02048     return sl_SyncObjWait(pSyncObj, SL_OS_WAIT_FOREVER);
02049 }
02050 
02051 #else
02052 _SlReturnVal_t  _SlDrvSyncObjWaitForever(_SlSyncObj_t *pSyncObj)
02053 {
02054     (void)sl_SyncObjWait(pSyncObj, SL_OS_WAIT_FOREVER);
02055 
02056     /*  if the wait is finished and we detect that restart is required (we in the middle of error handling),
02057           than we should abort immediately from the current API command execution
02058     */
02059     if (g_bDeviceRestartIsRequired == TRUE)
02060     {
02061         return SL_API_ABORTED;
02062     }
02063 
02064     return SL_RET_CODE_OK;
02065 }
02066 
02067 #endif
02068 
02069 
02070 #ifndef SL_TINY_EXT
02071        
02072 
02073 _SlReturnVal_t  _SlDrvSyncObjWaitTimeout(_SlSyncObj_t *pSyncObj, _u32 timeoutVal, SlDriverAPIWithTimeout_e apiIdx)
02074 {
02075     _SlReturnVal_t ret = sl_SyncObjWait(pSyncObj, timeoutVal);
02076 
02077     /* if timeout occured...*/
02078     if (ret)
02079     {
02080         _SlDriverHandleError(SL_DEVICE_DRIVER_TIMEOUT_ASYNC_EVENT, apiIdx, timeoutVal);
02081     }
02082     else if (g_bDeviceRestartIsRequired == TRUE)
02083     {
02084         return SL_API_ABORTED;
02085     }
02086 
02087     return SL_RET_CODE_OK;
02088 }
02089 
02090 
02091 void _SlDriverHandleError(SlDeviceDriverError_e eError, _u32 info1, _u32 info2)
02092 {
02093     _u8 i;
02094     SlDeviceEvent_t  devHandler;
02095 
02096     if (TRUE == g_bDeviceRestartIsRequired)
02097     {
02098             return;
02099     }
02100         
02101     /* set the restart flag */
02102     g_bDeviceRestartIsRequired = TRUE;
02103     
02104      /* Upon the deletion of the mutex, all thread waiting on this
02105      mutex will return immediately with an error (i.e. MUTEX_DELETED status) */
02106      (void)sl_LockObjDelete(&g_pCB->GlobalLockObj);
02107 
02108     /* signal all waiting sync objects */
02109     for (i=0; i< MAX_CONCURRENT_ACTIONS; i++)
02110     {
02111         SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[i].SyncObj);
02112     }
02113 
02114     /* prepare the event and notify the user app/ext libraries */
02115     devHandler.Event = eError;
02116 
02117     switch (eError)
02118     {
02119         case SL_DEVICE_ABORT_ERROR_EVENT:
02120         {
02121             devHandler.EventData.deviceReport.AbortType = (_u32)info1;
02122             devHandler.EventData.deviceReport.AbortData = (_u32)info2;
02123         }
02124         break;
02125         
02126         /* For asyn event timeout type error:
02127          * Info1 - Holds the SL API index (2 bytes)
02128          */
02129         case SL_DEVICE_DRIVER_TIMEOUT_ASYNC_EVENT:
02130 
02131         /* For cmd complete timeout type error:
02132          * Info1 - Holds the cmd opcode (2 bytes)
02133          */
02134         case SL_DEVICE_DRIVER_TIMEOUT_CMD_COMPLETE:
02135         {
02136             devHandler.EventData.deviceDriverReport.info = info1;
02137         }
02138         break;
02139 
02140         default:
02141             devHandler.EventData.deviceDriverReport.info = info1;
02142             break;
02143     }
02144 
02145     /* call the registered handlers */
02146     _SlDrvHandleGeneralEvents(&devHandler);
02147 
02148 }
02149 
02150 
02151 #if (defined(sl_GetTimestamp))
02152 
02153 void _SlDrvStartMeasureTimeout(_SlTimeoutParams_t *pTimeoutInfo, _u32 TimeoutInMsec)
02154 {
02155     pTimeoutInfo->Total10MSecUnits = TimeoutInMsec / 10;
02156     pTimeoutInfo->TSPrev = sl_GetTimestamp();
02157 }
02158 
02159 _u8 _SlDrvIsTimeoutExpired(_SlTimeoutParams_t *pTimeoutInfo)
02160 {
02161     _u32 TSCount;
02162 
02163     pTimeoutInfo->TSCurr = sl_GetTimestamp();
02164 
02165     if (pTimeoutInfo->TSCurr >= pTimeoutInfo->TSPrev)
02166     {
02167         pTimeoutInfo->DeltaTicks = pTimeoutInfo->TSCurr - pTimeoutInfo->TSPrev;
02168     }
02169     else
02170     {
02171         pTimeoutInfo->DeltaTicks =  (SL_TIMESTAMP_MAX_VALUE - pTimeoutInfo->TSPrev) + pTimeoutInfo->TSCurr;
02172     }
02173 
02174     TSCount = pTimeoutInfo->DeltaTicksReminder + pTimeoutInfo->DeltaTicks;
02175 
02176 
02177     if (TSCount > SL_TIMESTAMP_TICKS_IN_10_MILLISECONDS)
02178     {
02179         pTimeoutInfo->Total10MSecUnits -= (TSCount / SL_TIMESTAMP_TICKS_IN_10_MILLISECONDS);
02180         pTimeoutInfo->DeltaTicksReminder = TSCount % SL_TIMESTAMP_TICKS_IN_10_MILLISECONDS;
02181 
02182         if (pTimeoutInfo->Total10MSecUnits > 0)
02183         {
02184             pTimeoutInfo->TSPrev =  pTimeoutInfo->TSCurr;
02185         }
02186         else
02187         {
02188             return TRUE;
02189         }
02190     }
02191 
02192     return FALSE;
02193 }
02194 
02195 #endif
02196 
02197 #endif