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