1 /*
2  * device.c - CC31xx/CC32xx Host Driver Implementation
3  *
4  * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
5  *
6  *
7  *  Redistribution and use in source and binary forms, with or without
8  *  modification, are permitted provided that the following conditions
9  *  are met:
10  *
11  *    Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
14  *    Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the
17  *    distribution.
18  *
19  *    Neither the name of Texas Instruments Incorporated nor the names of
20  *    its contributors may be used to endorse or promote products derived
21  *    from this software without specific prior written permission.
22  *
23  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  *
35  */
36 
37 /*****************************************************************************/
38 /* Include files                                                             */
39 /*****************************************************************************/
40 #include <ti/drivers/net/wifi/simplelink.h>
41 #include <ti/drivers/net/wifi/source/protocol.h>
42 #include <ti/drivers/net/wifi/source/driver.h>
43 #include <ti/drivers/net/wifi/source/flowcont.h>
44 
45 /*****************************************************************************/
46 /* Internal functions                                                        */
47 /*****************************************************************************/
48 
49 static _i16 _SlDeviceGetStartResponseConvert(_i32 Status);
50 void _SlDeviceHandleResetRequestInternally(void);
51 void _SlDeviceResetRequestInitCompletedCB(_u32 Status, SlDeviceInitInfo_t *DeviceInitInfo);
52 
53 #define RESET_REQUEST_STOP_TIMEOUT (300)
54 
55 #ifndef SL_IF_OPEN_FLAGS
56 #define SL_IF_OPEN_FLAGS (0x0)
57 #endif
58 
59 #ifndef SL_IF_UART_REOPEN_FLAGS
60 #define SL_IF_UART_REOPEN_FLAGS (0x1)
61 #endif
62 
63 typedef struct
64 {
65     const void    *pIfHdl;   /* Holds the last opened interface handle */
66     _i8         *pDevName; /* Holds the last opened interface parameters */
67     _u32         ResetRequestSessionNumber; /* Special session number to be verified upon every reset request during provisioning */
68 } _SlDeviceCb_t;
69 
70 _SlDeviceCb_t DeviceCB; /* the device control block */
71 
72 static const _i16 StartResponseLUT[16] =
73 {
74     ROLE_RESERVED,
75     ROLE_STA,
76     SL_ERROR_ROLE_STA_ERR,
77     ROLE_AP,
78     SL_ERROR_ROLE_AP_ERR,
79     ROLE_P2P,
80     SL_ERROR_ROLE_P2P_ERR,
81     SL_ERROR_CALIB_FAIL,
82     SL_ERROR_FS_CORRUPTED_ERR,
83     SL_ERROR_FS_ALERT_ERR,
84     SL_ERROR_RESTORE_IMAGE_COMPLETE,
85     SL_ERROR_INCOMPLETE_PROGRAMMING,
86     ROLE_TAG,
87     SL_ERROR_ROLE_TAG_ERR,
88     SL_ERROR_FIPS_ERR,
89     SL_ERROR_GENERAL_ERR
90 };
91 
_SlDeviceGetStartResponseConvert(_i32 Status)92 static _i16 _SlDeviceGetStartResponseConvert(_i32 Status)
93 {
94     return StartResponseLUT[Status & 0xF];
95 }
96 
97 /*****************************************************************************/
98 /* API Functions                                                             */
99 /*****************************************************************************/
100 
101 /*****************************************************************************/
102 /* sl_Task                                                                   */
103 /*****************************************************************************/
104 #if _SL_INCLUDE_FUNC(sl_Task)
sl_Task(void * pEntry)105 void* sl_Task(void* pEntry)
106 {
107 #ifdef _SlTaskEntry
108     return (void*)_SlTaskEntry();
109 #else
110     return (void*)0;
111 #endif
112 }
113 #endif
114 
115 /*****************************************************************************/
116 /* sl_Start                                                                  */
117 /*****************************************************************************/
118 #if _SL_INCLUDE_FUNC(sl_Start)
sl_Start(const void * pIfHdl,_i8 * pDevName,const P_INIT_CALLBACK pInitCallBack)119 _i16 sl_Start(const void* pIfHdl, _i8*  pDevName, const P_INIT_CALLBACK pInitCallBack)
120 {
121     _i16 ObjIdx = MAX_CONCURRENT_ACTIONS;
122     InitComplete_t  AsyncRsp;
123     int ret = 0;    // added for releasePoolObj
124 
125     _SlDrvMemZero(&AsyncRsp, sizeof(InitComplete_t));
126 
127     /* verify no error handling in progress. if in progress than
128     ignore the API execution and return immediately with an error */
129     VERIFY_NO_ERROR_HANDLING_IN_PROGRESS();
130     if (SL_IS_DEVICE_STARTED)
131     {
132         return SL_RET_CODE_DEV_ALREADY_STARTED;
133     }
134     /* Perform any preprocessing before enable networking services */
135 #ifdef sl_DeviceEnablePreamble
136     sl_DeviceEnablePreamble();
137 #endif
138 
139     /* ControlBlock init */
140     (void)_SlDrvDriverCBInit();
141 
142     /* open the interface: usually SPI or UART */
143     if (NULL == pIfHdl)
144     {
145         g_pCB->FD = sl_IfOpen((void *)pDevName, SL_IF_OPEN_FLAGS);
146     }
147     else
148     {
149         g_pCB->FD = (_SlFd_t)pIfHdl;
150     }
151 
152     ObjIdx = _SlDrvProtectAsyncRespSetting((_u8 *)&AsyncRsp, START_STOP_ID, SL_MAX_SOCKETS);
153 
154     if (ObjIdx < 0)
155     {
156         return ObjIdx;
157     }
158 
159     if( g_pCB->FD >= (_SlFd_t)0)
160     {
161         /* store the interface parameters for the internal call of the
162            sl_start to be called upon reset request handling */
163         DeviceCB.pIfHdl = pIfHdl;
164         DeviceCB.pDevName = pDevName;
165 
166         /* Mark that device is in progress! */
167         SL_SET_DEVICE_START_IN_PROGRESS;
168 
169         sl_DeviceDisable();
170 
171         sl_IfRegIntHdlr((SL_P_EVENT_HANDLER)_SlDrvRxIrqHandler, NULL);
172 
173         g_pCB->pInitCallback = pInitCallBack;
174         sl_DeviceEnable();
175 
176         if (NULL == pInitCallBack)
177         {
178             ret = _SlDrvWaitForInternalAsyncEvent(ObjIdx, INIT_COMPLETE_TIMEOUT, SL_OPCODE_DEVICE_INITCOMPLETE);
179 
180             SL_UNSET_DEVICE_START_IN_PROGRESS;
181 
182             SL_SET_DEVICE_STARTED;
183 
184             /* release Pool Object */
185             _SlDrvReleasePoolObj(g_pCB->FunctionParams.AsyncExt.ActionIndex);
186             if(ret < 0)
187             {
188                 return ret;
189             }
190             else
191             {
192                 return _SlDeviceGetStartResponseConvert(AsyncRsp.Status);
193             }
194         }
195         else
196         {
197             return SL_RET_CODE_OK;
198         }
199     }
200     return SL_BAD_INTERFACE;
201 }
202 #endif
203 
204 /***************************************************************************
205 _SlDeviceHandleAsync_InitComplete - handles init complete signalling to
206 a waiting object
207 ****************************************************************************/
_SlDeviceHandleAsync_InitComplete(void * pVoidBuf)208 _SlReturnVal_t _SlDeviceHandleAsync_InitComplete(void *pVoidBuf)
209 {
210     InitComplete_t     *pMsgArgs   = (InitComplete_t *)_SL_RESP_ARGS_START(pVoidBuf);
211     SlDeviceInitInfo_t DeviceInitInfo;
212 
213     SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
214 
215     if(g_pCB->pInitCallback)
216     {
217         DeviceInitInfo.ChipId = pMsgArgs->ChipId;
218         DeviceInitInfo.MoreData = pMsgArgs->MoreData;
219         g_pCB->pInitCallback(_SlDeviceGetStartResponseConvert(pMsgArgs->Status), &DeviceInitInfo);
220     }
221     else
222     {
223         sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(InitComplete_t));
224         SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
225     }
226 
227         SL_DRV_PROTECTION_OBJ_UNLOCK();
228         if(g_pCB->pInitCallback)
229         {
230             SL_SET_DEVICE_STARTED;
231             SL_UNSET_DEVICE_START_IN_PROGRESS;
232             _SlDrvReleasePoolObj(g_pCB->FunctionParams.AsyncExt.ActionIndex);
233         }
234 
235         return SL_OS_RET_CODE_OK;
236     }
237 
238 
239 /***************************************************************************
240 _SlDeviceHandleAsync_Stop - handles stop signalling to
241 a waiting object
242 ****************************************************************************/
_SlDeviceHandleAsync_Stop(void * pVoidBuf)243 void _SlDeviceHandleAsync_Stop(void *pVoidBuf)
244 {
245     _BasicResponse_t     *pMsgArgs   = (_BasicResponse_t *)_SL_RESP_ARGS_START(pVoidBuf);
246 
247     VERIFY_SOCKET_CB(NULL != g_pCB->StopCB.pAsyncRsp);
248 
249     SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
250 
251     if (g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs != NULL)
252     {
253         sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(_BasicResponse_t));
254         SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
255     }
256 
257     SL_DRV_PROTECTION_OBJ_UNLOCK();
258 
259     return;
260 }
261 
262 
263 /*****************************************************************************
264 sl_stop
265 ******************************************************************************/
266 typedef union
267 {
268     SlDeviceStopCommand_t  Cmd;
269     _BasicResponse_t   Rsp;
270 }_SlStopMsg_u;
271 
272 static const _SlCmdCtrl_t _SlStopCmdCtrl =
273 {
274     SL_OPCODE_DEVICE_STOP_COMMAND,
275     (_SlArgSize_t)sizeof(SlDeviceStopCommand_t),
276     (_SlArgSize_t)sizeof(_BasicResponse_t)
277 };
278 
279 #if _SL_INCLUDE_FUNC(sl_Stop)
sl_Stop(const _u16 Timeout)280 _i16 sl_Stop(const _u16 Timeout)
281 {
282     _i16 RetVal=0;
283     _SlStopMsg_u      Msg;
284     _BasicResponse_t  AsyncRsp;
285     _i16 ObjIdx = MAX_CONCURRENT_ACTIONS;
286     _u8 ReleasePoolObject = FALSE;
287     _u8 IsProvInProgress = FALSE;
288 
289     /* NOTE: don't check VERIFY_API_ALLOWED(), this command is not
290      * filtered in error handling and also not filtered in NWP lock state.
291      * If we are in the middle of assert handling than ignore stopping
292      * the device with timeout and force immediate shutdown as we would like
293      * to avoid any additional commands to the NWP */
294     if( (Timeout != 0) && (SL_IS_DEVICE_STARTED)
295        && (!SL_IS_RESTART_REQUIRED))
296     {
297         /* Clear the Async response structure */
298         _SlDrvMemZero(&AsyncRsp, sizeof(_BasicResponse_t));
299 
300         /* let the device make the shutdown using the defined timeout */
301         Msg.Cmd.Timeout = Timeout;
302 
303         IsProvInProgress = SL_IS_PROVISIONING_IN_PROGRESS;
304 
305         /* if provisioning in progress do not take pool object as we are not going to wait for it  */
306         if (!IsProvInProgress)
307         {
308             ObjIdx = _SlDrvProtectAsyncRespSetting((_u8 *)&AsyncRsp, START_STOP_ID, SL_MAX_SOCKETS);
309             if (ObjIdx < 0)
310             {
311                 return ObjIdx;
312             }
313 
314             ReleasePoolObject = TRUE;
315         }
316 
317         /* Set the stop-in-progress flag */
318         SL_SET_DEVICE_STOP_IN_PROGRESS;
319 
320         VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlStopCmdCtrl, &Msg, NULL));
321 
322         int ret_pool = 0; // for _SlDrvReleasePoolObj
323         /* Do not wait for stop async event if provisioning is in progress */
324         if((SL_OS_RET_CODE_OK == (_i16)Msg.Rsp.status) && (!(IsProvInProgress)))
325         {
326             /* Wait for sync object to be signaled */
327             ret_pool = _SlDrvWaitForInternalAsyncEvent(ObjIdx, STOP_DEVICE_TIMEOUT, SL_OPCODE_DEVICE_STOP_ASYNC_RESPONSE);
328 
329             Msg.Rsp.status = AsyncRsp.status;
330             RetVal = Msg.Rsp.status;
331         }
332 
333         /* Release pool object only if taken */
334         if (ReleasePoolObject == TRUE)
335         {
336             _SlDrvReleasePoolObj(ObjIdx);
337             if(ret_pool < 0)
338             {
339                 return ret_pool;
340             }
341         }
342 
343         /* This macro wait for the NWP to raise a ready for shutdown indication.
344         * This function is unique for the CC32XX family, and expected to return
345         * in less than 600 mSec, which is the time takes for NWP to gracefully shutdown. */
346         WAIT_NWP_SHUTDOWN_READY;
347     }
348     else
349     {
350         if ((!SL_IS_DEVICE_STARTED)
351        && (!SL_IS_RESTART_REQUIRED))
352         {
353             sl_DeviceDisable();
354             return SL_RET_CODE_DEV_NOT_STARTED;
355         }
356         /* Set the stop-in-progress flag */
357         SL_SET_DEVICE_STOP_IN_PROGRESS;
358     }
359     /* Release (signal) all active and pending commands */
360     _SlDrvReleaseAllActivePendingPoolObj();
361 
362 #ifdef SL_PLATFORM_MULTI_THREADED
363     /* Do not continue until all sync object deleted (in relevant context) */
364     while (g_pCB->NumOfDeletedSyncObj < MAX_CONCURRENT_ACTIONS)
365     {
366         usleep(100000);
367     }
368 #endif
369 
370     /* Lock during stopping the interface */
371     SL_DRV_OBJ_LOCK_FOREVER(&GlobalLockObj);
372 
373     sl_IfRegIntHdlr(NULL, NULL);
374     sl_DeviceDisable();
375     RetVal = sl_IfClose(g_pCB->FD);
376 
377     (void)_SlDrvDriverCBDeinit();
378 
379     /* clear the stop-in-progress flag */
380     SL_UNSET_DEVICE_STOP_IN_PROGRESS;
381 
382     /* clear the device started flag */
383     SL_UNSET_DEVICE_STARTED;
384 
385     SL_DRV_OBJ_UNLOCK(&GlobalLockObj);
386 
387     return RetVal;
388 }
389 #endif
390 
391 
392 /*****************************************************************************
393 sl_DeviceEventMaskSet
394 *****************************************************************************/
395 typedef union
396 {
397     SlDeviceMaskEventSetCommand_t        Cmd;
398     _BasicResponse_t                Rsp;
399 }_SlEventMaskSetMsg_u;
400 
401 
402 #if _SL_INCLUDE_FUNC(sl_DeviceEventMaskSet)
403 
404 static const _SlCmdCtrl_t _SlEventMaskSetCmdCtrl =
405 {
406     SL_OPCODE_DEVICE_EVENTMASKSET,
407     (_SlArgSize_t)sizeof(SlDeviceMaskEventSetCommand_t),
408     (_SlArgSize_t)sizeof(_BasicResponse_t)
409 };
410 
411 
sl_DeviceEventMaskSet(const _u8 EventClass,const _u32 Mask)412 _i16 sl_DeviceEventMaskSet(const _u8 EventClass ,const _u32 Mask)
413 {
414     _SlEventMaskSetMsg_u Msg;
415 
416     /* verify that this api is allowed. if not allowed then
417     ignore the API execution and return immediately with an error */
418     VERIFY_API_ALLOWED(SL_OPCODE_SILO_DEVICE);
419 
420     Msg.Cmd.Group = EventClass;
421     Msg.Cmd.Mask = Mask;
422 
423     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlEventMaskSetCmdCtrl, &Msg, NULL));
424 
425     return (_i16)Msg.Rsp.status;
426 }
427 #endif
428 
429 /******************************************************************************
430 sl_EventMaskGet
431 ******************************************************************************/
432 typedef union
433 {
434     SlDeviceMaskEventGetCommand_t        Cmd;
435     SlDeviceMaskEventGetResponse_t      Rsp;
436 }_SlEventMaskGetMsg_u;
437 
438 
439 
440 #if _SL_INCLUDE_FUNC(sl_DeviceEventMaskGet)
441 
442 static const _SlCmdCtrl_t _SlEventMaskGetCmdCtrl =
443 {
444     SL_OPCODE_DEVICE_EVENTMASKGET,
445     (_SlArgSize_t)sizeof(SlDeviceMaskEventGetCommand_t),
446     (_SlArgSize_t)sizeof(SlDeviceMaskEventGetResponse_t)
447 };
448 
449 
sl_DeviceEventMaskGet(const _u8 EventClass,_u32 * pMask)450 _i16 sl_DeviceEventMaskGet(const _u8 EventClass,_u32 *pMask)
451 {
452     _SlEventMaskGetMsg_u Msg;
453 
454     /* verify that this api is allowed. if not allowed then
455     ignore the API execution and return immediately with an error */
456     VERIFY_API_ALLOWED(SL_OPCODE_SILO_DEVICE);
457 
458     Msg.Cmd.Group = EventClass;
459 
460     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlEventMaskGetCmdCtrl, &Msg, NULL));
461 
462     *pMask = Msg.Rsp.Mask;
463 
464     return SL_RET_CODE_OK;
465 }
466 #endif
467 
468 
469 
470 /******************************************************************************
471 sl_DeviceGet
472 ******************************************************************************/
473 
474 typedef union
475 {
476     SlDeviceSetGet_t        Cmd;
477     SlDeviceSetGet_t        Rsp;
478 }_SlDeviceMsgGet_u;
479 
480 
481 
482 #if _SL_INCLUDE_FUNC(sl_DeviceGet)
483 
484 static const _SlCmdCtrl_t _SlDeviceGetCmdCtrl =
485 {
486     SL_OPCODE_DEVICE_DEVICEGET,
487     (_SlArgSize_t)sizeof(SlDeviceSetGet_t),
488     (_SlArgSize_t)sizeof(SlDeviceSetGet_t)
489 };
490 
sl_DeviceGet(const _u8 DeviceGetId,_u8 * pOption,_u16 * pConfigLen,_u8 * pValues)491 _i16 sl_DeviceGet(const _u8 DeviceGetId, _u8 *pOption,_u16 *pConfigLen, _u8 *pValues)
492 {
493     _SlDeviceMsgGet_u         Msg;
494     _SlCmdExt_t               CmdExt;
495 
496     /* verify that this api is allowed. if not allowed then
497     ignore the API execution and return immediately with an error */
498     VERIFY_API_ALLOWED(SL_OPCODE_SILO_DEVICE);
499 
500     if (*pConfigLen == 0)
501     {
502         return SL_EZEROLEN;
503     }
504 
505     if( pOption )
506     {
507 
508        _SlDrvResetCmdExt(&CmdExt);
509         CmdExt.RxPayloadLen = (_i16)*pConfigLen;
510         CmdExt.pRxPayload = (_u8 *)pValues;
511 
512         Msg.Cmd.DeviceSetId = DeviceGetId;
513 
514         Msg.Cmd.Option   = (_u16)*pOption;
515 
516         VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlDeviceGetCmdCtrl, &Msg, &CmdExt));
517 
518         if( pOption )
519         {
520             *pOption = (_u8)Msg.Rsp.Option;
521         }
522 
523         if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen)
524         {
525             *pConfigLen = (_u16)CmdExt.RxPayloadLen;
526 
527             return SL_ESMALLBUF;
528         }
529         else
530         {
531             *pConfigLen = (_u16)CmdExt.ActualRxPayloadLen;
532         }
533 
534         return (_i16)Msg.Rsp.Status;
535     }
536     else
537     {
538         return SL_RET_CODE_INVALID_INPUT;
539     }
540 }
541 #endif
542 
543 /******************************************************************************
544 sl_DeviceSet
545 ******************************************************************************/
546 typedef union
547 {
548     SlDeviceSetGet_t    Cmd;
549     _BasicResponse_t   Rsp;
550 }_SlDeviceMsgSet_u;
551 
552 
553 
554 #if _SL_INCLUDE_FUNC(sl_DeviceSet)
555 
556 static const _SlCmdCtrl_t _SlDeviceSetCmdCtrl =
557 {
558     SL_OPCODE_DEVICE_DEVICESET,
559     (_SlArgSize_t)sizeof(SlDeviceSetGet_t),
560     (_SlArgSize_t)sizeof(_BasicResponse_t)
561 };
562 
sl_DeviceSet(const _u8 DeviceSetId,const _u8 Option,const _u16 ConfigLen,const _u8 * pValues)563 _i16 sl_DeviceSet(const _u8 DeviceSetId ,const _u8 Option,const _u16 ConfigLen,const _u8 *pValues)
564 {
565     _SlDeviceMsgSet_u         Msg;
566     _SlCmdExt_t               CmdExt;
567 
568     /* verify that this api is allowed. if not allowed then
569     ignore the API execution and return immediately with an error */
570     VERIFY_API_ALLOWED(SL_OPCODE_SILO_DEVICE);
571 
572     _SlDrvResetCmdExt(&CmdExt);
573 
574     CmdExt.TxPayload1Len = (ConfigLen+3) & (~3);
575     CmdExt.pTxPayload1 = (_u8 *)pValues;
576 
577     Msg.Cmd.DeviceSetId    = DeviceSetId;
578     Msg.Cmd.ConfigLen   = ConfigLen;
579     Msg.Cmd.Option   = Option;
580 
581     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlDeviceSetCmdCtrl, &Msg, &CmdExt));
582 
583     return (_i16)Msg.Rsp.status;
584 }
585 #endif
586 
587 
588 /******************************************************************************
589 _SlDeviceEventHandler - handles internally device async events
590 ******************************************************************************/
_SlDeviceEventHandler(void * pEventInfo)591 _SlReturnVal_t _SlDeviceEventHandler(void* pEventInfo)
592 {
593     DeviceEventInfo_t*    pInfo = (DeviceEventInfo_t*)pEventInfo;
594     _SlResponseHeader_t*  pHdr  = (_SlResponseHeader_t *)pInfo->pAsyncMsgBuff;
595     _BasicResponse_t     *pMsgArgs   = (_BasicResponse_t *)_SL_RESP_ARGS_START(pHdr);
596     SlDeviceEvent_t       DeviceEvent;
597 
598     _SlDrvMemZero(&DeviceEvent, sizeof(DeviceEvent));
599 
600     switch(pHdr->GenHeader.Opcode)
601     {
602     case SL_OPCODE_DEVICE_INITCOMPLETE:
603         _SlDeviceHandleAsync_InitComplete(pHdr);
604         break;
605     case SL_OPCODE_DEVICE_STOP_ASYNC_RESPONSE:
606         _SlDeviceHandleAsync_Stop(pHdr);
607         break;
608     case SL_OPCODE_DEVICE_RESET_REQUEST_ASYNC_EVENT:
609         {
610             SlDeviceResetRequestData_t *pResetRequestData = (SlDeviceResetRequestData_t*)pMsgArgs;
611 
612 #if defined(slcb_DeviceGeneralEvtHdlr) || defined (EXT_LIB_REGISTERED_GENERAL_EVENTS)
613             if (pResetRequestData->Caller == SL_DEVICE_RESET_REQUEST_CALLER_PROVISIONING_EXTERNAL_CONFIGURATION)
614             {
615                 /* call the registered events handlers (application/external lib) */
616                 DeviceEvent.Id = SL_DEVICE_EVENT_RESET_REQUEST;
617                 DeviceEvent.Data.ResetRequest.Status = 0;
618                 DeviceEvent.Data.ResetRequest.Caller = pResetRequestData->Caller;
619                 _SlDrvHandleGeneralEvents(&DeviceEvent);
620                 break;
621             }
622 #endif
623 
624             if (!_SlDrvIsApiInProgress() && SL_IS_PROVISIONING_IN_PROGRESS)
625             {
626                 if (pResetRequestData->SessionNumber != DeviceCB.ResetRequestSessionNumber)
627                 {
628                     /* store the last session number */
629                     DeviceCB.ResetRequestSessionNumber = pResetRequestData->SessionNumber;
630 
631                     /* perform the reset request */
632                     _SlDeviceHandleResetRequestInternally();
633                 }
634             }
635         }
636         break;
637 
638     case SL_OPCODE_DEVICE_ABORT:
639     {
640         /* release global lock of cmd context */
641         if (pInfo->bInCmdContext == TRUE)
642         {
643             SL_DRV_LOCK_GLOBAL_UNLOCK(TRUE);
644         }
645 
646         _SlDrvHandleFatalError(SL_DEVICE_EVENT_FATAL_DEVICE_ABORT,
647                                 *((_u32*)pMsgArgs - 1),    /* Abort type */
648                                 *((_u32*)pMsgArgs));       /* Abort data */
649         }
650         break;
651 
652     case  SL_OPCODE_DEVICE_DEVICE_ASYNC_GENERAL_ERROR:
653         {
654 #if defined(slcb_DeviceGeneralEvtHdlr) || defined (EXT_LIB_REGISTERED_GENERAL_EVENTS)
655 
656             DeviceEvent.Id = SL_DEVICE_EVENT_ERROR;
657             DeviceEvent.Data.Error.Code = pMsgArgs->status;
658             DeviceEvent.Data.Error.Source = (SlDeviceSource_e)pMsgArgs->sender;
659             _SlDrvHandleGeneralEvents(&DeviceEvent);
660 #endif
661         }
662         break;
663 
664     case SL_OPCODE_DEVICE_FLOW_CTRL_ASYNC_EVENT:
665         _SlFlowContSet((void *)pHdr);
666         break;
667     default:
668         SL_ERROR_TRACE2(MSG_306, "ASSERT: _SlDeviceEventHandler : invalid opcode = 0x%x = %1", pHdr->GenHeader.Opcode, pHdr->GenHeader.Opcode);
669     }
670 
671     return SL_OS_RET_CODE_OK;
672 }
673 
674 
_SlDeviceResetRequestInitCompletedCB(_u32 Status,SlDeviceInitInfo_t * DeviceInitInfo)675 void _SlDeviceResetRequestInitCompletedCB(_u32 Status, SlDeviceInitInfo_t *DeviceInitInfo)
676 {
677     /* Do nothing...*/
678 }
679 
680 
_SlDeviceHandleResetRequestInternally(void)681 void _SlDeviceHandleResetRequestInternally(void)
682 {
683     _u8 irqCountLast = RxIrqCnt;
684 #if (defined(slcb_GetTimestamp))
685       _SlTimeoutParams_t      TimeoutInfo={0};
686 
687       _SlDrvStartMeasureTimeout(&TimeoutInfo, 2*RESET_REQUEST_STOP_TIMEOUT);
688 #endif
689 
690     /* Here we send stop command with timeout, but the API will not blocked
691        Till the stop complete event is received as we in the middle of async event handling */
692     sl_Stop(RESET_REQUEST_STOP_TIMEOUT);
693 
694     /* wait till the stop complete cmd & async
695        event messages are received (2 Irqs) */
696     do
697     {
698 #if (defined(slcb_GetTimestamp))
699          if (_SlDrvIsTimeoutExpired(&TimeoutInfo))
700          {
701             break;
702          }
703 #endif
704     }
705     while((RxIrqCnt - irqCountLast) < 2);
706 
707     /* start the device again */
708     sl_Start(DeviceCB.pIfHdl, DeviceCB.pDevName ,_SlDeviceResetRequestInitCompletedCB);
709 
710 }
711 
712 
713 
714 /******************************************************************************
715 sl_DeviceStat
716 ******************************************************************************/
717 
sl_DeviceStatStart(const _u32 Flags)718 _i16 sl_DeviceStatStart(const _u32 Flags) // start collecting the statistics
719 {
720     SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
721     if(SL_IS_WLAN_RX_STAT_IN_PROGRESS)
722     {
723         SL_DRV_PROTECTION_OBJ_UNLOCK();
724         return SL_RET_CODE_WLAN_RX_STAT_IN_PROGRESS;
725     }
726     else
727     {
728        /* turn on flag indication for RX statistics is in progress
729         * to avoid parallel "starts" between
730         * Device statistics API and RX statistics API */
731         SL_SET_DEVICE_STAT_IN_PROGRESS;
732         SL_DRV_PROTECTION_OBJ_UNLOCK();
733        /* verify that this api is allowed. if not allowed then
734         ignore the API execution and return immediately with an error */
735         VERIFY_API_ALLOWED(SL_OPCODE_SILO_WLAN);
736         return _SlDrvBasicCmd(SL_OPCODE_WLAN_STARTRXSTATCOMMAND);
737     }
738 
739 }
740 
sl_DeviceStatGet(const _u16 ConfigId,_u16 length,void * buffer)741 _i16 sl_DeviceStatGet(const _u16 ConfigId,_u16 length,void* buffer)
742 {
743     _i16 RetVal = 0;
744     SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
745     /* Device statistics and Rx statistics cannot run parallel */
746     if(SL_IS_WLAN_RX_STAT_IN_PROGRESS)
747     {
748         SL_DRV_PROTECTION_OBJ_UNLOCK();
749         return SL_RET_CODE_WLAN_RX_STAT_IN_PROGRESS;
750     }
751     else
752     {
753         SL_DRV_PROTECTION_OBJ_UNLOCK();
754         if(SL_DEVICE_STAT_WLAN_RX == ConfigId )
755         {
756             /* In this case we use SL_OPCODE_WLAN_GETRXSTATCOMMAND even though we are at "Device" module -
757              * duo to the fact  we want  keep this API to call the exact same deprecated API which called from Wlan  */
758             _SlCmdCtrl_t CmdCtrl = {SL_OPCODE_WLAN_GETRXSTATCOMMAND, 0, (_SlArgSize_t)sizeof(SlDeviceGetStat_t)};
759 
760             /* verify that this api is allowed. if not allowed then
761             ignore the API execution and return immediately with an error */
762             VERIFY_API_ALLOWED(SL_OPCODE_SILO_WLAN);
763 
764             _SlDrvMemZero(buffer, (_u16)sizeof(SlDeviceGetStat_t));
765             VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, buffer, NULL));
766 
767         }
768         else
769         {
770             _u8 configOpt = ConfigId;
771             RetVal = sl_DeviceGet(SL_DEVICE_GENERAL,&configOpt,&length,(_u8* )buffer);
772         }
773 
774         return RetVal;
775     }
776 }
777 
sl_DeviceStatStop(const _u32 Flags)778 _i16 sl_DeviceStatStop(const _u32 Flags) //stop collecting the statistics
779 {
780     SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
781     if(SL_IS_WLAN_RX_STAT_IN_PROGRESS)
782     {
783         SL_DRV_PROTECTION_OBJ_UNLOCK();
784         return SL_RET_CODE_WLAN_RX_STAT_IN_PROGRESS;
785     }
786     else
787     {
788         SL_UNSET_DEVICE_STAT_IN_PROGRESS;
789         SL_DRV_PROTECTION_OBJ_UNLOCK();
790         /* verify that this api is allowed. if not allowed then
791            ignore the API execution and return immediately with an error */
792         VERIFY_API_ALLOWED(SL_OPCODE_SILO_WLAN);
793 
794         return _SlDrvBasicCmd(SL_OPCODE_WLAN_STOPRXSTATCOMMAND);
795 
796     }
797 
798 }
799 /******************************************************************************
800 sl_DeviceUartSetMode
801 ******************************************************************************/
802 #ifdef SL_IF_TYPE_UART
803 typedef union
804 {
805     SlDeviceUartSetModeCommand_t      Cmd;
806     SlDeviceUartSetModeResponse_t     Rsp;
807 }_SlUartSetModeMsg_u;
808 
809 
810 #if _SL_INCLUDE_FUNC(sl_DeviceUartSetMode)
811 
812 
813 const _SlCmdCtrl_t _SlUartSetModeCmdCtrl =
814 {
815     SL_OPCODE_DEVICE_SETUARTMODECOMMAND,
816     (_SlArgSize_t)sizeof(SlDeviceUartSetModeCommand_t),
817     (_SlArgSize_t)sizeof(SlDeviceUartSetModeResponse_t)
818 };
819 
sl_DeviceUartSetMode(const SlDeviceUartIfParams_t * pUartParams)820 _i16 sl_DeviceUartSetMode(const SlDeviceUartIfParams_t *pUartParams)
821 {
822     _SlUartSetModeMsg_u Msg;
823     _u32 magicCode = (_u32)0xFFFFFFFF;
824 
825     Msg.Cmd.BaudRate = pUartParams->BaudRate;
826     Msg.Cmd.FlowControlEnable = pUartParams->FlowControlEnable;
827 
828 
829     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlUartSetModeCmdCtrl, &Msg, NULL));
830 
831     /* cmd response OK, we can continue with the handshake */
832     if (SL_RET_CODE_OK == Msg.Rsp.status)
833     {
834         sl_IfMaskIntHdlr();
835 
836         /* Close the comm port */
837         sl_IfClose(g_pCB->FD);
838 
839         /* Re-open the comm port */
840         sl_IfOpen((void * )pUartParams, SL_IF_UART_REOPEN_FLAGS);
841 
842         sl_IfUnMaskIntHdlr();
843 
844         /* send the magic code and wait for the response */
845         sl_IfWrite(g_pCB->FD, (_u8* )&magicCode, 4);
846 
847         magicCode = UART_SET_MODE_MAGIC_CODE;
848         sl_IfWrite(g_pCB->FD, (_u8* )&magicCode, 4);
849 
850         /* clear magic code */
851         magicCode = 0;
852 
853         /* wait (blocking) till the magic code to be returned from device */
854         sl_IfRead(g_pCB->FD, (_u8* )&magicCode, 4);
855 
856         /* check for the received magic code matching */
857         if (UART_SET_MODE_MAGIC_CODE != magicCode)
858         {
859             _SL_ASSERT(0);
860         }
861     }
862 
863     return (_i16)Msg.Rsp.status;
864 }
865 #endif
866 #endif
867 
868