/*
* GeneralUtil.c
*
* Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Texas Instruments nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define __FILE_ID__ FILE_ID_52
#include "GeneralUtilApi.h"
#include "GeneralUtil.h"
#include "report.h"
#include "osApi.h"
/*************************************************************************
* LIST OBJ *
**************************************************************************
**************************************************************************
*
* The list object mange the allocation and deallocation of generic element.
* The obj create a list of N generic elements and fined a free entry for the Alloc process.
* And free the entry for dealloc.
*
*
***************************************************************************/
/*************************************************************************
* List_create *
**************************************************************************
* DESCRIPTION: This function initializes the List data module.
*
* INPUT: hOs - handle to Os Abstraction Layer
* MaxNumOfElements - the number of elemnts that will be Managed by the list
ContainerSize - The size of the basic data type managed by the list
* OUTPUT:
*
*
* RETURN: Handle to the allocated List data control block
************************************************************************/
TI_HANDLE List_create(TI_HANDLE hOs,int MaxNumOfElements,int ContainerSize)
{
int index;
List_t *List;
if( hOs == NULL )
{
WLAN_OS_REPORT(("FATAL ERROR:List_create(): OS handle Error - Aborting\n"));
return NULL;
}
/* alocate List block */
List = (List_t*)os_memoryAlloc(hOs, sizeof(List_t));
if(List == NULL)
return NULL;
/* alocate the List of Elements */
List->ElementList =(ListElement_t*)os_memoryAlloc(hOs, (sizeof(ListElement_t)*MaxNumOfElements));
if(List->ElementList == NULL)
{
os_memoryFree(List->hOs, List, sizeof(List_t));
return NULL;
}
/*Allocate the Data containers*/
for(index=0;index<MaxNumOfElements;index++)
{
List->ElementList[index].Container = os_memoryAlloc(hOs,ContainerSize);
if(List->ElementList[index].Container == NULL)
break;
List->ElementList[index].Inuse = TI_FALSE;
}
if (index != MaxNumOfElements) /*Not all the list element was allocated and*/
{ /*therefore we free the entire list and rap it up*/
index--;
for(;index>=0;index--)
os_memoryFree(hOs,List->ElementList[index].Container,ContainerSize);
os_memoryFree(List->hOs, List->ElementList, (sizeof(ListElement_t)*MaxNumOfElements));
os_memoryFree(List->hOs,List,(sizeof(List_t)));
return NULL;
}
List->MaxNumOfElements = MaxNumOfElements;
List->ContainerSize = ContainerSize;
return((TI_HANDLE)List);
}
/***************************************************************************
* List_Destroy *
****************************************************************************
* DESCRIPTION: This function unload the List data module.
*
* INPUTS: hCtrlData - the object
*
* OUTPUT:
*
* RETURNS: TI_OK - Unload succesfull
* TI_NOK - Unload unsuccesfull
***************************************************************************/
TI_STATUS List_Destroy(TI_HANDLE hList)
{
List_t* List = (List_t*)hList;
int index;
if(List!=NULL)
{
if(List->ElementList != NULL)
{
for(index=0;index<List->MaxNumOfElements;index++)
os_memoryFree(List->hOs,List->ElementList[index].Container,List->ContainerSize);
os_memoryFree(List->hOs,List->ElementList,(sizeof(ListElement_t)*List->MaxNumOfElements));
}
os_memoryFree(List->hOs, List, sizeof(List_t));
}
return TI_OK;
}
/***************************************************************************
* List_AllocElement *
****************************************************************************
*
*
* Fined an empty entry in the list and returns
* a pointer to a memory that contains an element that not in use.
*
* Note in multi Task environment we need to add semaphore to protect the
* Function.
*
***************************************************************************/
TI_HANDLE List_AllocElement(TI_HANDLE hList)
{
List_t* List = (List_t*)hList;
int index;
if (List == NULL)
return NULL;
for(index=0;index<List->MaxNumOfElements;index++)
{
if(!(List->ElementList[index].Inuse))
{
List->ElementList[index].Inuse = TI_TRUE;
os_memoryZero(List->hOs,List->ElementList[index].Container,List->ContainerSize);
return((TI_HANDLE)List->ElementList[index].Container);
}
}
return NULL;
}
/***************************************************************************
* List_FreeElement *
****************************************************************************
*
* Marks the entry that was allocated as free.
* An alloc process can use this space.
*
*
*
***************************************************************************/
TI_STATUS List_FreeElement(TI_HANDLE hList,TI_HANDLE Container)
{
List_t* List = (List_t*)hList;
int index;
if (List == NULL)
return TI_NOK;
for(index=0;index<List->MaxNumOfElements;index++)
{
if(List->ElementList[index].Container == Container)
{
if(!List->ElementList[index].Inuse)
return TI_NOK; /*double free not legal*/
List->ElementList[index].Inuse = TI_FALSE;
return TI_OK;
}
}
return TI_NOK;
}
/***************************************************************************
* List_GetFirst *
****************************************************************************
*
* For purposes of searching the element list (going over all the element in the list)
* Get first is used to reset an index for the search.
* This function is work combined with GetNext.
*
* Note this function can't be used in multi Task environment.
*
***************************************************************************/
TI_HANDLE List_GetFirst(TI_HANDLE hList)
{
List_t* List = (List_t*)hList;
int index;
if (List == NULL)
return NULL;
for(index=0;index<List->MaxNumOfElements;index++)
{
if(List->ElementList[index].Inuse)
{
List->CurrentIndex = index;
return (List->ElementList[index].Container);
}
}
return NULL;
}
/***************************************************************************
* List_GetNext *
****************************************************************************
*
* This function returns the next element in the list till null
* that indicate that there no more element or we have reached the end of the list.
* This function is work combined with GetFirst.
*
* Note this function can't be used in multi Task environment.
*
***************************************************************************/
TI_HANDLE List_GetNext(TI_HANDLE hList)
{
List_t* List = (List_t*)hList;
int index;
if (List == NULL)
return NULL;
/* the code works fine even if the elment is the last*/
for(index=List->CurrentIndex+1;index<List->MaxNumOfElements;index++)
{
if(List->ElementList[index].Inuse)
{
List->CurrentIndex = index;
return (List->ElementList[index].Container);
}
}
return NULL;
}
/***************************************************************************
* DISTRIBUTOR MANAGER *
****************************************************************************
***************************************************************************
*
* PURPOSE:The distributor manger supplies
* 1. Register mechanism that has a callback function and the condition
* (bit mask format) that will be used to distinguish if to call this callback.
* 2. Event occurrence function that go over all the registered function and compare
* the input mask to the callback mask condition.
*
*
*
***************************************************************************/
/***************************************************************************
* DistributorMgr_Create *
****************************************************************************
*
***************************************************************************/
TI_HANDLE DistributorMgr_Create(TI_HANDLE hOs , int MaxNotifReqElment)
{
DistributorMgr_t *DistributorMgr;
DistributorMgr = (DistributorMgr_t*)os_memoryAlloc(hOs, sizeof(DistributorMgr_t));
if(DistributorMgr == NULL)
return NULL;
DistributorMgr->hOs = hOs;
DistributorMgr->DistributionList = (List_t*)List_create(hOs,MaxNotifReqElment,sizeof(NotifReqElment_t));
if (DistributorMgr->DistributionList == NULL)
{
os_memoryFree(hOs, DistributorMgr, sizeof(DistributorMgr_t));
return NULL;
}
return (TI_HANDLE)DistributorMgr;
}
/************************************************************************/
/* DistributorMgr_Destroy */
/************************************************************************/
TI_STATUS DistributorMgr_Destroy(TI_HANDLE hDistributorMgr)
{
DistributorMgr_t *DistributorMgr =(DistributorMgr_t*)hDistributorMgr;
if(DistributorMgr == NULL)
return TI_NOK;
List_Destroy(DistributorMgr->DistributionList);
os_memoryFree(DistributorMgr->hOs, hDistributorMgr, sizeof(DistributorMgr_t));
return TI_OK;
}
/***************************************************************************
* DistributorMgr_Reg *
****************************************************************************
*
* Use by the client to register a callback function
* with the mask condition that will trigger the call.
*
* input
* TI_UINT16 Mask
* TI_HANDLE CallBack
* HANDLE Context
* TI_UINT32 Cookie
*
*
***************************************************************************/
TI_HANDLE DistributorMgr_Reg(TI_HANDLE hDistributorMgr,TI_UINT16 Mask,TI_HANDLE CallBack,
TI_HANDLE Context,TI_UINT32 Cookie)
{
DistributorMgr_t *DistributorMgr = (DistributorMgr_t*)hDistributorMgr;
NotifReqElment_t *NotifReqElment;
if(DistributorMgr == NULL)
return NULL;
NotifReqElment = (NotifReqElment_t*)List_AllocElement(DistributorMgr->DistributionList);
if (NotifReqElment == NULL)
return NULL ;
NotifReqElment->CallBack = (GeneralEventCall_t)CallBack;
NotifReqElment->Mask = Mask;
NotifReqElment->Context = Context;
NotifReqElment->Cookie = Cookie;
NotifReqElment->HaltReq = TI_FALSE;
return (TI_HANDLE)NotifReqElment;
}
/***************************************************************************
* DistributorMgr_ReReg *
****************************************************************************
*
***************************************************************************/
TI_STATUS DistributorMgr_ReReg(TI_HANDLE hDistributorMgr,TI_HANDLE ReqElmenth ,TI_UINT16 Mask,TI_HANDLE CallBack,TI_HANDLE Context,TI_UINT32 Cookie)
{
DistributorMgr_t *DistributorMgr = (DistributorMgr_t*)hDistributorMgr;
NotifReqElment_t *NotifReqElment = (NotifReqElment_t*)ReqElmenth;
if(DistributorMgr == NULL)
return TI_NOK;
if (NotifReqElment == NULL)
return TI_NOK;
NotifReqElment->CallBack = (GeneralEventCall_t)CallBack;
NotifReqElment->Mask = Mask;
NotifReqElment->Context = Context;
NotifReqElment->Cookie = Cookie;
return TI_OK;
}
/***************************************************************************
* DistributorMgr_AddToMask *
****************************************************************************
*
* Use this function to add mask bit to the bit mask condition that triggers the Callback
*
*
***************************************************************************/
TI_STATUS DistributorMgr_AddToMask(TI_HANDLE hDistributorMgr,TI_HANDLE ReqElmenth,TI_UINT16 Mask)
{
DistributorMgr_t *DistributorMgr = (DistributorMgr_t*)hDistributorMgr;
NotifReqElment_t *NotifReqElment = (NotifReqElment_t*)ReqElmenth;
if(DistributorMgr == NULL)
return TI_NOK;
if (NotifReqElment == NULL)
return TI_NOK;
NotifReqElment->Mask |= Mask;
return TI_OK;
}
/***************************************************************************
* DistributorMgr_HaltNotif *
****************************************************************************
*
* Use this function to add mask bit to the bit mask condition that triggers the Callback
*
*
***************************************************************************/
void DistributorMgr_HaltNotif(TI_HANDLE ReqElmenth)
{
NotifReqElment_t *NotifReqElment = (NotifReqElment_t*)ReqElmenth;
if (NotifReqElment == NULL)
return;
NotifReqElment->HaltReq = TI_TRUE;
}
/***************************************************************************
* DistributorMgr_RestartNotif *
****************************************************************************
*
* Use this function to add mask bit to the bit mask condition that triggers the Callback
*
*
***************************************************************************/
void DistributorMgr_RestartNotif(TI_HANDLE ReqElmenth)
{
NotifReqElment_t *NotifReqElment = (NotifReqElment_t*)ReqElmenth;
if (NotifReqElment == NULL)
return;
NotifReqElment->HaltReq = TI_FALSE;
}
/***************************************************************************
* DistributorMgr_UnReg *
****************************************************************************
*
*
***************************************************************************/
TI_STATUS DistributorMgr_UnReg(TI_HANDLE hDistributorMgr,TI_HANDLE RegEventHandle)
{
DistributorMgr_t *DistributorMgr = (DistributorMgr_t*)hDistributorMgr;
if(DistributorMgr == NULL)
return TI_NOK;
return List_FreeElement(DistributorMgr->DistributionList, RegEventHandle);
}
/***************************************************************************
* DistributorMgr_EventCall *
****************************************************************************
*
* When the client needs to invoke the callback calls function that corresponds
* to a specific event mask it will call this function with the desired mask.
* And event count that can be used to aggregate the events.
* that way calling this function not for every event
*
***************************************************************************/
void DistributorMgr_EventCall(TI_HANDLE hDistributorMgr,TI_UINT16 Mask,int EventCount)
{
DistributorMgr_t *DistributorMgr = (DistributorMgr_t*)hDistributorMgr;
NotifReqElment_t *NotifReqElment;
if(DistributorMgr == NULL)
return;
NotifReqElment = (NotifReqElment_t*)List_GetFirst(DistributorMgr->DistributionList);
while(NotifReqElment)
{
if((NotifReqElment->Mask & Mask) && !(NotifReqElment->HaltReq))
{
NotifReqElment->CallBack(NotifReqElment->Context,EventCount,Mask,
NotifReqElment->Cookie);
}
NotifReqElment = (NotifReqElment_t*)List_GetNext(DistributorMgr->DistributionList);
}
}
/*******************************************************/