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 */ 48static void scanCncnSm_RequestScr (TI_HANDLE hScanCncnClient); 49static void scanCncnSm_StartScan (TI_HANDLE hScanCncnClient); 50static void scanCncnSm_StopScan (TI_HANDLE hScanCncnClient); 51static void scanCncnSm_ScanComplete (TI_HANDLE hScanCncnClient); 52static void scanCncnSm_Nop (TI_HANDLE hScanCncnClient); 53static void scanCncnSm_ActionUnexpected (TI_HANDLE hScanCncnClient); 54static void scanCncnSm_RejectScan (TI_HANDLE hScanCncnClient); 55static void scanCncnSm_Recovery (TI_HANDLE hScanCncnClient); 56 57 58static 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 98static TI_INT8* uStateDescription[] = 99 { 100 "IDLE", 101 "SCR_WAIT", 102 "SCANNING", 103 "STOPPING" 104 }; 105 106static 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 */ 127TI_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 */ 176void 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 */ 219void 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 */ 239void 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 */ 261void 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 pScanCncnClient->bScanRejectedOn2_4 = TI_FALSE; 272 273 /* call the specific start scan command. It will handle errors by itself */ 274 pScanCncnClient->fStartScan (hScanCncnClient); 275} 276 277/** 278 * \fn scanCncnSm_StopScan 279 * \brief Scan concentrator SM action function for stoping scan by outside request 280 * 281 * Calls the SM specific stop scan function 282 * 283 * \param hScanCncnClient - Handle to the scan concentrator client object 284 * \return None 285 */ 286void scanCncnSm_StopScan (TI_HANDLE hScanCncnClient) 287{ 288 TScanCncnClient *pScanCncnClient = (TScanCncnClient*)hScanCncnClient; 289 290 TRACE0(pScanCncnClient->hReport, REPORT_SEVERITY_INFORMATION , "scanCncnSm_StopScan: SM is attempting to stop scan\n"); 291 292 /* call the scan SRV stop scan */ 293 pScanCncnClient->fStopScan (hScanCncnClient); 294} 295 296/** 297 * \fn scanCncnSm_ScanComplete 298 * \brief Scan concentrator SM action function for scan complete 299 * 300 * Unregister MLME, release SCR and call client scan complete CB, if not running within a request context 301 * 302 * \param hScanCncnClient - Handle to the scan concentrator client object 303 * \return None 304 */ 305void scanCncnSm_ScanComplete (TI_HANDLE hScanCncnClient) 306{ 307 TScanCncnClient *pScanCncnClient = (TScanCncnClient*)hScanCncnClient; 308 309 TRACE0(pScanCncnClient->hReport, REPORT_SEVERITY_INFORMATION , "scanCncnSm_ScanComplete: SM received scan complete event\n"); 310 311 /* release the SCR */ 312 pScanCncnClient->fScrRelease (hScanCncnClient); 313 314 /* Call the client scan complete callback */ 315 if (TI_FALSE == pScanCncnClient->bInRequest) 316 { 317 pScanCncnClient->tScanResultCB (pScanCncnClient->hScanResultCBObj, 318 pScanCncnClient->eScanResult, NULL, pScanCncnClient->uSPSScanResult); 319 } 320} 321 322/** 323 * \fn scanCncnSm_Nop 324 * \brief Scan concentrator SM action function for no operation 325 * 326 * Used when no operation is required not due to an error 327 * 328 * \param hScanCncnClient - Handle to the scan concentrator client object 329 * \return None 330 */ 331void scanCncnSm_Nop (TI_HANDLE hScanCncnClient) 332{ 333} 334 335/** 336 * \fn ScanCncnSm_ActionUnexpected 337 * \brief Scan concentrator SM action function for unexpected events 338 * 339 * Print an error message 340 * 341 * \param hScanCncnClient - Handle to the scan concentrator client object 342 * \return None 343 */ 344void scanCncnSm_ActionUnexpected (TI_HANDLE hScanCncnClient) 345{ 346 TScanCncnClient *pScanCncnClient = (TScanCncnClient*)hScanCncnClient; 347 348 TRACE0(pScanCncnClient->hReport, REPORT_SEVERITY_ERROR , "ScanCncnSm_ActionUnexpected: Unexpected event for current state\n"); 349 350 /* mark the scan status as failed */ 351 pScanCncnClient->eScanResult = SCAN_CRS_SCAN_FAILED; 352} 353 354/** 355 * \fn scanCncnSm_RejectScan 356 * \brief Scan concentrator SM action function for rejecting a scan by the SCR 357 * 358 * Releases the SCR and calls the client scan complete CB, if not running within a request context 359 * 360 * \param hScanCncnClient - Handle to the scan concentrator client object 361 * \return None 362 */ 363void scanCncnSm_RejectScan (TI_HANDLE hScanCncnClient) 364{ 365 TScanCncnClient *pScanCncnClient = (TScanCncnClient*)hScanCncnClient; 366 367 TRACE0(pScanCncnClient->hReport, REPORT_SEVERITY_INFORMATION , "scanCncnSm_RejectScan: SM received reject event\n"); 368 369 pScanCncnClient->bScanRejectedOn2_4 = TI_TRUE; 370 /* release the SCR */ 371 pScanCncnClient->fScrRelease (hScanCncnClient); 372 373 /* Call the client scan complete CB */ 374 if (TI_FALSE == pScanCncnClient->bInRequest) 375 { 376 pScanCncnClient->tScanResultCB (pScanCncnClient->hScanResultCBObj, pScanCncnClient->eScanResult, 377 NULL, pScanCncnClient->uSPSScanResult); 378 } 379} 380 381/** 382 * \fn scanCncnSm_Recovery 383 * \brief Scan concentrator SM action function for handling recovery during scan 384 * 385 * Calls the SM specific recovery handling function and send a scan complete event. Used to stop timer 386 * on one-shot scans 387 * 388 * \param hScanCncnClient - Handle to the scan concentrator client object 389 * \return None 390 */ 391void scanCncnSm_Recovery (TI_HANDLE hScanCncnClient) 392{ 393 TScanCncnClient *pScanCncnClient = (TScanCncnClient*)hScanCncnClient; 394 395 TRACE0(pScanCncnClient->hReport, REPORT_SEVERITY_INFORMATION , "scanCncnSm_Recovery: SM received reject event\n"); 396 397 /* Call the recovery specific function */ 398 pScanCncnClient->fRecovery (hScanCncnClient); 399 400 /* Call the client scan complete callback */ 401 if (TI_FALSE == pScanCncnClient->bInRequest) 402 { 403 pScanCncnClient->tScanResultCB (pScanCncnClient->hScanResultCBObj, 404 pScanCncnClient->eScanResult, NULL, pScanCncnClient->uSPSScanResult); 405 } 406} 407 408