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