Home | History | Annotate | Download | only in scr
      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