1 /*
2  * driver.c - CC31xx/CC32xx Host Driver Implementation
3  *
4  * Copyright (C) 2017 Texas Instruments Incorporated - http://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 *********************************************************************/
_SlDrvHandleGeneralEvents(SlDeviceEvent_t * slGeneralEvent)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 ************************************************************/
_SlDrvHandleWlanEvents(SlWlanEvent_t * slWlanEvent)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 ************************************************************/
_SlDrvHandleNetAppEvents(SlNetAppEvent_t * slNetAppEvent)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 ********************************************************************/
_SlDrvHandleHttpServerEvents(SlNetAppHttpServerEvent_t * slHttpServerEvent,SlNetAppHttpServerResponse_t * slHttpServerResponse)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 **************************************************************/
_SlDrvHandleSockEvents(SlSockEvent_t * slSockEvent)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 *********************************************************************/
_SlDrvHandleFatalErrorEvents(SlDeviceFatal_t * slFatalErrorEvent)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 *********************************************************************/
_SlDrvHandleNetAppRequestEvents(SlNetAppRequest_t * pNetAppRequest,SlNetAppResponse_t * pNetAppResponse)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 
_SlDrvDriverCBInit(void)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 *****************************************************************************/
_SlDrvDriverCBDeinit(void)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     /* Clear the restart device flag  */
742     SL_UNSET_RESTART_REQUIRED;
743 
744     return SL_OS_RET_CODE_OK;
745 }
746 
747 /*****************************************************************************
748 _SlDrvRxIrqHandler - Interrupt handler
749 *****************************************************************************/
_SlDrvRxIrqHandler(void * pValue)750 _SlReturnVal_t _SlDrvRxIrqHandler(void *pValue)
751 {
752     (void)pValue;
753 
754     sl_IfMaskIntHdlr();
755 
756     RxIrqCnt++;
757 
758     if (TRUE == g_pCB->WaitForCmdResp)
759     {
760         OSI_RET_OK_CHECK( sl_SyncObjSignalFromIRQ(&g_pCB->CmdSyncObj) );
761     }
762     else
763     {
764         (void)sl_Spawn((_SlSpawnEntryFunc_t)_SlDrvMsgReadSpawnCtx, NULL, SL_SPAWN_FLAG_FROM_SL_IRQ_HANDLER);
765     }
766     return SL_OS_RET_CODE_OK;
767 }
768 
769 /*****************************************************************************
770 _SlDrvDriverIsApiAllowed - on LOCKED state, only 3 commands are allowed
771 *****************************************************************************/
_SlDrvDriverIsApiAllowed(_u16 Silo)772 _SlReturnVal_t _SlDrvDriverIsApiAllowed(_u16 Silo)
773 {
774     if (!SL_IS_COMMAND_ALLOWED)
775     {
776         if (SL_IS_DEVICE_STOP_IN_PROGRESS)
777         {
778             return SL_RET_CODE_STOP_IN_PROGRESS;
779         }
780 
781         if ((SL_IS_DEVICE_LOCKED) && (SL_OPCODE_SILO_FS != Silo))
782         {
783             /* All APIs except the FS ones must be aborted if device is locked */
784             return SL_RET_CODE_DEV_LOCKED;
785         }
786         if (SL_IS_RESTART_REQUIRED)
787         {
788             /* API has been aborted due command not allowed when Restart required */
789             /* The opcodes allowed are: SL_OPCODE_DEVICE_STOP_COMMAND */
790             return SL_API_ABORTED;
791         }
792 
793         if (!SL_IS_DEVICE_STARTED)
794         {
795             return SL_RET_CODE_DEV_NOT_STARTED;
796         }
797 
798         if (( SL_IS_PROVISIONING_ACTIVE || SL_IS_PROVISIONING_INITIATED_BY_USER) && !(SL_IS_PROVISIONING_API_ALLOWED))
799         {
800             /* API has ignored due to provisioning in progress */
801             return SL_RET_CODE_PROVISIONING_IN_PROGRESS;
802         }
803 
804     }
805 
806     return SL_OS_RET_CODE_OK;
807 }
808 
809 
810 /*****************************************************************************
811 _SlDrvCmdOp
812 *****************************************************************************/
_SlDrvCmdOp(_SlCmdCtrl_t * pCmdCtrl,void * pTxRxDescBuff,_SlCmdExt_t * pCmdExt)813 _SlReturnVal_t _SlDrvCmdOp(
814     _SlCmdCtrl_t  *pCmdCtrl ,
815     void          *pTxRxDescBuff ,
816     _SlCmdExt_t   *pCmdExt)
817 {
818     _SlReturnVal_t RetVal;
819     _u8 IsLockRequired = TRUE;
820 
821     IsLockRequired = (SL_IS_PROVISIONING_IN_PROGRESS && (pCmdCtrl->Opcode == SL_OPCODE_DEVICE_STOP_COMMAND)) ? FALSE: TRUE;
822 
823     if (IsLockRequired)
824     {
825         _u32 GlobalLockFlags = GLOBAL_LOCK_FLAGS_UPDATE_API_IN_PROGRESS;
826 
827         /* check the special case of provisioning stop command */
828         if (pCmdCtrl->Opcode == SL_OPCODE_WLAN_PROVISIONING_COMMAND)
829         {
830             SlWlanProvisioningParams_t *pParams = (SlWlanProvisioningParams_t *)pTxRxDescBuff;
831 
832             /* No timeout specifies it is a stop provisioning command */
833             if (pParams->InactivityTimeoutSec == 0)
834             {
835                 GlobalLockFlags |= GLOBAL_LOCK_FLAGS_PROVISIONING_STOP_API;
836             }
837 
838         }
839 
840         GlobalLockFlags |= (((_u32)pCmdCtrl->Opcode) << 16);
841         SL_DRV_LOCK_GLOBAL_LOCK_FOREVER(GlobalLockFlags);
842     }
843 
844     /* In case the global was successfully taken but error in progress
845     it means it has been released as part of an error handling and we should abort immediately */
846     if (SL_IS_RESTART_REQUIRED)
847     {
848           if (IsLockRequired)
849           {
850               SL_DRV_LOCK_GLOBAL_UNLOCK(TRUE);
851           }
852 
853           return SL_API_ABORTED;
854     }
855 
856     g_pCB->WaitForCmdResp = TRUE;
857 
858     SL_TRACE1(DBG_MSG, MSG_312, "\n\r_SlDrvCmdOp: call _SlDrvMsgWrite: %x\n\r", pCmdCtrl->Opcode);
859 
860     /* send the message */
861     RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, pTxRxDescBuff);
862 
863     if(SL_OS_RET_CODE_OK == RetVal)
864     {
865         /* wait for respond */
866         RetVal = _SlDrvMsgReadCmdCtx(pCmdCtrl->Opcode, IsLockRequired); /* will free global lock */
867         SL_TRACE1(DBG_MSG, MSG_314, "\n\r_SlDrvCmdOp: exited _SlDrvMsgReadCmdCtx: %x\n\r", pCmdCtrl->Opcode);
868     }
869     else
870     {
871         if (IsLockRequired)
872         {
873             SL_DRV_LOCK_GLOBAL_UNLOCK(TRUE);
874         }
875 
876     }
877 
878     return RetVal;
879 }
880 
881 /*****************************************************************************
882 _SlDrvDataReadOp
883 *****************************************************************************/
_SlDrvDataReadOp(_SlSd_t Sd,_SlCmdCtrl_t * pCmdCtrl,void * pTxRxDescBuff,_SlCmdExt_t * pCmdExt)884 _SlReturnVal_t _SlDrvDataReadOp(
885     _SlSd_t             Sd,
886     _SlCmdCtrl_t        *pCmdCtrl ,
887     void                *pTxRxDescBuff ,
888     _SlCmdExt_t         *pCmdExt)
889 {
890     _SlReturnVal_t RetVal;
891     _i16 ObjIdx = MAX_CONCURRENT_ACTIONS;
892     _SlArgsData_t pArgsData;
893 
894     /* Validate input arguments */
895     _SL_ASSERT_ERROR(NULL != pCmdExt->pRxPayload, SL_RET_CODE_INVALID_INPUT);
896 
897     /* If zero bytes is requested, return error. */
898     /* This allows us not to fill remote socket's IP address in return arguments */
899     VERIFY_PROTOCOL(0 != pCmdExt->RxPayloadLen);
900 
901     /* Validate socket */
902     if((Sd & SL_BSD_SOCKET_ID_MASK) >= SL_MAX_SOCKETS)
903     {
904         return SL_ERROR_BSD_EBADF;
905     }
906 
907     /*Use Obj to issue the command, if not available try later*/
908     ObjIdx = _SlDrvWaitForPoolObj(RECV_ID, Sd & SL_BSD_SOCKET_ID_MASK);
909 
910     if (MAX_CONCURRENT_ACTIONS == ObjIdx)
911     {
912         return SL_POOL_IS_EMPTY;
913     }
914     if (SL_RET_CODE_STOP_IN_PROGRESS == ObjIdx)
915     {
916         return SL_RET_CODE_STOP_IN_PROGRESS;
917     }
918 
919     SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
920 
921     pArgsData.pData = pCmdExt->pRxPayload;
922     pArgsData.pArgs =  (_u8 *)pTxRxDescBuff;
923     g_pCB->ObjPool[ObjIdx].pRespArgs =  (_u8 *)&pArgsData;
924 
925     SL_DRV_PROTECTION_OBJ_UNLOCK();
926 
927 
928     /* Do Flow Control check/update for DataWrite operation */
929     SL_DRV_OBJ_LOCK_FOREVER(&g_pCB->FlowContCB.TxLockObj);
930 
931 
932     /* Clear SyncObj for the case it was signaled before TxPoolCnt */
933     /* dropped below '1' (last Data buffer was taken)  */
934     /* OSI_RET_OK_CHECK( sl_SyncObjClear(&g_pCB->FlowContCB.TxSyncObj) ); */
935     SL_DRV_SYNC_OBJ_CLEAR(&g_pCB->FlowContCB.TxSyncObj);
936 
937     if(g_pCB->FlowContCB.TxPoolCnt <= FLOW_CONT_MIN)
938     {
939 
940         /* If TxPoolCnt was increased by other thread at this moment,
941                  TxSyncObj won't wait here */
942 #if (defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))
943         if (_SlDrvIsSpawnOwnGlobalLock())
944         {
945             while (TRUE)
946             {
947                 /* If we are in spawn context, this is an API which was called from event handler,
948                 read any async event and check if we got signaled */
949                 _SlInternalSpawnWaitForEvent();
950                 /* is it mine? */
951                 if (0 == sl_SyncObjWait(&g_pCB->FlowContCB.TxSyncObj, SL_OS_NO_WAIT))
952                 {
953                     break;
954                 }
955             }
956         }
957         else
958 #endif
959         {
960             SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->FlowContCB.TxSyncObj);
961         }
962 
963     }
964 
965     SL_DRV_LOCK_GLOBAL_LOCK_FOREVER(GLOBAL_LOCK_FLAGS_UPDATE_API_IN_PROGRESS);
966 
967     /* In case the global was successfully taken but error in progress
968     it means it has been released as part of an error handling and we should abort immediately */
969     if (SL_IS_RESTART_REQUIRED)
970     {
971         SL_DRV_LOCK_GLOBAL_UNLOCK(TRUE);
972         return SL_API_ABORTED;
973     }
974 
975     /* Here we consider the case in which some cmd has been sent to the NWP,
976        And its allocated packet has not been freed yet. */
977     VERIFY_PROTOCOL(g_pCB->FlowContCB.TxPoolCnt > (FLOW_CONT_MIN - 1));
978     g_pCB->FlowContCB.TxPoolCnt--;
979 
980     SL_DRV_OBJ_UNLOCK(&g_pCB->FlowContCB.TxLockObj);
981 
982     /* send the message */
983     RetVal =  _SlDrvMsgWrite(pCmdCtrl, pCmdExt, (_u8 *)pTxRxDescBuff);
984 
985     SL_DRV_LOCK_GLOBAL_UNLOCK(TRUE);
986 
987     if(SL_OS_RET_CODE_OK == RetVal)
988     {
989         /* in case socket is non-blocking one, the async event should be received immediately */
990         if( g_pCB->SocketNonBlocking & (1<<(Sd & SL_BSD_SOCKET_ID_MASK) ))
991         {
992              _u16 opcodeAsyncEvent = (pCmdCtrl->Opcode ==  SL_OPCODE_SOCKET_RECV) ? SL_OPCODE_SOCKET_RECVASYNCRESPONSE : SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE;
993              RetVal = _SlDrvWaitForInternalAsyncEvent(ObjIdx, SL_DRIVER_TIMEOUT_SHORT, opcodeAsyncEvent);
994 
995         }
996         else
997         {
998             /* Wait for response message. Will be signaled by _SlDrvMsgRead. */
999             RetVal = _SlDrvWaitForInternalAsyncEvent(ObjIdx, 0, 0);
1000         }
1001 
1002     }
1003 
1004     _SlDrvReleasePoolObj(ObjIdx);
1005     return RetVal;
1006 }
1007 
1008 /* ******************************************************************************/
1009 /*   _SlDrvDataWriteOp                                                          */
1010 /* ******************************************************************************/
_SlDrvDataWriteOp(_SlSd_t Sd,_SlCmdCtrl_t * pCmdCtrl,void * pTxRxDescBuff,_SlCmdExt_t * pCmdExt)1011 _SlReturnVal_t _SlDrvDataWriteOp(
1012     _SlSd_t             Sd,
1013     _SlCmdCtrl_t  *pCmdCtrl ,
1014     void                *pTxRxDescBuff ,
1015     _SlCmdExt_t         *pCmdExt)
1016 {
1017     _SlReturnVal_t  RetVal = SL_ERROR_BSD_EAGAIN; /*  initiated as SL_EAGAIN for the non blocking mode */
1018     _u32 allocTxPoolPkts;
1019 
1020     while( 1 )
1021     {
1022         /*  Do Flow Control check/update for DataWrite operation */
1023         SL_DRV_OBJ_LOCK_FOREVER(&g_pCB->FlowContCB.TxLockObj);
1024 
1025         /*  Clear SyncObj for the case it was signaled before TxPoolCnt */
1026         /*  dropped below '1' (last Data buffer was taken) */
1027         /* OSI_RET_OK_CHECK( sl_SyncObjClear(&g_pCB->FlowContCB.TxSyncObj) ); */
1028         SL_DRV_SYNC_OBJ_CLEAR(&g_pCB->FlowContCB.TxSyncObj);
1029 
1030         /*  number of tx pool packet that will be used */
1031         allocTxPoolPkts = 1 + (pCmdExt->TxPayload1Len-1) / g_pCB->FlowContCB.MinTxPayloadSize; /* MinTxPayloadSize will be updated by Asunc event from NWP */
1032         /*  we have indication that the last send has failed - socket is no longer valid for operations  */
1033         if(g_pCB->SocketTXFailure & (1<<(Sd & SL_BSD_SOCKET_ID_MASK)))
1034         {
1035             SL_DRV_OBJ_UNLOCK(&g_pCB->FlowContCB.TxLockObj);
1036             return SL_ERROR_BSD_SOC_ERROR;
1037         }
1038         if(g_pCB->FlowContCB.TxPoolCnt <= FLOW_CONT_MIN + allocTxPoolPkts)
1039         {
1040             /*  we have indication that this socket is set as blocking and we try to  */
1041             /*  unblock it - return an error */
1042             if( g_pCB->SocketNonBlocking & (1<<(Sd & SL_BSD_SOCKET_ID_MASK) ))
1043             {
1044 #if (defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))
1045                 if (_SlDrvIsSpawnOwnGlobalLock())
1046                 {
1047                     _SlInternalSpawnWaitForEvent();
1048                 }
1049 #endif
1050                 SL_DRV_OBJ_UNLOCK(&g_pCB->FlowContCB.TxLockObj);
1051                 return RetVal;
1052             }
1053             /*  If TxPoolCnt was increased by other thread at this moment, */
1054             /*  TxSyncObj won't wait here */
1055 #if (defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))
1056             if (_SlDrvIsSpawnOwnGlobalLock())
1057             {
1058                 while (TRUE)
1059                 {
1060                     /* If we are in spawn context, this is an API which was called from event handler,
1061                     read any async event and check if we got signaled */
1062                     _SlInternalSpawnWaitForEvent();
1063                     /* is it mine? */
1064                     if (0 == sl_SyncObjWait(&g_pCB->FlowContCB.TxSyncObj, SL_OS_NO_WAIT))
1065                     {
1066                        break;
1067                     }
1068                 }
1069             }
1070             else
1071 #endif
1072             {
1073                 SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->FlowContCB.TxSyncObj);
1074             }
1075         }
1076         if(g_pCB->FlowContCB.TxPoolCnt > FLOW_CONT_MIN + allocTxPoolPkts )
1077         {
1078             break;
1079         }
1080         else
1081         {
1082             SL_DRV_OBJ_UNLOCK(&g_pCB->FlowContCB.TxLockObj);
1083         }
1084     }
1085 
1086     SL_DRV_LOCK_GLOBAL_LOCK_FOREVER(GLOBAL_LOCK_FLAGS_UPDATE_API_IN_PROGRESS);
1087 
1088     /* In case the global was succesffully taken but error in progress
1089     it means it has been released as part of an error handling and we should abort immediately */
1090     if (SL_IS_RESTART_REQUIRED)
1091     {
1092         SL_DRV_LOCK_GLOBAL_UNLOCK(TRUE);
1093         return SL_API_ABORTED;
1094     }
1095 
1096     /* Here we consider the case in which some cmd has been sent to the NWP,
1097     And its allocated packet has not been freed yet. */
1098     VERIFY_PROTOCOL(g_pCB->FlowContCB.TxPoolCnt > (FLOW_CONT_MIN + allocTxPoolPkts -1) );
1099     g_pCB->FlowContCB.TxPoolCnt -= (_u8)allocTxPoolPkts;
1100 
1101     SL_DRV_OBJ_UNLOCK(&g_pCB->FlowContCB.TxLockObj);
1102 
1103     SL_TRACE1(DBG_MSG, MSG_312, "\n\r_SlDrvCmdOp: call _SlDrvMsgWrite: %x\n\r", pCmdCtrl->Opcode);
1104 
1105     /* send the message */
1106     RetVal =  _SlDrvMsgWrite(pCmdCtrl, pCmdExt, pTxRxDescBuff);
1107     SL_DRV_LOCK_GLOBAL_UNLOCK(TRUE);
1108 
1109     return RetVal;
1110 }
1111 
1112 /* ******************************************************************************/
1113 /*  _SlDrvMsgWrite */
1114 /* ******************************************************************************/
_SlDrvMsgWrite(_SlCmdCtrl_t * pCmdCtrl,_SlCmdExt_t * pCmdExt,_u8 * pTxRxDescBuff)1115 static _SlReturnVal_t _SlDrvMsgWrite(_SlCmdCtrl_t  *pCmdCtrl,_SlCmdExt_t  *pCmdExt, _u8 *pTxRxDescBuff)
1116 {
1117     _u8 sendRxPayload = FALSE;
1118     _SL_ASSERT_ERROR(NULL != pCmdCtrl, SL_API_ABORTED);
1119 
1120     g_pCB->FunctionParams.pCmdCtrl = pCmdCtrl;
1121     g_pCB->FunctionParams.pTxRxDescBuff = pTxRxDescBuff;
1122     g_pCB->FunctionParams.pCmdExt = pCmdExt;
1123 
1124     g_pCB->TempProtocolHeader.Opcode   = pCmdCtrl->Opcode;
1125     g_pCB->TempProtocolHeader.Len   = (_u16)(_SL_PROTOCOL_CALC_LEN(pCmdCtrl, pCmdExt));
1126 
1127     if (pCmdExt && pCmdExt->RxPayloadLen < 0 )
1128     {
1129         pCmdExt->RxPayloadLen = pCmdExt->RxPayloadLen * (-1); /* change sign */
1130         sendRxPayload = TRUE;
1131         g_pCB->TempProtocolHeader.Len = g_pCB->TempProtocolHeader.Len + pCmdExt->RxPayloadLen;
1132     }
1133 
1134 #ifdef SL_START_WRITE_STAT
1135     sl_IfStartWriteSequence(g_pCB->FD);
1136 #endif
1137 
1138 #ifdef SL_IF_TYPE_UART
1139     /*  Write long sync pattern */
1140     NWP_IF_WRITE_CHECK(g_pCB->FD, (_u8 *)&g_H2NSyncPattern.Long, 2*SYNC_PATTERN_LEN);
1141 #else
1142     /*  Write short sync pattern */
1143     NWP_IF_WRITE_CHECK(g_pCB->FD, (_u8 *)&g_H2NSyncPattern.Short, SYNC_PATTERN_LEN);
1144 #endif
1145 
1146     /*  Header */
1147     NWP_IF_WRITE_CHECK(g_pCB->FD, (_u8 *)&g_pCB->TempProtocolHeader, _SL_CMD_HDR_SIZE);
1148 
1149     /*  Descriptors */
1150     if (pTxRxDescBuff && pCmdCtrl->TxDescLen > 0)
1151     {
1152         NWP_IF_WRITE_CHECK(g_pCB->FD, pTxRxDescBuff,
1153                            _SL_PROTOCOL_ALIGN_SIZE(pCmdCtrl->TxDescLen));
1154     }
1155 
1156     /*  A special mode where Rx payload and Rx length are used as Tx as well */
1157     /*  This mode requires no Rx payload on the response and currently used by fs_Close and sl_Send on */
1158     /*  transceiver mode */
1159     if (sendRxPayload == TRUE )
1160     {
1161          NWP_IF_WRITE_CHECK(g_pCB->FD, pCmdExt->pRxPayload,
1162                            _SL_PROTOCOL_ALIGN_SIZE(pCmdExt->RxPayloadLen));
1163     }
1164 
1165 
1166     /* if the message has some payload */
1167     if (pCmdExt)
1168     {
1169         /*  If the message has payload, it is mandatory that the message's arguments are protocol aligned. */
1170         /*  Otherwise the aligning of arguments will create a gap between arguments and payload. */
1171         VERIFY_PROTOCOL(_SL_IS_PROTOCOL_ALIGNED_SIZE(pCmdCtrl->TxDescLen));
1172 
1173         /* In case two seperated buffers were supplied we should merge the two buffers*/
1174         if ((pCmdExt->TxPayload1Len > 0) && (pCmdExt->TxPayload2Len > 0))
1175         {
1176             _u8 BuffInTheMiddle[4];
1177             _u8 FirstPayloadReminder = 0;
1178             _u8 SecondPayloadOffset = 0;
1179 
1180             FirstPayloadReminder = pCmdExt->TxPayload1Len & 3; /* calulate the first payload reminder */
1181 
1182             /* we first write the 4-bytes aligned payload part */
1183             pCmdExt->TxPayload1Len -= FirstPayloadReminder;
1184 
1185             /* writing the first transaction*/
1186             NWP_IF_WRITE_CHECK(g_pCB->FD, pCmdExt->pTxPayload1, pCmdExt->TxPayload1Len);
1187 
1188             /* Only if we the first payload is not aligned we need the intermediate transaction */
1189             if (FirstPayloadReminder != 0)
1190             {
1191                 /* here we count how many bytes we need to take from the second buffer */
1192                 SecondPayloadOffset = 4 - FirstPayloadReminder;
1193 
1194                 /* copy the first payload reminder */
1195                 sl_Memcpy(&BuffInTheMiddle[0], pCmdExt->pTxPayload1 + pCmdExt->TxPayload1Len, FirstPayloadReminder);
1196 
1197                 /* add the beginning of the second payload to complete 4-bytes transaction */
1198                 sl_Memcpy(&BuffInTheMiddle[FirstPayloadReminder], pCmdExt->pTxPayload2, SecondPayloadOffset);
1199 
1200                 /* write the second transaction of the 4-bytes buffer */
1201                 NWP_IF_WRITE_CHECK(g_pCB->FD, &BuffInTheMiddle[0], 4);
1202             }
1203 
1204 
1205             /* if we still has bytes to write in the second buffer  */
1206             if (pCmdExt->TxPayload2Len > SecondPayloadOffset)
1207             {
1208                 /* write the third transaction (truncated second payload) */
1209                 NWP_IF_WRITE_CHECK(g_pCB->FD,
1210                                    pCmdExt->pTxPayload2 + SecondPayloadOffset,
1211                                    _SL_PROTOCOL_ALIGN_SIZE(pCmdExt->TxPayload2Len - SecondPayloadOffset));
1212             }
1213 
1214         }
1215         else if (pCmdExt->TxPayload1Len > 0)
1216         {
1217             /* Only 1 payload supplied (Payload1) so just align to 4 bytes and send it */
1218             NWP_IF_WRITE_CHECK(g_pCB->FD, pCmdExt->pTxPayload1,
1219                             _SL_PROTOCOL_ALIGN_SIZE(pCmdExt->TxPayload1Len));
1220         }
1221         else if (pCmdExt->TxPayload2Len > 0)
1222         {
1223             /* Only 1 payload supplied (Payload2) so just align to 4 bytes and send it */
1224             NWP_IF_WRITE_CHECK(g_pCB->FD, pCmdExt->pTxPayload2,
1225                             _SL_PROTOCOL_ALIGN_SIZE(pCmdExt->TxPayload2Len));
1226 
1227         }
1228     }
1229 
1230     _SL_DBG_CNT_INC(MsgCnt.Write);
1231 
1232 #ifdef SL_START_WRITE_STAT
1233     sl_IfEndWriteSequence(g_pCB->FD);
1234 #endif
1235 
1236     return SL_OS_RET_CODE_OK;
1237 }
1238 
1239 /* ******************************************************************************/
1240 /*  _SlDrvMsgRead  */
1241 /* ******************************************************************************/
_SlDrvMsgRead(_u16 * outMsgReadLen,_u8 ** pOutAsyncBuf)1242 _SlReturnVal_t _SlDrvMsgRead(_u16* outMsgReadLen, _u8** pOutAsyncBuf)
1243 {
1244     /*  alignment for small memory models */
1245     union
1246     {
1247         _u8           TempBuf[_SL_RESP_HDR_SIZE];
1248         _u32          DummyBuf[2];
1249     } uBuf;
1250     _u8               TailBuffer[4];
1251     _u16              LengthToCopy;
1252     _u16              AlignedLengthRecv;
1253     _u8               *pAsyncBuf = NULL;
1254     _u16              OpCode;
1255     _u16              RespPayloadLen;
1256     _u8               sd = SL_MAX_SOCKETS;
1257     _SlReturnVal_t    RetVal;
1258     _SlRxMsgClass_e   RxMsgClass;
1259     int               Count = 0;
1260     /* Save parameters in global CB */
1261     g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler = NULL;
1262     _SlDrvMemZero(&TailBuffer[0], sizeof(TailBuffer));
1263 
1264     if (_SlDrvRxHdrRead((_u8*)(uBuf.TempBuf)) == SL_API_ABORTED)
1265     {
1266         SL_DRV_LOCK_GLOBAL_UNLOCK(TRUE);
1267 
1268         _SlDrvHandleFatalError(SL_DEVICE_EVENT_FATAL_SYNC_LOSS, 0, 0);
1269         return SL_API_ABORTED;
1270     }
1271 
1272     OpCode = OPCODE(uBuf.TempBuf);
1273     RespPayloadLen = (_u16)(RSP_PAYLOAD_LEN(uBuf.TempBuf));
1274 
1275     /* Update the NWP status */
1276     g_pCB->FlowContCB.TxPoolCnt = ((_SlResponseHeader_t *)uBuf.TempBuf)->TxPoolCnt;
1277     g_pCB->SocketNonBlocking = ((_SlResponseHeader_t *)uBuf.TempBuf)->SocketNonBlocking;
1278     g_pCB->SocketTXFailure = ((_SlResponseHeader_t *)uBuf.TempBuf)->SocketTXFailure;
1279     g_pCB->FlowContCB.MinTxPayloadSize = ((_SlResponseHeader_t *)uBuf.TempBuf)->MinMaxPayload;
1280 
1281     SL_SET_DEVICE_STATUS(((_SlResponseHeader_t *)uBuf.TempBuf)->DevStatus);
1282 
1283     if(g_pCB->FlowContCB.TxPoolCnt > FLOW_CONT_MIN)
1284     {
1285         sl_SyncObjGetCount(&g_pCB->FlowContCB.TxSyncObj, &Count);
1286         if (0 == Count)
1287         {
1288             SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->FlowContCB.TxSyncObj);
1289         }
1290     }
1291 
1292     /* Find the RX message class and set its Async event handler */
1293     _SlDrvClassifyRxMsg(OpCode);
1294 
1295     RxMsgClass = g_pCB->FunctionParams.AsyncExt.RxMsgClass;
1296 
1297     switch(RxMsgClass)
1298     {
1299         case ASYNC_EVT_CLASS:
1300         {
1301             VERIFY_PROTOCOL(NULL == pAsyncBuf);
1302 
1303 #ifdef SL_MEMORY_MGMT_DYNAMIC
1304             *pOutAsyncBuf = (_u8*)sl_Malloc(SL_ASYNC_MAX_MSG_LEN);
1305 
1306 #else
1307             *pOutAsyncBuf = g_StatMem.AsyncRespBuf;
1308 #endif
1309            /* set the local pointer to the allocated one */
1310             pAsyncBuf = *pOutAsyncBuf;
1311 
1312             MALLOC_OK_CHECK(pAsyncBuf);
1313 
1314             /* clear the async buffer */
1315             _SlDrvMemZero(pAsyncBuf, (_u16)SL_ASYNC_MAX_MSG_LEN);
1316             sl_Memcpy(pAsyncBuf, uBuf.TempBuf, _SL_RESP_HDR_SIZE);
1317 
1318             /* add the protocol header length */
1319             *outMsgReadLen = _SL_RESP_HDR_SIZE;
1320 
1321             if (_SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen) <= SL_ASYNC_MAX_PAYLOAD_LEN)
1322             {
1323                 AlignedLengthRecv = (_u16)_SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen);
1324             }
1325             else
1326             {
1327                 AlignedLengthRecv = (_u16)_SL_PROTOCOL_ALIGN_SIZE(SL_ASYNC_MAX_PAYLOAD_LEN);
1328             }
1329 
1330             /* complete the read of the entire message to the async buffer */
1331             if (RespPayloadLen > 0)
1332             {
1333                 NWP_IF_READ_CHECK(g_pCB->FD,
1334                                   pAsyncBuf + _SL_RESP_HDR_SIZE,
1335                                   AlignedLengthRecv);
1336                 *outMsgReadLen += AlignedLengthRecv;
1337             }
1338             /* In case ASYNC RX buffer length is smaller then the received data length, dump the rest */
1339             if ((_SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen) > SL_ASYNC_MAX_PAYLOAD_LEN))
1340             {
1341                 AlignedLengthRecv = (_u16)(_SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen) - SL_ASYNC_MAX_PAYLOAD_LEN);
1342                 while (AlignedLengthRecv > 0)
1343                 {
1344                     NWP_IF_READ_CHECK(g_pCB->FD,TailBuffer,4);
1345                     AlignedLengthRecv = AlignedLengthRecv - 4;
1346                 }
1347             }
1348 
1349             SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
1350 
1351             if (
1352                (SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE == OpCode) ||
1353                (SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE_V6 == OpCode) ||
1354                (SL_OPCODE_SOCKET_CONNECTASYNCRESPONSE == OpCode) ||
1355                (SL_OPCODE_SOCKET_SOCKETCLOSEASYNCEVENT == OpCode)
1356                )
1357                {
1358                    /* go over the active list if exist to find obj waiting for this Async event */
1359                    sd = ((((SlSocketResponse_t *)(pAsyncBuf + _SL_RESP_HDR_SIZE))->Sd) & SL_BSD_SOCKET_ID_MASK);
1360                }
1361             if (SL_OPCODE_SOCKET_SOCKETASYNCEVENT == OpCode)
1362                {
1363                    /* Save the socket descriptor which has been waiting for this opcode */
1364                    sd = ((((SlSocketAsyncEvent_t *)(pAsyncBuf + _SL_RESP_HDR_SIZE))->Sd) & SL_BSD_SOCKET_ID_MASK);
1365                }
1366 
1367                _SlDrvFindAndSetActiveObj(OpCode, sd);
1368 
1369                SL_DRV_PROTECTION_OBJ_UNLOCK();
1370 
1371                break;
1372         }
1373 
1374         case RECV_RESP_CLASS:
1375         {
1376             _u8   ExpArgSize; /*  Expected size of Recv/Recvfrom arguments */
1377 
1378             switch(OpCode)
1379             {
1380                 case SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE:
1381                     ExpArgSize = (_u8)RECVFROM_IPV4_ARGS_SIZE;
1382                     break;
1383                 case SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE_V6:
1384                     ExpArgSize = (_u8)RECVFROM_IPV6_ARGS_SIZE;
1385                     break;
1386                 default:
1387                     /* SL_OPCODE_SOCKET_RECVASYNCRESPONSE: */
1388                     ExpArgSize = (_u8)RECV_ARGS_SIZE;
1389             }
1390 
1391             /*  Read first 4 bytes of Recv/Recvfrom response to get SocketId and actual  */
1392             /*  response data length */
1393             NWP_IF_READ_CHECK(g_pCB->FD, &uBuf.TempBuf[4], RECV_ARGS_SIZE);
1394 
1395             /*  Validate Socket ID and Received Length value.  */
1396             VERIFY_PROTOCOL((SD(&uBuf.TempBuf[4])& SL_BSD_SOCKET_ID_MASK) < SL_MAX_SOCKETS);
1397 
1398             SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
1399 
1400             /* go over the active list if exist to find obj waiting for this Async event */
1401             RetVal = _SlDrvFindAndSetActiveObj(OpCode, SD(&uBuf.TempBuf[4]) & SL_BSD_SOCKET_ID_MASK);
1402 
1403 #if (defined(SL_PLATFORM_MULTI_THREADED) && !defined(slcb_SocketTriggerEventHandler))
1404             /* This case is for reading the receive response sent by clearing the control socket. */
1405             if((RetVal == SL_RET_OBJ_NOT_SET) && (SD(&uBuf.TempBuf[4]) == g_pCB->MultiSelectCB.CtrlSockFD))
1406             {
1407                 /*KW - we need to allocate the maximum possible which is 24*/
1408                 _u8 buffer[RECVFROM_IPV6_ARGS_SIZE];
1409 
1410                 sl_Memcpy(&buffer[0], &uBuf.TempBuf[4], RECV_ARGS_SIZE);
1411 
1412                if(ExpArgSize > (_u8)RECV_ARGS_SIZE)
1413                {
1414                    NWP_IF_READ_CHECK(g_pCB->FD,
1415                                      &buffer[RECV_ARGS_SIZE],
1416                                      ExpArgSize - RECV_ARGS_SIZE);
1417                }
1418 
1419                /*  Here g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pData contains requested(expected) Recv/Recvfrom DataSize. */
1420                /*  Overwrite requested DataSize with actual one. */
1421                /*  If error is received, this information will be read from arguments. */
1422                if(ACT_DATA_SIZE(&uBuf.TempBuf[4]) > 0)
1423                {
1424 
1425                    /*  Read 4 bytes aligned from interface */
1426                    /*  therefore check the requested length and read only  */
1427                    /*  4 bytes aligned data. The rest unaligned (if any) will be read */
1428                    /*  and copied to a TailBuffer  */
1429                    LengthToCopy = (_u16)(ACT_DATA_SIZE(&uBuf.TempBuf[4]) & (3));
1430                    AlignedLengthRecv = (_u16)(ACT_DATA_SIZE(&uBuf.TempBuf[4]) & (~3));
1431                    if( AlignedLengthRecv >= 4)
1432                    {
1433                        NWP_IF_READ_CHECK(g_pCB->FD, &buffer[ExpArgSize], AlignedLengthRecv);
1434                    }
1435                }
1436 
1437                SL_DRV_PROTECTION_OBJ_UNLOCK();
1438             }
1439             else
1440 #endif
1441             {
1442                 /* if _SlDrvFindAndSetActiveObj returned an error, release the protection lock, and return. */
1443                 if(RetVal < 0)
1444                 {
1445                     SL_DRV_PROTECTION_OBJ_UNLOCK();
1446                     return SL_API_ABORTED;
1447                 }
1448 
1449                 /*  Verify data is waited on this socket. The pArgs should have been set by _SlDrvDataReadOp(). */
1450                 VERIFY_SOCKET_CB(NULL !=  ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pData))->pArgs);
1451 
1452                 sl_Memcpy( ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pArgs, &uBuf.TempBuf[4], RECV_ARGS_SIZE);
1453 
1454                 if(ExpArgSize > (_u8)RECV_ARGS_SIZE)
1455                 {
1456                     NWP_IF_READ_CHECK(g_pCB->FD,
1457                         ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pArgs + RECV_ARGS_SIZE,
1458                         ExpArgSize - RECV_ARGS_SIZE);
1459                 }
1460 
1461                 /*  Here g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pData contains requested(expected) Recv/Recvfrom DataSize. */
1462                 /*  Overwrite requested DataSize with actual one. */
1463                 /*  If error is received, this information will be read from arguments. */
1464                 if(ACT_DATA_SIZE(&uBuf.TempBuf[4]) > 0)
1465                 {
1466                     VERIFY_SOCKET_CB(NULL != ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pData);
1467 
1468                     /*  Read 4 bytes aligned from interface */
1469                     /*  therefore check the requested length and read only  */
1470                     /*  4 bytes aligned data. The rest unaligned (if any) will be read */
1471                     /*  and copied to a TailBuffer  */
1472                     LengthToCopy = (_u16)(ACT_DATA_SIZE(&uBuf.TempBuf[4]) & (3));
1473                     AlignedLengthRecv = (_u16)(ACT_DATA_SIZE(&uBuf.TempBuf[4]) & (~3));
1474                     if( AlignedLengthRecv >= 4)
1475                     {
1476                         NWP_IF_READ_CHECK(g_pCB->FD,((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pData, AlignedLengthRecv);
1477                     }
1478                     /*  copy the unaligned part, if any */
1479                     if( LengthToCopy > 0)
1480                     {
1481                         NWP_IF_READ_CHECK(g_pCB->FD,TailBuffer,4);
1482                         /*  copy TailBuffer unaligned part (1/2/3 bytes) */
1483                         sl_Memcpy(((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pData + AlignedLengthRecv,TailBuffer,LengthToCopy);
1484                     }
1485                 }
1486                      SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
1487                      SL_DRV_PROTECTION_OBJ_UNLOCK();
1488             }
1489 
1490             break;
1491         }
1492 
1493         case CMD_RESP_CLASS:
1494         {
1495             /*  Some commands pass a maximum arguments size. */
1496             /*  In this case Driver will send extra dummy patterns to NWP if */
1497             /*  the response message is smaller than maximum. */
1498             /*  When RxDescLen is not exact, using RxPayloadLen is forbidden! */
1499             /*  If such case cannot be avoided - parse message here to detect */
1500             /*  arguments/payload border. */
1501             NWP_IF_READ_CHECK(g_pCB->FD,
1502                 g_pCB->FunctionParams.pTxRxDescBuff,
1503                 _SL_PROTOCOL_ALIGN_SIZE(g_pCB->FunctionParams.pCmdCtrl->RxDescLen));
1504 
1505             if((NULL != g_pCB->FunctionParams.pCmdExt) && (0 != g_pCB->FunctionParams.pCmdExt->RxPayloadLen))
1506             {
1507                 /*  Actual size of command's response payload: <msg_payload_len> - <rsp_args_len> */
1508                 _i16    ActDataSize = (_i16)(RSP_PAYLOAD_LEN(uBuf.TempBuf) - g_pCB->FunctionParams.pCmdCtrl->RxDescLen);
1509 
1510                 g_pCB->FunctionParams.pCmdExt->ActualRxPayloadLen = ActDataSize;
1511 
1512                 /* Check that the space prepared by user for the response data is sufficient. */
1513                 if(ActDataSize <= 0)
1514                 {
1515                     g_pCB->FunctionParams.pCmdExt->RxPayloadLen = 0;
1516                 }
1517                 else
1518                 {
1519                     /* In case the user supplied Rx buffer length which is smaller then the received data length, copy according to user length */
1520                     if (ActDataSize > g_pCB->FunctionParams.pCmdExt->RxPayloadLen)
1521                     {
1522                         LengthToCopy = (_u16)(g_pCB->FunctionParams.pCmdExt->RxPayloadLen & (3));
1523                         AlignedLengthRecv = (_u16)(g_pCB->FunctionParams.pCmdExt->RxPayloadLen & (~3));
1524                     }
1525                     else
1526                     {
1527                         LengthToCopy = (_u16)(ActDataSize & (3));
1528                         AlignedLengthRecv = (_u16)(ActDataSize & (~3));
1529                     }
1530                     /*  Read 4 bytes aligned from interface */
1531                     /*  therefore check the requested length and read only  */
1532                     /*  4 bytes aligned data. The rest unaligned (if any) will be read */
1533                     /*  and copied to a TailBuffer  */
1534 
1535                     if( AlignedLengthRecv >= 4)
1536                     {
1537                         NWP_IF_READ_CHECK(g_pCB->FD,
1538                             g_pCB->FunctionParams.pCmdExt->pRxPayload,
1539                             AlignedLengthRecv );
1540 
1541                     }
1542                     /*  copy the unaligned part, if any */
1543                     if( LengthToCopy > 0)
1544                     {
1545                         NWP_IF_READ_CHECK(g_pCB->FD,TailBuffer,4);
1546                         /*  copy TailBuffer unaligned part (1/2/3 bytes) */
1547                         sl_Memcpy(g_pCB->FunctionParams.pCmdExt->pRxPayload + AlignedLengthRecv,
1548                             TailBuffer,
1549                             LengthToCopy);
1550                         ActDataSize = ActDataSize-4;
1551                     }
1552                     /* In case the user supplied Rx buffer length which is smaller then the received data length, dump the rest */
1553                     if (ActDataSize > g_pCB->FunctionParams.pCmdExt->RxPayloadLen)
1554                     {
1555                         /* calculate the rest of the data size to dump  */
1556                         AlignedLengthRecv = (_u16)( (ActDataSize + 3 - g_pCB->FunctionParams.pCmdExt->RxPayloadLen) & (~3) );
1557                         while( AlignedLengthRecv > 0)
1558                         {
1559                             NWP_IF_READ_CHECK(g_pCB->FD,TailBuffer, 4 );
1560                             AlignedLengthRecv = AlignedLengthRecv - 4;
1561                         }
1562                     }
1563                 }
1564             }
1565 
1566             break;
1567         }
1568 
1569 #if (defined(SL_PLATFORM_MULTI_THREADED) && !defined(slcb_SocketTriggerEventHandler))
1570     case MULTI_SELECT_RESP_CLASS:
1571     {
1572         /* In case we read Select Response from NWP, and we're not waiting for
1573          * command complete, that means that a select command was send for a select Joiner. */
1574 
1575         _u8 Idx;
1576 
1577         NWP_IF_READ_CHECK(g_pCB->FD,
1578                           (_u8*)(&g_pCB->MultiSelectCB.SelectCmdResp),
1579                           _SL_PROTOCOL_ALIGN_SIZE(sizeof(_BasicResponse_t)));
1580 
1581         if(g_pCB->MultiSelectCB.SelectCmdResp.status != SL_RET_CODE_OK)
1582         {
1583             /* If a select response returns without Status O.K, this means that
1584              * something terribly wrong have happen. So we stop all waiting select callers,
1585              * and return command error. */
1586             g_pCB->MultiSelectCB.ActiveSelect = FALSE;
1587 
1588             for(Idx = 0 ; Idx < MAX_CONCURRENT_ACTIONS ; Idx++)
1589             {
1590                 if(g_pCB->MultiSelectCB.SelectEntry[Idx] != NULL)
1591                 {
1592                     sl_SyncObjSignal(&g_pCB->ObjPool[Idx].SyncObj);
1593                 }
1594             }
1595             /* Clean all table entries, and clear the global read/write fds  */
1596             _SlDrvMemZero(&g_pCB->MultiSelectCB, sizeof(_SlMultiSelectCB_t));
1597         }
1598 
1599         break;
1600     }
1601 #endif
1602 
1603     default:
1604         /*  DUMMY_MSG_CLASS: Flow control message has no payload. */
1605         break;
1606     }
1607 
1608     _SL_DBG_CNT_INC(MsgCnt.Read);
1609 
1610     /*  Unmask Interrupt call */
1611     sl_IfUnMaskIntHdlr();
1612 
1613     return SL_OS_RET_CODE_OK;
1614 }
1615 
1616 
1617 /* ******************************************************************************/
1618 /*  _SlDrvAsyncEventGenericHandler */
1619 /* ******************************************************************************/
_SlDrvAsyncEventGenericHandler(_u8 bInCmdContext,_u8 * pAsyncBuffer)1620 static void _SlDrvAsyncEventGenericHandler(_u8 bInCmdContext, _u8 *pAsyncBuffer)
1621 {
1622     _u32 SlAsyncEvent = 0;
1623     _u8  OpcodeFound = FALSE;
1624     _u8  i;
1625 
1626     _u32* pEventLocation  = NULL; /* This pointer will override the async buffer with the translated event type */
1627     _SlResponseHeader_t  *pHdr       = (_SlResponseHeader_t *)pAsyncBuffer;
1628 
1629 
1630     /* if no async event registered nothing to do..*/
1631     if (g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler == NULL)
1632     {
1633         return;
1634     }
1635 
1636     /* In case we in the middle of the provisioning, filter out
1637        all the async events except the provisioning ones  */
1638     if ( (( SL_IS_PROVISIONING_ACTIVE || SL_IS_PROVISIONING_INITIATED_BY_USER) && !(SL_IS_PROVISIONING_API_ALLOWED)) &&
1639           (pHdr->GenHeader.Opcode != SL_OPCODE_WLAN_PROVISIONING_STATUS_ASYNC_EVENT) &&
1640           (pHdr->GenHeader.Opcode != SL_OPCODE_DEVICE_RESET_REQUEST_ASYNC_EVENT) &&
1641           (pHdr->GenHeader.Opcode != SL_OPCODE_DEVICE_INITCOMPLETE) &&
1642           (pHdr->GenHeader.Opcode != SL_OPCODE_WLAN_PROVISIONING_PROFILE_ADDED_ASYNC_RESPONSE) &&
1643           (pHdr->GenHeader.Opcode != SL_OPCODE_NETAPP_REQUEST) )
1644     {
1645         return;
1646     }
1647 
1648     /* Iterate through all the opcode in the table */
1649     for (i=0; i< (_u8)(sizeof(OpcodeTranslateTable) / sizeof(OpcodeKeyVal_t)); i++)
1650     {
1651         if (OpcodeTranslateTable[i].opcode == pHdr->GenHeader.Opcode)
1652         {
1653             SlAsyncEvent = OpcodeTranslateTable[i].event;
1654             OpcodeFound = TRUE;
1655             break;
1656         }
1657     }
1658 
1659     /* No Async event found in the table */
1660     if (OpcodeFound == FALSE)
1661     {
1662         if ((pHdr->GenHeader.Opcode & SL_OPCODE_SILO_MASK) == SL_OPCODE_SILO_DEVICE)
1663         {
1664             DeviceEventInfo_t deviceEvent;
1665 
1666             deviceEvent.pAsyncMsgBuff = pAsyncBuffer;
1667             deviceEvent.bInCmdContext = bInCmdContext;
1668 
1669             g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler(&deviceEvent);
1670         }
1671         else
1672         {
1673             /* This case handles all the async events handlers of the DEVICE & SOCK Silos which are handled internally.
1674             For these cases we send the async even buffer as is */
1675             g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler(pAsyncBuffer);
1676         }
1677     }
1678     else
1679     {
1680        /* calculate the event type location to be filled in the async buffer */
1681        pEventLocation = (_u32*)(pAsyncBuffer + sizeof (_SlResponseHeader_t) - sizeof(SlAsyncEvent));
1682 
1683        /* Override the async buffer (before the data starts ) with our event type  */
1684        *pEventLocation = SlAsyncEvent;
1685 
1686        /* call the event handler registered by the user with our async buffer which now holds
1687                 the User's event type and its related data */
1688        g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler(pEventLocation);
1689 
1690     }
1691 }
1692 
1693 /* ******************************************************************************/
1694 /*  _SlDrvMsgReadCmdCtx  */
1695 /* ******************************************************************************/
_SlDrvMsgReadCmdCtx(_u16 cmdOpcode,_u8 IsLockRequired)1696 static _SlReturnVal_t _SlDrvMsgReadCmdCtx(_u16 cmdOpcode, _u8 IsLockRequired)
1697 {
1698     _u32 CmdCmpltTimeout;
1699     _i16 RetVal=0;
1700     _u8  *pAsyncBuf = NULL;
1701 
1702     /* the sl_FsOpen/sl_FsProgram APIs may take long time */
1703     if ((cmdOpcode == SL_OPCODE_NVMEM_FILEOPEN) || (cmdOpcode == SL_OPCODE_NVMEM_NVMEMFSPROGRAMMINGCOMMAND))
1704     {
1705         CmdCmpltTimeout = ((_u32)SL_DRIVER_TIMEOUT_LONG * 10);
1706     }
1707     else
1708     {
1709         /* For any FS command, the timeout will be the long one as the commnad response holds the full response data */
1710         CmdCmpltTimeout = (SL_OPCODE_SILO_FS & cmdOpcode)? (_u32)(SL_DRIVER_TIMEOUT_LONG) : (_u32)SL_DRIVER_TIMEOUT_SHORT;
1711     }
1712 
1713     /*  after command response is received and WaitForCmdResp */
1714     /*  flag is set FALSE, it is necessary to read out all */
1715     /*  Async messages in Commands context, because ssiDma_IsrHandleSignalFromSlave */
1716     /*  could have dispatched some Async messages to g_NwpIf.CmdSyncObj */
1717     /*  after command response but before this response has been processed */
1718     /*  by spi_singleRead and WaitForCmdResp was set FALSE. */
1719     while (TRUE == g_pCB->WaitForCmdResp)
1720     {
1721         if(_SL_PENDING_RX_MSG(g_pCB))
1722         {
1723             _u16 outMsgLen = 0;
1724 
1725             RetVal = _SlDrvMsgRead(&outMsgLen,&pAsyncBuf);
1726 
1727             if (RetVal != SL_OS_RET_CODE_OK)
1728             {
1729                 g_pCB->WaitForCmdResp = FALSE;
1730 
1731                 if ((IsLockRequired) && (RetVal != SL_API_ABORTED))
1732                 {
1733                     SL_DRV_LOCK_GLOBAL_UNLOCK(TRUE);
1734                 }
1735 
1736                 return SL_API_ABORTED;
1737             }
1738             g_pCB->RxDoneCnt++;
1739 
1740             if (CMD_RESP_CLASS == g_pCB->FunctionParams.AsyncExt.RxMsgClass)
1741             {
1742                 g_pCB->WaitForCmdResp = FALSE;
1743                 /*  In case CmdResp has been read without  waiting on CmdSyncObj -  that */
1744                 /*  Sync object. That to prevent old signal to be processed. */
1745                 SL_DRV_SYNC_OBJ_CLEAR(&g_pCB->CmdSyncObj);
1746             }
1747             else if (ASYNC_EVT_CLASS == g_pCB->FunctionParams.AsyncExt.RxMsgClass)
1748             {
1749 
1750 #ifdef SL_PLATFORM_MULTI_THREADED
1751                 /* Do not handle async events in command context */
1752                 /* All async events data will be stored in list and handled in spawn context */
1753                 RetVal = _SlSpawnMsgListInsert(outMsgLen, pAsyncBuf);
1754                 if (SL_RET_CODE_NO_FREE_ASYNC_BUFFERS_ERROR == RetVal)
1755                 {
1756                      _SlFindAndReleasePendingCmd();
1757                 }
1758 
1759 #else
1760                 _SlDrvAsyncEventGenericHandler(TRUE, pAsyncBuf);
1761 #endif
1762 
1763 #ifdef SL_MEMORY_MGMT_DYNAMIC
1764                 sl_Free(pAsyncBuf);
1765 #else
1766                 pAsyncBuf = NULL;
1767 #endif
1768             }
1769 #if (defined(SL_PLATFORM_MULTI_THREADED) && !defined(slcb_SocketTriggerEventHandler))
1770             else if(MULTI_SELECT_RESP_CLASS == g_pCB->FunctionParams.AsyncExt.RxMsgClass)
1771             {
1772                 sl_SyncObjSignal(&g_pCB->MultiSelectCB.SelectSyncObj);
1773             }
1774 #endif
1775         }
1776         else
1777         {
1778              /* CmdSyncObj will be signaled by IRQ */
1779             RetVal = sl_SyncObjWait(&g_pCB->CmdSyncObj, CmdCmpltTimeout);
1780             if (RetVal != 0)
1781             {
1782                 g_pCB->WaitForCmdResp = FALSE;
1783 
1784                 if (IsLockRequired)
1785                 {
1786                     SL_DRV_LOCK_GLOBAL_UNLOCK(TRUE);
1787                 }
1788 
1789                 /* only if device started handle the fatal error */
1790                 if (SL_IS_DEVICE_STARTED)
1791                 {
1792                     _SlDrvHandleFatalError(SL_DEVICE_EVENT_FATAL_NO_CMD_ACK, cmdOpcode, (_u32)CmdCmpltTimeout);
1793                 }
1794 
1795                 return SL_API_ABORTED;
1796             }
1797         }
1798     }
1799 
1800 #ifdef SL_PLATFORM_MULTI_THREADED
1801     if (_SlSpawnMsgListGetCount() > 0)
1802     {
1803         /* signal the spawn task to process the pending async events received during the cmd */
1804         sl_Spawn((_SlSpawnEntryFunc_t)_SlDrvMsgReadSpawnCtx, NULL, SL_SPAWN_FLAG_FROM_CMD_PROCESS);
1805     }
1806 #endif
1807 
1808     /*  If there are more pending Rx Msgs after CmdResp is received, */
1809     /*  that means that these are Async, Dummy or Read Data Msgs. */
1810     /*  Spawn _SlDrvMsgReadSpawnCtx to trigger reading these messages from */
1811     /*  Temporary context. */
1812     /*  sl_Spawn is activated, using a different context */
1813     if (IsLockRequired)
1814     {
1815         SL_DRV_LOCK_GLOBAL_UNLOCK(TRUE);
1816     }
1817 
1818     if(_SL_PENDING_RX_MSG(g_pCB))
1819     {
1820         sl_Spawn((_SlSpawnEntryFunc_t)_SlDrvMsgReadSpawnCtx, NULL, SL_SPAWN_FLAG_FROM_CMD_CTX);
1821     }
1822 
1823     return SL_OS_RET_CODE_OK;
1824 }
1825 
1826 /* ******************************************************************************/
1827 /*  _SlDrvMsgReadSpawnCtx                                                       */
1828 /* ******************************************************************************/
_SlDrvMsgReadSpawnCtx(void * pValue)1829 _SlReturnVal_t _SlDrvMsgReadSpawnCtx(void *pValue)
1830 {
1831     _SlReturnVal_t RetVal = SL_OS_RET_CODE_OK;
1832     _u16 outMsgLen = 0;
1833     _u8  *pAsyncBuf = NULL;
1834 
1835 #ifdef SL_POLLING_MODE_USED
1836 
1837     /*  for polling based systems */
1838     do
1839     {
1840         if (GlobalLockObj != NULL)
1841         {
1842             RetVal = sl_LockObjLock(&GlobalLockObj, 0);
1843 
1844             if (SL_OS_RET_CODE_OK != RetVal )
1845             {
1846                 if (TRUE == g_pCB->WaitForCmdResp)
1847                 {
1848                     SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->CmdSyncObj);
1849                     return SL_RET_CODE_OK;
1850                 }
1851             }
1852 
1853         }
1854 
1855     }
1856     while (SL_OS_RET_CODE_OK != RetVal);
1857 
1858 #else
1859     SL_DRV_LOCK_GLOBAL_LOCK_FOREVER(GLOBAL_LOCK_FLAGS_NONE);
1860 #endif
1861 
1862 #ifndef SL_PLATFORM_MULTI_THREADED
1863     /* set the global lock owner (spawn context) */
1864     _SlDrvSetGlobalLockOwner(GLOBAL_LOCK_CONTEXT_OWNER_SPAWN);
1865 #endif
1866     /* pValue parameter is currently not in use */
1867     (void)pValue;
1868 
1869     /*  Messages might have been read by CmdResp context. Therefore after */
1870     /*  getting LockObj, check again where the Pending RX Msg is still present. */
1871     if(FALSE == (_SL_PENDING_RX_MSG(g_pCB)))
1872     {
1873 #ifndef SL_PLATFORM_MULTI_THREADED
1874         /* clear the global lock owner (spawn context) */
1875         _SlDrvSetGlobalLockOwner(GLOBAL_LOCK_CONTEXT_OWNER_APP);
1876 #endif
1877         SL_DRV_LOCK_GLOBAL_UNLOCK(FALSE);
1878 
1879         return SL_RET_CODE_OK;
1880     }
1881 
1882     if (SL_IS_DEVICE_STARTED || SL_IS_DEVICE_START_IN_PROGRESS)
1883     {
1884 
1885         RetVal = _SlDrvMsgRead(&outMsgLen, &pAsyncBuf);
1886 
1887         if (RetVal != SL_OS_RET_CODE_OK)
1888         {
1889             if (RetVal != SL_API_ABORTED)
1890             {
1891     #ifndef SL_PLATFORM_MULTI_THREADED
1892                 /* clear the global lock owner (spawn context) */
1893                 _SlDrvSetGlobalLockOwner(GLOBAL_LOCK_CONTEXT_OWNER_APP);
1894     #endif
1895                 SL_DRV_LOCK_GLOBAL_UNLOCK(FALSE);
1896             }
1897             return SL_API_ABORTED;
1898         }
1899 
1900         g_pCB->RxDoneCnt++;
1901 
1902         switch(g_pCB->FunctionParams.AsyncExt.RxMsgClass)
1903         {
1904         case ASYNC_EVT_CLASS:
1905             /*  If got here and protected by LockObj a message is waiting  */
1906             /*  to be read */
1907             VERIFY_PROTOCOL(NULL != pAsyncBuf);
1908 
1909 
1910             _SlDrvAsyncEventGenericHandler(FALSE, pAsyncBuf);
1911 
1912     #ifdef SL_MEMORY_MGMT_DYNAMIC
1913             sl_Free(pAsyncBuf);
1914     #else
1915             pAsyncBuf = NULL;
1916     #endif
1917             break;
1918         case DUMMY_MSG_CLASS:
1919         case RECV_RESP_CLASS:
1920             /* These types are legal in this context. Do nothing */
1921             break;
1922         case CMD_RESP_CLASS:
1923             /* Command response is illegal in this context -  */
1924             /* One exception exists though: 'Select' response (SL_OPCODE_SOCKET_SELECTRESPONSE) Opcode = 0x1407 */
1925             break;
1926     #if (defined(SL_PLATFORM_MULTI_THREADED) && !defined(slcb_SocketTriggerEventHandler))
1927         case MULTI_SELECT_RESP_CLASS:
1928             /* If everything's OK, we signal for any other joiners to call 'Select'.*/
1929             sl_SyncObjSignal(&g_pCB->MultiSelectCB.SelectSyncObj);
1930             break;
1931     #endif
1932         default:
1933             _SL_ASSERT_ERROR(0, SL_API_ABORTED);
1934         }
1935     #ifndef SL_PLATFORM_MULTI_THREADED
1936         /* clear the global lock owner (spawn context) */
1937         _SlDrvSetGlobalLockOwner(GLOBAL_LOCK_CONTEXT_OWNER_APP);
1938     #endif
1939         SL_DRV_LOCK_GLOBAL_UNLOCK(FALSE);
1940         return(SL_RET_CODE_OK);
1941     }
1942     return(SL_RET_CODE_INTERFACE_CLOSED);
1943 }
1944 
1945 /*
1946 
1947 #define SL_OPCODE_SILO_DEVICE                           ( 0x0 << SL_OPCODE_SILO_OFFSET )
1948 #define SL_OPCODE_SILO_WLAN                             ( 0x1 << SL_OPCODE_SILO_OFFSET )
1949 #define SL_OPCODE_SILO_SOCKET                           ( 0x2 << SL_OPCODE_SILO_OFFSET )
1950 #define SL_OPCODE_SILO_NETAPP                           ( 0x3 << SL_OPCODE_SILO_OFFSET )
1951 #define SL_OPCODE_SILO_FS                               ( 0x4 << SL_OPCODE_SILO_OFFSET )
1952 #define SL_OPCODE_SILO_NETCFG                           ( 0x5 << SL_OPCODE_SILO_OFFSET )
1953 
1954 */
1955 
1956 /* The Lookup table below holds the event handlers to be called according to the incoming
1957     RX message SILO type */
1958 static const _SlSpawnEntryFunc_t RxMsgClassLUT[] = {
1959     (_SlSpawnEntryFunc_t)_SlDeviceEventHandler, /* SL_OPCODE_SILO_DEVICE */
1960 #if defined(slcb_WlanEvtHdlr) || defined(EXT_LIB_REGISTERED_WLAN_EVENTS)
1961     (_SlSpawnEntryFunc_t)_SlDrvHandleWlanEvents,           /* SL_OPCODE_SILO_WLAN */
1962 #else
1963     NULL,
1964 #endif
1965 #if defined (slcb_SockEvtHdlr) || defined(EXT_LIB_REGISTERED_SOCK_EVENTS)
1966     (_SlSpawnEntryFunc_t)_SlDrvHandleSockEvents,      /* SL_OPCODE_SILO_SOCKET */
1967 #else
1968     NULL,
1969 #endif
1970 #if defined(slcb_NetAppEvtHdlr) || defined(EXT_LIB_REGISTERED_NETAPP_EVENTS)
1971     (_SlSpawnEntryFunc_t)_SlDrvHandleNetAppEvents,    /* SL_OPCODE_SILO_NETAPP */
1972 #else
1973     NULL,
1974 #endif
1975     NULL,                                             /* SL_OPCODE_SILO_FS      */
1976     NULL,                                             /* SL_OPCODE_SILO_NETCFG  */
1977     (_SlSpawnEntryFunc_t)_SlNetUtilHandleAsync_Cmd,   /* SL_OPCODE_SILO_NETUTIL */
1978     NULL
1979 };
1980 
1981 
1982 /* ******************************************************************************/
1983 /*  _SlDrvClassifyRxMsg */
1984 /* ******************************************************************************/
_SlDrvClassifyRxMsg(_SlOpcode_t Opcode)1985 static _SlReturnVal_t _SlDrvClassifyRxMsg(
1986     _SlOpcode_t         Opcode)
1987 {
1988     _SlSpawnEntryFunc_t AsyncEvtHandler = NULL;
1989     _SlRxMsgClass_e     RxMsgClass  = CMD_RESP_CLASS;
1990     _u8               Silo;
1991 
1992 
1993     if (0 == (SL_OPCODE_SYNC & Opcode))
1994     {   /* Async event has received */
1995 
1996         if (SL_OPCODE_DEVICE_DEVICEASYNCDUMMY == Opcode)
1997         {
1998             RxMsgClass = DUMMY_MSG_CLASS;
1999         }
2000         else if ( (SL_OPCODE_SOCKET_RECVASYNCRESPONSE == Opcode) || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE == Opcode)
2001                     || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE_V6 == Opcode)
2002                 )
2003         {
2004             RxMsgClass = RECV_RESP_CLASS;
2005         }
2006         else
2007         {
2008             /* This is Async Event class message */
2009             RxMsgClass = ASYNC_EVT_CLASS;
2010 
2011             /* Despite the fact that 4 bits are allocated in the SILO field, we actually have only 6 SILOs
2012               So we can use the 8 options of SILO in look up table */
2013             Silo = (_u8)((Opcode >> SL_OPCODE_SILO_OFFSET) & 0x7);
2014 
2015             VERIFY_PROTOCOL(Silo < (_u8)(sizeof(RxMsgClassLUT)/sizeof(_SlSpawnEntryFunc_t)));
2016 
2017             /* Set the SILO's async event handler according to the LUT
2018                If this specific event requires a direct async event handler, the
2019                async event handler will be overwrite according to the action table */
2020             AsyncEvtHandler = RxMsgClassLUT[Silo];
2021 
2022             if ((SL_OPCODE_NETAPP_HTTPGETTOKENVALUE == Opcode) || (SL_OPCODE_NETAPP_HTTPPOSTTOKENVALUE == Opcode) ||
2023                 (SL_OPCODE_NETAPP_REQUEST == Opcode) || (SL_OPCODE_NETAPP_RESPONSE == Opcode) || (SL_OPCODE_NETAPP_SEND == Opcode))
2024             {
2025                 AsyncEvtHandler = _SlNetAppEventHandler;
2026             }
2027             else if (SL_OPCODE_NETAPP_PINGREPORTREQUESTRESPONSE == Opcode)
2028             {
2029                 AsyncEvtHandler = (_SlSpawnEntryFunc_t)_SlNetAppHandleAsync_PingResponse;
2030             }
2031         }
2032     }
2033 #if (defined(SL_PLATFORM_MULTI_THREADED) && !defined(slcb_SocketTriggerEventHandler))
2034     else if((Opcode == SL_OPCODE_SOCKET_SELECTRESPONSE) &&
2035             (g_pCB->FunctionParams.pCmdCtrl->Opcode != SL_OPCODE_SOCKET_SELECT))
2036     {
2037         /* Only in case this response came from a 'Select' sent in an Async event, Mark the message as MULTI_SELECT_RESPONSE */
2038         RxMsgClass = MULTI_SELECT_RESP_CLASS;
2039     }
2040 #endif
2041     g_pCB->FunctionParams.AsyncExt.RxMsgClass = RxMsgClass;
2042     g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler = AsyncEvtHandler;
2043 
2044     return SL_RET_CODE_OK;
2045 }
2046 
2047 
2048 /* ******************************************************************************/
2049 /*  _SlDrvRxHdrRead  */
2050 /* ******************************************************************************/
_SlDrvRxHdrRead(_u8 * pBuf)2051 static _SlReturnVal_t _SlDrvRxHdrRead(_u8 *pBuf)
2052 {
2053     _u8        ShiftIdx;
2054     _u8        TimeoutState = TIMEOUT_STATE_INIT_VAL;
2055     _u8        SearchSync = TRUE;
2056     _u8        SyncPattern[4];
2057 #if (defined(slcb_GetTimestamp))
2058      _SlTimeoutParams_t      TimeoutInfo={0};
2059 #endif
2060 
2061 #ifndef SL_IF_TYPE_UART
2062     /*  1. Write CNYS pattern to NWP when working in SPI mode only  */
2063     NWP_IF_WRITE_CHECK(g_pCB->FD, (_u8 *)&g_H2NCnysPattern.Short, SYNC_PATTERN_LEN);
2064 #endif
2065 
2066 #if (defined(slcb_GetTimestamp))
2067     _SlDrvStartMeasureTimeout(&TimeoutInfo, SYNC_PATTERN_TIMEOUT_IN_MSEC);
2068 #endif
2069 
2070     /*  2. Read 8 bytes (protocol aligned) - expected to be the sync pattern */
2071     NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[0], 8);
2072 
2073     /* read while first 4 bytes are different than last 4 bytes */
2074     while ( *(_u32 *)&pBuf[0] == *(_u32 *)&pBuf[4])
2075     {
2076          NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[4], 4);
2077 #if (defined(slcb_GetTimestamp))
2078         if (_SlDrvIsTimeoutExpired(&TimeoutInfo))
2079         {
2080             return SL_API_ABORTED;
2081         }
2082 #endif
2083     }
2084 
2085     /* scan for the sync pattern till found or timeout elapsed (if configured) */
2086     while (SearchSync && TimeoutState)
2087     {
2088         /* scan till we get the real sync pattern */
2089         for (ShiftIdx =0; ShiftIdx <=4 ; ShiftIdx++)
2090         {
2091            /* copy to local variable to ensure starting address which is 4-bytes aligned */
2092            sl_Memcpy(&SyncPattern[0],  &pBuf[ShiftIdx], 4);
2093 
2094            /* sync pattern found so complete the read to  4 bytes aligned */
2095            if (N2H_SYNC_PATTERN_MATCH(&SyncPattern[0], g_pCB->TxSeqNum))
2096            {
2097                    /* copy the bytes following the sync pattern to the buffer start */
2098                    sl_Memcpy(&pBuf[0],  &pBuf[ShiftIdx + SYNC_PATTERN_LEN], 4);
2099 
2100                    if (ShiftIdx != 0)
2101                    {
2102                          /* read the rest of the bytes (only if wer'e not aligned) (expected to complete the opcode + length fields ) */
2103                       NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[SYNC_PATTERN_LEN - ShiftIdx], ShiftIdx);
2104                    }
2105 
2106                   /* here we except to get the opcode + length or false doubled sync..*/
2107                   SearchSync = FALSE;
2108                   break;
2109            }
2110         }
2111 
2112         if (SearchSync == TRUE)
2113         {
2114             /* sync not found move top 4 bytes to bottom */
2115             *(_u32 *)&pBuf[0] = *(_u32 *)&pBuf[4];
2116 
2117             /* read 4 more bytes to the buffer top */
2118             NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[4], 4);
2119         }
2120 
2121  #if (defined (slcb_GetTimestamp))
2122 
2123         /* if we got here after first timeout detection, it means that we gave
2124             one more chance, and we can now exit the loop with timeout expiry  */
2125         if (TIMEOUT_ONE_MORE_SHOT == TimeoutState)
2126         {
2127             TimeoutState =  TIMEOUT_STATE_EXPIRY;
2128             break;
2129         }
2130 
2131         /* Timeout occurred. do not break now as we want to give one more chance in case
2132             the timeout occurred due to some external context switch */
2133         if (_SlDrvIsTimeoutExpired(&TimeoutInfo))
2134         {
2135             TimeoutState = TIMEOUT_ONE_MORE_SHOT;
2136         }
2137 
2138 #endif
2139     } /* end of while */
2140 
2141 #if (defined (slcb_GetTimestamp))
2142     if (TIMEOUT_STATE_EXPIRY  == TimeoutState)
2143     {
2144         return SL_API_ABORTED;
2145     }
2146 #endif
2147 
2148     /*  6. Scan for Double pattern. */
2149     while ( N2H_SYNC_PATTERN_MATCH(pBuf, g_pCB->TxSeqNum) )
2150     {
2151         _SL_DBG_CNT_INC(Work.DoubleSyncPattern);
2152         NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[0], SYNC_PATTERN_LEN);
2153     }
2154     g_pCB->TxSeqNum++;
2155 
2156     /*  7. Here we've read Generic Header (4 bytes opcode+length).
2157      * Now Read the Resp Specific header (4 more bytes). */
2158     NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[SYNC_PATTERN_LEN], _SL_RESP_SPEC_HDR_SIZE);
2159 
2160     return SL_RET_CODE_OK;
2161 }
2162 
2163 /* ***************************************************************************** */
2164 /*  _SlDrvBasicCmd */
2165 /* ***************************************************************************** */
2166 typedef union
2167 {
2168     _BasicResponse_t    Rsp;
2169 }_SlBasicCmdMsg_u;
2170 
2171 
_SlDrvBasicCmd(_SlOpcode_t Opcode)2172 _SlReturnVal_t _SlDrvBasicCmd(_SlOpcode_t Opcode)
2173 {
2174     _SlBasicCmdMsg_u       Msg;
2175     _SlCmdCtrl_t           CmdCtrl;
2176 
2177     _SlDrvMemZero(&Msg, (_u16)sizeof(_SlBasicCmdMsg_u));
2178     CmdCtrl.Opcode = Opcode;
2179     CmdCtrl.TxDescLen = 0;
2180     CmdCtrl.RxDescLen = (_SlArgSize_t)sizeof(_BasicResponse_t);
2181 
2182 
2183     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL));
2184 
2185     return (_SlReturnVal_t)Msg.Rsp.status;
2186 }
2187 
2188 /*****************************************************************************
2189   _SlDrvCmdSend_noLock
2190   Send SL command without waiting for command response
2191   This function is unprotected and the caller should make
2192   sure global lock is active. Used to send data within async event handler, where the driver is already locked.
2193 *****************************************************************************/
_SlDrvCmdSend_noLock(_SlCmdCtrl_t * pCmdCtrl,void * pTxRxDescBuff,_SlCmdExt_t * pCmdExt)2194 _SlReturnVal_t _SlDrvCmdSend_noLock(
2195     _SlCmdCtrl_t  *pCmdCtrl ,
2196     void          *pTxRxDescBuff ,
2197     _SlCmdExt_t   *pCmdExt)
2198 {
2199     _SlReturnVal_t RetVal;
2200     _u8            WaitForCmdRespOriginalVal;
2201 
2202     _SlFunctionParams_t originalFuncParms;
2203 
2204     /* save the current RespWait flag before clearing it */
2205     WaitForCmdRespOriginalVal = g_pCB->WaitForCmdResp;
2206 
2207     /* save the current command paramaters */
2208     sl_Memcpy(&originalFuncParms,  &g_pCB->FunctionParams, sizeof(_SlFunctionParams_t));
2209 
2210     g_pCB->WaitForCmdResp = FALSE;
2211 
2212     SL_TRACE0(DBG_MSG, MSG_312, "_SlDrvCmdSend_noLock: call _SlDrvMsgWrite");
2213 
2214     /* send the message */
2215     RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, pTxRxDescBuff);
2216 
2217     /* restore the original RespWait flag */
2218     g_pCB->WaitForCmdResp = WaitForCmdRespOriginalVal;
2219 
2220     /* restore the original command paramaters  */
2221     sl_Memcpy(&g_pCB->FunctionParams, &originalFuncParms, sizeof(_SlFunctionParams_t));
2222 
2223     return RetVal;
2224 }
2225 /*****************************************************************************
2226   _SlDrvCmdSend_noWait
2227   Send SL command without waiting for command response
2228   This function send command form any possiable context, without waiting.
2229 *****************************************************************************/
_SlDrvCmdSend_noWait(_SlCmdCtrl_t * pCmdCtrl,void * pTxRxDescBuff,_SlCmdExt_t * pCmdExt)2230 _SlReturnVal_t _SlDrvCmdSend_noWait(
2231     _SlCmdCtrl_t  *pCmdCtrl ,
2232     void          *pTxRxDescBuff ,
2233     _SlCmdExt_t   *pCmdExt)
2234 {
2235     _SlReturnVal_t RetVal;
2236 
2237     _SlFunctionParams_t originalFuncParms;
2238 
2239     SL_TRACE1(DBG_MSG, MSG_312, "\n\r_SlDrvCmdSend_noLock: call _SlDrvMsgWrite: %x\n\r", pCmdCtrl->Opcode);
2240 
2241     /* Save the current function parameters */
2242     sl_Memcpy(&originalFuncParms,  &g_pCB->FunctionParams, sizeof(_SlFunctionParams_t));
2243 
2244     /* send the message */
2245     RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, pTxRxDescBuff);
2246 
2247     /* Restore */
2248     sl_Memcpy(&g_pCB->FunctionParams, &originalFuncParms, sizeof(_SlFunctionParams_t));
2249 
2250     return RetVal;
2251 }
2252 
2253 /*****************************************************************************
2254   _SlDrvCmdSend
2255   Send SL command without waiting for command response
2256 *****************************************************************************/
_SlDrvCmdSend(_SlCmdCtrl_t * pCmdCtrl,void * pTxRxDescBuff,_SlCmdExt_t * pCmdExt)2257 _SlReturnVal_t _SlDrvCmdSend(
2258     _SlCmdCtrl_t  *pCmdCtrl ,
2259     void          *pTxRxDescBuff ,
2260     _SlCmdExt_t   *pCmdExt)
2261 {
2262     _SlReturnVal_t RetVal;
2263 
2264     _SlDrvObjLockWaitForever(&GlobalLockObj);
2265 
2266     g_pCB->WaitForCmdResp = FALSE;
2267 
2268     SL_TRACE1(DBG_MSG, MSG_312, "_SlDrvCmdSend: call _SlDrvMsgWrite:%x", pCmdCtrl->Opcode);
2269 
2270     /* send the message */
2271     RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, pTxRxDescBuff);
2272 
2273     _SlDrvObjUnLock(&GlobalLockObj);
2274 
2275     return RetVal;
2276 }
2277 
2278 
2279 /* ***************************************************************************** */
2280 /*  _SlDrvProtectAsyncRespSetting */
2281 /* ***************************************************************************** */
_SlDrvProtectAsyncRespSetting(_u8 * pAsyncRsp,_SlActionID_e ActionID,_u8 SocketID)2282 _SlReturnVal_t _SlDrvProtectAsyncRespSetting(_u8 *pAsyncRsp, _SlActionID_e ActionID, _u8 SocketID)
2283 {
2284     _i16 ObjIdx;
2285 
2286     /* Use Obj to issue the command, if not available try later */
2287     ObjIdx = _SlDrvWaitForPoolObj(ActionID, SocketID);
2288 
2289     if (SL_RET_CODE_STOP_IN_PROGRESS == ObjIdx)
2290     {
2291         return SL_RET_CODE_STOP_IN_PROGRESS;
2292     }
2293     else if (MAX_CONCURRENT_ACTIONS == ObjIdx)
2294     {
2295         return SL_POOL_IS_EMPTY;
2296     }
2297     else
2298     {
2299         SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
2300         g_pCB->ObjPool[ObjIdx].pRespArgs = pAsyncRsp;
2301         SL_DRV_PROTECTION_OBJ_UNLOCK();
2302     }
2303 
2304     return ObjIdx;
2305 }
2306 
2307 
2308 /* ***************************************************************************** */
2309 /*  _SlDrvIsSpawnOwnGlobalLock */
2310 /* ***************************************************************************** */
2311 #if (!defined (SL_PLATFORM_EXTERNAL_SPAWN))
_SlDrvIsSpawnOwnGlobalLock()2312 _u8 _SlDrvIsSpawnOwnGlobalLock()
2313 {
2314 #ifdef SL_PLATFORM_MULTI_THREADED
2315     _u32 ThreadId = (_i32)sl_GetThreadID();
2316     return _SlInternalIsItSpawnThread(ThreadId);
2317 #else
2318     return (gGlobalLockContextOwner == GLOBAL_LOCK_CONTEXT_OWNER_SPAWN);
2319 #endif
2320 }
2321 #endif
2322 /* ***************************************************************************** */
2323 /*  _SlDrvWaitForPoolObj */
2324 /* ***************************************************************************** */
_SlDrvWaitForPoolObj(_u8 ActionID,_u8 SocketID)2325 _SlReturnVal_t _SlDrvWaitForPoolObj(_u8 ActionID, _u8 SocketID)
2326 {
2327     _u8 CurrObjIndex = MAX_CONCURRENT_ACTIONS;
2328 
2329     /* Get free object  */
2330     SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
2331 
2332     if (MAX_CONCURRENT_ACTIONS > g_pCB->FreePoolIdx)
2333     {
2334         /* save the current obj index */
2335         CurrObjIndex = g_pCB->FreePoolIdx;
2336         /* set the new free index */
2337         if (MAX_CONCURRENT_ACTIONS > g_pCB->ObjPool[CurrObjIndex].NextIndex)
2338         {
2339             g_pCB->FreePoolIdx = g_pCB->ObjPool[CurrObjIndex].NextIndex;
2340         }
2341         else
2342         {
2343             /* No further free actions available */
2344             g_pCB->FreePoolIdx = MAX_CONCURRENT_ACTIONS;
2345         }
2346     }
2347     else
2348     {
2349         SL_DRV_PROTECTION_OBJ_UNLOCK();
2350         return CurrObjIndex;
2351     }
2352     g_pCB->ObjPool[CurrObjIndex].ActionID = (_u8)ActionID;
2353     if (SL_MAX_SOCKETS > SocketID)
2354     {
2355         g_pCB->ObjPool[CurrObjIndex].AdditionalData = SocketID;
2356     }
2357     /*In case this action is socket related, SocketID bit will be on
2358     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 */
2359     while ( ( (SL_MAX_SOCKETS > SocketID) && (g_pCB->ActiveActionsBitmap & (1<<SocketID)) ) ||
2360             ( (g_pCB->ActiveActionsBitmap & ( MULTI_SELECT_MASK & (1<<ActionID))) && (SL_MAX_SOCKETS == SocketID) ) )
2361     {
2362         /* If we are in spawn context, this is an API which was called from event handler,
2363         return error since there is no option to block the spawn context on the pending sync obj */
2364 #if (defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))
2365         if (_SlDrvIsSpawnOwnGlobalLock())
2366         {
2367             g_pCB->ObjPool[CurrObjIndex].ActionID = 0;
2368             g_pCB->ObjPool[CurrObjIndex].AdditionalData = SL_MAX_SOCKETS;
2369             g_pCB->FreePoolIdx = CurrObjIndex;
2370             SL_DRV_PROTECTION_OBJ_UNLOCK();
2371             return MAX_CONCURRENT_ACTIONS;
2372         }
2373 #endif
2374         /* action in progress - move to pending list */
2375         g_pCB->ObjPool[CurrObjIndex].NextIndex = g_pCB->PendingPoolIdx;
2376         g_pCB->PendingPoolIdx = CurrObjIndex;
2377         SL_DRV_PROTECTION_OBJ_UNLOCK();
2378 
2379         /* wait for action to be free */
2380         (void)_SlDrvSyncObjWaitForever(&g_pCB->ObjPool[CurrObjIndex].SyncObj);
2381         if (SL_IS_DEVICE_STOP_IN_PROGRESS)
2382         {
2383             OSI_RET_OK_CHECK(sl_SyncObjDelete(&g_pCB->ObjPool[CurrObjIndex].SyncObj));
2384             SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
2385             g_pCB->NumOfDeletedSyncObj++;
2386             SL_DRV_PROTECTION_OBJ_UNLOCK();
2387             return SL_RET_CODE_STOP_IN_PROGRESS;
2388         }
2389 
2390         /* set params and move to active (remove from pending list at _SlDrvReleasePoolObj) */
2391         SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
2392     }
2393 
2394     /* mark as active. Set socket as active if action is on socket, otherwise mark action as active */
2395     if (SL_MAX_SOCKETS > SocketID)
2396     {
2397         g_pCB->ActiveActionsBitmap |= (1<<SocketID);
2398     }
2399     else
2400     {
2401         g_pCB->ActiveActionsBitmap |= (1<<ActionID);
2402     }
2403     /* move to active list  */
2404     g_pCB->ObjPool[CurrObjIndex].NextIndex = g_pCB->ActivePoolIdx;
2405     g_pCB->ActivePoolIdx = CurrObjIndex;
2406 
2407     /* unlock */
2408     SL_DRV_PROTECTION_OBJ_UNLOCK();
2409 
2410     /* Increment the API in progress counter as this routine is called for every
2411        API, which will be waiting for async event to be released */
2412     _SlDrvUpdateApiInProgress(API_IN_PROGRESS_UPDATE_INCREMENT);
2413 
2414     return CurrObjIndex;
2415 }
2416 
2417 /* ******************************************************************************/
2418 /*  _SlDrvReleasePoolObj */
2419 /* ******************************************************************************/
_SlDrvReleasePoolObj(_u8 ObjIdx)2420 _SlReturnVal_t _SlDrvReleasePoolObj(_u8 ObjIdx)
2421 {
2422     _u8 PendingIndex;
2423 
2424     /* Delete sync obj in case stop in progress and return */
2425     if (SL_IS_DEVICE_STOP_IN_PROGRESS)
2426     {
2427         OSI_RET_OK_CHECK(sl_SyncObjDelete(&g_pCB->ObjPool[ObjIdx].SyncObj));
2428         SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
2429         g_pCB->NumOfDeletedSyncObj++;
2430         SL_DRV_PROTECTION_OBJ_UNLOCK();
2431         return SL_RET_CODE_OK;
2432     }
2433 
2434     SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
2435 
2436     /* go over the pending list and release other pending action if needed */
2437     PendingIndex = g_pCB->PendingPoolIdx;
2438 
2439     while(MAX_CONCURRENT_ACTIONS > PendingIndex)
2440     {
2441         /* In case this action is socket related, SocketID is in use, otherwise will be set to SL_MAX_SOCKETS */
2442         if ( (g_pCB->ObjPool[PendingIndex].ActionID == g_pCB->ObjPool[ObjIdx].ActionID) &&
2443             ( (SL_MAX_SOCKETS == (g_pCB->ObjPool[PendingIndex].AdditionalData & SL_BSD_SOCKET_ID_MASK)) ||
2444             ((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) ))) )
2445         {
2446             /* remove from pending list */
2447             _SlDrvRemoveFromList(&g_pCB->PendingPoolIdx, PendingIndex);
2448              SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[PendingIndex].SyncObj);
2449              break;
2450         }
2451         PendingIndex = g_pCB->ObjPool[PendingIndex].NextIndex;
2452     }
2453 
2454     if (SL_MAX_SOCKETS > (g_pCB->ObjPool[ObjIdx].AdditionalData & SL_BSD_SOCKET_ID_MASK))
2455     {
2456     /* unset socketID  */
2457         g_pCB->ActiveActionsBitmap &= ~(1<<(g_pCB->ObjPool[ObjIdx].AdditionalData & SL_BSD_SOCKET_ID_MASK));
2458     }
2459     else
2460     {
2461     /* unset actionID  */
2462         g_pCB->ActiveActionsBitmap &= ~(1<<g_pCB->ObjPool[ObjIdx].ActionID);
2463     }
2464 
2465     /* delete old data */
2466     g_pCB->ObjPool[ObjIdx].pRespArgs = NULL;
2467     g_pCB->ObjPool[ObjIdx].ActionID = 0;
2468     g_pCB->ObjPool[ObjIdx].AdditionalData = SL_MAX_SOCKETS;
2469 
2470     /* remove from active list */
2471     _SlDrvRemoveFromList(&g_pCB->ActivePoolIdx, ObjIdx);
2472 
2473     /* move to free list */
2474     g_pCB->ObjPool[ObjIdx].NextIndex = g_pCB->FreePoolIdx;
2475     g_pCB->FreePoolIdx = ObjIdx;
2476 
2477     SL_DRV_PROTECTION_OBJ_UNLOCK();
2478 
2479     /* Here we decrement the API in progrees counter as we just released the pool object,
2480        which is held till the API is finished (async event received) */
2481     _SlDrvUpdateApiInProgress(API_IN_PROGRESS_UPDATE_DECREMENT);
2482     return SL_RET_CODE_OK;
2483 }
2484 
2485 /* ******************************************************************************/
2486 /*  _SlDrvReleaseAllActivePendingPoolObj */
2487 /* ******************************************************************************/
_SlDrvReleaseAllActivePendingPoolObj()2488 _SlReturnVal_t _SlDrvReleaseAllActivePendingPoolObj()
2489 {
2490     _u8 ActiveIndex;
2491 
2492     SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
2493 
2494     /* go over the active list and release each action with error */
2495     ActiveIndex = g_pCB->ActivePoolIdx;
2496 
2497     while (MAX_CONCURRENT_ACTIONS > ActiveIndex)
2498     {
2499         /* Set error in case sync objects release due to stop device command */
2500         if (g_pCB->ObjPool[ActiveIndex].ActionID == NETUTIL_CMD_ID)
2501         {
2502             ((_SlNetUtilCmdData_t *)(g_pCB->ObjPool[ActiveIndex].pRespArgs))->Status = SL_RET_CODE_STOP_IN_PROGRESS;
2503         }
2504         else if (g_pCB->ObjPool[ActiveIndex].ActionID == RECV_ID)
2505         {
2506             ((SlSocketResponse_t *)((_SlArgsData_t *)(g_pCB->ObjPool[ActiveIndex].pRespArgs))->pArgs)->StatusOrLen = SL_RET_CODE_STOP_IN_PROGRESS;
2507         }
2508         /* First 2 bytes of all async response holds the status except with NETUTIL_CMD_ID and RECV_ID */
2509         else
2510         {
2511             ((SlSocketResponse_t *)(g_pCB->ObjPool[ActiveIndex].pRespArgs))->StatusOrLen = SL_RET_CODE_STOP_IN_PROGRESS;
2512         }
2513         /* Signal the pool obj*/
2514         SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[ActiveIndex].SyncObj);
2515         ActiveIndex = g_pCB->ObjPool[ActiveIndex].NextIndex;
2516     }
2517 
2518     /* go over the pending list and release each action */
2519     ActiveIndex = g_pCB->PendingPoolIdx;
2520 
2521     while (MAX_CONCURRENT_ACTIONS > ActiveIndex)
2522     {
2523         /* Signal the pool obj*/
2524         SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[ActiveIndex].SyncObj);
2525         ActiveIndex = g_pCB->ObjPool[ActiveIndex].NextIndex;
2526     }
2527 
2528     /* Delete only unoccupied objects from the Free list, other obj (pending and active)
2529     will be deleted from the relevant context */
2530     ActiveIndex = g_pCB->FreePoolIdx;
2531     while(MAX_CONCURRENT_ACTIONS > ActiveIndex)
2532     {
2533         OSI_RET_OK_CHECK(sl_SyncObjDelete(&g_pCB->ObjPool[ActiveIndex].SyncObj));
2534         g_pCB->NumOfDeletedSyncObj++;
2535         ActiveIndex = g_pCB->ObjPool[ActiveIndex].NextIndex;
2536     }
2537     /* In case trigger select in progress, delete the sync obj */
2538 #if defined(slcb_SocketTriggerEventHandler)
2539     if (MAX_CONCURRENT_ACTIONS != g_pCB->SocketTriggerSelect.Info.ObjPoolIdx)
2540     {
2541         OSI_RET_OK_CHECK(sl_SyncObjDelete(&g_pCB->ObjPool[g_pCB->SocketTriggerSelect.Info.ObjPoolIdx].SyncObj));
2542         g_pCB->NumOfDeletedSyncObj++;
2543     }
2544 #endif
2545     SL_DRV_PROTECTION_OBJ_UNLOCK();
2546     return SL_RET_CODE_OK;
2547 }
2548 
2549 /* ******************************************************************************/
2550 /* _SlDrvRemoveFromList  */
2551 /* ******************************************************************************/
_SlDrvRemoveFromList(_u8 * ListIndex,_u8 ItemIndex)2552 static void _SlDrvRemoveFromList(_u8 *ListIndex, _u8 ItemIndex)
2553 {
2554     _u8 Idx;
2555 
2556     if (MAX_CONCURRENT_ACTIONS == g_pCB->ObjPool[*ListIndex].NextIndex)
2557     {
2558         *ListIndex = MAX_CONCURRENT_ACTIONS;
2559     }
2560     /* need to remove the first item in the list and therefore update the global which holds this index */
2561     else if (*ListIndex == ItemIndex)
2562     {
2563         *ListIndex = g_pCB->ObjPool[ItemIndex].NextIndex;
2564     }
2565     else
2566     {
2567         Idx = *ListIndex;
2568 
2569         while(MAX_CONCURRENT_ACTIONS > Idx)
2570         {
2571             /* remove from list */
2572             if (g_pCB->ObjPool[Idx].NextIndex == ItemIndex)
2573             {
2574                 g_pCB->ObjPool[Idx].NextIndex = g_pCB->ObjPool[ItemIndex].NextIndex;
2575                 break;
2576             }
2577 
2578             Idx = g_pCB->ObjPool[Idx].NextIndex;
2579         }
2580     }
2581 }
2582 
2583 
2584 /* ******************************************************************************/
2585 /*  _SlDrvFindAndSetActiveObj                                                     */
2586 /* ******************************************************************************/
_SlDrvFindAndSetActiveObj(_SlOpcode_t Opcode,_u8 Sd)2587 static _SlReturnVal_t _SlDrvFindAndSetActiveObj(_SlOpcode_t  Opcode, _u8 Sd)
2588 {
2589     _u8 ActiveIndex;
2590 
2591     ActiveIndex = g_pCB->ActivePoolIdx;
2592     /* go over the active list if exist to find obj waiting for this Async event */
2593 
2594     while (MAX_CONCURRENT_ACTIONS > ActiveIndex)
2595     {
2596         /* unset the Ipv4\IPv6 bit in the opcode if family bit was set  */
2597         if (g_pCB->ObjPool[ActiveIndex].AdditionalData & SL_NETAPP_FAMILY_MASK)
2598         {
2599             Opcode &= ~SL_OPCODE_IPV6;
2600         }
2601 
2602         if ((g_pCB->ObjPool[ActiveIndex].ActionID == RECV_ID) && (Sd == g_pCB->ObjPool[ActiveIndex].AdditionalData) &&
2603                         ( (SL_OPCODE_SOCKET_RECVASYNCRESPONSE == Opcode) || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE == Opcode)
2604                         || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE_V6 == Opcode))
2605                )
2606         {
2607             g_pCB->FunctionParams.AsyncExt.ActionIndex = ActiveIndex;
2608             return SL_RET_CODE_OK;
2609         }
2610         /* In case this action is socket related, SocketID is in use, otherwise will be set to SL_MAX_SOCKETS */
2611         if ( (_SlActionLookupTable[ g_pCB->ObjPool[ActiveIndex].ActionID - MAX_SOCKET_ENUM_IDX].ActionAsyncOpcode == Opcode) &&
2612             ( ((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)) ) )
2613         {
2614             /* set handler */
2615             g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler = _SlActionLookupTable[ g_pCB->ObjPool[ActiveIndex].ActionID - MAX_SOCKET_ENUM_IDX].AsyncEventHandler;
2616             g_pCB->FunctionParams.AsyncExt.ActionIndex = ActiveIndex;
2617             return SL_RET_CODE_OK;
2618         }
2619         ActiveIndex = g_pCB->ObjPool[ActiveIndex].NextIndex;
2620     }
2621 
2622     return SL_RET_OBJ_NOT_SET;
2623 }
2624 
2625 #if defined(slcb_NetAppHttpServerHdlr) || defined(EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS)
_SlDrvDispatchHttpServerEvents(SlNetAppHttpServerEvent_t * slHttpServerEvent,SlNetAppHttpServerResponse_t * slHttpServerResponse)2626 void _SlDrvDispatchHttpServerEvents(SlNetAppHttpServerEvent_t *slHttpServerEvent, SlNetAppHttpServerResponse_t *slHttpServerResponse)
2627 {
2628     _SlDrvHandleHttpServerEvents (slHttpServerEvent, slHttpServerResponse);
2629 }
2630 #endif
2631 
2632 #if defined(slcb_NetAppRequestHdlr) || defined(EXT_LIB_REGISTERED_NETAPP_REQUEST_EVENTS)
_SlDrvDispatchNetAppRequestEvents(SlNetAppRequest_t * slNetAppRequestEvent,SlNetAppResponse_t * slNetAppResponse)2633 void _SlDrvDispatchNetAppRequestEvents(SlNetAppRequest_t *slNetAppRequestEvent, SlNetAppResponse_t *slNetAppResponse)
2634 {
2635     _SlDrvHandleNetAppRequestEvents (slNetAppRequestEvent, slNetAppResponse);
2636 }
2637 #endif
2638 
2639 
2640 /* Wrappers for the object functions */
_SlDrvSyncObjSignal(_SlSyncObj_t * pSyncObj)2641 _SlReturnVal_t _SlDrvSyncObjSignal(_SlSyncObj_t *pSyncObj)
2642 {
2643     OSI_RET_OK_CHECK(sl_SyncObjSignal(pSyncObj));
2644     return SL_OS_RET_CODE_OK;
2645 }
2646 
_SlDrvObjLockWaitForever(_SlLockObj_t * pLockObj)2647 _SlReturnVal_t _SlDrvObjLockWaitForever(_SlLockObj_t *pLockObj)
2648 {
2649     OSI_RET_OK_CHECK(sl_LockObjLock(pLockObj, SL_OS_WAIT_FOREVER));
2650     return SL_OS_RET_CODE_OK;
2651 }
2652 
_SlDrvProtectionObjLockWaitForever(void)2653 _SlReturnVal_t _SlDrvProtectionObjLockWaitForever(void)
2654 {
2655     OSI_RET_OK_CHECK(sl_LockObjLock(&g_pCB->ProtectionLockObj, SL_OS_WAIT_FOREVER));
2656 
2657     return SL_OS_RET_CODE_OK;
2658 }
2659 
_SlDrvObjUnLock(_SlLockObj_t * pLockObj)2660 _SlReturnVal_t _SlDrvObjUnLock(_SlLockObj_t *pLockObj)
2661 {
2662     OSI_RET_OK_CHECK(sl_LockObjUnlock(pLockObj));
2663 
2664     return SL_OS_RET_CODE_OK;
2665 }
2666 
_SlDrvProtectionObjUnLock(void)2667 _SlReturnVal_t _SlDrvProtectionObjUnLock(void)
2668 {
2669     OSI_RET_OK_CHECK(sl_LockObjUnlock(&g_pCB->ProtectionLockObj));
2670     return SL_OS_RET_CODE_OK;
2671 }
2672 
_SlDrvObjGlobalLockWaitForever(_u32 Flags)2673 _SlReturnVal_t _SlDrvObjGlobalLockWaitForever(_u32 Flags)
2674 {
2675     _SlReturnVal_t ret;
2676     _u16 Opcode;
2677     _u16 Silo;
2678     _u8 UpdateApiInProgress = (Flags & GLOBAL_LOCK_FLAGS_UPDATE_API_IN_PROGRESS);
2679     _u16 IsProvStopApi = (Flags & GLOBAL_LOCK_FLAGS_PROVISIONING_STOP_API);
2680 
2681     if (SL_IS_RESTART_REQUIRED)
2682     {
2683          return SL_API_ABORTED;
2684     }
2685 
2686     gGlobalLockCntRequested++;
2687 
2688     ret = sl_LockObjLock(&GlobalLockObj, SL_OS_WAIT_FOREVER);
2689 
2690     /*  start/stop device is in progress so return right away */
2691     if (SL_IS_DEVICE_START_IN_PROGRESS || SL_IS_DEVICE_STOP_IN_PROGRESS || SL_IS_PROVISIONING_IN_PROGRESS)
2692     {
2693         return ret;
2694     }
2695 
2696     /* after the lock acquired check if API is allowed */
2697     if (0 == ret)
2698     {
2699 
2700         Opcode = (Flags >> 16);
2701         Silo = Opcode & ((0xF << SL_OPCODE_SILO_OFFSET));
2702 
2703         /* After acquiring the lock, check if there is stop in progress */
2704         if (Opcode != SL_OPCODE_DEVICE_STOP_COMMAND)
2705         {
2706             _i16 Status = _SlDrvDriverIsApiAllowed(Silo);
2707 
2708             if (Status)
2709             {
2710                 sl_LockObjUnlock(&GlobalLockObj);
2711                 return Status;
2712             }
2713         }
2714     }
2715 
2716     /* if lock was successfully taken and increment of the API in progress is required */
2717     if ((0 == ret) && (UpdateApiInProgress))
2718     {
2719         if (!SL_IS_PROVISIONING_ACTIVE || SL_IS_PROVISIONING_API_ALLOWED)
2720         {
2721             /* Increment the API in progress counter */
2722             _SlDrvUpdateApiInProgress(API_IN_PROGRESS_UPDATE_INCREMENT);
2723         }
2724         /* if we are in provisioning than don't abort the stop provisioning cmd.. */
2725         else if (FALSE == IsProvStopApi )
2726         {
2727             /*  Provisioning is active so release the lock immediately as
2728                 we do not want to allow more APIs to run. */
2729             SL_DRV_LOCK_GLOBAL_UNLOCK(TRUE);
2730             return SL_RET_CODE_PROVISIONING_IN_PROGRESS;
2731         }
2732     }
2733 
2734     return ret;
2735 }
_SlDrvGlobalObjUnLock(_u8 bDecrementApiInProgress)2736 _SlReturnVal_t _SlDrvGlobalObjUnLock(_u8 bDecrementApiInProgress)
2737 {
2738     gGlobalLockCntReleased++;
2739 
2740     OSI_RET_OK_CHECK(sl_LockObjUnlock(&GlobalLockObj));
2741 
2742     if (bDecrementApiInProgress)
2743     {
2744         _SlDrvUpdateApiInProgress(API_IN_PROGRESS_UPDATE_DECREMENT);
2745     }
2746 
2747     return SL_OS_RET_CODE_OK;
2748 }
2749 
_SlDrvMemZero(void * Addr,_u16 size)2750 void _SlDrvMemZero(void* Addr, _u16 size)
2751 {
2752     sl_Memset(Addr, 0, size);
2753 }
2754 
2755 
_SlDrvResetCmdExt(_SlCmdExt_t * pCmdExt)2756 void _SlDrvResetCmdExt(_SlCmdExt_t* pCmdExt)
2757 {
2758     _SlDrvMemZero(pCmdExt, (_u16)sizeof (_SlCmdExt_t));
2759 }
2760 
2761 
2762 
_SlDrvSyncObjWaitForever(_SlSyncObj_t * pSyncObj)2763 _SlReturnVal_t  _SlDrvSyncObjWaitForever(_SlSyncObj_t *pSyncObj)
2764 {
2765     _SlReturnVal_t RetVal = sl_SyncObjWait(pSyncObj, SL_OS_WAIT_FOREVER);
2766 
2767     /*  if the wait is finished and we detect that restart is required (we in the middle of error handling),
2768           than we should abort immediately from the current API command execution
2769     */
2770     if (SL_IS_RESTART_REQUIRED)
2771     {
2772         return SL_API_ABORTED;
2773     }
2774 
2775     return RetVal;
2776 }
2777 
2778 
2779 #if (defined(slcb_GetTimestamp))
2780 
_SlDrvStartMeasureTimeout(_SlTimeoutParams_t * pTimeoutInfo,_u32 TimeoutInMsec)2781 void _SlDrvStartMeasureTimeout(_SlTimeoutParams_t *pTimeoutInfo, _u32 TimeoutInMsec)
2782 {
2783     _SlDrvMemZero(pTimeoutInfo, sizeof (_SlTimeoutParams_t));
2784 
2785     pTimeoutInfo->Total10MSecUnits = TimeoutInMsec / 10;
2786     pTimeoutInfo->TSPrev = slcb_GetTimestamp();
2787 }
2788 
_SlDrvIsTimeoutExpired(_SlTimeoutParams_t * pTimeoutInfo)2789 _u8 _SlDrvIsTimeoutExpired(_SlTimeoutParams_t *pTimeoutInfo)
2790 {
2791     _u32 TSCount;
2792 
2793     pTimeoutInfo->TSCurr = slcb_GetTimestamp();
2794 
2795     if (pTimeoutInfo->TSCurr >= pTimeoutInfo->TSPrev)
2796     {
2797         pTimeoutInfo->DeltaTicks = pTimeoutInfo->TSCurr - pTimeoutInfo->TSPrev;
2798     }
2799     else
2800     {
2801         pTimeoutInfo->DeltaTicks =  (SL_TIMESTAMP_MAX_VALUE - pTimeoutInfo->TSPrev) + pTimeoutInfo->TSCurr;
2802     }
2803 
2804     TSCount = pTimeoutInfo->DeltaTicksReminder + pTimeoutInfo->DeltaTicks;
2805 
2806 
2807     if (TSCount > SL_TIMESTAMP_TICKS_IN_10_MILLISECONDS)
2808     {
2809         pTimeoutInfo->Total10MSecUnits -= (TSCount / SL_TIMESTAMP_TICKS_IN_10_MILLISECONDS);
2810         pTimeoutInfo->DeltaTicksReminder = TSCount % SL_TIMESTAMP_TICKS_IN_10_MILLISECONDS;
2811 
2812         if (pTimeoutInfo->Total10MSecUnits > 0)
2813         {
2814             pTimeoutInfo->TSPrev =  pTimeoutInfo->TSCurr;
2815         }
2816         else
2817         {
2818             return TRUE;
2819         }
2820     }
2821 
2822     return FALSE;
2823 }
2824 
2825 #endif
2826 
_SlDrvHandleFatalError(_u32 errorId,_u32 info1,_u32 info2)2827 void _SlDrvHandleFatalError(_u32 errorId, _u32 info1, _u32 info2)
2828 {
2829     _u8 i;
2830     SlDeviceFatal_t  FatalEvent;
2831 
2832     _SlDrvMemZero(&FatalEvent, sizeof(FatalEvent));
2833 
2834     if (SL_IS_RESTART_REQUIRED)
2835     {
2836         return;
2837     }
2838 
2839     /* set the restart flag */
2840     SL_SET_RESTART_REQUIRED;
2841 
2842      /* Upon the deletion of the mutex, all thread waiting on this
2843      mutex will return immediately with an error (i.e. MUTEX_DELETED status) */
2844      (void)sl_LockObjDelete(&GlobalLockObj);
2845 
2846      /* Mark the global lock as deleted */
2847      SL_UNSET_GLOBAL_LOCK_INIT;
2848 
2849     /* signal all waiting sync objects */
2850     for (i=0; i< MAX_CONCURRENT_ACTIONS; i++)
2851     {
2852         SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[i].SyncObj);
2853     }
2854 
2855     /* prepare the event and notify the user app/ext libraries */
2856     FatalEvent.Id = errorId;
2857 
2858     switch (errorId)
2859     {
2860         case SL_DEVICE_EVENT_FATAL_DEVICE_ABORT:
2861         {
2862             /* set the Abort Type */
2863             FatalEvent.Data.DeviceAssert.Code = info1;
2864 
2865             /* set the Abort Data */
2866             FatalEvent.Data.DeviceAssert.Value = info2;
2867         }
2868         break;
2869 
2870         case SL_DEVICE_EVENT_FATAL_NO_CMD_ACK:
2871         {
2872             /* set the command opcode */
2873             FatalEvent.Data.NoCmdAck.Code = info1;
2874         }
2875         break;
2876 
2877         case SL_DEVICE_EVENT_FATAL_CMD_TIMEOUT:
2878         {
2879             /* set the expected async event opcode */
2880             FatalEvent.Data.CmdTimeout.Code = info1;
2881         }
2882         break;
2883 
2884         case SL_DEVICE_EVENT_FATAL_SYNC_LOSS:
2885         case SL_DEVICE_EVENT_FATAL_DRIVER_ABORT:
2886             /* No Info to transport */
2887             break;
2888 
2889     }
2890 
2891 #if defined(slcb_DeviceFatalErrorEvtHdlr) || defined (EXT_LIB_REGISTERED_FATAL_ERROR_EVENTS)
2892     /* call the registered fatal error handlers */
2893     _SlDrvHandleFatalErrorEvents(&FatalEvent);
2894 #endif
2895 }
2896 
_SlDrvSyncObjWaitTimeout(_SlSyncObj_t * pSyncObj,_u32 timeoutVal,_u32 asyncEventOpcode)2897 _SlReturnVal_t  _SlDrvSyncObjWaitTimeout(_SlSyncObj_t *pSyncObj, _u32 timeoutVal, _u32 asyncEventOpcode)
2898 {
2899     _SlReturnVal_t ret = sl_SyncObjWait(pSyncObj, timeoutVal);
2900 
2901     /* if timeout occured...*/
2902     if (ret)
2903     {
2904         _SlDrvHandleFatalError(SL_DEVICE_EVENT_FATAL_CMD_TIMEOUT, asyncEventOpcode, timeoutVal);
2905         return SL_API_ABORTED;
2906     }
2907     else if (SL_IS_RESTART_REQUIRED)
2908     {
2909         return SL_API_ABORTED;
2910     }
2911 
2912     return SL_RET_CODE_OK;
2913 }
2914 
2915 
_SlDrvUpdateApiInProgress(_i8 Value)2916 static void _SlDrvUpdateApiInProgress(_i8 Value)
2917 {
2918     SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
2919 
2920     g_pCB->ApiInProgressCnt  += Value;
2921 
2922     SL_DRV_PROTECTION_OBJ_UNLOCK();
2923 }
2924 
_SlDrvIsApiInProgress(void)2925 _i8 _SlDrvIsApiInProgress(void)
2926 {
2927     if (g_pCB != NULL)
2928     {
2929         return (g_pCB->ApiInProgressCnt > 0);
2930     }
2931 
2932     return TRUE;
2933 }
2934 
2935 
2936 #ifdef slcb_GetTimestamp
2937 
_SlDrvSleep(_u16 DurationInMsec)2938 void _SlDrvSleep(_u16 DurationInMsec)
2939 {
2940     _SlTimeoutParams_t      TimeoutInfo={0};
2941 
2942     _SlDrvStartMeasureTimeout(&TimeoutInfo, DurationInMsec);
2943 
2944     while(!_SlDrvIsTimeoutExpired(&TimeoutInfo));
2945 }
2946 #endif
2947 
2948 #ifndef SL_PLATFORM_MULTI_THREADED
_SlDrvSetGlobalLockOwner(_u8 Owner)2949 void _SlDrvSetGlobalLockOwner(_u8 Owner)
2950 {
2951     gGlobalLockContextOwner = Owner;
2952 }
2953 #endif
2954 
2955 
_SlDrvWaitForInternalAsyncEvent(_u8 ObjIdx,_u32 Timeout,_SlOpcode_t Opcode)2956 _SlReturnVal_t _SlDrvWaitForInternalAsyncEvent(_u8 ObjIdx , _u32 Timeout, _SlOpcode_t Opcode)
2957 {
2958 
2959 #if (defined(SL_PLATFORM_EXTERNAL_SPAWN) || !defined(SL_PLATFORM_MULTI_THREADED))
2960     SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->ObjPool[ObjIdx].SyncObj);
2961     return SL_OS_RET_CODE_OK;
2962 #else
2963     _SlTimeoutParams_t SlTimeoutInfo = { 0 };
2964     if (_SlDrvIsSpawnOwnGlobalLock())
2965     {
2966 #if (defined(slcb_GetTimestamp))
2967         _SlDrvStartMeasureTimeout(&SlTimeoutInfo, Timeout);
2968         while (!Timeout || !_SlDrvIsTimeoutExpired(&SlTimeoutInfo))
2969 #endif
2970         {
2971             /* If we are in spawn context, this is an API which was called from event handler,
2972             read any async event and check if we got signaled */
2973             _SlInternalSpawnWaitForEvent();
2974             /* is it mine? */
2975             if (0 == sl_SyncObjWait(&g_pCB->ObjPool[ObjIdx].SyncObj, SL_OS_NO_WAIT))
2976             {
2977                 return SL_OS_RET_CODE_OK;
2978             }
2979         }
2980         /* if timeout occured...*/
2981         _SlDrvHandleFatalError(SL_DEVICE_EVENT_FATAL_CMD_TIMEOUT, Opcode, Timeout);
2982         return SL_API_ABORTED;
2983     }
2984     else
2985     {
2986         if (Timeout)
2987         {
2988             SL_DRV_SYNC_OBJ_WAIT_TIMEOUT(&g_pCB->ObjPool[ObjIdx].SyncObj, Timeout, Opcode);
2989         }
2990         else
2991         {
2992             SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->ObjPool[ObjIdx].SyncObj);
2993         }
2994         return SL_OS_RET_CODE_OK;
2995     }
2996 
2997 #endif
2998 }
2999 
3000 #if (defined(SL_PLATFORM_MULTI_THREADED) && !defined(SL_MEMORY_MGMT_DYNAMIC))
_SlGetStatSpawnListItem(_u16 AsyncEventLen)3001 _SlAsyncRespBuf_t* _SlGetStatSpawnListItem(_u16 AsyncEventLen)
3002 {
3003     _u8 Idx = 0;
3004     /* Find free buffer from the pool */
3005     while (Idx < SL_MAX_ASYNC_BUFFERS)
3006     {
3007         if (0xFF == g_StatMem.AsyncBufPool[Idx].ActionIndex)
3008         {
3009             /* copy buffer */
3010             return &g_StatMem.AsyncBufPool[Idx];
3011         }
3012         Idx++;
3013     }
3014     return NULL;
3015 }
3016 #endif
3017 
3018 #if defined(SL_PLATFORM_MULTI_THREADED)
_SlSpawnMsgListInsert(_u16 AsyncEventLen,_u8 * pAsyncBuf)3019 _SlReturnVal_t _SlSpawnMsgListInsert(_u16 AsyncEventLen, _u8 *pAsyncBuf)
3020 {
3021     _SlReturnVal_t RetVal = SL_OS_RET_CODE_OK;
3022 
3023     /* protect the item insertion */
3024     SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
3025 
3026 #ifdef SL_MEMORY_MGMT_DYNAMIC
3027     _SlSpawnMsgItem_t* pCurr = NULL;
3028     _SlSpawnMsgItem_t* pItem;
3029 
3030     pItem = (_SlSpawnMsgItem_t*)sl_Malloc(sizeof(_SlSpawnMsgItem_t));
3031     if (pItem == NULL)
3032     {
3033         RetVal = SL_RET_CODE_NO_FREE_ASYNC_BUFFERS_ERROR;
3034         SL_DRV_PROTECTION_OBJ_UNLOCK();
3035         return RetVal;
3036     }
3037     /* now allocate the buffer itself */
3038     pItem->Buffer = (void*)sl_Malloc(AsyncEventLen);
3039     if (pItem->Buffer == NULL)
3040     {
3041         sl_Free(pItem);
3042         RetVal = SL_RET_CODE_NO_FREE_ASYNC_BUFFERS_ERROR;
3043         SL_DRV_PROTECTION_OBJ_UNLOCK();
3044         return RetVal;
3045     }
3046     pItem->next = NULL;
3047     /* if list is empty point to the allocated one */
3048     if (g_pCB->spawnMsgList == NULL)
3049     {
3050         g_pCB->spawnMsgList = pItem;
3051     }
3052     else
3053     {
3054         pCurr = g_pCB->spawnMsgList;
3055         /* go to end of list */
3056         while (pCurr->next != NULL)
3057         {
3058             pCurr = pCurr->next;
3059         }
3060         /* we point to last item in list - add the new one  */
3061         pCurr->next = pItem;
3062     }
3063 #else
3064     _SlAsyncRespBuf_t* pItem = (_SlAsyncRespBuf_t*)_SlGetStatSpawnListItem(AsyncEventLen);
3065 #endif
3066     if ((NULL != pItem) && (NULL != pItem->Buffer))
3067     {
3068         /* save the action idx */
3069         pItem->ActionIndex = g_pCB->FunctionParams.AsyncExt.ActionIndex;
3070         /* save the corresponding AsyncHndlr (if registered) */
3071         pItem->AsyncHndlr = g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler;
3072         /* copy the async event that we read to the buffer */
3073         sl_Memcpy(pItem->Buffer, pAsyncBuf, AsyncEventLen);
3074     }
3075     else
3076     {
3077             RetVal = SL_RET_CODE_NO_FREE_ASYNC_BUFFERS_ERROR;
3078     }
3079         SL_DRV_PROTECTION_OBJ_UNLOCK();
3080         return RetVal;
3081 }
3082 
_SlSpawnMsgListProcess()3083 _SlReturnVal_t _SlSpawnMsgListProcess()
3084 {
3085 
3086 #ifdef SL_MEMORY_MGMT_DYNAMIC
3087     _SlSpawnMsgItem_t* pHead = g_pCB->spawnMsgList;
3088     _SlSpawnMsgItem_t* pCurr = pHead;
3089     _SlSpawnMsgItem_t* pLast = pHead;
3090 
3091     while (pCurr != NULL)
3092     {
3093         /* lock during action */
3094         SL_DRV_LOCK_GLOBAL_LOCK_FOREVER(GLOBAL_LOCK_FLAGS_NONE);
3095         /* load the async event params */
3096         g_pCB->FunctionParams.AsyncExt.ActionIndex = pCurr->ActionIndex;
3097         g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler = pCurr->AsyncHndlr;
3098 
3099         pLast = pCurr;
3100         pCurr = pCurr->next;
3101 
3102         /* move the list head to point to the next item (or null) */
3103         g_pCB->spawnMsgList = pCurr;
3104         /* Handle async event: here we are in spawn context, after context
3105         * switch from command context. */
3106         _SlDrvAsyncEventGenericHandler(FALSE, pLast->Buffer);
3107 
3108         /* free the copied buffer inside the item  */
3109         sl_Free(pLast->Buffer);
3110 
3111         /* free the spawn msg item */
3112         sl_Free(pLast);
3113 
3114         SL_DRV_LOCK_GLOBAL_UNLOCK(FALSE);
3115     }
3116 
3117 #else
3118     _u8 i;
3119 
3120     for (i = 0; i < SL_MAX_ASYNC_BUFFERS; i++)
3121     {
3122         if (0xFF != g_StatMem.AsyncBufPool[i].ActionIndex)
3123         {
3124             /* lock during action */
3125 
3126             SL_DRV_LOCK_GLOBAL_LOCK_FOREVER(GLOBAL_LOCK_FLAGS_NONE);
3127 
3128             /* load the async event params */
3129             g_pCB->FunctionParams.AsyncExt.ActionIndex = g_StatMem.AsyncBufPool[i].ActionIndex;
3130             g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler = g_StatMem.AsyncBufPool[i].AsyncHndlr;
3131 
3132             /* Handle async event: here we are in spawn context, after context
3133             * switch from command context. */
3134             _SlDrvAsyncEventGenericHandler(FALSE, (unsigned char *)&(g_StatMem.AsyncBufPool[i].Buffer));
3135 
3136             SL_DRV_LOCK_GLOBAL_UNLOCK(FALSE);
3137 
3138             SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
3139             g_StatMem.AsyncBufPool[i].ActionIndex = 0xFF;
3140             SL_DRV_PROTECTION_OBJ_UNLOCK();
3141         }
3142     }
3143 #endif
3144     return SL_OS_RET_CODE_OK;
3145 }
3146 
_SlSpawnMsgListGetCount()3147 _u16 _SlSpawnMsgListGetCount()
3148 {
3149     _u16 NumOfItems = 0;
3150 #ifdef SL_MEMORY_MGMT_DYNAMIC
3151     _SlSpawnMsgItem_t* pCurr = g_pCB->spawnMsgList;
3152 
3153     /* protect the item insertion  */
3154     SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
3155     while (pCurr != NULL)
3156     {
3157         NumOfItems++;
3158 
3159         pCurr = pCurr->next;
3160     }
3161     SL_DRV_PROTECTION_OBJ_UNLOCK();
3162 
3163 #else
3164     _u8 i;
3165     /* protect counting parameters  */
3166     SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
3167 
3168     for (i = 0; i < SL_MAX_ASYNC_BUFFERS; i++)
3169     {
3170         if (0xFF != g_StatMem.AsyncBufPool[i].ActionIndex)
3171         {
3172             NumOfItems++;
3173         }
3174     }
3175     SL_DRV_PROTECTION_OBJ_UNLOCK();
3176 #endif
3177     return NumOfItems;
3178 }
3179 
3180 
_SlFindAndReleasePendingCmd()3181 void _SlFindAndReleasePendingCmd()
3182 {
3183     /* In case there is no free buffer to store the async event until context switch release the command and return specific error */
3184     ((SlSocketResponse_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->StatusOrLen = SL_RET_CODE_NO_FREE_ASYNC_BUFFERS_ERROR;
3185     /* signal pending cmd */
3186     SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
3187 }
3188 #endif
3189