SimpleLink CC31xx/CC32xx Host Driver  Version 3.0.1.70
Simplifies the implementation of Internet connectivity
driver.c
1 /*
2  * driver.c - CC31xx/CC32xx Host Driver Implementation
3  *
4  * Copyright (C) 2017 Texas Instruments Incorporated - https://www.ti.com/
5  *
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  *
14  * Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the
17  * distribution.
18  *
19  * Neither the name of Texas Instruments Incorporated nor the names of
20  * its contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  *
35 */
36 
37 /*****************************************************************************/
38 /* Include files */
39 /*****************************************************************************/
40 #include <ti/drivers/net/wifi/simplelink.h>
41 #include <ti/drivers/net/wifi/source/protocol.h>
42 #include <ti/drivers/net/wifi/source/driver.h>
43 #include <ti/drivers/net/wifi/source/flowcont.h>
44 /*****************************************************************************/
45 /* Macro declarations */
46 /*****************************************************************************/
47 
48 #ifndef SL_PLATFORM_MULTI_THREADED
49 
50 #define GLOBAL_LOCK_CONTEXT_OWNER_APP (1)
51 #define GLOBAL_LOCK_CONTEXT_OWNER_SPAWN (2)
52 
53 _u8 gGlobalLockContextOwner = GLOBAL_LOCK_CONTEXT_OWNER_APP;
54 
55 #endif
56 
57 _u8 gGlobalLockCntRequested=0;
58 _u8 gGlobalLockCntReleased=0;
59 
60 
61 /* static functions declaration */
62 static void _SlDrvUpdateApiInProgress(_i8 Value);
63 
64 #define API_IN_PROGRESS_UPDATE_NONE (0)
65 #define API_IN_PROGRESS_UPDATE_INCREMENT (1)
66 #define API_IN_PROGRESS_UPDATE_DECREMENT (-1)
67 
68 
69 /* 2 LSB of the N2H_SYNC_PATTERN are for sequence number
70 only in SPI interface
71 support backward sync pattern */
72 #define N2H_SYNC_PATTERN_SEQ_NUM_BITS ((_u32)0x00000003) /* Bits 0..1 - use the 2 LBS for seq num */
73 #define N2H_SYNC_PATTERN_SEQ_NUM_EXISTS ((_u32)0x00000004) /* Bit 2 - sign that sequence number exists in the sync pattern */
74 #define N2H_SYNC_PATTERN_MASK ((_u32)0xFFFFFFF8) /* Bits 3..31 - constant SYNC PATTERN */
75 #define N2H_SYNC_SPI_BUGS_MASK ((_u32)0x7FFF7F7F) /* Bits 7,15,31 - ignore the SPI (8,16,32 bites bus) error bits */
76 #define BUF_SYNC_SPIM(pBuf) ((*(_u32 *)(pBuf)) & N2H_SYNC_SPI_BUGS_MASK)
77 
78 #define N2H_SYNC_SPIM (N2H_SYNC_PATTERN & N2H_SYNC_SPI_BUGS_MASK)
79 #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)))
80 #define MATCH_WOUT_SEQ_NUM(pBuf) ( BUF_SYNC_SPIM(pBuf) == N2H_SYNC_SPIM )
81 #define MATCH_WITH_SEQ_NUM(pBuf, TxSeqNum) ( BUF_SYNC_SPIM(pBuf) == (N2H_SYNC_SPIM_WITH_SEQ(TxSeqNum)) )
82 #define N2H_SYNC_PATTERN_MATCH(pBuf, TxSeqNum) \
83  ( \
84  ( (*((_u32 *)pBuf) & N2H_SYNC_PATTERN_SEQ_NUM_EXISTS) && ( MATCH_WITH_SEQ_NUM(pBuf, TxSeqNum) ) ) || \
85  ( !(*((_u32 *)pBuf) & N2H_SYNC_PATTERN_SEQ_NUM_EXISTS) && ( MATCH_WOUT_SEQ_NUM(pBuf ) ) ) \
86  )
87 
88 #define OPCODE(_ptr) (((_SlResponseHeader_t *)(_ptr))->GenHeader.Opcode)
89 #define RSP_PAYLOAD_LEN(_ptr) (((_SlResponseHeader_t *)(_ptr))->GenHeader.Len - _SL_RESP_SPEC_HDR_SIZE)
90 #define SD(_ptr) (((SlSocketAddrResponse_u *)(_ptr))->IpV4.Sd)
91 /* Actual size of Recv/Recvfrom response data */
92 #define ACT_DATA_SIZE(_ptr) (((SlSocketAddrResponse_u *)(_ptr))->IpV4.StatusOrLen)
93 
94 #if (defined(SL_PLATFORM_MULTI_THREADED) && !defined(slcb_SocketTriggerEventHandler))
95 #define MULTI_SELECT_MASK (~(1 << SELECT_ID))
96 #else
97 #define MULTI_SELECT_MASK (0xFFFFFFFF)
98 #endif
99 /* Internal function prototype declaration */
100 
101 
102 /* General Events handling*/
103 #if defined (EXT_LIB_REGISTERED_GENERAL_EVENTS)
104 
105 typedef _SlEventPropogationStatus_e (*general_callback) (SlDeviceEvent_t *);
106 
107 static const general_callback general_callbacks[] =
108 {
109 #ifdef SlExtLib1GeneralEventHandler
110  SlExtLib1GeneralEventHandler,
111 #endif
112 
113 #ifdef SlExtLib2GeneralEventHandler
114  SlExtLib2GeneralEventHandler,
115 #endif
116 
117 #ifdef SlExtLib3GeneralEventHandler
118  SlExtLib3GeneralEventHandler,
119 #endif
120 
121 #ifdef SlExtLib4GeneralEventHandler
122  SlExtLib4GeneralEventHandler,
123 #endif
124 
125 #ifdef SlExtLib5GeneralEventHandler
126  SlExtLib5GeneralEventHandler,
127 #endif
128 };
129 
130 #undef _SlDrvHandleGeneralEvents
131 
132 /********************************************************************
133  _SlDrvHandleGeneralEvents
134  Iterates through all the general(device) event handlers which are
135  registered by the external libs/user application.
136 *********************************************************************/
137 void _SlDrvHandleGeneralEvents(SlDeviceEvent_t *slGeneralEvent)
138 {
139  _u8 i;
140 
141  /* Iterate over all the extenal libs handlers */
142  for ( i = 0 ; i < sizeof(general_callbacks)/sizeof(general_callbacks[0]) ; i++ )
143  {
144  if (EVENT_PROPAGATION_BLOCK == general_callbacks[i](slGeneralEvent) )
145  {
146  /* exit immediately and do not call the user specific handler as well */
147  return;
148  }
149  }
150 
151 /* At last call the Application specific handler if registered */
152 #ifdef slcb_DeviceGeneralEvtHdlr
153  slcb_DeviceGeneralEvtHdlr(slGeneralEvent);
154 #endif
155 
156 }
157 #endif
158 
159 
160 /* WLAN Events handling*/
161 
162 #if defined (EXT_LIB_REGISTERED_WLAN_EVENTS)
163 
164 typedef _SlEventPropogationStatus_e (*wlan_callback) (SlWlanEvent_t *);
165 
166 static wlan_callback wlan_callbacks[] =
167 {
168 #ifdef SlExtLib1WlanEventHandler
169  SlExtLib1WlanEventHandler,
170 #endif
171 
172 #ifdef SlExtLib2WlanEventHandler
173  SlExtLib2WlanEventHandler,
174 #endif
175 
176 #ifdef SlExtLib3WlanEventHandler
177  SlExtLib3WlanEventHandler,
178 #endif
179 
180 #ifdef SlExtLib4WlanEventHandler
181  SlExtLib4WlanEventHandler,
182 #endif
183 
184 #ifdef SlExtLib5WlanEventHandler
185  SlExtLib5WlanEventHandler,
186 #endif
187 };
188 
189 #undef _SlDrvHandleWlanEvents
190 
191 /***********************************************************
192  _SlDrvHandleWlanEvents
193  Iterates through all the wlan event handlers which are
194  registered by the external libs/user application.
195 ************************************************************/
196 void _SlDrvHandleWlanEvents(SlWlanEvent_t *slWlanEvent)
197 {
198  _u8 i;
199 
200  /* Iterate over all the extenal libs handlers */
201  for ( i = 0 ; i < sizeof(wlan_callbacks)/sizeof(wlan_callbacks[0]) ; i++ )
202  {
203  if ( EVENT_PROPAGATION_BLOCK == wlan_callbacks[i](slWlanEvent) )
204  {
205  /* exit immediately and do not call the user specific handler as well */
206  return;
207  }
208  }
209 
210 /* At last call the Application specific handler if registered */
211 #ifdef slcb_WlanEvtHdlr
212  slcb_WlanEvtHdlr(slWlanEvent);
213 #endif
214 
215 }
216 #endif
217 
218 
219 /* NetApp Events handling */
220 #if defined (EXT_LIB_REGISTERED_NETAPP_EVENTS)
221 
222 typedef _SlEventPropogationStatus_e (*netApp_callback) (SlNetAppEvent_t *);
223 
224 static const netApp_callback netApp_callbacks[] =
225 {
226 #ifdef SlExtLib1NetAppEventHandler
227  SlExtLib1NetAppEventHandler,
228 #endif
229 
230 #ifdef SlExtLib2NetAppEventHandler
231  SlExtLib2NetAppEventHandler,
232 #endif
233 
234 #ifdef SlExtLib3NetAppEventHandler
235  SlExtLib3NetAppEventHandler,
236 #endif
237 
238 #ifdef SlExtLib4NetAppEventHandler
239  SlExtLib4NetAppEventHandler,
240 #endif
241 
242 #ifdef SlExtLib5NetAppEventHandler
243  SlExtLib5NetAppEventHandler,
244 #endif
245 };
246 
247 #undef _SlDrvHandleNetAppEvents
248 
249 /************************************************************
250  _SlDrvHandleNetAppEvents
251  Iterates through all the net app event handlers which are
252  registered by the external libs/user application.
253 ************************************************************/
254 void _SlDrvHandleNetAppEvents(SlNetAppEvent_t *slNetAppEvent)
255 {
256  _u8 i;
257 
258  /* Iterate over all the extenal libs handlers */
259  for ( i = 0 ; i < sizeof(netApp_callbacks)/sizeof(netApp_callbacks[0]) ; i++ )
260  {
261  if (EVENT_PROPAGATION_BLOCK == netApp_callbacks[i](slNetAppEvent) )
262  {
263  /* exit immediately and do not call the user specific handler as well */
264  return;
265  }
266  }
267 
268 /* At last call the Application specific handler if registered */
269 #ifdef slcb_NetAppEvtHdlr
270  slcb_NetAppEvtHdlr(slNetAppEvent);
271 #endif
272 
273 }
274 #endif
275 
276 
277 /* Http Server Events handling */
278 #if defined (EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS)
279 
280 typedef _SlEventPropogationStatus_e (*httpServer_callback) (SlNetAppHttpServerEvent_t*, SlNetAppHttpServerResponse_t*);
281 
282 static const httpServer_callback httpServer_callbacks[] =
283 {
284 #ifdef SlExtLib1HttpServerEventHandler
285  SlExtLib1HttpServerEventHandler,
286 #endif
287 
288 #ifdef SlExtLib2HttpServerEventHandler
289  SlExtLib2HttpServerEventHandler,
290 #endif
291 
292 #ifdef SlExtLib3HttpServerEventHandler
293  SlExtLib3HttpServerEventHandler,
294 #endif
295 
296 #ifdef SlExtLib4HttpServerEventHandler
297  SlExtLib4HttpServerEventHandler,
298 #endif
299 
300 #ifdef SlExtLib5HttpServerEventHandler
301  SlExtLib5HttpServerEventHandler,
302 #endif
303 };
304 
305 #undef _SlDrvHandleHttpServerEvents
306 
307 /*******************************************************************
308  _SlDrvHandleHttpServerEvents
309  Iterates through all the http server event handlers which are
310  registered by the external libs/user application.
311 ********************************************************************/
312 void _SlDrvHandleHttpServerEvents(SlNetAppHttpServerEvent_t *slHttpServerEvent, SlNetAppHttpServerResponse_t *slHttpServerResponse)
313 {
314  _u8 i;
315 
316  /* Iterate over all the external libs handlers */
317  for ( i = 0 ; i < sizeof(httpServer_callbacks)/sizeof(httpServer_callbacks[0]) ; i++ )
318  {
319  if ( EVENT_PROPAGATION_BLOCK == httpServer_callbacks[i](slHttpServerEvent, slHttpServerResponse) )
320  {
321  /* exit immediately and do not call the user specific handler as well */
322  return;
323  }
324  }
325 
326 /* At last call the Application specific handler if registered */
327 #ifdef slcb_NetAppHttpServerHdlr
328  slcb_NetAppHttpServerHdlr(slHttpServerEvent, slHttpServerResponse);
329 #endif
330 
331 }
332 #endif
333 
334 
335 /* Socket Events */
336 #if defined (EXT_LIB_REGISTERED_SOCK_EVENTS)
337 
338 typedef _SlEventPropogationStatus_e (*sock_callback) (SlSockEvent_t *);
339 
340 static const sock_callback sock_callbacks[] =
341 {
342 #ifdef SlExtLib1SockEventHandler
343  SlExtLib1SockEventHandler,
344 #endif
345 
346 #ifdef SlExtLib2SockEventHandler
347  SlExtLib2SockEventHandler,
348 #endif
349 
350 #ifdef SlExtLib3SockEventHandler
351  SlExtLib3SockEventHandler,
352 #endif
353 
354 #ifdef SlExtLib4SockEventHandler
355  SlExtLib4SockEventHandler,
356 #endif
357 
358 #ifdef SlExtLib5SockEventHandler
359  SlExtLib5SockEventHandler,
360 #endif
361 };
362 
363 /*************************************************************
364  _SlDrvHandleSockEvents
365  Iterates through all the socket event handlers which are
366  registered by the external libs/user application.
367 **************************************************************/
368 void _SlDrvHandleSockEvents(SlSockEvent_t *slSockEvent)
369 {
370  _u8 i;
371 
372  /* Iterate over all the external libs handlers */
373  for ( i = 0 ; i < sizeof(sock_callbacks)/sizeof(sock_callbacks[0]) ; i++ )
374  {
375  if ( EVENT_PROPAGATION_BLOCK == sock_callbacks[i](slSockEvent) )
376  {
377  /* exit immediately and do not call the user specific handler as well */
378  return;
379  }
380  }
381 
382 /* At last call the Application specific handler if registered */
383 #ifdef slcb_SockEvtHdlr
384  slcb_SockEvtHdlr(slSockEvent);
385 #endif
386 
387 }
388 
389 #endif
390 
391 /* Fatal Error Events handling*/
392 #if defined (EXT_LIB_REGISTERED_FATAL_ERROR_EVENTS)
393 
394 typedef _SlEventPropogationStatus_e (*fatal_error_callback) (SlDeviceEvent_t *);
395 
396 static const fatal_error_callback fatal_error_callbacks[] =
397 {
398 #ifdef SlExtLib1FatalErrorEventHandler
399  SlExtLib1FatalErrorEventHandler,
400 #endif
401 
402 #ifdef SlExtLib2FatalErrorEventHandler
403  SlExtLib2FatalErrorEventHandler,
404 #endif
405 
406 #ifdef SlExtLib3FatalErrorEventHandler
407  SlExtLib3FatalErrorEventHandler,
408 #endif
409 
410 #ifdef SlExtLib4FatalErrorEventHandler
411  SlExtLib4FatalErrorEventHandler,
412 #endif
413 
414 #ifdef SlExtLib5FatalErrorEventHandler
415  SlExtLib5FatalErrorEventHandler,
416 #endif
417 };
418 
419 #undef _SlDrvHandleFatalErrorEvents
420 
421 /********************************************************************
422  _SlDrvHandleFatalErrorEvents
423  Iterates through all the fatal error (device) event handlers which are
424  registered by the external libs/user application.
425 *********************************************************************/
426 void _SlDrvHandleFatalErrorEvents(SlDeviceFatal_t *slFatalErrorEvent)
427 {
428  _u8 i;
429 
430  /* Iterate over all the extenal libs handlers */
431  for ( i = 0 ; i < sizeof(fatal_error_callbacks)/sizeof(fatal_error_callbacks[0]) ; i++ )
432  {
433  if (EVENT_PROPAGATION_BLOCK == fatal_error_callbacks[i](slFatalErrorEvent) )
434  {
435  /* exit immediately and do not call the user specific handler as well */
436  return;
437  }
438  }
439 
440 /* At last call the Application specific handler if registered */
441 #ifdef slcb_DeviceFatalErrorEvtHdlr
442  slcb_DeviceFatalErrorEvtHdlr(slFatalErrorEvent);
443 #endif
444 
445 }
446 #endif
447 
448 /* NetApp request handler */
449 #if defined (EXT_LIB_REGISTERED_NETAPP_REQUEST_EVENTS)
450 
451 typedef _SlEventPropogationStatus_e (*netapp_request_callback) (SlNetAppRequest_t*, SlNetAppResponse_t*);
452 
453 static const netapp_request_callback netapp_request_callbacks[] =
454 {
455 #ifdef SlExtLib1NetAppRequestEventHandler
456  SlExtLib1NetAppRequestEventHandler,
457 #endif
458 
459 #ifdef SlExtLib2NetAppRequestEventHandler
460  SlExtLib2NetAppRequestEventHandler,
461 #endif
462 
463 #ifdef SlExtLib3NetAppRequestEventHandler
464  SlExtLib3NetAppRequestEventHandler,
465 #endif
466 
467 #ifdef SlExtLib4NetAppRequestEventHandler
468  SlExtLib4NetAppRequestEventHandler,
469 #endif
470 
471 #ifdef SlExtLib5NetAppRequestEventHandler
472  SlExtLib5NetAppRequestEventHandler,
473 #endif
474 };
475 
476 #undef _SlDrvHandleNetAppRequestEvents
477 
478 /********************************************************************
479  _SlDrvHandleNetAppRequest
480  Iterates through all the netapp request handlers which are
481  registered by the external libs/user application.
482 *********************************************************************/
483 void _SlDrvHandleNetAppRequestEvents(SlNetAppRequest_t *pNetAppRequest, SlNetAppResponse_t *pNetAppResponse)
484 {
485  _u8 i;
486 
487  /* Iterate over all the extenal libs handlers */
488  for ( i = 0 ; i < sizeof(netapp_request_callbacks)/sizeof(netapp_request_callbacks[0]) ; i++ )
489  {
490  if (EVENT_PROPAGATION_BLOCK == netapp_request_callbacks[i](pNetAppRequest, pNetAppResponse) )
491  {
492  /* exit immediately and do not call the user specific handler as well */
493  return;
494  }
495  }
496 
497 /* At last call the Application specific handler if registered */
498 #ifdef slcb_NetAppRequestHdlr
499  slcb_NetAppRequestHdlr(pNetAppRequest, pNetAppResponse);
500 #endif
501 
502 }
503 #endif
504 
505 
506 #ifndef SL_MEMORY_MGMT_DYNAMIC
507 typedef struct
508 {
509  _u32 Align;
510 #ifdef SL_PLATFORM_MULTI_THREADED
511  _SlAsyncRespBuf_t AsyncBufPool[SL_MAX_ASYNC_BUFFERS];
512 #endif
513  _u8 AsyncRespBuf[SL_ASYNC_MAX_MSG_LEN];
514 }_SlStatMem_t;
515 
516 static _SlStatMem_t g_StatMem;
517 #endif
518 
519 
520 /*****************************************************************************/
521 /* Variables */
522 /*****************************************************************************/
523 _SlDriverCb_t g_CB;
524 static const _SlSyncPattern_t g_H2NSyncPattern = H2N_SYNC_PATTERN;
525 
526 #ifndef SL_IF_TYPE_UART
527 static const _SlSyncPattern_t g_H2NCnysPattern = H2N_CNYS_PATTERN;
528 #endif
529 _volatile _u8 RxIrqCnt;
530 
531 _u16 g_SlDeviceStatus = 0;
532 _SlLockObj_t GlobalLockObj;
533 
534 const _SlActionLookup_t _SlActionLookupTable[] =
535 {
536  {ACCEPT_ID, SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE, (_SlSpawnEntryFunc_t)_SlSocketHandleAsync_Accept},
537  {CONNECT_ID, SL_OPCODE_SOCKET_CONNECTASYNCRESPONSE,(_SlSpawnEntryFunc_t)_SlSocketHandleAsync_Connect},
538  {SELECT_ID, SL_OPCODE_SOCKET_SELECTASYNCRESPONSE,(_SlSpawnEntryFunc_t)_SlSocketHandleAsync_Select},
539  {GETHOSYBYNAME_ID, SL_OPCODE_NETAPP_DNSGETHOSTBYNAMEASYNCRESPONSE,(_SlSpawnEntryFunc_t)_SlNetAppHandleAsync_DnsGetHostByName},
540  {GETHOSYBYSERVICE_ID, SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICEASYNCRESPONSE,(_SlSpawnEntryFunc_t)_SlNetAppHandleAsync_DnsGetHostByService},
541  {PING_ID, SL_OPCODE_NETAPP_PINGREPORTREQUESTRESPONSE, (_SlSpawnEntryFunc_t)_SlNetAppHandleAsync_PingResponse},
542  {NETAPP_RECEIVE_ID, SL_OPCODE_NETAPP_RECEIVE, (_SlSpawnEntryFunc_t)_SlNetAppHandleAsync_NetAppReceive},
543  {START_STOP_ID, SL_OPCODE_DEVICE_STOP_ASYNC_RESPONSE,(_SlSpawnEntryFunc_t)_SlDeviceHandleAsync_Stop},
544  {NETUTIL_CMD_ID, SL_OPCODE_NETUTIL_COMMANDASYNCRESPONSE,(_SlSpawnEntryFunc_t)_SlNetUtilHandleAsync_Cmd},
545  {CLOSE_ID, SL_OPCODE_SOCKET_SOCKETCLOSEASYNCEVENT,(_SlSpawnEntryFunc_t)_SlSocketHandleAsync_Close}
546 };
547 
548 
549 typedef struct
550 {
551  _u16 opcode;
552  _u8 event;
553 } OpcodeKeyVal_t;
554 
555 
556 /* The table translates opcode to user's event type */
557 const OpcodeKeyVal_t OpcodeTranslateTable[] =
558 {
559  {SL_OPCODE_WLAN_STA_ASYNCCONNECTEDRESPONSE, SL_WLAN_EVENT_CONNECT},
560  {SL_OPCODE_WLAN_P2PCL_ASYNCCONNECTEDRESPONSE, SL_WLAN_EVENT_P2P_CONNECT},
561  {SL_OPCODE_WLAN_STA_ASYNCDISCONNECTEDRESPONSE, SL_WLAN_EVENT_DISCONNECT},
562  {SL_OPCODE_WLAN_P2PCL_ASYNCDISCONNECTEDRESPONSE,SL_WLAN_EVENT_P2P_DISCONNECT},
563  {SL_OPCODE_WLAN_ASYNC_STA_ADDED, SL_WLAN_EVENT_STA_ADDED},
564  {SL_OPCODE_WLAN_ASYNC_P2PCL_ADDED,SL_WLAN_EVENT_P2P_CLIENT_ADDED},
565  {SL_OPCODE_WLAN_ASYNC_STA_REMOVED, SL_WLAN_EVENT_STA_REMOVED},
566  {SL_OPCODE_WLAN_ASYNC_P2PCL_REMOVED,SL_WLAN_EVENT_P2P_CLIENT_REMOVED},
567  {SL_OPCODE_WLAN_P2P_DEV_FOUND,SL_WLAN_EVENT_P2P_DEVFOUND},
568  {SL_OPCODE_WLAN_P2P_NEG_REQ_RECEIVED, SL_WLAN_EVENT_P2P_REQUEST},
569  {SL_OPCODE_WLAN_P2P_CONNECTION_FAILED, SL_WLAN_EVENT_P2P_CONNECTFAIL},
570  {SL_OPCODE_WLAN_PROVISIONING_STATUS_ASYNC_EVENT, SL_WLAN_EVENT_PROVISIONING_STATUS},
571  {SL_OPCODE_WLAN_PROVISIONING_PROFILE_ADDED_ASYNC_RESPONSE, SL_WLAN_EVENT_PROVISIONING_PROFILE_ADDED},
572  {SL_OPCODE_WLAN_RX_FILTER_ASYNC_RESPONSE,SL_WLAN_EVENT_RXFILTER},
573  {SL_OPCODE_WLAN_LINK_QUALITY_RESPONSE, SL_WLAN_EVENT_LINK_QUALITY_TRIGGER},
574 
575  {SL_OPCODE_NETAPP_IPACQUIRED, SL_NETAPP_EVENT_IPV4_ACQUIRED},
576  {SL_OPCODE_NETAPP_IPACQUIRED_V6, SL_NETAPP_EVENT_IPV6_ACQUIRED},
577  {SL_OPCODE_NETAPP_IP_LEASED, SL_NETAPP_EVENT_DHCPV4_LEASED},
578  {SL_OPCODE_NETAPP_IP_RELEASED, SL_NETAPP_EVENT_DHCPV4_RELEASED},
579  {SL_OPCODE_NETAPP_IP_COLLISION, SL_NETAPP_EVENT_IP_COLLISION},
580  {SL_OPCODE_NETAPP_IPV4_LOST, SL_NETAPP_EVENT_IPV4_LOST},
581  {SL_OPCODE_NETAPP_DHCP_IPV4_ACQUIRE_TIMEOUT, SL_NETAPP_EVENT_DHCP_IPV4_ACQUIRE_TIMEOUT},
582  {SL_OPCODE_NETAPP_IPV6_LOST_V6, SL_NETAPP_EVENT_IPV6_LOST},
583  {SL_OPCODE_NETAPP_NO_IP_COLLISION_DETECTED, SL_NETAPP_EVENT_NO_IPV4_COLLISION_DETECTED},
584  {SL_OPCODE_NETAPP_NO_LOCAL_IP_COLLISION_DETECTED_V6, SL_NETAPP_EVENT_NO_LOCAL_IPV6_COLLISION_DETECTED},
585  {SL_OPCODE_NETAPP_NO_GLOBAL_IP_COLLISION_DETECTED_V6, SL_NETAPP_EVENT_NO_GLOBAL_IPV6_COLLISION_DETECTED},
586  {SL_OPCODE_SOCKET_TXFAILEDASYNCRESPONSE, SL_SOCKET_TX_FAILED_EVENT},
587  {SL_OPCODE_SOCKET_SOCKETASYNCEVENT, SL_SOCKET_ASYNC_EVENT}
588 
589 };
590 
591 
592 
593 _SlDriverCb_t* g_pCB = NULL;
594 P_SL_DEV_PING_CALLBACK pPingCallBackFunc = NULL;
595 
596 /*****************************************************************************/
597 /* Function prototypes */
598 /*****************************************************************************/
599 static _SlReturnVal_t _SlDrvMsgRead(_u16* outMsgReadLen, _u8** pAsyncBuf);
600 static _SlReturnVal_t _SlDrvMsgWrite(_SlCmdCtrl_t *pCmdCtrl,_SlCmdExt_t *pCmdExt, _u8 *pTxRxDescBuff);
601 static _SlReturnVal_t _SlDrvMsgReadCmdCtx(_u16 cmdOpcode, _u8 IsLockRequired);
602 static _SlReturnVal_t _SlDrvClassifyRxMsg(_SlOpcode_t Opcode );
603 static _SlReturnVal_t _SlDrvRxHdrRead(_u8 *pBuf);
604 static void _SlDrvAsyncEventGenericHandler(_u8 bInCmdContext, _u8 *pAsyncBuffer);
605 static void _SlDrvRemoveFromList(_u8* ListIndex, _u8 ItemIndex);
606 static _SlReturnVal_t _SlDrvFindAndSetActiveObj(_SlOpcode_t Opcode, _u8 Sd);
607 
608 /*****************************************************************************/
609 /* Internal functions */
610 /*****************************************************************************/
611 
612 
613 /*****************************************************************************
614 _SlDrvDriverCBInit - init Driver Control Block
615 *****************************************************************************/
616 
617 _SlReturnVal_t _SlDrvDriverCBInit(void)
618 {
619  _u8 Idx =0;
620 
621  g_pCB = &g_CB;
622 
623 #ifndef SL_PLATFORM_MULTI_THREADED
624  {
625  extern _SlNonOsCB_t g__SlNonOsCB;
626  sl_Memset(&g__SlNonOsCB, 0, sizeof(g__SlNonOsCB));
627  }
628 #endif
629 
630  _SlDrvMemZero(g_pCB, (_u16)sizeof(_SlDriverCb_t));
631  RxIrqCnt = 0;
632  OSI_RET_OK_CHECK( sl_SyncObjCreate(&g_pCB->CmdSyncObj, "CmdSyncObj") );
633  SL_DRV_SYNC_OBJ_CLEAR(&g_pCB->CmdSyncObj);
634 
635  if (!SL_IS_GLOBAL_LOCK_INIT)
636  {
637  OSI_RET_OK_CHECK( sl_LockObjCreate(&GlobalLockObj, "GlobalLockObj") );
638  SL_SET_GLOBAL_LOCK_INIT;
639  }
640 
641  OSI_RET_OK_CHECK( sl_LockObjCreate(&g_pCB->ProtectionLockObj, "ProtectionLockObj") );
642  g_pCB->NumOfDeletedSyncObj = 0;
643 #if defined(slcb_SocketTriggerEventHandler)
644  g_pCB->SocketTriggerSelect.Info.ObjPoolIdx = MAX_CONCURRENT_ACTIONS;
645 #endif
646  /* Init Drv object */
647  _SlDrvMemZero(&g_pCB->ObjPool[0], (_u16)(MAX_CONCURRENT_ACTIONS*sizeof(_SlPoolObj_t)));
648  /* place all Obj in the free list*/
649  g_pCB->FreePoolIdx = 0;
650 
651  for (Idx = 0 ; Idx < MAX_CONCURRENT_ACTIONS ; Idx++)
652  {
653  g_pCB->ObjPool[Idx].NextIndex = Idx + 1;
654  g_pCB->ObjPool[Idx].AdditionalData = SL_MAX_SOCKETS;
655 
656  OSI_RET_OK_CHECK( sl_SyncObjCreate(&g_pCB->ObjPool[Idx].SyncObj, "SyncObj"));
657  SL_DRV_SYNC_OBJ_CLEAR(&g_pCB->ObjPool[Idx].SyncObj);
658  }
659 
660  g_pCB->ActivePoolIdx = MAX_CONCURRENT_ACTIONS;
661  g_pCB->PendingPoolIdx = MAX_CONCURRENT_ACTIONS;
662 
663 #ifdef SL_PLATFORM_MULTI_THREADED
664 
665 #ifdef SL_MEMORY_MGMT_DYNAMIC
666  /* reset the spawn messages list */
667  g_pCB->spawnMsgList = NULL;
668 #else
669  for (Idx = 0; Idx < SL_MAX_ASYNC_BUFFERS; Idx++)
670  {
671  g_StatMem.AsyncBufPool[Idx].ActionIndex = 0xFF;
672  g_StatMem.AsyncBufPool[Idx].AsyncHndlr = NULL;
673  }
674 #endif
675 #else
676  /* clear the global lock owner */
677  _SlDrvSetGlobalLockOwner(GLOBAL_LOCK_CONTEXT_OWNER_APP);
678 #endif
679  /* Flow control init */
680  g_pCB->FlowContCB.TxPoolCnt = FLOW_CONT_MIN;
681  OSI_RET_OK_CHECK(sl_LockObjCreate(&g_pCB->FlowContCB.TxLockObj, "TxLockObj"));
682  OSI_RET_OK_CHECK(sl_SyncObjCreate(&g_pCB->FlowContCB.TxSyncObj, "TxSyncObj"));
683  g_pCB->FlowContCB.MinTxPayloadSize = 1536; /* init maximum length */
684 
685 #if (defined(SL_PLATFORM_MULTI_THREADED) && !defined(slcb_SocketTriggerEventHandler))
686  OSI_RET_OK_CHECK(sl_LockObjCreate(&g_pCB->MultiSelectCB.SelectLockObj, "SelectLockObj"));
687  OSI_RET_OK_CHECK(sl_SyncObjCreate(&g_pCB->MultiSelectCB.SelectSyncObj, "SelectSyncObj"));
688  SL_DRV_SYNC_OBJ_CLEAR(&g_pCB->MultiSelectCB.SelectSyncObj);
689  g_pCB->MultiSelectCB.CtrlSockFD = 0xFF;
690 #endif
691  return SL_OS_RET_CODE_OK;
692 }
693 
694 /*****************************************************************************
695 _SlDrvDriverCBDeinit - De init Driver Control Block
696 *****************************************************************************/
697 _SlReturnVal_t _SlDrvDriverCBDeinit(void)
698 {
699 #ifdef SL_MEMORY_MGMT_DYNAMIC
700  _SlSpawnMsgItem_t* pCurr;
701  _SlSpawnMsgItem_t* pNext;
702 #endif
703 
704  /* Flow control de-init */
705  g_pCB->FlowContCB.TxPoolCnt = 0;
706 
707  SL_SET_DEVICE_STATUS(0);
708 
709  SL_UNSET_DEVICE_STARTED;
710 
711  OSI_RET_OK_CHECK(sl_LockObjDelete(&g_pCB->FlowContCB.TxLockObj));
712  OSI_RET_OK_CHECK(sl_SyncObjDelete(&g_pCB->FlowContCB.TxSyncObj));
713 #if (defined(SL_PLATFORM_MULTI_THREADED) && !defined(slcb_SocketTriggerEventHandler))
714  OSI_RET_OK_CHECK(sl_LockObjDelete(&g_pCB->MultiSelectCB.SelectLockObj));
715  OSI_RET_OK_CHECK(sl_SyncObjDelete(&g_pCB->MultiSelectCB.SelectSyncObj));
716 #endif
717  OSI_RET_OK_CHECK( sl_SyncObjDelete(&g_pCB->CmdSyncObj));
718 
719  OSI_RET_OK_CHECK( sl_LockObjDelete(&g_pCB->ProtectionLockObj) );
720 
721  g_pCB->FreePoolIdx = 0;
722  g_pCB->PendingPoolIdx = MAX_CONCURRENT_ACTIONS;
723  g_pCB->ActivePoolIdx = MAX_CONCURRENT_ACTIONS;
724 
725 #ifdef SL_MEMORY_MGMT_DYNAMIC
726  /* Release linked list of async buffers */
727  pCurr = g_pCB->spawnMsgList;
728  while (NULL != pCurr)
729  {
730  pNext = pCurr->next;
731  sl_Free(pCurr->Buffer);
732  sl_Free(pCurr);
733  pCurr = pNext;
734  }
735  g_pCB->spawnMsgList = NULL;
736 
737 #endif
738 
739  g_pCB = NULL;
740 
741  return SL_OS_RET_CODE_OK;
742 }
743 
744 /*****************************************************************************
745 _SlDrvRxIrqHandler - Interrupt handler
746 *****************************************************************************/
747 _SlReturnVal_t _SlDrvRxIrqHandler(void *pValue)
748 {
749  (void)pValue;
750 
751  sl_IfMaskIntHdlr();
752 
753  RxIrqCnt++;
754 
755  if (TRUE == g_pCB->WaitForCmdResp)
756  {
757  OSI_RET_OK_CHECK( sl_SyncObjSignalFromIRQ(&g_pCB->CmdSyncObj) );
758  }
759  else
760  {
761  (void)sl_Spawn((_SlSpawnEntryFunc_t)_SlDrvMsgReadSpawnCtx, NULL, SL_SPAWN_FLAG_FROM_SL_IRQ_HANDLER);
762  }
763  return SL_OS_RET_CODE_OK;
764 }
765 
766 /*****************************************************************************
767 _SlDrvDriverIsApiAllowed - on LOCKED state, only 3 commands are allowed
768 *****************************************************************************/
769 _SlReturnVal_t _SlDrvDriverIsApiAllowed(_u16 Silo)
770 {
771  if (!SL_IS_COMMAND_ALLOWED)
772  {
773  if (SL_IS_DEVICE_STOP_IN_PROGRESS)
774  {
775  return SL_RET_CODE_STOP_IN_PROGRESS;
776  }
777 
778  if ((SL_IS_DEVICE_LOCKED) && (SL_OPCODE_SILO_FS != Silo))
779  {
780  /* All APIs except the FS ones must be aborted if device is locked */
781  return SL_RET_CODE_DEV_LOCKED;
782  }
783  if (SL_IS_RESTART_REQUIRED)
784  {
785  /* API has been aborted due command not allowed when Restart required */
786  /* The opcodes allowed are: SL_OPCODE_DEVICE_STOP_COMMAND */
787  return SL_API_ABORTED;
788  }
789 
790  if (!SL_IS_DEVICE_STARTED)
791  {
792  return SL_RET_CODE_DEV_NOT_STARTED;
793  }
794 
795  if (( SL_IS_PROVISIONING_ACTIVE || SL_IS_PROVISIONING_INITIATED_BY_USER) && !(SL_IS_PROVISIONING_API_ALLOWED))
796  {
797  /* API has ignored due to provisioning in progress */
798  return SL_RET_CODE_PROVISIONING_IN_PROGRESS;
799  }
800 
801  }
802 
803  return SL_OS_RET_CODE_OK;
804 }
805 
806 
807 /*****************************************************************************
808 _SlDrvCmdOp
809 *****************************************************************************/
810 _SlReturnVal_t _SlDrvCmdOp(
811  _SlCmdCtrl_t *pCmdCtrl ,
812  void *pTxRxDescBuff ,
813  _SlCmdExt_t *pCmdExt)
814 {
815  _SlReturnVal_t RetVal;
816  _u8 IsLockRequired = TRUE;
817 
818  IsLockRequired = (SL_IS_PROVISIONING_IN_PROGRESS && (pCmdCtrl->Opcode == SL_OPCODE_DEVICE_STOP_COMMAND)) ? FALSE: TRUE;
819 
820  if (IsLockRequired)
821  {
822  _u32 GlobalLockFlags = GLOBAL_LOCK_FLAGS_UPDATE_API_IN_PROGRESS;
823 
824  /* check the special case of provisioning stop command */
825  if (pCmdCtrl->Opcode == SL_OPCODE_WLAN_PROVISIONING_COMMAND)
826  {
827  SlWlanProvisioningParams_t *pParams = (SlWlanProvisioningParams_t *)pTxRxDescBuff;
828 
829  /* No timeout specifies it is a stop provisioning command */
830  if (pParams->InactivityTimeoutSec == 0)
831  {
832  GlobalLockFlags |= GLOBAL_LOCK_FLAGS_PROVISIONING_STOP_API;
833  }
834 
835  }
836 
837  GlobalLockFlags |= (((_u32)pCmdCtrl->Opcode) << 16);
838  SL_DRV_LOCK_GLOBAL_LOCK_FOREVER(GlobalLockFlags);
839  }
840 
841  /* In case the global was successfully taken but error in progress
842  it means it has been released as part of an error handling and we should abort immediately */
843  if (SL_IS_RESTART_REQUIRED)
844  {
845  if (IsLockRequired)
846  {
847  SL_DRV_LOCK_GLOBAL_UNLOCK(TRUE);
848  }
849 
850  return SL_API_ABORTED;
851  }
852 
853  g_pCB->WaitForCmdResp = TRUE;
854 
855  SL_TRACE1(DBG_MSG, MSG_312, "\n\r_SlDrvCmdOp: call _SlDrvMsgWrite: %x\n\r", pCmdCtrl->Opcode);
856 
857  /* send the message */
858  RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, pTxRxDescBuff);
859 
860  if(SL_OS_RET_CODE_OK == RetVal)
861  {
862  /* wait for respond */
863  RetVal = _SlDrvMsgReadCmdCtx(pCmdCtrl->Opcode, IsLockRequired); /* will free global lock */
864  SL_TRACE1(DBG_MSG, MSG_314, "\n\r_SlDrvCmdOp: exited _SlDrvMsgReadCmdCtx: %x\n\r", pCmdCtrl->Opcode);
865  }
866  else
867  {
868  if (IsLockRequired)
869  {
870  SL_DRV_LOCK_GLOBAL_UNLOCK(TRUE);
871  }
872 
873  }
874 
875  return RetVal;
876 }
877 
878 /*****************************************************************************
879 _SlDrvDataReadOp
880 *****************************************************************************/
881 _SlReturnVal_t _SlDrvDataReadOp(
882  _SlSd_t Sd,
883  _SlCmdCtrl_t *pCmdCtrl ,
884  void *pTxRxDescBuff ,
885  _SlCmdExt_t *pCmdExt)
886 {
887  _SlReturnVal_t RetVal;
888  _i16 ObjIdx = MAX_CONCURRENT_ACTIONS;
889  _SlArgsData_t pArgsData;
890 
891  /* Validate input arguments */
892  _SL_ASSERT_ERROR(NULL != pCmdExt->pRxPayload, SL_RET_CODE_INVALID_INPUT);
893 
894  /* If zero bytes is requested, return error. */
895  /* This allows us not to fill remote socket's IP address in return arguments */
896  VERIFY_PROTOCOL(0 != pCmdExt->RxPayloadLen);
897 
898  /* Validate socket */
899  if((Sd & SL_BSD_SOCKET_ID_MASK) >= SL_MAX_SOCKETS)
900  {
901  return SL_ERROR_BSD_EBADF;
902  }
903 
904  /*Use Obj to issue the command, if not available try later*/
905  ObjIdx = _SlDrvWaitForPoolObj(RECV_ID, Sd & SL_BSD_SOCKET_ID_MASK);
906 
907  if (MAX_CONCURRENT_ACTIONS == ObjIdx)
908  {
909  return SL_POOL_IS_EMPTY;
910  }
911  if (SL_RET_CODE_STOP_IN_PROGRESS == ObjIdx)
912  {
913  return SL_RET_CODE_STOP_IN_PROGRESS;
914  }
915 
916  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
917 
918  pArgsData.pData = pCmdExt->pRxPayload;
919  pArgsData.pArgs = (_u8 *)pTxRxDescBuff;
920  g_pCB->ObjPool[ObjIdx].pRespArgs = (_u8 *)&pArgsData;
921 
922  SL_DRV_PROTECTION_OBJ_UNLOCK();
923 
924 
925  /* Do Flow Control check/update for DataWrite operation */
926  SL_DRV_OBJ_LOCK_FOREVER(&g_pCB->FlowContCB.TxLockObj);
927 
928 
929  /* Clear SyncObj for the case it was signaled before TxPoolCnt */
930  /* dropped below '1' (last Data buffer was taken) */
931  /* OSI_RET_OK_CHECK( sl_SyncObjClear(&g_pCB->FlowContCB.TxSyncObj) ); */
932  SL_DRV_SYNC_OBJ_CLEAR(&g_pCB->FlowContCB.TxSyncObj);
933 
934  if(g_pCB->FlowContCB.TxPoolCnt <= FLOW_CONT_MIN)
935  {
936 
937  /* If TxPoolCnt was increased by other thread at this moment,
938  TxSyncObj won't wait here */
939 #if (defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))
940  if (_SlDrvIsSpawnOwnGlobalLock())
941  {
942  while (TRUE)
943  {
944  /* If we are in spawn context, this is an API which was called from event handler,
945  read any async event and check if we got signaled */
946  _SlInternalSpawnWaitForEvent();
947  /* is it mine? */
948  if (0 == sl_SyncObjWait(&g_pCB->FlowContCB.TxSyncObj, SL_OS_NO_WAIT))
949  {
950  break;
951  }
952  }
953  }
954  else
955 #endif
956  {
957  SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->FlowContCB.TxSyncObj);
958  }
959 
960  }
961 
962  SL_DRV_LOCK_GLOBAL_LOCK_FOREVER(GLOBAL_LOCK_FLAGS_UPDATE_API_IN_PROGRESS);
963 
964  /* In case the global was successfully taken but error in progress
965  it means it has been released as part of an error handling and we should abort immediately */
966  if (SL_IS_RESTART_REQUIRED)
967  {
968  SL_DRV_LOCK_GLOBAL_UNLOCK(TRUE);
969  return SL_API_ABORTED;
970  }
971 
972  /* Here we consider the case in which some cmd has been sent to the NWP,
973  And its allocated packet has not been freed yet. */
974  VERIFY_PROTOCOL(g_pCB->FlowContCB.TxPoolCnt > (FLOW_CONT_MIN - 1));
975  g_pCB->FlowContCB.TxPoolCnt--;
976 
977  SL_DRV_OBJ_UNLOCK(&g_pCB->FlowContCB.TxLockObj);
978 
979  /* send the message */
980  RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, (_u8 *)pTxRxDescBuff);
981 
982  SL_DRV_LOCK_GLOBAL_UNLOCK(TRUE);
983 
984  if(SL_OS_RET_CODE_OK == RetVal)
985  {
986  /* in case socket is non-blocking one, the async event should be received immediately */
987  if( g_pCB->SocketNonBlocking & (1<<(Sd & SL_BSD_SOCKET_ID_MASK) ))
988  {
989  _u16 opcodeAsyncEvent = (pCmdCtrl->Opcode == SL_OPCODE_SOCKET_RECV) ? SL_OPCODE_SOCKET_RECVASYNCRESPONSE : SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE;
990  RetVal = _SlDrvWaitForInternalAsyncEvent(ObjIdx, SL_DRIVER_TIMEOUT_SHORT, opcodeAsyncEvent);
991 
992  }
993  else
994  {
995  /* Wait for response message. Will be signaled by _SlDrvMsgRead. */
996  RetVal = _SlDrvWaitForInternalAsyncEvent(ObjIdx, 0, 0);
997  }
998 
999  }
1000 
1001  _SlDrvReleasePoolObj(ObjIdx);
1002  return RetVal;
1003 }
1004 
1005 /* ******************************************************************************/
1006 /* _SlDrvDataWriteOp */
1007 /* ******************************************************************************/
1008 _SlReturnVal_t _SlDrvDataWriteOp(
1009  _SlSd_t Sd,
1010  _SlCmdCtrl_t *pCmdCtrl ,
1011  void *pTxRxDescBuff ,
1012  _SlCmdExt_t *pCmdExt)
1013 {
1014  _SlReturnVal_t RetVal = SL_ERROR_BSD_EAGAIN; /* initiated as SL_EAGAIN for the non blocking mode */
1015  _u32 allocTxPoolPkts;
1016 
1017  while( 1 )
1018  {
1019  /* Do Flow Control check/update for DataWrite operation */
1020  SL_DRV_OBJ_LOCK_FOREVER(&g_pCB->FlowContCB.TxLockObj);
1021 
1022  /* Clear SyncObj for the case it was signaled before TxPoolCnt */
1023  /* dropped below '1' (last Data buffer was taken) */
1024  /* OSI_RET_OK_CHECK( sl_SyncObjClear(&g_pCB->FlowContCB.TxSyncObj) ); */
1025  SL_DRV_SYNC_OBJ_CLEAR(&g_pCB->FlowContCB.TxSyncObj);
1026 
1027  /* number of tx pool packet that will be used */
1028  allocTxPoolPkts = 1 + (pCmdExt->TxPayload1Len-1) / g_pCB->FlowContCB.MinTxPayloadSize; /* MinTxPayloadSize will be updated by Asunc event from NWP */
1029  /* we have indication that the last send has failed - socket is no longer valid for operations */
1030  if(g_pCB->SocketTXFailure & (1<<(Sd & SL_BSD_SOCKET_ID_MASK)))
1031  {
1032  SL_DRV_OBJ_UNLOCK(&g_pCB->FlowContCB.TxLockObj);
1033  return SL_ERROR_BSD_SOC_ERROR;
1034  }
1035  if(g_pCB->FlowContCB.TxPoolCnt <= FLOW_CONT_MIN + allocTxPoolPkts)
1036  {
1037  /* we have indication that this socket is set as blocking and we try to */
1038  /* unblock it - return an error */
1039  if( g_pCB->SocketNonBlocking & (1<<(Sd & SL_BSD_SOCKET_ID_MASK) ))
1040  {
1041 #if (defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))
1042  if (_SlDrvIsSpawnOwnGlobalLock())
1043  {
1044  _SlInternalSpawnWaitForEvent();
1045  }
1046 #endif
1047  SL_DRV_OBJ_UNLOCK(&g_pCB->FlowContCB.TxLockObj);
1048  return RetVal;
1049  }
1050  /* If TxPoolCnt was increased by other thread at this moment, */
1051  /* TxSyncObj won't wait here */
1052 #if (defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))
1053  if (_SlDrvIsSpawnOwnGlobalLock())
1054  {
1055  while (TRUE)
1056  {
1057  /* If we are in spawn context, this is an API which was called from event handler,
1058  read any async event and check if we got signaled */
1059  _SlInternalSpawnWaitForEvent();
1060  /* is it mine? */
1061  if (0 == sl_SyncObjWait(&g_pCB->FlowContCB.TxSyncObj, SL_OS_NO_WAIT))
1062  {
1063  break;
1064  }
1065  }
1066  }
1067  else
1068 #endif
1069  {
1070  SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->FlowContCB.TxSyncObj);
1071  }
1072  }
1073  if(g_pCB->FlowContCB.TxPoolCnt > FLOW_CONT_MIN + allocTxPoolPkts )
1074  {
1075  break;
1076  }
1077  else
1078  {
1079  SL_DRV_OBJ_UNLOCK(&g_pCB->FlowContCB.TxLockObj);
1080  }
1081  }
1082 
1083  SL_DRV_LOCK_GLOBAL_LOCK_FOREVER(GLOBAL_LOCK_FLAGS_UPDATE_API_IN_PROGRESS);
1084 
1085  /* In case the global was succesffully taken but error in progress
1086  it means it has been released as part of an error handling and we should abort immediately */
1087  if (SL_IS_RESTART_REQUIRED)
1088  {
1089  SL_DRV_LOCK_GLOBAL_UNLOCK(TRUE);
1090  return SL_API_ABORTED;
1091  }
1092 
1093  /* Here we consider the case in which some cmd has been sent to the NWP,
1094  And its allocated packet has not been freed yet. */
1095  VERIFY_PROTOCOL(g_pCB->FlowContCB.TxPoolCnt > (FLOW_CONT_MIN + allocTxPoolPkts -1) );
1096  g_pCB->FlowContCB.TxPoolCnt -= (_u8)allocTxPoolPkts;
1097 
1098  SL_DRV_OBJ_UNLOCK(&g_pCB->FlowContCB.TxLockObj);
1099 
1100  SL_TRACE1(DBG_MSG, MSG_312, "\n\r_SlDrvCmdOp: call _SlDrvMsgWrite: %x\n\r", pCmdCtrl->Opcode);
1101 
1102  /* send the message */
1103  RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, pTxRxDescBuff);
1104  SL_DRV_LOCK_GLOBAL_UNLOCK(TRUE);
1105 
1106  return RetVal;
1107 }
1108 
1109 /* ******************************************************************************/
1110 /* _SlDrvMsgWrite */
1111 /* ******************************************************************************/
1112 static _SlReturnVal_t _SlDrvMsgWrite(_SlCmdCtrl_t *pCmdCtrl,_SlCmdExt_t *pCmdExt, _u8 *pTxRxDescBuff)
1113 {
1114  _u8 sendRxPayload = FALSE;
1115  _SL_ASSERT_ERROR(NULL != pCmdCtrl, SL_API_ABORTED);
1116 
1117  g_pCB->FunctionParams.pCmdCtrl = pCmdCtrl;
1118  g_pCB->FunctionParams.pTxRxDescBuff = pTxRxDescBuff;
1119  g_pCB->FunctionParams.pCmdExt = pCmdExt;
1120 
1121  g_pCB->TempProtocolHeader.Opcode = pCmdCtrl->Opcode;
1122  g_pCB->TempProtocolHeader.Len = (_u16)(_SL_PROTOCOL_CALC_LEN(pCmdCtrl, pCmdExt));
1123 
1124  if (pCmdExt && pCmdExt->RxPayloadLen < 0 )
1125  {
1126  pCmdExt->RxPayloadLen = pCmdExt->RxPayloadLen * (-1); /* change sign */
1127  sendRxPayload = TRUE;
1128  g_pCB->TempProtocolHeader.Len = g_pCB->TempProtocolHeader.Len + pCmdExt->RxPayloadLen;
1129  }
1130 
1131 #ifdef SL_START_WRITE_STAT
1132  sl_IfStartWriteSequence(g_pCB->FD);
1133 #endif
1134 
1135 #ifdef SL_IF_TYPE_UART
1136  /* Write long sync pattern */
1137  NWP_IF_WRITE_CHECK(g_pCB->FD, (_u8 *)&g_H2NSyncPattern.Long, 2*SYNC_PATTERN_LEN);
1138 #else
1139  /* Write short sync pattern */
1140  NWP_IF_WRITE_CHECK(g_pCB->FD, (_u8 *)&g_H2NSyncPattern.Short, SYNC_PATTERN_LEN);
1141 #endif
1142 
1143  /* Header */
1144  NWP_IF_WRITE_CHECK(g_pCB->FD, (_u8 *)&g_pCB->TempProtocolHeader, _SL_CMD_HDR_SIZE);
1145 
1146  /* Descriptors */
1147  if (pTxRxDescBuff && pCmdCtrl->TxDescLen > 0)
1148  {
1149  NWP_IF_WRITE_CHECK(g_pCB->FD, pTxRxDescBuff,
1150  _SL_PROTOCOL_ALIGN_SIZE(pCmdCtrl->TxDescLen));
1151  }
1152 
1153  /* A special mode where Rx payload and Rx length are used as Tx as well */
1154  /* This mode requires no Rx payload on the response and currently used by fs_Close and sl_Send on */
1155  /* transceiver mode */
1156  if (sendRxPayload == TRUE )
1157  {
1158  NWP_IF_WRITE_CHECK(g_pCB->FD, pCmdExt->pRxPayload,
1159  _SL_PROTOCOL_ALIGN_SIZE(pCmdExt->RxPayloadLen));
1160  }
1161 
1162 
1163  /* if the message has some payload */
1164  if (pCmdExt)
1165  {
1166  /* If the message has payload, it is mandatory that the message's arguments are protocol aligned. */
1167  /* Otherwise the aligning of arguments will create a gap between arguments and payload. */
1168  VERIFY_PROTOCOL(_SL_IS_PROTOCOL_ALIGNED_SIZE(pCmdCtrl->TxDescLen));
1169 
1170  /* In case two seperated buffers were supplied we should merge the two buffers*/
1171  if ((pCmdExt->TxPayload1Len > 0) && (pCmdExt->TxPayload2Len > 0))
1172  {
1173  _u8 BuffInTheMiddle[4];
1174  _u8 FirstPayloadReminder = 0;
1175  _u8 SecondPayloadOffset = 0;
1176 
1177  FirstPayloadReminder = pCmdExt->TxPayload1Len & 3; /* calulate the first payload reminder */
1178 
1179  /* we first write the 4-bytes aligned payload part */
1180  pCmdExt->TxPayload1Len -= FirstPayloadReminder;
1181 
1182  /* writing the first transaction*/
1183  NWP_IF_WRITE_CHECK(g_pCB->FD, pCmdExt->pTxPayload1, pCmdExt->TxPayload1Len);
1184 
1185  /* Only if we the first payload is not aligned we need the intermediate transaction */
1186  if (FirstPayloadReminder != 0)
1187  {
1188  /* here we count how many bytes we need to take from the second buffer */
1189  SecondPayloadOffset = 4 - FirstPayloadReminder;
1190 
1191  /* copy the first payload reminder */
1192  sl_Memcpy(&BuffInTheMiddle[0], pCmdExt->pTxPayload1 + pCmdExt->TxPayload1Len, FirstPayloadReminder);
1193 
1194  /* add the beginning of the second payload to complete 4-bytes transaction */
1195  sl_Memcpy(&BuffInTheMiddle[FirstPayloadReminder], pCmdExt->pTxPayload2, SecondPayloadOffset);
1196 
1197  /* write the second transaction of the 4-bytes buffer */
1198  NWP_IF_WRITE_CHECK(g_pCB->FD, &BuffInTheMiddle[0], 4);
1199  }
1200 
1201 
1202  /* if we still has bytes to write in the second buffer */
1203  if (pCmdExt->TxPayload2Len > SecondPayloadOffset)
1204  {
1205  /* write the third transaction (truncated second payload) */
1206  NWP_IF_WRITE_CHECK(g_pCB->FD,
1207  pCmdExt->pTxPayload2 + SecondPayloadOffset,
1208  _SL_PROTOCOL_ALIGN_SIZE(pCmdExt->TxPayload2Len - SecondPayloadOffset));
1209  }
1210 
1211  }
1212  else if (pCmdExt->TxPayload1Len > 0)
1213  {
1214  /* Only 1 payload supplied (Payload1) so just align to 4 bytes and send it */
1215  NWP_IF_WRITE_CHECK(g_pCB->FD, pCmdExt->pTxPayload1,
1216  _SL_PROTOCOL_ALIGN_SIZE(pCmdExt->TxPayload1Len));
1217  }
1218  else if (pCmdExt->TxPayload2Len > 0)
1219  {
1220  /* Only 1 payload supplied (Payload2) so just align to 4 bytes and send it */
1221  NWP_IF_WRITE_CHECK(g_pCB->FD, pCmdExt->pTxPayload2,
1222  _SL_PROTOCOL_ALIGN_SIZE(pCmdExt->TxPayload2Len));
1223 
1224  }
1225  }
1226 
1227  _SL_DBG_CNT_INC(MsgCnt.Write);
1228 
1229 #ifdef SL_START_WRITE_STAT
1230  sl_IfEndWriteSequence(g_pCB->FD);
1231 #endif
1232 
1233  return SL_OS_RET_CODE_OK;
1234 }
1235 
1236 /* ******************************************************************************/
1237 /* _SlDrvMsgRead */
1238 /* ******************************************************************************/
1239 _SlReturnVal_t _SlDrvMsgRead(_u16* outMsgReadLen, _u8** pOutAsyncBuf)
1240 {
1241  /* alignment for small memory models */
1242  union
1243  {
1244  _u8 TempBuf[_SL_RESP_HDR_SIZE];
1245  _u32 DummyBuf[2];
1246  } uBuf;
1247  _u8 TailBuffer[4];
1248  _u16 LengthToCopy;
1249  _u16 AlignedLengthRecv;
1250  _u8 *pAsyncBuf = NULL;
1251  _u16 OpCode;
1252  _u16 RespPayloadLen;
1253  _u8 sd = SL_MAX_SOCKETS;
1254  _SlReturnVal_t RetVal;
1255  _SlRxMsgClass_e RxMsgClass;
1256  int Count = 0;
1257  /* Save parameters in global CB */
1258  g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler = NULL;
1259  _SlDrvMemZero(&TailBuffer[0], sizeof(TailBuffer));
1260 
1261  if (_SlDrvRxHdrRead((_u8*)(uBuf.TempBuf)) == SL_API_ABORTED)
1262  {
1263  SL_DRV_LOCK_GLOBAL_UNLOCK(TRUE);
1264 
1265  _SlDrvHandleFatalError(SL_DEVICE_EVENT_FATAL_SYNC_LOSS, 0, 0);
1266  return SL_API_ABORTED;
1267  }
1268 
1269  OpCode = OPCODE(uBuf.TempBuf);
1270  RespPayloadLen = (_u16)(RSP_PAYLOAD_LEN(uBuf.TempBuf));
1271 
1272  /* Update the NWP status */
1273  g_pCB->FlowContCB.TxPoolCnt = ((_SlResponseHeader_t *)uBuf.TempBuf)->TxPoolCnt;
1274  g_pCB->SocketNonBlocking = ((_SlResponseHeader_t *)uBuf.TempBuf)->SocketNonBlocking;
1275  g_pCB->SocketTXFailure = ((_SlResponseHeader_t *)uBuf.TempBuf)->SocketTXFailure;
1276  g_pCB->FlowContCB.MinTxPayloadSize = ((_SlResponseHeader_t *)uBuf.TempBuf)->MinMaxPayload;
1277 
1278  SL_SET_DEVICE_STATUS(((_SlResponseHeader_t *)uBuf.TempBuf)->DevStatus);
1279 
1280  if(g_pCB->FlowContCB.TxPoolCnt > FLOW_CONT_MIN)
1281  {
1282  sl_SyncObjGetCount(&g_pCB->FlowContCB.TxSyncObj, &Count);
1283  if (0 == Count)
1284  {
1285  SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->FlowContCB.TxSyncObj);
1286  }
1287  }
1288 
1289  /* Find the RX message class and set its Async event handler */
1290  _SlDrvClassifyRxMsg(OpCode);
1291 
1292  RxMsgClass = g_pCB->FunctionParams.AsyncExt.RxMsgClass;
1293 
1294  switch(RxMsgClass)
1295  {
1296  case ASYNC_EVT_CLASS:
1297  {
1298  VERIFY_PROTOCOL(NULL == pAsyncBuf);
1299 
1300 #ifdef SL_MEMORY_MGMT_DYNAMIC
1301  *pOutAsyncBuf = (_u8*)sl_Malloc(SL_ASYNC_MAX_MSG_LEN);
1302 
1303 #else
1304  *pOutAsyncBuf = g_StatMem.AsyncRespBuf;
1305 #endif
1306  /* set the local pointer to the allocated one */
1307  pAsyncBuf = *pOutAsyncBuf;
1308 
1309  MALLOC_OK_CHECK(pAsyncBuf);
1310 
1311  /* clear the async buffer */
1312  _SlDrvMemZero(pAsyncBuf, (_u16)SL_ASYNC_MAX_MSG_LEN);
1313  sl_Memcpy(pAsyncBuf, uBuf.TempBuf, _SL_RESP_HDR_SIZE);
1314 
1315  /* add the protocol header length */
1316  *outMsgReadLen = _SL_RESP_HDR_SIZE;
1317 
1318  if (_SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen) <= SL_ASYNC_MAX_PAYLOAD_LEN)
1319  {
1320  AlignedLengthRecv = (_u16)_SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen);
1321  }
1322  else
1323  {
1324  AlignedLengthRecv = (_u16)_SL_PROTOCOL_ALIGN_SIZE(SL_ASYNC_MAX_PAYLOAD_LEN);
1325  }
1326 
1327  /* complete the read of the entire message to the async buffer */
1328  if (RespPayloadLen > 0)
1329  {
1330  NWP_IF_READ_CHECK(g_pCB->FD,
1331  pAsyncBuf + _SL_RESP_HDR_SIZE,
1332  AlignedLengthRecv);
1333  *outMsgReadLen += AlignedLengthRecv;
1334  }
1335  /* In case ASYNC RX buffer length is smaller then the received data length, dump the rest */
1336  if ((_SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen) > SL_ASYNC_MAX_PAYLOAD_LEN))
1337  {
1338  AlignedLengthRecv = (_u16)(_SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen) - SL_ASYNC_MAX_PAYLOAD_LEN);
1339  while (AlignedLengthRecv > 0)
1340  {
1341  NWP_IF_READ_CHECK(g_pCB->FD,TailBuffer,4);
1342  AlignedLengthRecv = AlignedLengthRecv - 4;
1343  }
1344  }
1345 
1346  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
1347 
1348  if (
1349  (SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE == OpCode) ||
1350  (SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE_V6 == OpCode) ||
1351  (SL_OPCODE_SOCKET_CONNECTASYNCRESPONSE == OpCode) ||
1352  (SL_OPCODE_SOCKET_SOCKETCLOSEASYNCEVENT == OpCode)
1353  )
1354  {
1355  /* go over the active list if exist to find obj waiting for this Async event */
1356  sd = ((((SlSocketResponse_t *)(pAsyncBuf + _SL_RESP_HDR_SIZE))->Sd) & SL_BSD_SOCKET_ID_MASK);
1357  }
1358  if (SL_OPCODE_SOCKET_SOCKETASYNCEVENT == OpCode)
1359  {
1360  /* Save the socket descriptor which has been waiting for this opcode */
1361  sd = ((((SlSocketAsyncEvent_t *)(pAsyncBuf + _SL_RESP_HDR_SIZE))->Sd) & SL_BSD_SOCKET_ID_MASK);
1362  }
1363 
1364  _SlDrvFindAndSetActiveObj(OpCode, sd);
1365 
1366  SL_DRV_PROTECTION_OBJ_UNLOCK();
1367 
1368  break;
1369  }
1370 
1371  case RECV_RESP_CLASS:
1372  {
1373  _u8 ExpArgSize; /* Expected size of Recv/Recvfrom arguments */
1374 
1375  switch(OpCode)
1376  {
1377  case SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE:
1378  ExpArgSize = (_u8)RECVFROM_IPV4_ARGS_SIZE;
1379  break;
1380  case SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE_V6:
1381  ExpArgSize = (_u8)RECVFROM_IPV6_ARGS_SIZE;
1382  break;
1383  default:
1384  /* SL_OPCODE_SOCKET_RECVASYNCRESPONSE: */
1385  ExpArgSize = (_u8)RECV_ARGS_SIZE;
1386  }
1387 
1388  /* Read first 4 bytes of Recv/Recvfrom response to get SocketId and actual */
1389  /* response data length */
1390  NWP_IF_READ_CHECK(g_pCB->FD, &uBuf.TempBuf[4], RECV_ARGS_SIZE);
1391 
1392  /* Validate Socket ID and Received Length value. */
1393  VERIFY_PROTOCOL((SD(&uBuf.TempBuf[4])& SL_BSD_SOCKET_ID_MASK) < SL_MAX_SOCKETS);
1394 
1395  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
1396 
1397  /* go over the active list if exist to find obj waiting for this Async event */
1398  RetVal = _SlDrvFindAndSetActiveObj(OpCode, SD(&uBuf.TempBuf[4]) & SL_BSD_SOCKET_ID_MASK);
1399 
1400 #if (defined(SL_PLATFORM_MULTI_THREADED) && !defined(slcb_SocketTriggerEventHandler))
1401  /* This case is for reading the receive response sent by clearing the control socket. */
1402  if((RetVal == SL_RET_OBJ_NOT_SET) && (SD(&uBuf.TempBuf[4]) == g_pCB->MultiSelectCB.CtrlSockFD))
1403  {
1404  /*KW - we need to allocate the maximum possible which is 24*/
1405  _u8 buffer[RECVFROM_IPV6_ARGS_SIZE];
1406 
1407  sl_Memcpy(&buffer[0], &uBuf.TempBuf[4], RECV_ARGS_SIZE);
1408 
1409  if(ExpArgSize > (_u8)RECV_ARGS_SIZE)
1410  {
1411  NWP_IF_READ_CHECK(g_pCB->FD,
1412  &buffer[RECV_ARGS_SIZE],
1413  ExpArgSize - RECV_ARGS_SIZE);
1414  }
1415 
1416  /* Here g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pData contains requested(expected) Recv/Recvfrom DataSize. */
1417  /* Overwrite requested DataSize with actual one. */
1418  /* If error is received, this information will be read from arguments. */
1419  if(ACT_DATA_SIZE(&uBuf.TempBuf[4]) > 0)
1420  {
1421 
1422  /* Read 4 bytes aligned from interface */
1423  /* therefore check the requested length and read only */
1424  /* 4 bytes aligned data. The rest unaligned (if any) will be read */
1425  /* and copied to a TailBuffer */
1426  LengthToCopy = (_u16)(ACT_DATA_SIZE(&uBuf.TempBuf[4]) & (3));
1427  AlignedLengthRecv = (_u16)(ACT_DATA_SIZE(&uBuf.TempBuf[4]) & (~3));
1428  if( AlignedLengthRecv >= 4)
1429  {
1430  NWP_IF_READ_CHECK(g_pCB->FD, &buffer[ExpArgSize], AlignedLengthRecv);
1431  }
1432  }
1433 
1434  SL_DRV_PROTECTION_OBJ_UNLOCK();
1435  }
1436  else
1437 #endif
1438  {
1439  /* if _SlDrvFindAndSetActiveObj returned an error, release the protection lock, and return. */
1440  if(RetVal < 0)
1441  {
1442  SL_DRV_PROTECTION_OBJ_UNLOCK();
1443  SL_DRV_LOCK_GLOBAL_UNLOCK(TRUE);
1444  return SL_API_ABORTED;
1445  }
1446 
1447  /* Verify data is waited on this socket. The pArgs should have been set by _SlDrvDataReadOp(). */
1448  VERIFY_SOCKET_CB(NULL != ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pData))->pArgs);
1449 
1450  sl_Memcpy( ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pArgs, &uBuf.TempBuf[4], RECV_ARGS_SIZE);
1451 
1452  if(ExpArgSize > (_u8)RECV_ARGS_SIZE)
1453  {
1454  NWP_IF_READ_CHECK(g_pCB->FD,
1455  ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pArgs + RECV_ARGS_SIZE,
1456  ExpArgSize - RECV_ARGS_SIZE);
1457  }
1458 
1459  /* Here g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pData contains requested(expected) Recv/Recvfrom DataSize. */
1460  /* Overwrite requested DataSize with actual one. */
1461  /* If error is received, this information will be read from arguments. */
1462  if(ACT_DATA_SIZE(&uBuf.TempBuf[4]) > 0)
1463  {
1464  VERIFY_SOCKET_CB(NULL != ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pData);
1465 
1466  /* Read 4 bytes aligned from interface */
1467  /* therefore check the requested length and read only */
1468  /* 4 bytes aligned data. The rest unaligned (if any) will be read */
1469  /* and copied to a TailBuffer */
1470  LengthToCopy = (_u16)(ACT_DATA_SIZE(&uBuf.TempBuf[4]) & (3));
1471  AlignedLengthRecv = (_u16)(ACT_DATA_SIZE(&uBuf.TempBuf[4]) & (~3));
1472  if( AlignedLengthRecv >= 4)
1473  {
1474  NWP_IF_READ_CHECK(g_pCB->FD,((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pData, AlignedLengthRecv);
1475  }
1476  /* copy the unaligned part, if any */
1477  if( LengthToCopy > 0)
1478  {
1479  NWP_IF_READ_CHECK(g_pCB->FD,TailBuffer,4);
1480  /* copy TailBuffer unaligned part (1/2/3 bytes) */
1481  sl_Memcpy(((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pData + AlignedLengthRecv,TailBuffer,LengthToCopy);
1482  }
1483  }
1484  SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
1485  SL_DRV_PROTECTION_OBJ_UNLOCK();
1486  }
1487 
1488  break;
1489  }
1490 
1491  case CMD_RESP_CLASS:
1492  {
1493  /* Some commands pass a maximum arguments size. */
1494  /* In this case Driver will send extra dummy patterns to NWP if */
1495  /* the response message is smaller than maximum. */
1496  /* When RxDescLen is not exact, using RxPayloadLen is forbidden! */
1497  /* If such case cannot be avoided - parse message here to detect */
1498  /* arguments/payload border. */
1499  NWP_IF_READ_CHECK(g_pCB->FD,
1500  g_pCB->FunctionParams.pTxRxDescBuff,
1501  _SL_PROTOCOL_ALIGN_SIZE(g_pCB->FunctionParams.pCmdCtrl->RxDescLen));
1502 
1503  if((NULL != g_pCB->FunctionParams.pCmdExt) && (0 != g_pCB->FunctionParams.pCmdExt->RxPayloadLen))
1504  {
1505  /* Actual size of command's response payload: <msg_payload_len> - <rsp_args_len> */
1506  _i16 ActDataSize = (_i16)(RSP_PAYLOAD_LEN(uBuf.TempBuf) - g_pCB->FunctionParams.pCmdCtrl->RxDescLen);
1507 
1508  g_pCB->FunctionParams.pCmdExt->ActualRxPayloadLen = ActDataSize;
1509 
1510  /* Check that the space prepared by user for the response data is sufficient. */
1511  if(ActDataSize <= 0)
1512  {
1513  g_pCB->FunctionParams.pCmdExt->RxPayloadLen = 0;
1514  }
1515  else
1516  {
1517  /* In case the user supplied Rx buffer length which is smaller then the received data length, copy according to user length */
1518  if (ActDataSize > g_pCB->FunctionParams.pCmdExt->RxPayloadLen)
1519  {
1520  LengthToCopy = (_u16)(g_pCB->FunctionParams.pCmdExt->RxPayloadLen & (3));
1521  AlignedLengthRecv = (_u16)(g_pCB->FunctionParams.pCmdExt->RxPayloadLen & (~3));
1522  }
1523  else
1524  {
1525  LengthToCopy = (_u16)(ActDataSize & (3));
1526  AlignedLengthRecv = (_u16)(ActDataSize & (~3));
1527  }
1528  /* Read 4 bytes aligned from interface */
1529  /* therefore check the requested length and read only */
1530  /* 4 bytes aligned data. The rest unaligned (if any) will be read */
1531  /* and copied to a TailBuffer */
1532 
1533  if( AlignedLengthRecv >= 4)
1534  {
1535  NWP_IF_READ_CHECK(g_pCB->FD,
1536  g_pCB->FunctionParams.pCmdExt->pRxPayload,
1537  AlignedLengthRecv );
1538 
1539  }
1540  /* copy the unaligned part, if any */
1541  if( LengthToCopy > 0)
1542  {
1543  NWP_IF_READ_CHECK(g_pCB->FD,TailBuffer,4);
1544  /* copy TailBuffer unaligned part (1/2/3 bytes) */
1545  sl_Memcpy(g_pCB->FunctionParams.pCmdExt->pRxPayload + AlignedLengthRecv,
1546  TailBuffer,
1547  LengthToCopy);
1548  ActDataSize = ActDataSize-4;
1549  }
1550  /* In case the user supplied Rx buffer length which is smaller then the received data length, dump the rest */
1551  if (ActDataSize > g_pCB->FunctionParams.pCmdExt->RxPayloadLen)
1552  {
1553  /* calculate the rest of the data size to dump */
1554  AlignedLengthRecv = (_u16)( (ActDataSize + 3 - g_pCB->FunctionParams.pCmdExt->RxPayloadLen) & (~3) );
1555  while( AlignedLengthRecv > 0)
1556  {
1557  NWP_IF_READ_CHECK(g_pCB->FD,TailBuffer, 4 );
1558  AlignedLengthRecv = AlignedLengthRecv - 4;
1559  }
1560  }
1561  }
1562  }
1563 
1564  break;
1565  }
1566 
1567 #if (defined(SL_PLATFORM_MULTI_THREADED) && !defined(slcb_SocketTriggerEventHandler))
1568  case MULTI_SELECT_RESP_CLASS:
1569  {
1570  /* In case we read Select Response from NWP, and we're not waiting for
1571  * command complete, that means that a select command was send for a select Joiner. */
1572 
1573  _u8 Idx;
1574 
1575  NWP_IF_READ_CHECK(g_pCB->FD,
1576  (_u8*)(&g_pCB->MultiSelectCB.SelectCmdResp),
1577  _SL_PROTOCOL_ALIGN_SIZE(sizeof(_BasicResponse_t)));
1578 
1579  if(g_pCB->MultiSelectCB.SelectCmdResp.status != SL_RET_CODE_OK)
1580  {
1581  /* If a select response returns without Status O.K, this means that
1582  * something terribly wrong have happen. So we stop all waiting select callers,
1583  * and return command error. */
1584  g_pCB->MultiSelectCB.ActiveSelect = FALSE;
1585 
1586  for(Idx = 0 ; Idx < MAX_CONCURRENT_ACTIONS ; Idx++)
1587  {
1588  if(g_pCB->MultiSelectCB.SelectEntry[Idx] != NULL)
1589  {
1590  sl_SyncObjSignal(&g_pCB->ObjPool[Idx].SyncObj);
1591  }
1592  }
1593  /* Clean all table entries, and clear the global read/write fds */
1594  _SlDrvMemZero(&g_pCB->MultiSelectCB, sizeof(_SlMultiSelectCB_t));
1595  }
1596 
1597  break;
1598  }
1599 #endif
1600 
1601  default:
1602  /* DUMMY_MSG_CLASS: Flow control message has no payload. */
1603  break;
1604  }
1605 
1606  _SL_DBG_CNT_INC(MsgCnt.Read);
1607 
1608  /* Unmask Interrupt call */
1609  sl_IfUnMaskIntHdlr();
1610 
1611  return SL_OS_RET_CODE_OK;
1612 }
1613 
1614 
1615 /* ******************************************************************************/
1616 /* _SlDrvAsyncEventGenericHandler */
1617 /* ******************************************************************************/
1618 static void _SlDrvAsyncEventGenericHandler(_u8 bInCmdContext, _u8 *pAsyncBuffer)
1619 {
1620  _u32 SlAsyncEvent = 0;
1621  _u8 OpcodeFound = FALSE;
1622  _u8 i;
1623 
1624  _u32* pEventLocation = NULL; /* This pointer will override the async buffer with the translated event type */
1625  _SlResponseHeader_t *pHdr = (_SlResponseHeader_t *)pAsyncBuffer;
1626 
1627 
1628  /* if no async event registered nothing to do..*/
1629  if (g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler == NULL)
1630  {
1631  return;
1632  }
1633 
1634  /* In case we in the middle of the provisioning, filter out
1635  all the async events except the provisioning ones */
1636  if ( (( SL_IS_PROVISIONING_ACTIVE || SL_IS_PROVISIONING_INITIATED_BY_USER) && !(SL_IS_PROVISIONING_API_ALLOWED)) &&
1637  (pHdr->GenHeader.Opcode != SL_OPCODE_WLAN_PROVISIONING_STATUS_ASYNC_EVENT) &&
1638  (pHdr->GenHeader.Opcode != SL_OPCODE_DEVICE_RESET_REQUEST_ASYNC_EVENT) &&
1639  (pHdr->GenHeader.Opcode != SL_OPCODE_DEVICE_INITCOMPLETE) &&
1640  (pHdr->GenHeader.Opcode != SL_OPCODE_WLAN_PROVISIONING_PROFILE_ADDED_ASYNC_RESPONSE) &&
1641  (pHdr->GenHeader.Opcode != SL_OPCODE_NETAPP_REQUEST) )
1642  {
1643  return;
1644  }
1645 
1646  /* Iterate through all the opcode in the table */
1647  for (i=0; i< (_u8)(sizeof(OpcodeTranslateTable) / sizeof(OpcodeKeyVal_t)); i++)
1648  {
1649  if (OpcodeTranslateTable[i].opcode == pHdr->GenHeader.Opcode)
1650  {
1651  SlAsyncEvent = OpcodeTranslateTable[i].event;
1652  OpcodeFound = TRUE;
1653  break;
1654  }
1655  }
1656 
1657  /* No Async event found in the table */
1658  if (OpcodeFound == FALSE)
1659  {
1660  if ((pHdr->GenHeader.Opcode & SL_OPCODE_SILO_MASK) == SL_OPCODE_SILO_DEVICE)
1661  {
1662  DeviceEventInfo_t deviceEvent;
1663 
1664  deviceEvent.pAsyncMsgBuff = pAsyncBuffer;
1665  deviceEvent.bInCmdContext = bInCmdContext;
1666 
1667  g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler(&deviceEvent);
1668  }
1669  else
1670  {
1671  /* This case handles all the async events handlers of the DEVICE & SOCK Silos which are handled internally.
1672  For these cases we send the async even buffer as is */
1673  g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler(pAsyncBuffer);
1674  }
1675  }
1676  else
1677  {
1678  /* calculate the event type location to be filled in the async buffer */
1679  pEventLocation = (_u32*)(pAsyncBuffer + sizeof (_SlResponseHeader_t) - sizeof(SlAsyncEvent));
1680 
1681  /* Override the async buffer (before the data starts ) with our event type */
1682  *pEventLocation = SlAsyncEvent;
1683 
1684  /* call the event handler registered by the user with our async buffer which now holds
1685  the User's event type and its related data */
1686  g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler(pEventLocation);
1687 
1688  }
1689 }
1690 
1691 /* ******************************************************************************/
1692 /* _SlDrvMsgReadCmdCtx */
1693 /* ******************************************************************************/
1694 static _SlReturnVal_t _SlDrvMsgReadCmdCtx(_u16 cmdOpcode, _u8 IsLockRequired)
1695 {
1696  _u32 CmdCmpltTimeout;
1697  _i16 RetVal=0;
1698  _u8 *pAsyncBuf = NULL;
1699 
1700  /* the sl_FsOpen/sl_FsProgram APIs may take long time */
1701  if ((cmdOpcode == SL_OPCODE_NVMEM_FILEOPEN) || (cmdOpcode == SL_OPCODE_NVMEM_NVMEMFSPROGRAMMINGCOMMAND))
1702  {
1703  CmdCmpltTimeout = ((_u32)SL_DRIVER_TIMEOUT_LONG * 10);
1704  }
1705  else
1706  {
1707  /* For any FS command, the timeout will be the long one as the commnad response holds the full response data */
1708  CmdCmpltTimeout = (SL_OPCODE_SILO_FS & cmdOpcode)? (_u32)(SL_DRIVER_TIMEOUT_LONG) : (_u32)SL_DRIVER_TIMEOUT_SHORT;
1709  }
1710 
1711  /* after command response is received and WaitForCmdResp */
1712  /* flag is set FALSE, it is necessary to read out all */
1713  /* Async messages in Commands context, because ssiDma_IsrHandleSignalFromSlave */
1714  /* could have dispatched some Async messages to g_NwpIf.CmdSyncObj */
1715  /* after command response but before this response has been processed */
1716  /* by spi_singleRead and WaitForCmdResp was set FALSE. */
1717  while (TRUE == g_pCB->WaitForCmdResp)
1718  {
1719  if(_SL_PENDING_RX_MSG(g_pCB))
1720  {
1721  _u16 outMsgLen = 0;
1722 
1723  RetVal = _SlDrvMsgRead(&outMsgLen,&pAsyncBuf);
1724 
1725  if (RetVal != SL_OS_RET_CODE_OK)
1726  {
1727  g_pCB->WaitForCmdResp = FALSE;
1728 
1729  if ((IsLockRequired) && (RetVal != SL_API_ABORTED))
1730  {
1731  SL_DRV_LOCK_GLOBAL_UNLOCK(TRUE);
1732  }
1733 
1734  return SL_API_ABORTED;
1735  }
1736  g_pCB->RxDoneCnt++;
1737 
1738  if (CMD_RESP_CLASS == g_pCB->FunctionParams.AsyncExt.RxMsgClass)
1739  {
1740  g_pCB->WaitForCmdResp = FALSE;
1741  /* In case CmdResp has been read without waiting on CmdSyncObj - that */
1742  /* Sync object. That to prevent old signal to be processed. */
1743  SL_DRV_SYNC_OBJ_CLEAR(&g_pCB->CmdSyncObj);
1744  }
1745  else if (ASYNC_EVT_CLASS == g_pCB->FunctionParams.AsyncExt.RxMsgClass)
1746  {
1747 
1748 #ifdef SL_PLATFORM_MULTI_THREADED
1749  /* Do not handle async events in command context */
1750  /* All async events data will be stored in list and handled in spawn context */
1751  RetVal = _SlSpawnMsgListInsert(outMsgLen, pAsyncBuf);
1752  if (SL_RET_CODE_NO_FREE_ASYNC_BUFFERS_ERROR == RetVal)
1753  {
1754  _SlFindAndReleasePendingCmd();
1755  }
1756 
1757 #else
1758  _SlDrvAsyncEventGenericHandler(TRUE, pAsyncBuf);
1759 #endif
1760 
1761 #ifdef SL_MEMORY_MGMT_DYNAMIC
1762  sl_Free(pAsyncBuf);
1763 #else
1764  pAsyncBuf = NULL;
1765 #endif
1766  }
1767 #if (defined(SL_PLATFORM_MULTI_THREADED) && !defined(slcb_SocketTriggerEventHandler))
1768  else if(MULTI_SELECT_RESP_CLASS == g_pCB->FunctionParams.AsyncExt.RxMsgClass)
1769  {
1770  sl_SyncObjSignal(&g_pCB->MultiSelectCB.SelectSyncObj);
1771  }
1772 #endif
1773  }
1774  else
1775  {
1776  /* CmdSyncObj will be signaled by IRQ */
1777  RetVal = sl_SyncObjWait(&g_pCB->CmdSyncObj, CmdCmpltTimeout);
1778  if (RetVal != 0)
1779  {
1780  g_pCB->WaitForCmdResp = FALSE;
1781 
1782  if (IsLockRequired)
1783  {
1784  SL_DRV_LOCK_GLOBAL_UNLOCK(TRUE);
1785  }
1786 
1787  /* only if device started handle the fatal error */
1788  if (SL_IS_DEVICE_STARTED)
1789  {
1790  _SlDrvHandleFatalError(SL_DEVICE_EVENT_FATAL_NO_CMD_ACK, cmdOpcode, (_u32)CmdCmpltTimeout);
1791  }
1792 
1793  return SL_API_ABORTED;
1794  }
1795  }
1796  }
1797 
1798 #ifdef SL_PLATFORM_MULTI_THREADED
1799  if (_SlSpawnMsgListGetCount() > 0)
1800  {
1801  /* signal the spawn task to process the pending async events received during the cmd */
1802  sl_Spawn((_SlSpawnEntryFunc_t)_SlDrvMsgReadSpawnCtx, NULL, SL_SPAWN_FLAG_FROM_CMD_PROCESS);
1803  }
1804 #endif
1805 
1806  /* If there are more pending Rx Msgs after CmdResp is received, */
1807  /* that means that these are Async, Dummy or Read Data Msgs. */
1808  /* Spawn _SlDrvMsgReadSpawnCtx to trigger reading these messages from */
1809  /* Temporary context. */
1810  /* sl_Spawn is activated, using a different context */
1811  if (IsLockRequired)
1812  {
1813  SL_DRV_LOCK_GLOBAL_UNLOCK(TRUE);
1814  }
1815 
1816  if(_SL_PENDING_RX_MSG(g_pCB))
1817  {
1818  sl_Spawn((_SlSpawnEntryFunc_t)_SlDrvMsgReadSpawnCtx, NULL, SL_SPAWN_FLAG_FROM_CMD_CTX);
1819  }
1820 
1821  return SL_OS_RET_CODE_OK;
1822 }
1823 
1824 /* ******************************************************************************/
1825 /* _SlDrvMsgReadSpawnCtx */
1826 /* ******************************************************************************/
1827 _SlReturnVal_t _SlDrvMsgReadSpawnCtx(void *pValue)
1828 {
1829  _SlReturnVal_t RetVal = SL_OS_RET_CODE_OK;
1830  _u16 outMsgLen = 0;
1831  _u8 *pAsyncBuf = NULL;
1832 
1833 #ifdef SL_POLLING_MODE_USED
1834 
1835  /* for polling based systems */
1836  do
1837  {
1838  if (GlobalLockObj != NULL)
1839  {
1840  RetVal = sl_LockObjLock(&GlobalLockObj, 0);
1841 
1842  if (SL_OS_RET_CODE_OK != RetVal )
1843  {
1844  if (TRUE == g_pCB->WaitForCmdResp)
1845  {
1846  SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->CmdSyncObj);
1847  return SL_RET_CODE_OK;
1848  }
1849  }
1850 
1851  }
1852 
1853  }
1854  while (SL_OS_RET_CODE_OK != RetVal);
1855 
1856 #else
1857  SL_DRV_LOCK_GLOBAL_LOCK_FOREVER(GLOBAL_LOCK_FLAGS_NONE);
1858 #endif
1859 
1860 #ifndef SL_PLATFORM_MULTI_THREADED
1861  /* set the global lock owner (spawn context) */
1862  _SlDrvSetGlobalLockOwner(GLOBAL_LOCK_CONTEXT_OWNER_SPAWN);
1863 #endif
1864  /* pValue parameter is currently not in use */
1865  (void)pValue;
1866 
1867  /* Messages might have been read by CmdResp context. Therefore after */
1868  /* getting LockObj, check again where the Pending RX Msg is still present. */
1869  if(FALSE == (_SL_PENDING_RX_MSG(g_pCB)))
1870  {
1871 #ifndef SL_PLATFORM_MULTI_THREADED
1872  /* clear the global lock owner (spawn context) */
1873  _SlDrvSetGlobalLockOwner(GLOBAL_LOCK_CONTEXT_OWNER_APP);
1874 #endif
1875  SL_DRV_LOCK_GLOBAL_UNLOCK(FALSE);
1876 
1877  return SL_RET_CODE_OK;
1878  }
1879 
1880  if (SL_IS_DEVICE_STARTED || SL_IS_DEVICE_START_IN_PROGRESS)
1881  {
1882 
1883  RetVal = _SlDrvMsgRead(&outMsgLen, &pAsyncBuf);
1884 
1885  if (RetVal != SL_OS_RET_CODE_OK)
1886  {
1887  if (RetVal != SL_API_ABORTED)
1888  {
1889  #ifndef SL_PLATFORM_MULTI_THREADED
1890  /* clear the global lock owner (spawn context) */
1891  _SlDrvSetGlobalLockOwner(GLOBAL_LOCK_CONTEXT_OWNER_APP);
1892  #endif
1893  SL_DRV_LOCK_GLOBAL_UNLOCK(FALSE);
1894  }
1895  return SL_API_ABORTED;
1896  }
1897 
1898  g_pCB->RxDoneCnt++;
1899 
1900  switch(g_pCB->FunctionParams.AsyncExt.RxMsgClass)
1901  {
1902  case ASYNC_EVT_CLASS:
1903  /* If got here and protected by LockObj a message is waiting */
1904  /* to be read */
1905  VERIFY_PROTOCOL(NULL != pAsyncBuf);
1906 
1907 
1908  _SlDrvAsyncEventGenericHandler(FALSE, pAsyncBuf);
1909 
1910  #ifdef SL_MEMORY_MGMT_DYNAMIC
1911  sl_Free(pAsyncBuf);
1912  #else
1913  pAsyncBuf = NULL;
1914  #endif
1915  break;
1916  case DUMMY_MSG_CLASS:
1917  case RECV_RESP_CLASS:
1918  /* These types are legal in this context. Do nothing */
1919  break;
1920  case CMD_RESP_CLASS:
1921  /* Command response is illegal in this context - */
1922  /* One exception exists though: 'Select' response (SL_OPCODE_SOCKET_SELECTRESPONSE) Opcode = 0x1407 */
1923  break;
1924  #if (defined(SL_PLATFORM_MULTI_THREADED) && !defined(slcb_SocketTriggerEventHandler))
1925  case MULTI_SELECT_RESP_CLASS:
1926  /* If everything's OK, we signal for any other joiners to call 'Select'.*/
1927  sl_SyncObjSignal(&g_pCB->MultiSelectCB.SelectSyncObj);
1928  break;
1929  #endif
1930  default:
1931  _SL_ASSERT_ERROR(0, SL_API_ABORTED);
1932  }
1933  #ifndef SL_PLATFORM_MULTI_THREADED
1934  /* clear the global lock owner (spawn context) */
1935  _SlDrvSetGlobalLockOwner(GLOBAL_LOCK_CONTEXT_OWNER_APP);
1936  #endif
1937  SL_DRV_LOCK_GLOBAL_UNLOCK(FALSE);
1938  return(SL_RET_CODE_OK);
1939  }
1940  return(SL_RET_CODE_INTERFACE_CLOSED);
1941 }
1942 
1943 /*
1944 
1945 #define SL_OPCODE_SILO_DEVICE ( 0x0 << SL_OPCODE_SILO_OFFSET )
1946 #define SL_OPCODE_SILO_WLAN ( 0x1 << SL_OPCODE_SILO_OFFSET )
1947 #define SL_OPCODE_SILO_SOCKET ( 0x2 << SL_OPCODE_SILO_OFFSET )
1948 #define SL_OPCODE_SILO_NETAPP ( 0x3 << SL_OPCODE_SILO_OFFSET )
1949 #define SL_OPCODE_SILO_FS ( 0x4 << SL_OPCODE_SILO_OFFSET )
1950 #define SL_OPCODE_SILO_NETCFG ( 0x5 << SL_OPCODE_SILO_OFFSET )
1951 
1952 */
1953 
1954 /* The Lookup table below holds the event handlers to be called according to the incoming
1955  RX message SILO type */
1956 static const _SlSpawnEntryFunc_t RxMsgClassLUT[] = {
1957  (_SlSpawnEntryFunc_t)_SlDeviceEventHandler, /* SL_OPCODE_SILO_DEVICE */
1958 #if defined(slcb_WlanEvtHdlr) || defined(EXT_LIB_REGISTERED_WLAN_EVENTS)
1959  (_SlSpawnEntryFunc_t)_SlDrvHandleWlanEvents, /* SL_OPCODE_SILO_WLAN */
1960 #else
1961  NULL,
1962 #endif
1963 #if defined (slcb_SockEvtHdlr) || defined(EXT_LIB_REGISTERED_SOCK_EVENTS)
1964  (_SlSpawnEntryFunc_t)_SlDrvHandleSockEvents, /* SL_OPCODE_SILO_SOCKET */
1965 #else
1966  NULL,
1967 #endif
1968 #if defined(slcb_NetAppEvtHdlr) || defined(EXT_LIB_REGISTERED_NETAPP_EVENTS)
1969  (_SlSpawnEntryFunc_t)_SlDrvHandleNetAppEvents, /* SL_OPCODE_SILO_NETAPP */
1970 #else
1971  NULL,
1972 #endif
1973  NULL, /* SL_OPCODE_SILO_FS */
1974  NULL, /* SL_OPCODE_SILO_NETCFG */
1975  (_SlSpawnEntryFunc_t)_SlNetUtilHandleAsync_Cmd, /* SL_OPCODE_SILO_NETUTIL */
1976  NULL
1977 };
1978 
1979 
1980 /* ******************************************************************************/
1981 /* _SlDrvClassifyRxMsg */
1982 /* ******************************************************************************/
1983 static _SlReturnVal_t _SlDrvClassifyRxMsg(
1984  _SlOpcode_t Opcode)
1985 {
1986  _SlSpawnEntryFunc_t AsyncEvtHandler = NULL;
1987  _SlRxMsgClass_e RxMsgClass = CMD_RESP_CLASS;
1988  _u8 Silo;
1989 
1990 
1991  if (0 == (SL_OPCODE_SYNC & Opcode))
1992  { /* Async event has received */
1993 
1994  if (SL_OPCODE_DEVICE_DEVICEASYNCDUMMY == Opcode)
1995  {
1996  RxMsgClass = DUMMY_MSG_CLASS;
1997  }
1998  else if ( (SL_OPCODE_SOCKET_RECVASYNCRESPONSE == Opcode) || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE == Opcode)
1999  || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE_V6 == Opcode)
2000  )
2001  {
2002  RxMsgClass = RECV_RESP_CLASS;
2003  }
2004  else
2005  {
2006  /* This is Async Event class message */
2007  RxMsgClass = ASYNC_EVT_CLASS;
2008 
2009  /* Despite the fact that 4 bits are allocated in the SILO field, we actually have only 6 SILOs
2010  So we can use the 8 options of SILO in look up table */
2011  Silo = (_u8)((Opcode >> SL_OPCODE_SILO_OFFSET) & 0x7);
2012 
2013  VERIFY_PROTOCOL(Silo < (_u8)(sizeof(RxMsgClassLUT)/sizeof(_SlSpawnEntryFunc_t)));
2014 
2015  /* Set the SILO's async event handler according to the LUT
2016  If this specific event requires a direct async event handler, the
2017  async event handler will be overwrite according to the action table */
2018  AsyncEvtHandler = RxMsgClassLUT[Silo];
2019 
2020  if ((SL_OPCODE_NETAPP_HTTPGETTOKENVALUE == Opcode) || (SL_OPCODE_NETAPP_HTTPPOSTTOKENVALUE == Opcode) ||
2021  (SL_OPCODE_NETAPP_REQUEST == Opcode) || (SL_OPCODE_NETAPP_RESPONSE == Opcode) || (SL_OPCODE_NETAPP_SEND == Opcode))
2022  {
2023  AsyncEvtHandler = _SlNetAppEventHandler;
2024  }
2025  else if (SL_OPCODE_NETAPP_PINGREPORTREQUESTRESPONSE == Opcode)
2026  {
2027  AsyncEvtHandler = (_SlSpawnEntryFunc_t)_SlNetAppHandleAsync_PingResponse;
2028  }
2029  }
2030  }
2031 #if (defined(SL_PLATFORM_MULTI_THREADED) && !defined(slcb_SocketTriggerEventHandler))
2032  else if((Opcode == SL_OPCODE_SOCKET_SELECTRESPONSE) &&
2033  (g_pCB->FunctionParams.pCmdCtrl->Opcode != SL_OPCODE_SOCKET_SELECT))
2034  {
2035  /* Only in case this response came from a 'Select' sent in an Async event, Mark the message as MULTI_SELECT_RESPONSE */
2036  RxMsgClass = MULTI_SELECT_RESP_CLASS;
2037  }
2038 #endif
2039  g_pCB->FunctionParams.AsyncExt.RxMsgClass = RxMsgClass;
2040  g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler = AsyncEvtHandler;
2041 
2042  return SL_RET_CODE_OK;
2043 }
2044 
2045 
2046 /* ******************************************************************************/
2047 /* _SlDrvRxHdrRead */
2048 /* ******************************************************************************/
2049 static _SlReturnVal_t _SlDrvRxHdrRead(_u8 *pBuf)
2050 {
2051  _u8 ShiftIdx;
2052  _u8 TimeoutState = TIMEOUT_STATE_INIT_VAL;
2053  _u8 SearchSync = TRUE;
2054  _u8 SyncPattern[4];
2055 #if (defined(slcb_GetTimestamp))
2056  _SlTimeoutParams_t TimeoutInfo={0};
2057 #endif
2058 
2059 #ifndef SL_IF_TYPE_UART
2060  /* 1. Write CNYS pattern to NWP when working in SPI mode only */
2061  NWP_IF_WRITE_CHECK(g_pCB->FD, (_u8 *)&g_H2NCnysPattern.Short, SYNC_PATTERN_LEN);
2062 #endif
2063 
2064 #if (defined(slcb_GetTimestamp))
2065  _SlDrvStartMeasureTimeout(&TimeoutInfo, SYNC_PATTERN_TIMEOUT_IN_MSEC);
2066 #endif
2067 
2068  /* 2. Read 8 bytes (protocol aligned) - expected to be the sync pattern */
2069  NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[0], 8);
2070 
2071  /* read while first 4 bytes are different than last 4 bytes */
2072  while ( *(_u32 *)&pBuf[0] == *(_u32 *)&pBuf[4])
2073  {
2074  NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[4], 4);
2075 #if (defined(slcb_GetTimestamp))
2076  if (_SlDrvIsTimeoutExpired(&TimeoutInfo))
2077  {
2078  return SL_API_ABORTED;
2079  }
2080 #endif
2081  }
2082 
2083  /* scan for the sync pattern till found or timeout elapsed (if configured) */
2084  while (SearchSync && TimeoutState)
2085  {
2086  /* scan till we get the real sync pattern */
2087  for (ShiftIdx =0; ShiftIdx <=4 ; ShiftIdx++)
2088  {
2089  /* copy to local variable to ensure starting address which is 4-bytes aligned */
2090  sl_Memcpy(&SyncPattern[0], &pBuf[ShiftIdx], 4);
2091 
2092  /* sync pattern found so complete the read to 4 bytes aligned */
2093  if (N2H_SYNC_PATTERN_MATCH(&SyncPattern[0], g_pCB->TxSeqNum))
2094  {
2095  /* copy the bytes following the sync pattern to the buffer start */
2096  sl_Memcpy(&pBuf[0], &pBuf[ShiftIdx + SYNC_PATTERN_LEN], 4);
2097 
2098  if (ShiftIdx != 0)
2099  {
2100  /* read the rest of the bytes (only if wer'e not aligned) (expected to complete the opcode + length fields ) */
2101  NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[SYNC_PATTERN_LEN - ShiftIdx], ShiftIdx);
2102  }
2103 
2104  /* here we except to get the opcode + length or false doubled sync..*/
2105  SearchSync = FALSE;
2106  break;
2107  }
2108  }
2109 
2110  if (SearchSync == TRUE)
2111  {
2112  /* sync not found move top 4 bytes to bottom */
2113  *(_u32 *)&pBuf[0] = *(_u32 *)&pBuf[4];
2114 
2115  /* read 4 more bytes to the buffer top */
2116  NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[4], 4);
2117  }
2118 
2119  #if (defined (slcb_GetTimestamp))
2120 
2121  /* if we got here after first timeout detection, it means that we gave
2122  one more chance, and we can now exit the loop with timeout expiry */
2123  if (TIMEOUT_ONE_MORE_SHOT == TimeoutState)
2124  {
2125  TimeoutState = TIMEOUT_STATE_EXPIRY;
2126  break;
2127  }
2128 
2129  /* Timeout occurred. do not break now as we want to give one more chance in case
2130  the timeout occurred due to some external context switch */
2131  if (_SlDrvIsTimeoutExpired(&TimeoutInfo))
2132  {
2133  TimeoutState = TIMEOUT_ONE_MORE_SHOT;
2134  }
2135 
2136 #endif
2137  } /* end of while */
2138 
2139 #if (defined (slcb_GetTimestamp))
2140  if (TIMEOUT_STATE_EXPIRY == TimeoutState)
2141  {
2142  return SL_API_ABORTED;
2143  }
2144 #endif
2145 
2146  /* 6. Scan for Double pattern. */
2147  while ( N2H_SYNC_PATTERN_MATCH(pBuf, g_pCB->TxSeqNum) )
2148  {
2149  _SL_DBG_CNT_INC(Work.DoubleSyncPattern);
2150  NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[0], SYNC_PATTERN_LEN);
2151  }
2152  g_pCB->TxSeqNum++;
2153 
2154  /* 7. Here we've read Generic Header (4 bytes opcode+length).
2155  * Now Read the Resp Specific header (4 more bytes). */
2156  NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[SYNC_PATTERN_LEN], _SL_RESP_SPEC_HDR_SIZE);
2157 
2158  return SL_RET_CODE_OK;
2159 }
2160 
2161 /* ***************************************************************************** */
2162 /* _SlDrvBasicCmd */
2163 /* ***************************************************************************** */
2164 typedef union
2165 {
2166  _BasicResponse_t Rsp;
2167 }_SlBasicCmdMsg_u;
2168 
2169 
2170 _SlReturnVal_t _SlDrvBasicCmd(_SlOpcode_t Opcode)
2171 {
2172  _SlBasicCmdMsg_u Msg;
2173  _SlCmdCtrl_t CmdCtrl;
2174 
2175  _SlDrvMemZero(&Msg, (_u16)sizeof(_SlBasicCmdMsg_u));
2176  CmdCtrl.Opcode = Opcode;
2177  CmdCtrl.TxDescLen = 0;
2178  CmdCtrl.RxDescLen = (_SlArgSize_t)sizeof(_BasicResponse_t);
2179 
2180 
2181  VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL));
2182 
2183  return (_SlReturnVal_t)Msg.Rsp.status;
2184 }
2185 
2186 /*****************************************************************************
2187  _SlDrvCmdSend_noLock
2188  Send SL command without waiting for command response
2189  This function is unprotected and the caller should make
2190  sure global lock is active. Used to send data within async event handler, where the driver is already locked.
2191 *****************************************************************************/
2192 _SlReturnVal_t _SlDrvCmdSend_noLock(
2193  _SlCmdCtrl_t *pCmdCtrl ,
2194  void *pTxRxDescBuff ,
2195  _SlCmdExt_t *pCmdExt)
2196 {
2197  _SlReturnVal_t RetVal;
2198  _u8 WaitForCmdRespOriginalVal;
2199 
2200  _SlFunctionParams_t originalFuncParms;
2201 
2202  /* save the current RespWait flag before clearing it */
2203  WaitForCmdRespOriginalVal = g_pCB->WaitForCmdResp;
2204 
2205  /* save the current command paramaters */
2206  sl_Memcpy(&originalFuncParms, &g_pCB->FunctionParams, sizeof(_SlFunctionParams_t));
2207 
2208  g_pCB->WaitForCmdResp = FALSE;
2209 
2210  SL_TRACE0(DBG_MSG, MSG_312, "_SlDrvCmdSend_noLock: call _SlDrvMsgWrite");
2211 
2212  /* send the message */
2213  RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, pTxRxDescBuff);
2214 
2215  /* restore the original RespWait flag */
2216  g_pCB->WaitForCmdResp = WaitForCmdRespOriginalVal;
2217 
2218  /* restore the original command paramaters */
2219  sl_Memcpy(&g_pCB->FunctionParams, &originalFuncParms, sizeof(_SlFunctionParams_t));
2220 
2221  return RetVal;
2222 }
2223 /*****************************************************************************
2224  _SlDrvCmdSend_noWait
2225  Send SL command without waiting for command response
2226  This function send command form any possiable context, without waiting.
2227 *****************************************************************************/
2228 _SlReturnVal_t _SlDrvCmdSend_noWait(
2229  _SlCmdCtrl_t *pCmdCtrl ,
2230  void *pTxRxDescBuff ,
2231  _SlCmdExt_t *pCmdExt)
2232 {
2233  _SlReturnVal_t RetVal;
2234 
2235  _SlFunctionParams_t originalFuncParms;
2236 
2237  SL_TRACE1(DBG_MSG, MSG_312, "\n\r_SlDrvCmdSend_noLock: call _SlDrvMsgWrite: %x\n\r", pCmdCtrl->Opcode);
2238 
2239  /* Save the current function parameters */
2240  sl_Memcpy(&originalFuncParms, &g_pCB->FunctionParams, sizeof(_SlFunctionParams_t));
2241 
2242  /* send the message */
2243  RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, pTxRxDescBuff);
2244 
2245  /* Restore */
2246  sl_Memcpy(&g_pCB->FunctionParams, &originalFuncParms, sizeof(_SlFunctionParams_t));
2247 
2248  return RetVal;
2249 }
2250 
2251 /*****************************************************************************
2252  _SlDrvCmdSend
2253  Send SL command without waiting for command response
2254 *****************************************************************************/
2255 _SlReturnVal_t _SlDrvCmdSend(
2256  _SlCmdCtrl_t *pCmdCtrl ,
2257  void *pTxRxDescBuff ,
2258  _SlCmdExt_t *pCmdExt)
2259 {
2260  _SlReturnVal_t RetVal;
2261 
2262  _SlDrvObjLockWaitForever(&GlobalLockObj);
2263 
2264  g_pCB->WaitForCmdResp = FALSE;
2265 
2266  SL_TRACE1(DBG_MSG, MSG_312, "_SlDrvCmdSend: call _SlDrvMsgWrite:%x", pCmdCtrl->Opcode);
2267 
2268  /* send the message */
2269  RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, pTxRxDescBuff);
2270 
2271  _SlDrvObjUnLock(&GlobalLockObj);
2272 
2273  return RetVal;
2274 }
2275 
2276 
2277 /* ***************************************************************************** */
2278 /* _SlDrvProtectAsyncRespSetting */
2279 /* ***************************************************************************** */
2280 _SlReturnVal_t _SlDrvProtectAsyncRespSetting(_u8 *pAsyncRsp, _SlActionID_e ActionID, _u8 SocketID)
2281 {
2282  _i16 ObjIdx;
2283 
2284  /* Use Obj to issue the command, if not available try later */
2285  ObjIdx = _SlDrvWaitForPoolObj(ActionID, SocketID);
2286 
2287  if (SL_RET_CODE_STOP_IN_PROGRESS == ObjIdx)
2288  {
2289  return SL_RET_CODE_STOP_IN_PROGRESS;
2290  }
2291  else if (MAX_CONCURRENT_ACTIONS == ObjIdx)
2292  {
2293  return SL_POOL_IS_EMPTY;
2294  }
2295  else
2296  {
2297  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
2298  g_pCB->ObjPool[ObjIdx].pRespArgs = pAsyncRsp;
2299  SL_DRV_PROTECTION_OBJ_UNLOCK();
2300  }
2301 
2302  return ObjIdx;
2303 }
2304 
2305 
2306 /* ***************************************************************************** */
2307 /* _SlDrvIsSpawnOwnGlobalLock */
2308 /* ***************************************************************************** */
2309 #if (!defined (SL_PLATFORM_EXTERNAL_SPAWN))
2310 _u8 _SlDrvIsSpawnOwnGlobalLock()
2311 {
2312 #ifdef SL_PLATFORM_MULTI_THREADED
2313  _u32 ThreadId = (_i32)sl_GetThreadID();
2314  return _SlInternalIsItSpawnThread(ThreadId);
2315 #else
2316  return (gGlobalLockContextOwner == GLOBAL_LOCK_CONTEXT_OWNER_SPAWN);
2317 #endif
2318 }
2319 #endif
2320 /* ***************************************************************************** */
2321 /* _SlDrvWaitForPoolObj */
2322 /* ***************************************************************************** */
2323 _SlReturnVal_t _SlDrvWaitForPoolObj(_u8 ActionID, _u8 SocketID)
2324 {
2325  _u8 CurrObjIndex = MAX_CONCURRENT_ACTIONS;
2326 
2327  /* Get free object */
2328  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
2329 
2330  if (MAX_CONCURRENT_ACTIONS > g_pCB->FreePoolIdx)
2331  {
2332  /* save the current obj index */
2333  CurrObjIndex = g_pCB->FreePoolIdx;
2334  /* set the new free index */
2335  if (MAX_CONCURRENT_ACTIONS > g_pCB->ObjPool[CurrObjIndex].NextIndex)
2336  {
2337  g_pCB->FreePoolIdx = g_pCB->ObjPool[CurrObjIndex].NextIndex;
2338  }
2339  else
2340  {
2341  /* No further free actions available */
2342  g_pCB->FreePoolIdx = MAX_CONCURRENT_ACTIONS;
2343  }
2344  }
2345  else
2346  {
2347  SL_DRV_PROTECTION_OBJ_UNLOCK();
2348  return CurrObjIndex;
2349  }
2350  g_pCB->ObjPool[CurrObjIndex].ActionID = (_u8)ActionID;
2351  if (SL_MAX_SOCKETS > SocketID)
2352  {
2353  g_pCB->ObjPool[CurrObjIndex].AdditionalData = SocketID;
2354  }
2355  /*In case this action is socket related, SocketID bit will be on
2356  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 */
2357  while ( ( (SL_MAX_SOCKETS > SocketID) && (g_pCB->ActiveActionsBitmap & (1<<SocketID)) ) ||
2358  ( (g_pCB->ActiveActionsBitmap & ( MULTI_SELECT_MASK & (1<<ActionID))) && (SL_MAX_SOCKETS == SocketID) ) )
2359  {
2360  /* If we are in spawn context, this is an API which was called from event handler,
2361  return error since there is no option to block the spawn context on the pending sync obj */
2362 #if (defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))
2363  if (_SlDrvIsSpawnOwnGlobalLock())
2364  {
2365  g_pCB->ObjPool[CurrObjIndex].ActionID = 0;
2366  g_pCB->ObjPool[CurrObjIndex].AdditionalData = SL_MAX_SOCKETS;
2367  g_pCB->FreePoolIdx = CurrObjIndex;
2368  SL_DRV_PROTECTION_OBJ_UNLOCK();
2369  return MAX_CONCURRENT_ACTIONS;
2370  }
2371 #endif
2372  /* action in progress - move to pending list */
2373  g_pCB->ObjPool[CurrObjIndex].NextIndex = g_pCB->PendingPoolIdx;
2374  g_pCB->PendingPoolIdx = CurrObjIndex;
2375  SL_DRV_PROTECTION_OBJ_UNLOCK();
2376 
2377  /* wait for action to be free */
2378  (void)_SlDrvSyncObjWaitForever(&g_pCB->ObjPool[CurrObjIndex].SyncObj);
2379  if (SL_IS_DEVICE_STOP_IN_PROGRESS)
2380  {
2381  OSI_RET_OK_CHECK(sl_SyncObjDelete(&g_pCB->ObjPool[CurrObjIndex].SyncObj));
2382  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
2383  g_pCB->NumOfDeletedSyncObj++;
2384  SL_DRV_PROTECTION_OBJ_UNLOCK();
2385  return SL_RET_CODE_STOP_IN_PROGRESS;
2386  }
2387 
2388  /* set params and move to active (remove from pending list at _SlDrvReleasePoolObj) */
2389  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
2390  }
2391 
2392  /* mark as active. Set socket as active if action is on socket, otherwise mark action as active */
2393  if (SL_MAX_SOCKETS > SocketID)
2394  {
2395  g_pCB->ActiveActionsBitmap |= (1<<SocketID);
2396  }
2397  else
2398  {
2399  g_pCB->ActiveActionsBitmap |= (1<<ActionID);
2400  }
2401  /* move to active list */
2402  g_pCB->ObjPool[CurrObjIndex].NextIndex = g_pCB->ActivePoolIdx;
2403  g_pCB->ActivePoolIdx = CurrObjIndex;
2404 
2405  /* unlock */
2406  SL_DRV_PROTECTION_OBJ_UNLOCK();
2407 
2408  /* Increment the API in progress counter as this routine is called for every
2409  API, which will be waiting for async event to be released */
2410  _SlDrvUpdateApiInProgress(API_IN_PROGRESS_UPDATE_INCREMENT);
2411 
2412  return CurrObjIndex;
2413 }
2414 
2415 /* ******************************************************************************/
2416 /* _SlDrvReleasePoolObj */
2417 /* ******************************************************************************/
2418 _SlReturnVal_t _SlDrvReleasePoolObj(_u8 ObjIdx)
2419 {
2420  _u8 PendingIndex;
2421 
2422  /* Delete sync obj in case stop in progress and return */
2423  if (SL_IS_DEVICE_STOP_IN_PROGRESS)
2424  {
2425  OSI_RET_OK_CHECK(sl_SyncObjDelete(&g_pCB->ObjPool[ObjIdx].SyncObj));
2426  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
2427  g_pCB->NumOfDeletedSyncObj++;
2428  SL_DRV_PROTECTION_OBJ_UNLOCK();
2429  return SL_RET_CODE_OK;
2430  }
2431 
2432  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
2433 
2434  /* go over the pending list and release other pending action if needed */
2435  PendingIndex = g_pCB->PendingPoolIdx;
2436 
2437  while(MAX_CONCURRENT_ACTIONS > PendingIndex)
2438  {
2439  /* In case this action is socket related, SocketID is in use, otherwise will be set to SL_MAX_SOCKETS */
2440  if ( (g_pCB->ObjPool[PendingIndex].ActionID == g_pCB->ObjPool[ObjIdx].ActionID) &&
2441  ( (SL_MAX_SOCKETS == (g_pCB->ObjPool[PendingIndex].AdditionalData & SL_BSD_SOCKET_ID_MASK)) ||
2442  ((SL_MAX_SOCKETS > (g_pCB->ObjPool[ObjIdx].AdditionalData & SL_BSD_SOCKET_ID_MASK)) && ( (g_pCB->ObjPool[PendingIndex].AdditionalData & SL_BSD_SOCKET_ID_MASK) == (g_pCB->ObjPool[ObjIdx].AdditionalData & SL_BSD_SOCKET_ID_MASK) ))) )
2443  {
2444  /* remove from pending list */
2445  _SlDrvRemoveFromList(&g_pCB->PendingPoolIdx, PendingIndex);
2446  SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[PendingIndex].SyncObj);
2447  break;
2448  }
2449  PendingIndex = g_pCB->ObjPool[PendingIndex].NextIndex;
2450  }
2451 
2452  //if this action is socket relate but the correlate bit is off , return without deleting old data
2453  if (SL_MAX_SOCKETS > (g_pCB->ObjPool[ObjIdx].AdditionalData & SL_BSD_SOCKET_ID_MASK))
2454  {
2455  if (!((1 << (g_pCB->ObjPool[ObjIdx].AdditionalData & SL_BSD_SOCKET_ID_MASK)) & g_pCB->ActiveActionsBitmap))
2456  {
2457  return SL_RET_CODE_OK;
2458  }
2459  }
2460  //if this action has action ID but the correlate bit is off, return without deleting old data
2461  else
2462  {
2463  if ((!((1 << g_pCB->ObjPool[ObjIdx].ActionID) & g_pCB->ActiveActionsBitmap))
2464  && ( SELECT_ID != g_pCB->ObjPool[ObjIdx].ActionID)) // multiple select can take more then one pool obj with the same actionID
2465  {
2466  return SL_RET_CODE_OK;
2467  }
2468  }
2469 
2470 
2471  if (SL_MAX_SOCKETS > (g_pCB->ObjPool[ObjIdx].AdditionalData & SL_BSD_SOCKET_ID_MASK))
2472  {
2473  /* unset socketID */
2474  g_pCB->ActiveActionsBitmap &= ~(1<<(g_pCB->ObjPool[ObjIdx].AdditionalData & SL_BSD_SOCKET_ID_MASK));
2475  }
2476  else
2477  {
2478  /* unset actionID */
2479  g_pCB->ActiveActionsBitmap &= ~(1<<g_pCB->ObjPool[ObjIdx].ActionID);
2480  }
2481 
2482  /* delete old data */
2483  g_pCB->ObjPool[ObjIdx].pRespArgs = NULL;
2484  g_pCB->ObjPool[ObjIdx].ActionID = 0;
2485  g_pCB->ObjPool[ObjIdx].AdditionalData = SL_MAX_SOCKETS;
2486 
2487  /* remove from active list */
2488  _SlDrvRemoveFromList(&g_pCB->ActivePoolIdx, ObjIdx);
2489 
2490  /* move to free list */
2491  g_pCB->ObjPool[ObjIdx].NextIndex = g_pCB->FreePoolIdx;
2492  g_pCB->FreePoolIdx = ObjIdx;
2493 
2494  SL_DRV_PROTECTION_OBJ_UNLOCK();
2495 
2496  /* Here we decrement the API in progrees counter as we just released the pool object,
2497  which is held till the API is finished (async event received) */
2498  _SlDrvUpdateApiInProgress(API_IN_PROGRESS_UPDATE_DECREMENT);
2499  return SL_RET_CODE_OK;
2500 }
2501 
2502 /* ******************************************************************************/
2503 /* _SlDrvReleaseAllActivePendingPoolObj */
2504 /* ******************************************************************************/
2505 _SlReturnVal_t _SlDrvReleaseAllActivePendingPoolObj()
2506 {
2507  _u8 ActiveIndex;
2508 
2509  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
2510 
2511  /* go over the active list and release each action with error */
2512  ActiveIndex = g_pCB->ActivePoolIdx;
2513 
2514  while (MAX_CONCURRENT_ACTIONS > ActiveIndex)
2515  {
2516  /* Set error in case sync objects release due to stop device command */
2517  if (g_pCB->ObjPool[ActiveIndex].ActionID == NETUTIL_CMD_ID)
2518  {
2519  ((_SlNetUtilCmdData_t *)(g_pCB->ObjPool[ActiveIndex].pRespArgs))->Status = SL_RET_CODE_STOP_IN_PROGRESS;
2520  }
2521  else if (g_pCB->ObjPool[ActiveIndex].ActionID == RECV_ID)
2522  {
2523  ((SlSocketResponse_t *)((_SlArgsData_t *)(g_pCB->ObjPool[ActiveIndex].pRespArgs))->pArgs)->StatusOrLen = SL_RET_CODE_STOP_IN_PROGRESS;
2524  }
2525  /* First 2 bytes of all async response holds the status except with NETUTIL_CMD_ID and RECV_ID */
2526  else
2527  {
2528  ((SlSocketResponse_t *)(g_pCB->ObjPool[ActiveIndex].pRespArgs))->StatusOrLen = SL_RET_CODE_STOP_IN_PROGRESS;
2529  }
2530  /* Signal the pool obj*/
2531  SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[ActiveIndex].SyncObj);
2532  ActiveIndex = g_pCB->ObjPool[ActiveIndex].NextIndex;
2533  }
2534 
2535  /* go over the pending list and release each action */
2536  ActiveIndex = g_pCB->PendingPoolIdx;
2537 
2538  while (MAX_CONCURRENT_ACTIONS > ActiveIndex)
2539  {
2540  /* Signal the pool obj*/
2541  SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[ActiveIndex].SyncObj);
2542  ActiveIndex = g_pCB->ObjPool[ActiveIndex].NextIndex;
2543  }
2544 
2545  /* Delete only unoccupied objects from the Free list, other obj (pending and active)
2546  will be deleted from the relevant context */
2547  ActiveIndex = g_pCB->FreePoolIdx;
2548  while(MAX_CONCURRENT_ACTIONS > ActiveIndex)
2549  {
2550  OSI_RET_OK_CHECK(sl_SyncObjDelete(&g_pCB->ObjPool[ActiveIndex].SyncObj));
2551  g_pCB->NumOfDeletedSyncObj++;
2552  ActiveIndex = g_pCB->ObjPool[ActiveIndex].NextIndex;
2553  }
2554  /* In case trigger select in progress, delete the sync obj */
2555 #if defined(slcb_SocketTriggerEventHandler)
2556  if (MAX_CONCURRENT_ACTIONS != g_pCB->SocketTriggerSelect.Info.ObjPoolIdx)
2557  {
2558  OSI_RET_OK_CHECK(sl_SyncObjDelete(&g_pCB->ObjPool[g_pCB->SocketTriggerSelect.Info.ObjPoolIdx].SyncObj));
2559  g_pCB->NumOfDeletedSyncObj++;
2560  }
2561 #endif
2562  SL_DRV_PROTECTION_OBJ_UNLOCK();
2563  return SL_RET_CODE_OK;
2564 }
2565 
2566 /* ******************************************************************************/
2567 /* _SlDrvRemoveFromList */
2568 /* ******************************************************************************/
2569 static void _SlDrvRemoveFromList(_u8 *ListIndex, _u8 ItemIndex)
2570 {
2571  _u8 Idx;
2572 
2573  if (MAX_CONCURRENT_ACTIONS == g_pCB->ObjPool[*ListIndex].NextIndex)
2574  {
2575  *ListIndex = MAX_CONCURRENT_ACTIONS;
2576  }
2577  /* need to remove the first item in the list and therefore update the global which holds this index */
2578  else if (*ListIndex == ItemIndex)
2579  {
2580  *ListIndex = g_pCB->ObjPool[ItemIndex].NextIndex;
2581  }
2582  else
2583  {
2584  Idx = *ListIndex;
2585 
2586  while(MAX_CONCURRENT_ACTIONS > Idx)
2587  {
2588  /* remove from list */
2589  if (g_pCB->ObjPool[Idx].NextIndex == ItemIndex)
2590  {
2591  g_pCB->ObjPool[Idx].NextIndex = g_pCB->ObjPool[ItemIndex].NextIndex;
2592  break;
2593  }
2594 
2595  Idx = g_pCB->ObjPool[Idx].NextIndex;
2596  }
2597  }
2598 }
2599 
2600 
2601 /* ******************************************************************************/
2602 /* _SlDrvFindAndSetActiveObj */
2603 /* ******************************************************************************/
2604 static _SlReturnVal_t _SlDrvFindAndSetActiveObj(_SlOpcode_t Opcode, _u8 Sd)
2605 {
2606  _u8 ActiveIndex;
2607 
2608  ActiveIndex = g_pCB->ActivePoolIdx;
2609  /* go over the active list if exist to find obj waiting for this Async event */
2610 
2611  while (MAX_CONCURRENT_ACTIONS > ActiveIndex)
2612  {
2613  /* unset the Ipv4\IPv6 bit in the opcode if family bit was set */
2614  if (g_pCB->ObjPool[ActiveIndex].AdditionalData & SL_NETAPP_FAMILY_MASK)
2615  {
2616  Opcode &= ~SL_OPCODE_IPV6;
2617  }
2618 
2619  if ((g_pCB->ObjPool[ActiveIndex].ActionID == RECV_ID) && (Sd == g_pCB->ObjPool[ActiveIndex].AdditionalData) &&
2620  ( (SL_OPCODE_SOCKET_RECVASYNCRESPONSE == Opcode) || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE == Opcode)
2621  || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE_V6 == Opcode))
2622  )
2623  {
2624  g_pCB->FunctionParams.AsyncExt.ActionIndex = ActiveIndex;
2625  return SL_RET_CODE_OK;
2626  }
2627  /* In case this action is socket related, SocketID is in use, otherwise will be set to SL_MAX_SOCKETS */
2628  if ( (_SlActionLookupTable[ g_pCB->ObjPool[ActiveIndex].ActionID - MAX_SOCKET_ENUM_IDX].ActionAsyncOpcode == Opcode) &&
2629  ( ((Sd == (g_pCB->ObjPool[ActiveIndex].AdditionalData & SL_BSD_SOCKET_ID_MASK) ) && (SL_MAX_SOCKETS > Sd)) || (SL_MAX_SOCKETS == (g_pCB->ObjPool[ActiveIndex].AdditionalData & SL_BSD_SOCKET_ID_MASK)) ) )
2630  {
2631  /* set handler */
2632  g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler = _SlActionLookupTable[ g_pCB->ObjPool[ActiveIndex].ActionID - MAX_SOCKET_ENUM_IDX].AsyncEventHandler;
2633  g_pCB->FunctionParams.AsyncExt.ActionIndex = ActiveIndex;
2634  return SL_RET_CODE_OK;
2635  }
2636  ActiveIndex = g_pCB->ObjPool[ActiveIndex].NextIndex;
2637  }
2638 
2639  return SL_RET_OBJ_NOT_SET;
2640 }
2641 
2642 #if defined(slcb_NetAppHttpServerHdlr) || defined(EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS)
2643 void _SlDrvDispatchHttpServerEvents(SlNetAppHttpServerEvent_t *slHttpServerEvent, SlNetAppHttpServerResponse_t *slHttpServerResponse)
2644 {
2645  _SlDrvHandleHttpServerEvents (slHttpServerEvent, slHttpServerResponse);
2646 }
2647 #endif
2648 
2649 #if defined(slcb_NetAppRequestHdlr) || defined(EXT_LIB_REGISTERED_NETAPP_REQUEST_EVENTS)
2650 void _SlDrvDispatchNetAppRequestEvents(SlNetAppRequest_t *slNetAppRequestEvent, SlNetAppResponse_t *slNetAppResponse)
2651 {
2652  _SlDrvHandleNetAppRequestEvents (slNetAppRequestEvent, slNetAppResponse);
2653 }
2654 #endif
2655 
2656 
2657 /* Wrappers for the object functions */
2658 _SlReturnVal_t _SlDrvSyncObjSignal(_SlSyncObj_t *pSyncObj)
2659 {
2660  OSI_RET_OK_CHECK(sl_SyncObjSignal(pSyncObj));
2661  return SL_OS_RET_CODE_OK;
2662 }
2663 
2664 _SlReturnVal_t _SlDrvObjLockWaitForever(_SlLockObj_t *pLockObj)
2665 {
2666  OSI_RET_OK_CHECK(sl_LockObjLock(pLockObj, SL_OS_WAIT_FOREVER));
2667  return SL_OS_RET_CODE_OK;
2668 }
2669 
2670 _SlReturnVal_t _SlDrvProtectionObjLockWaitForever(void)
2671 {
2672  OSI_RET_OK_CHECK(sl_LockObjLock(&g_pCB->ProtectionLockObj, SL_OS_WAIT_FOREVER));
2673 
2674  return SL_OS_RET_CODE_OK;
2675 }
2676 
2677 _SlReturnVal_t _SlDrvObjUnLock(_SlLockObj_t *pLockObj)
2678 {
2679  OSI_RET_OK_CHECK(sl_LockObjUnlock(pLockObj));
2680 
2681  return SL_OS_RET_CODE_OK;
2682 }
2683 
2684 _SlReturnVal_t _SlDrvProtectionObjUnLock(void)
2685 {
2686  OSI_RET_OK_CHECK(sl_LockObjUnlock(&g_pCB->ProtectionLockObj));
2687  return SL_OS_RET_CODE_OK;
2688 }
2689 
2690 _SlReturnVal_t _SlDrvObjGlobalLockWaitForever(_u32 Flags)
2691 {
2692  _SlReturnVal_t ret;
2693  _u16 Opcode;
2694  _u16 Silo;
2695  _u8 UpdateApiInProgress = (Flags & GLOBAL_LOCK_FLAGS_UPDATE_API_IN_PROGRESS);
2696  _u16 IsProvStopApi = (Flags & GLOBAL_LOCK_FLAGS_PROVISIONING_STOP_API);
2697 
2698  if (SL_IS_RESTART_REQUIRED)
2699  {
2700  return SL_API_ABORTED;
2701  }
2702 
2703  gGlobalLockCntRequested++;
2704 
2705  ret = sl_LockObjLock(&GlobalLockObj, SL_OS_WAIT_FOREVER);
2706 
2707  /* start/stop device is in progress so return right away */
2708  if (SL_IS_DEVICE_START_IN_PROGRESS || SL_IS_DEVICE_STOP_IN_PROGRESS || SL_IS_PROVISIONING_IN_PROGRESS)
2709  {
2710  return ret;
2711  }
2712 
2713  /* after the lock acquired check if API is allowed */
2714  if (0 == ret)
2715  {
2716 
2717  Opcode = (Flags >> 16);
2718  Silo = Opcode & ((0xF << SL_OPCODE_SILO_OFFSET));
2719 
2720  /* After acquiring the lock, check if there is stop in progress */
2721  if (Opcode != SL_OPCODE_DEVICE_STOP_COMMAND)
2722  {
2723  _i16 Status = _SlDrvDriverIsApiAllowed(Silo);
2724 
2725  if (Status)
2726  {
2727  sl_LockObjUnlock(&GlobalLockObj);
2728  return Status;
2729  }
2730  }
2731  }
2732 
2733  /* if lock was successfully taken and increment of the API in progress is required */
2734  if ((0 == ret) && (UpdateApiInProgress))
2735  {
2736  if (!SL_IS_PROVISIONING_ACTIVE || SL_IS_PROVISIONING_API_ALLOWED)
2737  {
2738  /* Increment the API in progress counter */
2739  _SlDrvUpdateApiInProgress(API_IN_PROGRESS_UPDATE_INCREMENT);
2740  }
2741  /* if we are in provisioning than don't abort the stop provisioning cmd.. */
2742  else if (FALSE == IsProvStopApi )
2743  {
2744  /* Provisioning is active so release the lock immediately as
2745  we do not want to allow more APIs to run. */
2746  SL_DRV_LOCK_GLOBAL_UNLOCK(TRUE);
2747  return SL_RET_CODE_PROVISIONING_IN_PROGRESS;
2748  }
2749  }
2750 
2751  return ret;
2752 }
2753 _SlReturnVal_t _SlDrvGlobalObjUnLock(_u8 bDecrementApiInProgress)
2754 {
2755  gGlobalLockCntReleased++;
2756 
2757  OSI_RET_OK_CHECK(sl_LockObjUnlock(&GlobalLockObj));
2758 
2759  if (bDecrementApiInProgress)
2760  {
2761  _SlDrvUpdateApiInProgress(API_IN_PROGRESS_UPDATE_DECREMENT);
2762  }
2763 
2764  return SL_OS_RET_CODE_OK;
2765 }
2766 
2767 void _SlDrvMemZero(void* Addr, _u16 size)
2768 {
2769  sl_Memset(Addr, 0, size);
2770 }
2771 
2772 
2773 void _SlDrvResetCmdExt(_SlCmdExt_t* pCmdExt)
2774 {
2775  _SlDrvMemZero(pCmdExt, (_u16)sizeof (_SlCmdExt_t));
2776 }
2777 
2778 
2779 
2780 _SlReturnVal_t _SlDrvSyncObjWaitForever(_SlSyncObj_t *pSyncObj)
2781 {
2782  _SlReturnVal_t RetVal = sl_SyncObjWait(pSyncObj, SL_OS_WAIT_FOREVER);
2783 
2784  /* if the wait is finished and we detect that restart is required (we in the middle of error handling),
2785  than we should abort immediately from the current API command execution
2786  */
2787  if (SL_IS_RESTART_REQUIRED)
2788  {
2789  return SL_API_ABORTED;
2790  }
2791 
2792  return RetVal;
2793 }
2794 
2795 
2796 #if (defined(slcb_GetTimestamp))
2797 
2798 void _SlDrvStartMeasureTimeout(_SlTimeoutParams_t *pTimeoutInfo, _u32 TimeoutInMsec)
2799 {
2800  _SlDrvMemZero(pTimeoutInfo, sizeof (_SlTimeoutParams_t));
2801 
2802  pTimeoutInfo->Total10MSecUnits = TimeoutInMsec / 10;
2803  pTimeoutInfo->TSPrev = slcb_GetTimestamp();
2804 }
2805 
2806 _u8 _SlDrvIsTimeoutExpired(_SlTimeoutParams_t *pTimeoutInfo)
2807 {
2808  _u32 TSCount;
2809 
2810  pTimeoutInfo->TSCurr = slcb_GetTimestamp();
2811 
2812  if (pTimeoutInfo->TSCurr >= pTimeoutInfo->TSPrev)
2813  {
2814  pTimeoutInfo->DeltaTicks = pTimeoutInfo->TSCurr - pTimeoutInfo->TSPrev;
2815  }
2816  else
2817  {
2818  pTimeoutInfo->DeltaTicks = (SL_TIMESTAMP_MAX_VALUE - pTimeoutInfo->TSPrev) + pTimeoutInfo->TSCurr;
2819  }
2820 
2821  TSCount = pTimeoutInfo->DeltaTicksReminder + pTimeoutInfo->DeltaTicks;
2822 
2823 
2824  if (TSCount > SL_TIMESTAMP_TICKS_IN_10_MILLISECONDS)
2825  {
2826  pTimeoutInfo->Total10MSecUnits -= (TSCount / SL_TIMESTAMP_TICKS_IN_10_MILLISECONDS);
2827  pTimeoutInfo->DeltaTicksReminder = TSCount % SL_TIMESTAMP_TICKS_IN_10_MILLISECONDS;
2828 
2829  if (pTimeoutInfo->Total10MSecUnits > 0)
2830  {
2831  pTimeoutInfo->TSPrev = pTimeoutInfo->TSCurr;
2832  }
2833  else
2834  {
2835  return TRUE;
2836  }
2837  }
2838 
2839  return FALSE;
2840 }
2841 
2842 #endif
2843 
2844 void _SlDrvHandleFatalError(_u32 errorId, _u32 info1, _u32 info2)
2845 {
2846  _u8 i;
2847  SlDeviceFatal_t FatalEvent;
2848 
2849  _SlDrvMemZero(&FatalEvent, sizeof(FatalEvent));
2850 
2851  if (SL_IS_RESTART_REQUIRED)
2852  {
2853  return;
2854  }
2855 
2856  /* set the restart flag */
2857  SL_SET_RESTART_REQUIRED;
2858 
2859  /* Upon the deletion of the mutex, all thread waiting on this
2860  mutex will return immediately with an error (i.e. MUTEX_DELETED status) */
2861  (void)sl_LockObjDelete(&GlobalLockObj);
2862 
2863  /* Mark the global lock as deleted */
2864  SL_UNSET_GLOBAL_LOCK_INIT;
2865 
2866  /* signal all waiting sync objects */
2867  for (i=0; i< MAX_CONCURRENT_ACTIONS; i++)
2868  {
2869  SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[i].SyncObj);
2870  }
2871 
2872  /* prepare the event and notify the user app/ext libraries */
2873  FatalEvent.Id = errorId;
2874 
2875  switch (errorId)
2876  {
2877  case SL_DEVICE_EVENT_FATAL_DEVICE_ABORT:
2878  {
2879  /* set the Abort Type */
2880  FatalEvent.Data.DeviceAssert.Code = info1;
2881 
2882  /* set the Abort Data */
2883  FatalEvent.Data.DeviceAssert.Value = info2;
2884  }
2885  break;
2886 
2887  case SL_DEVICE_EVENT_FATAL_NO_CMD_ACK:
2888  {
2889  /* set the command opcode */
2890  FatalEvent.Data.NoCmdAck.Code = info1;
2891  }
2892  break;
2893 
2894  case SL_DEVICE_EVENT_FATAL_CMD_TIMEOUT:
2895  {
2896  /* set the expected async event opcode */
2897  FatalEvent.Data.CmdTimeout.Code = info1;
2898  }
2899  break;
2900 
2901  case SL_DEVICE_EVENT_FATAL_SYNC_LOSS:
2902  case SL_DEVICE_EVENT_FATAL_DRIVER_ABORT:
2903  /* No Info to transport */
2904  break;
2905 
2906  }
2907 
2908 #if defined(slcb_DeviceFatalErrorEvtHdlr) || defined (EXT_LIB_REGISTERED_FATAL_ERROR_EVENTS)
2909  /* call the registered fatal error handlers */
2910  _SlDrvHandleFatalErrorEvents(&FatalEvent);
2911 #endif
2912 }
2913 
2914 _SlReturnVal_t _SlDrvSyncObjWaitTimeout(_SlSyncObj_t *pSyncObj, _u32 timeoutVal, _u32 asyncEventOpcode)
2915 {
2916  _SlReturnVal_t ret = sl_SyncObjWait(pSyncObj, timeoutVal);
2917 
2918  /* if timeout occured...*/
2919  if (ret)
2920  {
2921  _SlDrvHandleFatalError(SL_DEVICE_EVENT_FATAL_CMD_TIMEOUT, asyncEventOpcode, timeoutVal);
2922  return SL_API_ABORTED;
2923  }
2924  else if (SL_IS_RESTART_REQUIRED)
2925  {
2926  return SL_API_ABORTED;
2927  }
2928 
2929  return SL_RET_CODE_OK;
2930 }
2931 
2932 
2933 static void _SlDrvUpdateApiInProgress(_i8 Value)
2934 {
2935  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
2936 
2937  g_pCB->ApiInProgressCnt += Value;
2938 
2939  SL_DRV_PROTECTION_OBJ_UNLOCK();
2940 }
2941 
2942 _i8 _SlDrvIsApiInProgress(void)
2943 {
2944  if (g_pCB != NULL)
2945  {
2946  return (g_pCB->ApiInProgressCnt > 0);
2947  }
2948 
2949  return TRUE;
2950 }
2951 
2952 
2953 #ifdef slcb_GetTimestamp
2954 
2955 void _SlDrvSleep(_u16 DurationInMsec)
2956 {
2957  _SlTimeoutParams_t TimeoutInfo={0};
2958 
2959  _SlDrvStartMeasureTimeout(&TimeoutInfo, DurationInMsec);
2960 
2961  while(!_SlDrvIsTimeoutExpired(&TimeoutInfo));
2962 }
2963 #endif
2964 
2965 #ifndef SL_PLATFORM_MULTI_THREADED
2966 void _SlDrvSetGlobalLockOwner(_u8 Owner)
2967 {
2968  gGlobalLockContextOwner = Owner;
2969 }
2970 #endif
2971 
2972 
2973 _SlReturnVal_t _SlDrvWaitForInternalAsyncEvent(_u8 ObjIdx , _u32 Timeout, _SlOpcode_t Opcode)
2974 {
2975 
2976 #if (defined(SL_PLATFORM_EXTERNAL_SPAWN) || !defined(SL_PLATFORM_MULTI_THREADED))
2977  SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->ObjPool[ObjIdx].SyncObj);
2978  return SL_OS_RET_CODE_OK;
2979 #else
2980  _SlTimeoutParams_t SlTimeoutInfo = { 0 };
2981  if (_SlDrvIsSpawnOwnGlobalLock())
2982  {
2983 #if (defined(slcb_GetTimestamp))
2984  _SlDrvStartMeasureTimeout(&SlTimeoutInfo, Timeout);
2985  while (!Timeout || !_SlDrvIsTimeoutExpired(&SlTimeoutInfo))
2986 #endif
2987  {
2988  /* If we are in spawn context, this is an API which was called from event handler,
2989  read any async event and check if we got signaled */
2990  _SlInternalSpawnWaitForEvent();
2991  /* is it mine? */
2992  if (0 == sl_SyncObjWait(&g_pCB->ObjPool[ObjIdx].SyncObj, SL_OS_NO_WAIT))
2993  {
2994  return SL_OS_RET_CODE_OK;
2995  }
2996  }
2997  /* if timeout occured...*/
2998  _SlDrvHandleFatalError(SL_DEVICE_EVENT_FATAL_CMD_TIMEOUT, Opcode, Timeout);
2999  return SL_API_ABORTED;
3000  }
3001  else
3002  {
3003  if (Timeout)
3004  {
3005  SL_DRV_SYNC_OBJ_WAIT_TIMEOUT(&g_pCB->ObjPool[ObjIdx].SyncObj, Timeout, Opcode);
3006  }
3007  else
3008  {
3009  SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->ObjPool[ObjIdx].SyncObj);
3010  }
3011  return SL_OS_RET_CODE_OK;
3012  }
3013 
3014 #endif
3015 }
3016 
3017 #if (defined(SL_PLATFORM_MULTI_THREADED) && !defined(SL_MEMORY_MGMT_DYNAMIC))
3018 _SlAsyncRespBuf_t* _SlGetStatSpawnListItem(_u16 AsyncEventLen)
3019 {
3020  _u8 Idx = 0;
3021  /* Find free buffer from the pool */
3022  while (Idx < SL_MAX_ASYNC_BUFFERS)
3023  {
3024  if (0xFF == g_StatMem.AsyncBufPool[Idx].ActionIndex)
3025  {
3026  /* copy buffer */
3027  return &g_StatMem.AsyncBufPool[Idx];
3028  }
3029  Idx++;
3030  }
3031  return NULL;
3032 }
3033 #endif
3034 
3035 #if defined(SL_PLATFORM_MULTI_THREADED)
3036 _SlReturnVal_t _SlSpawnMsgListInsert(_u16 AsyncEventLen, _u8 *pAsyncBuf)
3037 {
3038  _SlReturnVal_t RetVal = SL_OS_RET_CODE_OK;
3039 
3040  /* protect the item insertion */
3041  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
3042 
3043 #ifdef SL_MEMORY_MGMT_DYNAMIC
3044  _SlSpawnMsgItem_t* pCurr = NULL;
3045  _SlSpawnMsgItem_t* pItem;
3046 
3047  pItem = (_SlSpawnMsgItem_t*)sl_Malloc(sizeof(_SlSpawnMsgItem_t));
3048  if (pItem == NULL)
3049  {
3050  RetVal = SL_RET_CODE_NO_FREE_ASYNC_BUFFERS_ERROR;
3051  SL_DRV_PROTECTION_OBJ_UNLOCK();
3052  return RetVal;
3053  }
3054  /* now allocate the buffer itself */
3055  pItem->Buffer = (void*)sl_Malloc(AsyncEventLen);
3056  if (pItem->Buffer == NULL)
3057  {
3058  sl_Free(pItem);
3059  RetVal = SL_RET_CODE_NO_FREE_ASYNC_BUFFERS_ERROR;
3060  SL_DRV_PROTECTION_OBJ_UNLOCK();
3061  return RetVal;
3062  }
3063  pItem->next = NULL;
3064  /* if list is empty point to the allocated one */
3065  if (g_pCB->spawnMsgList == NULL)
3066  {
3067  g_pCB->spawnMsgList = pItem;
3068  }
3069  else
3070  {
3071  pCurr = g_pCB->spawnMsgList;
3072  /* go to end of list */
3073  while (pCurr->next != NULL)
3074  {
3075  pCurr = pCurr->next;
3076  }
3077  /* we point to last item in list - add the new one */
3078  pCurr->next = pItem;
3079  }
3080 #else
3081  _SlAsyncRespBuf_t* pItem = (_SlAsyncRespBuf_t*)_SlGetStatSpawnListItem(AsyncEventLen);
3082 #endif
3083  if ((NULL != pItem) && (NULL != pItem->Buffer))
3084  {
3085  /* save the action idx */
3086  pItem->ActionIndex = g_pCB->FunctionParams.AsyncExt.ActionIndex;
3087  /* save the corresponding AsyncHndlr (if registered) */
3088  pItem->AsyncHndlr = g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler;
3089  /* copy the async event that we read to the buffer */
3090  sl_Memcpy(pItem->Buffer, pAsyncBuf, AsyncEventLen);
3091  }
3092  else
3093  {
3094  RetVal = SL_RET_CODE_NO_FREE_ASYNC_BUFFERS_ERROR;
3095  }
3096  SL_DRV_PROTECTION_OBJ_UNLOCK();
3097  return RetVal;
3098 }
3099 
3100 _SlReturnVal_t _SlSpawnMsgListProcess()
3101 {
3102 
3103 #ifdef SL_MEMORY_MGMT_DYNAMIC
3104  _SlSpawnMsgItem_t* pHead = g_pCB->spawnMsgList;
3105  _SlSpawnMsgItem_t* pCurr = pHead;
3106  _SlSpawnMsgItem_t* pLast = pHead;
3107 
3108  while (pCurr != NULL)
3109  {
3110  /* lock during action */
3111  SL_DRV_LOCK_GLOBAL_LOCK_FOREVER(GLOBAL_LOCK_FLAGS_NONE);
3112  /* load the async event params */
3113  g_pCB->FunctionParams.AsyncExt.ActionIndex = pCurr->ActionIndex;
3114  g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler = pCurr->AsyncHndlr;
3115 
3116  pLast = pCurr;
3117  pCurr = pCurr->next;
3118 
3119  /* move the list head to point to the next item (or null) */
3120  g_pCB->spawnMsgList = pCurr;
3121  /* Handle async event: here we are in spawn context, after context
3122  * switch from command context. */
3123  _SlDrvAsyncEventGenericHandler(FALSE, pLast->Buffer);
3124 
3125  /* free the copied buffer inside the item */
3126  sl_Free(pLast->Buffer);
3127 
3128  /* free the spawn msg item */
3129  sl_Free(pLast);
3130 
3131  SL_DRV_LOCK_GLOBAL_UNLOCK(FALSE);
3132  }
3133 
3134 #else
3135  _u8 i;
3136 
3137  for (i = 0; i < SL_MAX_ASYNC_BUFFERS; i++)
3138  {
3139  if (0xFF != g_StatMem.AsyncBufPool[i].ActionIndex)
3140  {
3141  /* lock during action */
3142 
3143  SL_DRV_LOCK_GLOBAL_LOCK_FOREVER(GLOBAL_LOCK_FLAGS_NONE);
3144 
3145  /* load the async event params */
3146  g_pCB->FunctionParams.AsyncExt.ActionIndex = g_StatMem.AsyncBufPool[i].ActionIndex;
3147  g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler = g_StatMem.AsyncBufPool[i].AsyncHndlr;
3148 
3149  /* Handle async event: here we are in spawn context, after context
3150  * switch from command context. */
3151  _SlDrvAsyncEventGenericHandler(FALSE, (unsigned char *)&(g_StatMem.AsyncBufPool[i].Buffer));
3152 
3153  SL_DRV_LOCK_GLOBAL_UNLOCK(FALSE);
3154 
3155  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
3156  g_StatMem.AsyncBufPool[i].ActionIndex = 0xFF;
3157  SL_DRV_PROTECTION_OBJ_UNLOCK();
3158  }
3159  }
3160 #endif
3161  return SL_OS_RET_CODE_OK;
3162 }
3163 
3164 _u16 _SlSpawnMsgListGetCount()
3165 {
3166  _u16 NumOfItems = 0;
3167 #ifdef SL_MEMORY_MGMT_DYNAMIC
3168  _SlSpawnMsgItem_t* pCurr = g_pCB->spawnMsgList;
3169 
3170  /* protect the item insertion */
3171  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
3172  while (pCurr != NULL)
3173  {
3174  NumOfItems++;
3175 
3176  pCurr = pCurr->next;
3177  }
3178  SL_DRV_PROTECTION_OBJ_UNLOCK();
3179 
3180 #else
3181  _u8 i;
3182  /* protect counting parameters */
3183  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
3184 
3185  for (i = 0; i < SL_MAX_ASYNC_BUFFERS; i++)
3186  {
3187  if (0xFF != g_StatMem.AsyncBufPool[i].ActionIndex)
3188  {
3189  NumOfItems++;
3190  }
3191  }
3192  SL_DRV_PROTECTION_OBJ_UNLOCK();
3193 #endif
3194  return NumOfItems;
3195 }
3196 
3197 
3198 void _SlFindAndReleasePendingCmd()
3199 {
3200  if(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs != NULL)
3201  {
3202  /* In case there is no free buffer to store the async event until context switch release the command and return specific error */
3203  ((SlSocketResponse_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->StatusOrLen = SL_RET_CODE_NO_FREE_ASYNC_BUFFERS_ERROR;
3204  /* signal pending cmd */
3205  SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
3206  }
3207 }
3208 #endif
void slcb_NetAppRequestHdlr(SlNetAppRequest_t *pNetAppRequest, SlNetAppResponse_t *pNetAppResponse)
General netapp async event.
void slcb_DeviceFatalErrorEvtHdlr(SlDeviceFatal_t *pSlFatalErrorEvent)
Fatal Error event for inspecting fatal error.
void slcb_SockEvtHdlr(SlSockEvent_t *pSlSockEvent)
Socket Async event handler.
_u32 slcb_GetTimestamp(void)
Get the timer counter value (timestamp). The timer must count from zero to its MAX value...
void slcb_WlanEvtHdlr(SlWlanEvent_t *pSlWlanEvent)
WLAN Async event handler.
void slcb_NetAppEvtHdlr(SlNetAppEvent_t *pSlNetAppEvent)
NETAPP Async event handler.
void slcb_NetAppHttpServerHdlr(SlNetAppHttpServerEvent_t *pSlHttpServerEvent, SlNetAppHttpServerResponse_t *pSlHttpServerResponse)
HTTP server async event.
void slcb_DeviceGeneralEvtHdlr(SlDeviceEvent_t *pSlDeviceEvent)
General async event for inspecting general events.