/* * 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); } } /*******************************************************/