1 /** \file Scr.c 2 * \brief This file include the SCR module implementation 3 * \author Ronen Kalish 4 * \date 01-Dec-2004 5 */ 6 /**************************************************************************** 7 **+-----------------------------------------------------------------------+** 8 **| |** 9 **| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |** 10 **| All rights reserved. |** 11 **| |** 12 **| Redistribution and use in source and binary forms, with or without |** 13 **| modification, are permitted provided that the following conditions |** 14 **| are met: |** 15 **| |** 16 **| * Redistributions of source code must retain the above copyright |** 17 **| notice, this list of conditions and the following disclaimer. |** 18 **| * Redistributions in binary form must reproduce the above copyright |** 19 **| notice, this list of conditions and the following disclaimer in |** 20 **| the documentation and/or other materials provided with the |** 21 **| distribution. |** 22 **| * Neither the name Texas Instruments nor the names of its |** 23 **| contributors may be used to endorse or promote products derived |** 24 **| from this software without specific prior written permission. |** 25 **| |** 26 **| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |** 27 **| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |** 28 **| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |** 29 **| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |** 30 **| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |** 31 **| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |** 32 **| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |** 33 **| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |** 34 **| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |** 35 **| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |** 36 **| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |** 37 **| |** 38 **+-----------------------------------------------------------------------+** 39 ****************************************************************************/ 40 41 #include "report.h" 42 #include "scr.h" 43 #include "osApi.h" 44 45 46 /* 47 *********************************************************************** 48 * External data definitions. 49 *********************************************************************** 50 */ 51 52 /** 53 * \brief This array holds configuration values for abort others field for different clients.\n 54 */ 55 static scr_clientId_e abortOthers[ SCR_CID_NUM_OF_CLIENTS ] = 56 /* APP_SCAN DRV_FG CONT_SCAN EXC_MSR BASIC_MSR CONNECT IMMED_SCN SWITCH_CHNL*/ 57 { SCR_CID_NO_CLIENT, SCR_CID_NO_CLIENT, SCR_CID_NO_CLIENT, SCR_CID_NO_CLIENT, SCR_CID_NO_CLIENT, SCR_CID_BASIC_MEASURE, SCR_CID_BASIC_MEASURE, SCR_CID_BASIC_MEASURE }; 58 59 /** 60 * \brief This array holds configuration values for the client status field for different clients and groups. \n 61 */ 62 static BOOLEAN clientStaus [SCR_MID_NUM_OF_MODES][ SCR_GID_NUM_OF_GROUPS ][ SCR_CID_NUM_OF_CLIENTS ] = 63 { /* This is the table for Normal mode */ 64 {/* client status for idle group */ 65 { FALSE, /**< client status for SCR_CID_APP_SCAN */ 66 FALSE, /**< client status for SCR_CID_DRIVER_FG_SCAN */ 67 FALSE, /**< client status for SCR_CID_CONT_SCAN */ 68 FALSE, /**< client status for SCR_CID_EXC_MEASURE */ 69 FALSE, /**< client status for SCR_CID_BASIC_MEASURE */ 70 FALSE, /**< client status for SCR_CID_CONNECT */ 71 FALSE, /**< client status for SCR_CID_IMMED_SCAN */ 72 FALSE, /**< client status for SCR_CID_SWITCH_CHANNEL */ }, 73 /* client status for inter scan gorup */ 74 { TRUE, /**< client status for SCR_CID_APP_SCAN */ 75 FALSE, /**< client status for SCR_CID_DRIVER_FG_SCAN */ 76 FALSE, /**< client status for SCR_CID_CONT_SCAN */ 77 FALSE, /**< client status for SCR_CID_EXC_MEASURE */ 78 FALSE, /**< client status for SCR_CID_BASIC_MEASURE */ 79 FALSE, /**< client status for SCR_CID_CONNECT */ 80 FALSE, /**< client status for SCR_CID_IMMED_SCAN */ 81 FALSE, /**< client status for SCR_CID_SWITCH_CHANNEL */ }, 82 /* client status for connect group */ 83 { FALSE, /**< client status for SCR_CID_APP_SCAN */ 84 TRUE, /**< client status for SCR_CID_DRIVER_FG_SCAN */ 85 FALSE, /**< client status for SCR_CID_CONT_SCAN */ 86 FALSE, /**< client status for SCR_CID_EXC_MEASURE */ 87 FALSE, /**< client status for SCR_CID_BASIC_MEASURE */ 88 TRUE, /**< client status for SCR_CID_CONNECT */ 89 FALSE, /**< client status for SCR_CID_IMMED_SCAN */ 90 FALSE, /**< client status for SCR_CID_SWITCH_CHANNEL */ }, 91 /* client status for connected group */ 92 { TRUE, /**< client status for SCR_CID_APP_SCAN */ 93 FALSE, /**< client status for SCR_CID_DRIVER_FG_SCAN */ 94 TRUE, /**< client status for SCR_CID_CONT_SCAN */ 95 TRUE, /**< client status for SCR_CID_EXC_MEASURE */ 96 TRUE, /**< client status for SCR_CID_BASIC_MEASURE */ 97 FALSE, /**< client status for SCR_CID_CONNECT */ 98 FALSE, /**< client status for SCR_CID_IMMED_SCAN */ 99 TRUE, /**< client status for SCR_CID_SWITCH_CHANNEL */ }, 100 /* client status for roaming group */ 101 { FALSE, /**< client status for SCR_CID_APP_SCAN */ 102 FALSE, /**< client status for SCR_CID_DRIVER_FG_SCAN */ 103 FALSE, /**< client status for SCR_CID_CONT_SCAN */ 104 FALSE, /**< client status for SCR_CID_EXC_MEASURE */ 105 FALSE, /**< client status for SCR_CID_BASIC_MEASURE */ 106 TRUE, /**< client status for SCR_CID_CONNECT */ 107 TRUE, /**< client status for SCR_CID_IMMED_SCAN */ 108 FALSE, /**< client status for SCR_CID_SWITCH_CHANNEL */ } 109 }, 110 111 /* This is the table for the Soft gemini mode */ 112 113 { /* client status for idle group */ 114 { FALSE, /**< client status for SCR_CID_APP_SCAN */ 115 FALSE, /**< client status for SCR_CID_DRIVER_FG_SCAN */ 116 FALSE, /**< client status for SCR_CID_CONT_SCAN */ 117 FALSE, /**< client status for SCR_CID_EXC_MEASURE */ 118 FALSE, /**< client status for SCR_CID_BASIC_MEASURE */ 119 FALSE, /**< client status for SCR_CID_CONNECT */ 120 FALSE, /**< client status for SCR_CID_IMMED_SCAN */ 121 FALSE, /**< client status for SCR_CID_SWITCH_CHANNEL */ }, 122 /* client status for inter scan gorup */ 123 { TRUE, /**< client status for SCR_CID_APP_SCAN */ 124 FALSE, /**< client status for SCR_CID_DRIVER_FG_SCAN */ 125 FALSE, /**< client status for SCR_CID_CONT_SCAN */ 126 FALSE, /**< client status for SCR_CID_EXC_MEASURE */ 127 FALSE, /**< client status for SCR_CID_BASIC_MEASURE */ 128 FALSE, /**< client status for SCR_CID_CONNECT */ 129 FALSE, /**< client status for SCR_CID_IMMED_SCAN */ 130 FALSE, /**< client status for SCR_CID_SWITCH_CHANNEL */ }, 131 /* client status for connect group */ 132 { FALSE, /**< client status for SCR_CID_APP_SCAN */ 133 TRUE, /**< client status for SCR_CID_DRIVER_FG_SCAN */ 134 FALSE, /**< client status for SCR_CID_CONT_SCAN */ 135 FALSE, /**< client status for SCR_CID_EXC_MEASURE */ 136 FALSE, /**< client status for SCR_CID_BASIC_MEASURE */ 137 TRUE, /**< client status for SCR_CID_CONNECT */ 138 FALSE, /**< client status for SCR_CID_IMMED_SCAN */ 139 FALSE, /**< client status for SCR_CID_SWITCH_CHANNEL */ }, 140 /* client status for connected group */ 141 { TRUE, /**< client status for SCR_CID_APP_SCAN */ 142 FALSE, /**< client status for SCR_CID_DRIVER_FG_SCAN */ 143 TRUE, /**< client status for SCR_CID_CONT_SCAN */ 144 TRUE, /**< client status for SCR_CID_EXC_MEASURE */ 145 TRUE, /**< client status for SCR_CID_BASIC_MEASURE */ 146 FALSE, /**< client status for SCR_CID_CONNECT */ 147 FALSE, /**< client status for SCR_CID_IMMED_SCAN */ 148 TRUE, /**< client status for SCR_CID_SWITCH_CHANNEL */ }, 149 /* client status for roaming group */ 150 { FALSE, /**< client status for SCR_CID_APP_SCAN */ 151 FALSE, /**< client status for SCR_CID_DRIVER_FG_SCAN */ 152 FALSE, /**< client status for SCR_CID_CONT_SCAN */ 153 FALSE, /**< client status for SCR_CID_EXC_MEASURE */ 154 FALSE, /**< client status for SCR_CID_BASIC_MEASURE */ 155 TRUE, /**< client status for SCR_CID_CONNECT */ 156 TRUE, /**< client status for SCR_CID_IMMED_SCAN */ 157 FALSE, /**< client status for SCR_CID_SWITCH_CHANNEL */ } 158 } 159 }; 160 161 162 /** 163 * \author Ronen Kalish\n 164 * \date 01-Dec-2004\n 165 * \brief Creates the SCR object 166 * 167 * Function Scope \e Public.\n 168 * \param hOS - handle to the OS object.\n 169 * \return a handle to the SCR object.\n 170 */ 171 TI_HANDLE scr_create( TI_HANDLE hOS ) 172 { 173 /* allocate the SCR object */ 174 scr_t *pScr = os_memoryAlloc( hOS, sizeof(scr_t) ); 175 176 if ( NULL == pScr ) 177 { 178 WLAN_OS_REPORT( ("ERROR: Failed to create SCR module") ); 179 return NULL; 180 } 181 182 /* store the OS handle */ 183 pScr->hOS = hOS; 184 185 return pScr; 186 } 187 188 /** 189 * \author Ronen Kalish\n 190 * \date 01-Dec-2004\n 191 * \brief Finalizes the SCR object (freeing memory) 192 * 193 * Function Scope \e Public.\n 194 * \param hScr - handle to the SCR object.\n 195 */ 196 void scr_release( TI_HANDLE hScr ) 197 { 198 scr_t *pScr = (scr_t*)hScr; 199 200 os_memoryFree( pScr->hOS, hScr, sizeof(scr_t) ); 201 } 202 203 /** 204 * \author Ronen Kalish\n 205 * \date 01-Dec-2004\n 206 * \brief Initializes the SCR object 207 * 208 * Function Scope \e Public.\n 209 * \param hScr - handle to the SCR object.\n 210 * \param hReport - handle to the report module.\n 211 */ 212 void scr_init( TI_HANDLE hScr, TI_HANDLE hReport ) 213 { 214 int i; 215 scr_t *pScr = (scr_t*)hScr; 216 217 /* store the report object */ 218 pScr->hReport = hReport; 219 220 /* mark current group as idle */ 221 pScr->currentGroup = SCR_GID_IDLE; 222 223 /* mark current mode as normal */ 224 pScr->currentMode = SCR_MID_NORMAL; 225 226 /* signal not within request process */ 227 pScr->statusNotficationPending = FALSE; 228 229 /* mark that no client is currently running */ 230 pScr->runningClient = SCR_CID_NO_CLIENT; 231 232 /* initialize client array */ 233 for ( i = 0; i < SCR_CID_NUM_OF_CLIENTS; i++ ) 234 { 235 pScr->clientArray[ i ].state = SCR_CS_IDLE; 236 pScr->clientArray[ i ].currentPendingReason = SCR_PR_NONE; 237 pScr->clientArray[ i ].clientRequestCB = NULL; 238 pScr->clientArray[ i ].ClientRequestCBObj = NULL; 239 } 240 241 WLAN_REPORT_INIT( hReport, SCR_MODULE_LOG, (".....SCR configured successfully\n")); 242 } 243 244 /** 245 * \author Ronen Kalish\n 246 * \date 01-Dec-2004\n 247 * \brief Registers the callback function to be used per client. 248 * 249 * Function Scope \e Public.\n 250 * \param hScr - handle to the SCR object.\n 251 * \param client - the client ID.\n 252 * \param callbackFunc - the address of the callback function to use.\n 253 * \param callbackObj - the handle of the object to pass to the callback function (the client object).\n 254 */ 255 void scr_registerClientCB( TI_HANDLE hScr, 256 scr_clientId_e client, 257 scr_callback_t callbackFunc, 258 TI_HANDLE callbackObj ) 259 { 260 scr_t *pScr = (scr_t*)hScr; 261 262 #ifdef TI_DBG 263 if (client >= SCR_CID_NUM_OF_CLIENTS) 264 { 265 WLAN_REPORT_ERROR( pScr->hReport, SCR_MODULE_LOG, 266 ("Attempting to register callback for invalid client %d\n", client) ); 267 return; 268 } 269 #endif 270 pScr->clientArray[ client ].clientRequestCB = callbackFunc; 271 pScr->clientArray[ client ].ClientRequestCBObj = callbackObj; 272 } 273 274 /** 275 * \author Ronen Kalish\n 276 * \date 01-Dec-2004\n 277 * \brief Notifies the running process upon a firmware reset. 278 * 279 * Function Scope \e Public.\n 280 * \param hScr - handle to the SCR object.\n 281 */ 282 void scr_notifyFWReset( TI_HANDLE hScr ) 283 { 284 scr_t *pScr = (scr_t*)hScr; 285 286 /* if a client is currently running, notify it of the recovery event */ 287 if ( SCR_CID_NO_CLIENT != pScr->runningClient ) 288 { 289 WLAN_REPORT_INFORMATION( pScr->hReport, 290 SCR_MODULE_LOG, 291 ("FW reset occured. Client %d Notified.\n", pScr->runningClient) ); 292 if ( NULL != pScr->clientArray[ pScr->runningClient ].clientRequestCB ) 293 { 294 pScr->clientArray[ pScr->runningClient ].clientRequestCB( pScr->clientArray[ pScr->runningClient ].ClientRequestCBObj, 295 SCR_CRS_FW_RESET, SCR_PR_NONE ); 296 } 297 else 298 { 299 WLAN_REPORT_ERROR( pScr->hReport, SCR_MODULE_LOG, 300 ("Trying to call client %d callback, which is NULL\n", pScr->runningClient) ); 301 } 302 } 303 #ifdef TI_DBG 304 else 305 { 306 WLAN_REPORT_INFORMATION( pScr->hReport, 307 SCR_MODULE_LOG, 308 ("FW reset occured. No client was running.\n") ); 309 } 310 #endif 311 } 312 313 /** 314 * \author Ronen Kalish\n 315 * \date 27-April-2005\n 316 * \brief Changes the current SCR group.\n 317 * 318 * Function Scope \e Public.\n 319 * \param hScr - handle to the SCR object.\n 320 * \param newGroup - the new group to use.\n 321 */ 322 void scr_setGroup( TI_HANDLE hScr, scr_groupId_e newGroup ) 323 { 324 scr_t *pScr = (scr_t*)hScr; 325 int i,highestPending; 326 327 WLAN_REPORT_INFORMATION( pScr->hReport, SCR_MODULE_LOG, ("Setting group %d.\n", newGroup) ); 328 329 #ifdef TI_DBG 330 if (newGroup >= SCR_GID_NUM_OF_GROUPS) 331 { 332 WLAN_REPORT_ERROR( pScr->hReport, SCR_MODULE_LOG, 333 ("Attempting to set invalid group to %d\n", newGroup) ); 334 return; 335 } 336 #endif 337 338 /* keep the new group */ 339 pScr->currentGroup = newGroup; 340 341 /* for all pending clients */ 342 for ( i = 0; i < SCR_CID_NUM_OF_CLIENTS; i++ ) 343 { 344 /* if the pending reason has escalated */ 345 if ( (pScr->clientArray[ i ].state == SCR_CS_PENDING) && /* the client is pending */ 346 (pScr->clientArray[ i ].currentPendingReason < SCR_PR_DIFFERENT_GROUP_RUNNING) && /* the client was enabled in the previous group */ 347 (FALSE == clientStaus[pScr->currentMode][ newGroup ][ i ]) ) /* the client is not enabled in the new group */ 348 { 349 /* mark the new pending reason */ 350 pScr->clientArray[ i ].currentPendingReason = SCR_PR_DIFFERENT_GROUP_RUNNING; 351 352 /* notify the client of the change, using its callback */ 353 if ( NULL != pScr->clientArray[ i ].clientRequestCB ) 354 { 355 pScr->clientArray[ i ].clientRequestCB( pScr->clientArray[ i ].ClientRequestCBObj, 356 SCR_CRS_PEND, SCR_PR_DIFFERENT_GROUP_RUNNING ); 357 } 358 else 359 { 360 WLAN_REPORT_ERROR( pScr->hReport, SCR_MODULE_LOG, 361 ("Trying to call client %d callback, which is NULL\n", i) ); 362 } 363 } 364 } 365 366 /* if no client is running call the client with the highest pending client */ 367 /* because now , after group change , clients can be enabled */ 368 if ( SCR_CID_NO_CLIENT == pScr->runningClient ) 369 { 370 highestPending = scrFindHighest( hScr, SCR_CS_PENDING, (UINT8)(SCR_CID_NUM_OF_CLIENTS - 1), 0 ); 371 if (SCR_CID_NO_CLIENT != highestPending) 372 { 373 pScr->clientArray[ highestPending ].state = SCR_CS_RUNNING; 374 pScr->clientArray[ highestPending ].currentPendingReason = SCR_PR_NONE; 375 pScr->runningClient = (scr_clientId_e)highestPending; 376 if ( NULL != pScr->clientArray[ highestPending ].clientRequestCB ) 377 { 378 pScr->clientArray[ highestPending ].clientRequestCB( pScr->clientArray[ highestPending ].ClientRequestCBObj, 379 SCR_CRS_RUN, SCR_PR_NONE ); 380 } 381 else 382 { 383 WLAN_REPORT_ERROR( pScr->hReport, SCR_MODULE_LOG, 384 ("Trying to call client %d callback, which is NULL\n", highestPending) ); 385 } 386 } 387 } 388 389 } 390 391 /** 392 * \author Yuval Adler\n 393 * \date 23-Nov-2005\n 394 * \brief Changes the current SCR mode.\n 395 * 396 * Function Scope \e Public.\n 397 * \param hScr - handle to the SCR object.\n 398 * \param newMode - the new mode to use.\n 399 */ 400 void scr_setMode( TI_HANDLE hScr, scr_modeId_e newMode ) 401 { 402 scr_t *pScr = (scr_t*)hScr; 403 int i,highestPending; 404 405 WLAN_REPORT_INFORMATION( pScr->hReport, SCR_MODULE_LOG, ("Setting mode %d.\n", newMode) ); 406 407 #ifdef TI_DBG 408 if (newMode >= SCR_MID_NUM_OF_MODES) 409 { 410 WLAN_REPORT_ERROR( pScr->hReport, SCR_MODULE_LOG, 411 ("Attempting to set invalid mode to %d\n", newMode) ); 412 return; 413 } 414 #endif 415 416 /* keep the new mode */ 417 pScr->currentMode= newMode; 418 419 /* Stage I : if someone is running and shouldn't be running in the new mode - Abort it */ 420 if ( SCR_CID_NO_CLIENT != pScr->runningClient && 421 (FALSE == clientStaus[ pScr->currentMode ][ pScr->currentGroup ][ pScr->runningClient ]) ) 422 { 423 /* abort the running client */ 424 pScr->clientArray[ pScr->runningClient ].state = SCR_CS_ABORTING; 425 if ( NULL != pScr->clientArray[ pScr->runningClient ].clientRequestCB ) 426 { 427 WLAN_REPORT_INFORMATION( pScr->hReport, SCR_MODULE_LOG, 428 ("Sending abort request to client %d\n", pScr->runningClient) ); 429 pScr->clientArray[ pScr->runningClient ].clientRequestCB( pScr->clientArray[ pScr->runningClient ].ClientRequestCBObj, 430 SCR_CRS_ABORT, 431 SCR_PR_NONE ); 432 } 433 else 434 { 435 WLAN_REPORT_ERROR( pScr->hReport, SCR_MODULE_LOG, 436 ("Trying to call client %d callback, which is NULL\n", pScr->runningClient) ); 437 } 438 439 } 440 441 /* Stage II : notify escalated pending reason */ 442 /* for all pending clients */ 443 for ( i = 0; i < SCR_CID_NUM_OF_CLIENTS; i++ ) 444 { 445 /* if the pending reason has escalated */ 446 if ( (pScr->clientArray[ i ].state == SCR_CS_PENDING) && /* the client is pending */ 447 (pScr->clientArray[ i ].currentPendingReason < SCR_PR_DIFFERENT_GROUP_RUNNING) && /* the client was enabled in the previous group */ 448 (FALSE == clientStaus[ pScr->currentMode ][ pScr->currentGroup ][ i ]) ) /* the client is not enabled in the new group/mode */ 449 { 450 /* mark the new pending reason */ 451 pScr->clientArray[ i ].currentPendingReason = SCR_PR_DIFFERENT_GROUP_RUNNING; 452 453 /* notify the client of the change, using its callback */ 454 if ( NULL != pScr->clientArray[ i ].clientRequestCB ) 455 { 456 pScr->clientArray[ i ].clientRequestCB( pScr->clientArray[ i ].ClientRequestCBObj, 457 SCR_CRS_PEND, SCR_PR_DIFFERENT_GROUP_RUNNING ); 458 } 459 else 460 { 461 WLAN_REPORT_ERROR( pScr->hReport, SCR_MODULE_LOG, 462 ("Trying to call client %d callback, which is NULL\n", i) ); 463 } 464 } 465 } 466 467 468 /* Stage III : call Highest Pending Client who is enabled in the new mode */ 469 if ( SCR_CID_NO_CLIENT == pScr->runningClient ) 470 { 471 highestPending = scrFindHighest( hScr, SCR_CS_PENDING, (UINT8)(SCR_CID_NUM_OF_CLIENTS - 1), 0 ); 472 if (SCR_CID_NO_CLIENT != highestPending) 473 { 474 pScr->clientArray[ highestPending ].state = SCR_CS_RUNNING; 475 pScr->clientArray[ highestPending ].currentPendingReason = SCR_PR_NONE; 476 pScr->runningClient = (scr_clientId_e)highestPending; 477 if ( NULL != pScr->clientArray[ highestPending ].clientRequestCB ) 478 { 479 pScr->clientArray[ highestPending ].clientRequestCB( pScr->clientArray[ highestPending ].ClientRequestCBObj, 480 SCR_CRS_RUN, SCR_PR_NONE ); 481 } 482 else 483 { 484 WLAN_REPORT_ERROR( pScr->hReport, SCR_MODULE_LOG, 485 ("Trying to call client %d callback, which is NULL\n", highestPending) ); 486 } 487 } 488 } 489 490 } 491 492 493 /** 494 * \author Ronen Kalish\n 495 * \date 01-Dec-2004\n 496 * \brief Request the channel use by a client 497 * 498 * Function Scope \e Public.\n 499 * \param hScr - handle to the SCR object.\n 500 * \param client - the client ID requesting the channel.\n 501 * \param pPendReason - the reason for a pend reply.\n 502 * \return The request status.\n 503 * \retval SCR_CRS_REJECT the channel cannot be allocated to this client. 504 * \retval SCR_CRS_PEND the channel is currently busy, and this client had been placed on the waiting list. 505 * \retval SCR_CRS_RUN the channel is allocated to this client. 506 */ 507 scr_clientRequestStatus_e scr_clientRequest( TI_HANDLE hScr, scr_clientId_e client, scr_pendReason_e* pPendReason ) 508 { 509 scr_t *pScr = (scr_t*)hScr; 510 511 WLAN_REPORT_INFORMATION( pScr->hReport, SCR_MODULE_LOG, ("Client %d requesting the channel.\n", client) ); 512 513 #ifdef TI_DBG 514 if (client >= SCR_CID_NUM_OF_CLIENTS) 515 { 516 WLAN_REPORT_ERROR( pScr->hReport, SCR_MODULE_LOG, 517 ("Attempting to request SCR for invalid client %d\n", client) ); 518 return SCR_CRS_PEND; 519 } 520 #endif 521 522 *pPendReason = SCR_PR_NONE; 523 524 /* check if already inside a request - shouldn't happen!!! */ 525 if ( TRUE == pScr->statusNotficationPending ) 526 { 527 WLAN_REPORT_ERROR( pScr->hReport, SCR_MODULE_LOG, ("request call while already in request!\n") ); 528 return SCR_CRS_PEND; 529 } 530 531 /* check if current running client is requesting */ 532 if ( client == pScr->runningClient ) 533 { 534 WLAN_REPORT_WARNING( pScr->hReport, SCR_MODULE_LOG, ("Client %d re-requesting SCR\n", client) ); 535 return SCR_CRS_RUN; 536 } 537 538 /* check if the client is enabled in the current group */ 539 if ( TRUE != clientStaus[ pScr->currentMode ][ pScr->currentGroup ][ client ]) 540 { 541 pScr->clientArray[ client ].state = SCR_CS_PENDING; 542 pScr->clientArray[ client ].currentPendingReason = *pPendReason = SCR_PR_DIFFERENT_GROUP_RUNNING; 543 return SCR_CRS_PEND; 544 } 545 546 /* check if a there's no running client at the moment */ 547 if ( SCR_CID_NO_CLIENT == pScr->runningClient ) 548 { 549 /* no running or aborted client - allow access */ 550 WLAN_REPORT_INFORMATION( pScr->hReport, SCR_MODULE_LOG, 551 ("channel allocated to client: %d\n", client) ); 552 pScr->clientArray[ client ].state = SCR_CS_RUNNING; 553 pScr->runningClient = client; 554 return SCR_CRS_RUN; 555 } 556 557 /* check if any client is aborting at the moment */ 558 if ( SCR_CS_ABORTING == pScr->clientArray[ pScr->runningClient ].state ) 559 { 560 /* a client is currently aborting, but there still might be a pending client with higher priority 561 than the client currently requesting the SCR. If such client exists, the requesting client is 562 notified that it is pending because of this pending client, rather than the one currently aborting. 563 */ 564 scr_clientId_e highestPending; 565 highestPending = (scr_clientId_e)scrFindHighest( hScr, SCR_CS_PENDING, (UINT8)(SCR_CID_NUM_OF_CLIENTS - 1), client ); 566 if ( (SCR_CID_NO_CLIENT == highestPending) || 567 (highestPending < client) ) 568 { 569 /* if the requesting client has higher priority than the current highest priority pending client, 570 the current highest priority pending client should be notified that its pending reason has 571 changed (it is no longer waiting for current running client to abort, but for the requesting 572 client to finish, once the current has aborted */ 573 if ( (highestPending != SCR_CID_NO_CLIENT) && 574 (SCR_PR_OTHER_CLIENT_ABORTING == pScr->clientArray[ highestPending ].currentPendingReason) ) 575 { 576 577 if ( NULL != pScr->clientArray[ highestPending ].clientRequestCB ) 578 { 579 pScr->clientArray[ highestPending ].clientRequestCB( pScr->clientArray[ highestPending ].ClientRequestCBObj, 580 SCR_CRS_PEND, SCR_PR_OTHER_CLIENT_RUNNING ); 581 } 582 else 583 { 584 WLAN_REPORT_ERROR( pScr->hReport, SCR_MODULE_LOG, 585 ("Trying to call client %d callback, which is NULL\n", highestPending) ); 586 } 587 } 588 pScr->clientArray[ client ].currentPendingReason = *pPendReason = SCR_PR_OTHER_CLIENT_ABORTING; 589 } 590 else 591 { 592 pScr->clientArray[ client ].currentPendingReason = *pPendReason = SCR_PR_OTHER_CLIENT_RUNNING; 593 } 594 pScr->clientArray[ client ].state = SCR_CS_PENDING; 595 return SCR_CRS_PEND; 596 } 597 598 /* check if a client with higher priority is running */ 599 if (pScr->runningClient > client) 600 { 601 pScr->clientArray[ client ].state = SCR_CS_PENDING; 602 pScr->clientArray[ client ].currentPendingReason = *pPendReason = SCR_PR_OTHER_CLIENT_RUNNING; 603 return SCR_CRS_PEND; 604 } 605 606 /* if the client is not supposed to abort lower priority clients */ 607 if ( (SCR_CID_NO_CLIENT == abortOthers[ client ]) || /* client is not supposed to abort any other client */ 608 (pScr->runningClient > abortOthers[ client ]) ) /* client is not supposed to abort running client */ 609 { 610 /* wait for the lower priority client */ 611 pScr->clientArray[ client ].state = SCR_CS_PENDING; 612 pScr->clientArray[ client ].currentPendingReason = *pPendReason = SCR_PR_OTHER_CLIENT_RUNNING; 613 return SCR_CRS_PEND; 614 } 615 616 /* at this point, there is a lower priority client running, that should be aborted: */ 617 /* mark the requesting client as pending (until the abort process will be completed) */ 618 pScr->clientArray[ client ].state = SCR_CS_PENDING; 619 620 /* mark that we are in the middle of a request (if a re-entrance will occur in the complete) */ 621 pScr->statusNotficationPending = TRUE; 622 623 /* abort the running client */ 624 pScr->clientArray[ pScr->runningClient ].state = SCR_CS_ABORTING; 625 if ( NULL != pScr->clientArray[ pScr->runningClient ].clientRequestCB ) 626 { 627 WLAN_REPORT_INFORMATION( pScr->hReport, SCR_MODULE_LOG, 628 ("Sending abort request to client %d\n", pScr->runningClient) ); 629 pScr->clientArray[ pScr->runningClient ].clientRequestCB( pScr->clientArray[ pScr->runningClient ].ClientRequestCBObj, 630 SCR_CRS_ABORT, 631 SCR_PR_NONE ); 632 } 633 else 634 { 635 WLAN_REPORT_ERROR( pScr->hReport, SCR_MODULE_LOG, 636 ("Trying to call client %d callback, which is NULL\n", pScr->runningClient) ); 637 } 638 639 /* mark that we have finished the request process */ 640 pScr->statusNotficationPending = FALSE; 641 642 /* return the current status (in case the completion changed the client status to run) */ 643 if ( SCR_CS_RUNNING == pScr->clientArray[ client ].state ) 644 { 645 WLAN_REPORT_INFORMATION( pScr->hReport, SCR_MODULE_LOG, 646 ("channel allocated to client: %d\n", client) ); 647 return SCR_CRS_RUN; 648 } 649 else 650 { 651 pScr->clientArray[ client].currentPendingReason = *pPendReason = SCR_PR_OTHER_CLIENT_ABORTING; 652 return SCR_CRS_PEND; 653 } 654 } 655 656 /** 657 * \author Ronen Kalish\n 658 * \date 01-Dec-2004\n 659 * \brief Notifies the SCR that the client doe not require the channel any longer 660 * 661 * This function can be called both by clients that are in possession of the channel, and by 662 * clients that are pending to use the channel.\n 663 * Function Scope \e Public.\n 664 * \param hScr - handle to the SCR object.\n 665 * \param client - the client releasing the channel.\n 666 * \return OK if successful, NOK otherwise.\n 667 */ 668 void scr_clientComplete( TI_HANDLE hScr, scr_clientId_e client ) 669 { 670 int highestPending; 671 scr_t *pScr = (scr_t*)hScr; 672 673 WLAN_REPORT_INFORMATION( pScr->hReport, SCR_MODULE_LOG, ("Client %d releasing the channel.\n", client) ); 674 675 #ifdef TI_DBG 676 if (client >= SCR_CID_NUM_OF_CLIENTS) 677 { 678 WLAN_REPORT_ERROR( pScr->hReport, SCR_MODULE_LOG, 679 ("Attempting to release SCR for invalid client %d\n", client) ); 680 return; 681 } 682 #endif 683 684 /* mark client state as idle */ 685 pScr->clientArray[ client ].state = SCR_CS_IDLE; 686 pScr->clientArray[ client ].currentPendingReason = SCR_PR_NONE; 687 688 /* if completing client is running (or aborting) */ 689 if ( pScr->runningClient == client ) 690 { 691 /* mark no running client */ 692 pScr->runningClient = SCR_CID_NO_CLIENT; 693 694 /* find the pending client with highest priority */ 695 highestPending = scrFindHighest( hScr, SCR_CS_PENDING, (UINT8)(SCR_CID_NUM_OF_CLIENTS-1), 0 ); 696 697 /* if a pending client exists */ 698 if ( SCR_CID_NO_CLIENT != highestPending ) 699 { 700 /* mark the client with highest priority as running */ 701 pScr->clientArray[ highestPending ].state = SCR_CS_RUNNING; 702 pScr->clientArray[ highestPending ].currentPendingReason = SCR_PR_NONE; 703 pScr->runningClient = (scr_clientId_e)highestPending; 704 705 /* if the SCR is not called from within a client request (re-entrance) */ 706 if ( FALSE == pScr->statusNotficationPending ) 707 { 708 if ( NULL != pScr->clientArray[ highestPending ].clientRequestCB ) 709 { 710 pScr->clientArray[ highestPending ].clientRequestCB( pScr->clientArray[ highestPending ].ClientRequestCBObj, 711 SCR_CRS_RUN, SCR_PR_NONE ); 712 } 713 else 714 { 715 WLAN_REPORT_ERROR( pScr->hReport, SCR_MODULE_LOG, 716 ("Trying to call client %d callback, which is NULL\n", highestPending) ); 717 } 718 } 719 } 720 } 721 } 722 723 /** 724 * \author Ronen Kalish\n 725 * \date 01-Dec-2004\n 726 * \brief Searches the client database for a client with matching state, from startFrom to endAt (inclusive). 727 * \brief Only searches for clients that are enabled at the current group!!!!\n 728 * 729 * Function Scope \e Private.\n 730 * \param hScr - handle to the SCR object.\n 731 * \param requiredState - the state to match.\n 732 * \param startFrom - the highest priority to begin searching from.\n 733 * \param endAt - the lowest priority to include in the search 734 * \return the client ID if found, -1 otherwise.\n 735 */ 736 INT8 scrFindHighest( TI_HANDLE hScr, 737 scr_clientState_e requiredState, 738 int startFrom, 739 int endAt ) 740 { 741 int i; 742 scr_t *pScr = (scr_t*)hScr; 743 744 /* loop on all clients, from start to end */ 745 for ( i = startFrom; i >= endAt; i-- ) 746 { 747 /* check if the client state matches the required state */ 748 if ( (TRUE == clientStaus[ pScr->currentMode ][ pScr->currentGroup ][ i ]) && /* client is enabled in current group */ 749 (requiredState == pScr->clientArray[ i ].state) ) /* client is in required state */ 750 { 751 /* and if so, return the client index */ 752 return i; 753 } 754 } 755 756 return SCR_CID_NO_CLIENT; 757 } 758