1 /*
2 * ScanCncnSm.c
3 *
4 * Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved.
5 * All rights reserved.
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 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name Texas Instruments nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /** \file ScanCncnSm.c
35 * \brief Scan concentrator state machine implementation
36 *
37 * \see ScanCncnSm.h, ScanCncnSmSpecific.c
38 */
39
40
41 #define __FILE_ID__ FILE_ID_79
42 #include "osTIType.h"
43 #include "GenSM.h"
44 #include "ScanCncnSm.h"
45 #include "report.h"
46
47 /* state machine action functions */
48 static void scanCncnSm_RequestScr (TI_HANDLE hScanCncnClient);
49 static void scanCncnSm_StartScan (TI_HANDLE hScanCncnClient);
50 static void scanCncnSm_StopScan (TI_HANDLE hScanCncnClient);
51 static void scanCncnSm_ScanComplete (TI_HANDLE hScanCncnClient);
52 static void scanCncnSm_Nop (TI_HANDLE hScanCncnClient);
53 static void scanCncnSm_ActionUnexpected (TI_HANDLE hScanCncnClient);
54 static void scanCncnSm_RejectScan (TI_HANDLE hScanCncnClient);
55 static void scanCncnSm_Recovery (TI_HANDLE hScanCncnClient);
56
57
58 static TGenSM_actionCell tSmMatrix[ SCAN_CNCN_SM_NUMBER_OF_STATES ][ SCAN_CNCN_SM_NUMBER_OF_EVENTS ] =
59 {
60 { /* SCAN_CNCN_SM_STATE_IDLE */
61 { SCAN_CNCN_SM_STATE_SCR_WAIT, scanCncnSm_RequestScr }, /* SCAN_CNCN_SM_EVENT_START */
62 { SCAN_CNCN_SM_STATE_IDLE, scanCncnSm_ActionUnexpected }, /* SCAN_CNCN_SM_EVENT_RUN */
63 { SCAN_CNCN_SM_STATE_IDLE, scanCncnSm_ActionUnexpected }, /* SCAN_CNCN_SM_EVENT_SCAN_COMPLETE */
64 { SCAN_CNCN_SM_STATE_IDLE, scanCncnSm_ActionUnexpected }, /* SCAN_CNCN_SM_EVENT_STOP */
65 { SCAN_CNCN_SM_STATE_IDLE, scanCncnSm_ActionUnexpected }, /* SCAN_CNCN_SM_EVENT_ABORT */
66 { SCAN_CNCN_SM_STATE_IDLE, scanCncnSm_ActionUnexpected }, /* SCAN_CNCN_SM_EVENT_RECOVERY */
67 { SCAN_CNCN_SM_STATE_IDLE, scanCncnSm_ActionUnexpected } /* SCAN_CNCN_SM_EVENT_REJECT */
68 },
69 { /* SCAN_CNCN_SM_STATE_SCR_WAIT */
70 { SCAN_CNCN_SM_STATE_SCR_WAIT, scanCncnSm_ActionUnexpected }, /* SCAN_CNCN_SM_EVENT_START */
71 { SCAN_CNCN_SM_STATE_SCANNING, scanCncnSm_StartScan }, /* SCAN_CNCN_SM_EVENT_RUN */
72 { SCAN_CNCN_SM_STATE_SCR_WAIT, scanCncnSm_ActionUnexpected }, /* SCAN_CNCN_SM_EVENT_SCAN_COMPLETE */
73 { SCAN_CNCN_SM_STATE_IDLE, scanCncnSm_RejectScan }, /* SCAN_CNCN_SM_EVENT_STOP */
74 { SCAN_CNCN_SM_STATE_SCR_WAIT, scanCncnSm_ActionUnexpected }, /* SCAN_CNCN_SM_EVENT_ABORT */
75 { SCAN_CNCN_SM_STATE_SCR_WAIT, scanCncnSm_ActionUnexpected }, /* SCAN_CNCN_SM_EVENT_RECOVERY */
76 { SCAN_CNCN_SM_STATE_IDLE, scanCncnSm_RejectScan } /* SCAN_CNCN_SM_EVENT_REJECT */
77 },
78 { /* SCAN_CNCN_SM_STATE_SCANNING */
79 { SCAN_CNCN_SM_STATE_SCANNING, scanCncnSm_ActionUnexpected }, /* SCAN_CNCN_SM_EVENT_START */
80 { SCAN_CNCN_SM_STATE_SCANNING, scanCncnSm_ActionUnexpected }, /* SCAN_CNCN_SM_EVENT_RUN */
81 { SCAN_CNCN_SM_STATE_IDLE, scanCncnSm_ScanComplete }, /* SCAN_CNCN_SM_EVENT_SCAN_COMPLETE */
82 { SCAN_CNCN_SM_STATE_STOPPING, scanCncnSm_StopScan }, /* SCAN_CNCN_SM_EVENT_STOP */
83 { SCAN_CNCN_SM_STATE_STOPPING, scanCncnSm_StopScan }, /* SCAN_CNCN_SM_EVENT_ABORT */
84 { SCAN_CNCN_SM_STATE_IDLE, scanCncnSm_Recovery }, /* SCAN_CNCN_SM_EVENT_RECOVERY */
85 { SCAN_CNCN_SM_STATE_SCANNING, scanCncnSm_ActionUnexpected } /* SCAN_CNCN_SM_EVENT_REJECT */
86 },
87 { /* SCAN_CNCN_SM_STATE_STOPPING */
88 { SCAN_CNCN_SM_STATE_STOPPING, scanCncnSm_ActionUnexpected }, /* SCAN_CNCN_SM_EVENT_START */
89 { SCAN_CNCN_SM_STATE_STOPPING, scanCncnSm_ActionUnexpected }, /* SCAN_CNCN_SM_EVENT_RUN */
90 { SCAN_CNCN_SM_STATE_IDLE, scanCncnSm_ScanComplete }, /* SCAN_CNCN_SM_EVENT_SCAN_COMPLETE */
91 { SCAN_CNCN_SM_STATE_STOPPING, scanCncnSm_Nop }, /* SCAN_CNCN_SM_EVENT_STOP */
92 { SCAN_CNCN_SM_STATE_STOPPING, scanCncnSm_Nop }, /* SCAN_CNCN_SM_EVENT_ABORT */
93 { SCAN_CNCN_SM_STATE_IDLE, scanCncnSm_Recovery }, /* SCAN_CNCN_SM_EVENT_RECOVERY */
94 { SCAN_CNCN_SM_STATE_STOPPING, scanCncnSm_ActionUnexpected } /* SCAN_CNCN_SM_EVENT_REJECT */
95 }
96 };
97
98 static TI_INT8* uStateDescription[] =
99 {
100 "IDLE",
101 "SCR_WAIT",
102 "SCANNING",
103 "STOPPING"
104 };
105
106 static TI_INT8* uEventDescription[] =
107 {
108 "START",
109 "RUN",
110 "SCAN_COMPLETE",
111 "STOP",
112 "ABORT",
113 "RECOVERY",
114 "REJECT",
115 };
116
117 /**
118 * \fn scanCncnSm_Create
119 * \brief Cerates a scan concentrator client object
120 *
121 * Cerates a scan concentrator client - allocates object and create a state-machine instance
122 *
123 * \param hOS - handle to the OS object
124 * \return Handle to the new scan concentrator client object
125 * \sa scanCncnSm_Init, scanCncnSm_Destroy
126 */
scanCncnSm_Create(TI_HANDLE hOS)127 TI_HANDLE scanCncnSm_Create (TI_HANDLE hOS)
128 {
129 TScanCncnClient *pScanCncnClient;
130
131 /* allocate space for the scan concentartor client object */
132 pScanCncnClient = os_memoryAlloc (hOS, sizeof (TScanCncnClient));
133 if (NULL == pScanCncnClient)
134 {
135 WLAN_OS_REPORT (("scanCncnSm_Cretae: not enough space for scan concentrator client object\n"));
136 return NULL;
137 }
138
139 /* store the OS object handle */
140 pScanCncnClient->hOS = hOS;
141
142 /* allocate the state machine object */
143 pScanCncnClient->hGenSM = genSM_Create (hOS);
144 if (NULL == pScanCncnClient->hGenSM)
145 {
146 WLAN_OS_REPORT (("scanCncnSm_Cretae: not enough space for scan concentrator client state-machine\n"));
147 return NULL;
148 }
149
150 /* return the new object */
151 return (TI_HANDLE)pScanCncnClient;
152 }
153
154 /**
155 * \fn scanCncnSm_Init
156 * \brief Initialize a scan concentartor client object
157 *
158 * Initialize a scan concentartor client object - store handles and specific SM functions
159 *
160 * \note Some of the values (e.g. scan result CB( are initialized from the main scan concentartor object)
161 * \param hScanCncnClient - handle to the scan concnentrator client object
162 * \param hReport - handle to the report object
163 * \param hTWD - handle to the TWD object
164 * \param hSCR - handle to the SCR object
165 * \param hApConn - handle to the AP connection object
166 * \param hMlme - handle to the MLME object
167 * \param fScrRequest - SM specific SCR request finction
168 * \param fScrRelease - SM specific SCR release finction
169 * \param fStartScan - SM specific scan start finction
170 * \param fStopScan - SM specific scan stop finction
171 * \param fRecovery - SM specific recovery handling function
172 * \param pScanSmName - state machine name
173 * \return None
174 * \sa scanCncnSm_Cretae
175 */
scanCncnSm_Init(TI_HANDLE hScanCncnClient,TI_HANDLE hReport,TI_HANDLE hTWD,TI_HANDLE hSCR,TI_HANDLE hApConn,TI_HANDLE hMlme,TI_HANDLE hScanCncn,TScanPrivateSMFunction fScrRequest,TScanPrivateSMFunction fScrRelease,TScanPrivateSMFunction fStartScan,TScanPrivateSMFunction fStopScan,TScanPrivateSMFunction fRecovery,TI_INT8 * pScanSmName)176 void scanCncnSm_Init (TI_HANDLE hScanCncnClient, TI_HANDLE hReport, TI_HANDLE hTWD, TI_HANDLE hSCR,
177 TI_HANDLE hApConn, TI_HANDLE hMlme, TI_HANDLE hScanCncn, TScanPrivateSMFunction fScrRequest,
178 TScanPrivateSMFunction fScrRelease, TScanPrivateSMFunction fStartScan,
179 TScanPrivateSMFunction fStopScan, TScanPrivateSMFunction fRecovery, TI_INT8* pScanSmName)
180 {
181 TScanCncnClient *pScanCncnClient = (TScanCncnClient*)hScanCncnClient;
182
183 /* store handles */
184 pScanCncnClient->hReport = hReport;
185 pScanCncnClient->hTWD = hTWD;
186 pScanCncnClient->hSCR = hSCR;
187 pScanCncnClient->hApConn = hApConn;
188 pScanCncnClient->hMlme = hMlme;
189 pScanCncnClient->hScanCncn = hScanCncn;
190
191 /* store private functions */
192 pScanCncnClient->fScrRequest = fScrRequest;
193 pScanCncnClient->fScrRelease = fScrRelease;
194 pScanCncnClient->fStartScan = fStartScan;
195 pScanCncnClient->fStopScan = fStopScan;
196 pScanCncnClient->fRecovery = fRecovery;
197
198 /* store SM name */
199 pScanCncnClient->pScanSmName = pScanSmName;
200
201 /* initialize the state-machine */
202 genSM_Init (pScanCncnClient->hGenSM, hReport);
203 genSM_SetDefaults (pScanCncnClient->hGenSM, SCAN_CNCN_SM_NUMBER_OF_STATES, SCAN_CNCN_SM_NUMBER_OF_EVENTS,
204 (TGenSM_matrix)tSmMatrix, SCAN_CNCN_SM_STATE_IDLE, pScanCncnClient->pScanSmName, uStateDescription,
205 uEventDescription, __FILE_ID__);
206 }
207
208 /**
209 * \fn scanCncnSm_Destroy
210 * \brief Destroys a scan concentartor client object
211 *
212 * Destroys a scan concentartor client object. destroys the state-machine object and
213 * de-allcoates system resources
214 *
215 * \param hScanCncnClient - handle to the scan concnentrator client object
216 * \return None
217 * \sa scanCncnSm_Cretae
218 */
scanCncnSm_Destroy(TI_HANDLE hScanCncnClient)219 void scanCncnSm_Destroy (TI_HANDLE hScanCncnClient)
220 {
221 TScanCncnClient *pScanCncnClient = (TScanCncnClient*)hScanCncnClient;
222
223 /* free the state-machine */
224 genSM_Unload (pScanCncnClient->hGenSM);
225
226 /* Free object storage space */
227 os_memoryFree (pScanCncnClient->hOS, hScanCncnClient, sizeof (TScanCncnClient));
228 }
229
230 /**
231 * \fn scanCncnSm_RequestScr
232 * \brief Scan concentartor SM action function for SCR request
233 *
234 * Calls the Sm specific SCR request function
235 *
236 * \param hScanCncnClient - Handle to the scan concentrator client object
237 * \return None
238 */
scanCncnSm_RequestScr(TI_HANDLE hScanCncnClient)239 void scanCncnSm_RequestScr (TI_HANDLE hScanCncnClient)
240 {
241 TScanCncnClient *pScanCncnClient = (TScanCncnClient*)hScanCncnClient;
242
243 TRACE0(pScanCncnClient->hReport, REPORT_SEVERITY_INFORMATION , "scanCncnSm_RequestScr: SM requesting SCR\n");
244
245 /*
246 * just call the specific SCR request function, it will send an event if necessary
247 * according to SCR return code by itself
248 */
249 pScanCncnClient->fScrRequest (hScanCncnClient);
250 }
251
252 /**
253 * \fn scanCncnSm_StartScan
254 * \brief Scan concentrator SM action function for starting scan
255 *
256 * Register for MLME CB and call the SM specific scan start function
257 *
258 * \param hScanCncnClient - Handle to the scan concentrator client object
259 * \return None
260 */
scanCncnSm_StartScan(TI_HANDLE hScanCncnClient)261 void scanCncnSm_StartScan (TI_HANDLE hScanCncnClient)
262 {
263 TScanCncnClient *pScanCncnClient = (TScanCncnClient*)hScanCncnClient;
264
265 TRACE0(pScanCncnClient->hReport, REPORT_SEVERITY_INFORMATION , "scanCncnSm_StartScan: SM attempting to start scan.\n");
266
267 /* set scan result counter and flag */
268 pScanCncnClient->uResultCounter = 0;
269 pScanCncnClient->uResultExpectedNumber = 0;
270 pScanCncnClient->bScanCompletePending = TI_FALSE;
271
272 /* call the specific start scan command. It will handle errors by itself */
273 pScanCncnClient->fStartScan (hScanCncnClient);
274 }
275
276 /**
277 * \fn scanCncnSm_StopScan
278 * \brief Scan concentrator SM action function for stoping scan by outside request
279 *
280 * Calls the SM specific stop scan function
281 *
282 * \param hScanCncnClient - Handle to the scan concentrator client object
283 * \return None
284 */
scanCncnSm_StopScan(TI_HANDLE hScanCncnClient)285 void scanCncnSm_StopScan (TI_HANDLE hScanCncnClient)
286 {
287 TScanCncnClient *pScanCncnClient = (TScanCncnClient*)hScanCncnClient;
288
289 TRACE0(pScanCncnClient->hReport, REPORT_SEVERITY_INFORMATION , "scanCncnSm_StopScan: SM is attempting to stop scan\n");
290
291 /* call the scan SRV stop scan */
292 pScanCncnClient->fStopScan (hScanCncnClient);
293 }
294
295 /**
296 * \fn scanCncnSm_ScanComplete
297 * \brief Scan concentrator SM action function for scan complete
298 *
299 * Unregister MLME, release SCR and call client scan complete CB, if not running within a request context
300 *
301 * \param hScanCncnClient - Handle to the scan concentrator client object
302 * \return None
303 */
scanCncnSm_ScanComplete(TI_HANDLE hScanCncnClient)304 void scanCncnSm_ScanComplete (TI_HANDLE hScanCncnClient)
305 {
306 TScanCncnClient *pScanCncnClient = (TScanCncnClient*)hScanCncnClient;
307
308 TRACE0(pScanCncnClient->hReport, REPORT_SEVERITY_INFORMATION , "scanCncnSm_ScanComplete: SM received scan complete event\n");
309
310 /* release the SCR */
311 pScanCncnClient->fScrRelease (hScanCncnClient);
312
313 /* Call the client scan complete callback */
314 if (TI_FALSE == pScanCncnClient->bInRequest)
315 {
316 pScanCncnClient->tScanResultCB (pScanCncnClient->hScanResultCBObj,
317 pScanCncnClient->eScanResult, NULL, pScanCncnClient->uSPSScanResult);
318 }
319 }
320
321 /**
322 * \fn scanCncnSm_Nop
323 * \brief Scan concentrator SM action function for no operation
324 *
325 * Used when no operation is required not due to an error
326 *
327 * \param hScanCncnClient - Handle to the scan concentrator client object
328 * \return None
329 */
scanCncnSm_Nop(TI_HANDLE hScanCncnClient)330 void scanCncnSm_Nop (TI_HANDLE hScanCncnClient)
331 {
332 }
333
334 /**
335 * \fn ScanCncnSm_ActionUnexpected
336 * \brief Scan concentrator SM action function for unexpected events
337 *
338 * Print an error message
339 *
340 * \param hScanCncnClient - Handle to the scan concentrator client object
341 * \return None
342 */
scanCncnSm_ActionUnexpected(TI_HANDLE hScanCncnClient)343 void scanCncnSm_ActionUnexpected (TI_HANDLE hScanCncnClient)
344 {
345 TScanCncnClient *pScanCncnClient = (TScanCncnClient*)hScanCncnClient;
346
347 TRACE0(pScanCncnClient->hReport, REPORT_SEVERITY_ERROR , "ScanCncnSm_ActionUnexpected: Unexpected event for current state\n");
348
349 /* mark the scan status as failed */
350 pScanCncnClient->eScanResult = SCAN_CRS_SCAN_FAILED;
351 }
352
353 /**
354 * \fn scanCncnSm_RejectScan
355 * \brief Scan concentrator SM action function for rejecting a scan by the SCR
356 *
357 * Releases the SCR and calls the client scan complete CB, if not running within a request context
358 *
359 * \param hScanCncnClient - Handle to the scan concentrator client object
360 * \return None
361 */
scanCncnSm_RejectScan(TI_HANDLE hScanCncnClient)362 void scanCncnSm_RejectScan (TI_HANDLE hScanCncnClient)
363 {
364 TScanCncnClient *pScanCncnClient = (TScanCncnClient*)hScanCncnClient;
365
366 TRACE0(pScanCncnClient->hReport, REPORT_SEVERITY_INFORMATION , "scanCncnSm_RejectScan: SM received reject event\n");
367
368 /* release the SCR */
369 pScanCncnClient->fScrRelease (hScanCncnClient);
370
371 /* Call the client scan complete CB */
372 if (TI_FALSE == pScanCncnClient->bInRequest)
373 {
374 pScanCncnClient->tScanResultCB (pScanCncnClient->hScanResultCBObj, pScanCncnClient->eScanResult,
375 NULL, pScanCncnClient->uSPSScanResult);
376 }
377 }
378
379 /**
380 * \fn scanCncnSm_Recovery
381 * \brief Scan concentrator SM action function for handling recovery during scan
382 *
383 * Calls the SM specific recovery handling function and send a scan complete event. Used to stop timer
384 * on one-shot scans
385 *
386 * \param hScanCncnClient - Handle to the scan concentrator client object
387 * \return None
388 */
scanCncnSm_Recovery(TI_HANDLE hScanCncnClient)389 void scanCncnSm_Recovery (TI_HANDLE hScanCncnClient)
390 {
391 TScanCncnClient *pScanCncnClient = (TScanCncnClient*)hScanCncnClient;
392
393 TRACE0(pScanCncnClient->hReport, REPORT_SEVERITY_INFORMATION , "scanCncnSm_Recovery: SM received reject event\n");
394
395 /* Call the recovery specific function */
396 pScanCncnClient->fRecovery (hScanCncnClient);
397
398 /* Call the client scan complete callback */
399 if (TI_FALSE == pScanCncnClient->bInRequest)
400 {
401 pScanCncnClient->tScanResultCB (pScanCncnClient->hScanResultCBObj,
402 pScanCncnClient->eScanResult, NULL, pScanCncnClient->uSPSScanResult);
403 }
404 }
405
406