1/* 2 * GeneralUtil.c 3 * 4 * Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name Texas Instruments nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34#define __FILE_ID__ FILE_ID_52 35#include "GeneralUtilApi.h" 36#include "GeneralUtil.h" 37#include "report.h" 38#include "osApi.h" 39 40/************************************************************************* 41* LIST OBJ * 42************************************************************************** 43************************************************************************** 44* 45 * The list object mange the allocation and deallocation of generic element. 46 * The obj create a list of N generic elements and fined a free entry for the Alloc process. 47 * And free the entry for dealloc. 48 * 49 * 50***************************************************************************/ 51 52 53 54/************************************************************************* 55* List_create * 56************************************************************************** 57* DESCRIPTION: This function initializes the List data module. 58* 59* INPUT: hOs - handle to Os Abstraction Layer 60* MaxNumOfElements - the number of elemnts that will be Managed by the list 61 ContainerSize - The size of the basic data type managed by the list 62* OUTPUT: 63* 64* 65* RETURN: Handle to the allocated List data control block 66************************************************************************/ 67TI_HANDLE List_create(TI_HANDLE hOs,int MaxNumOfElements,int ContainerSize) 68{ 69 int index; 70 List_t *List; 71 72 if( hOs == NULL ) 73 { 74 WLAN_OS_REPORT(("FATAL ERROR:List_create(): OS handle Error - Aborting\n")); 75 return NULL; 76 } 77 78 /* alocate List block */ 79 List = (List_t*)os_memoryAlloc(hOs, sizeof(List_t)); 80 if(List == NULL) 81 return NULL; 82 83 84 /* alocate the List of Elements */ 85 List->ElementList =(ListElement_t*)os_memoryAlloc(hOs, (sizeof(ListElement_t)*MaxNumOfElements)); 86 if(List->ElementList == NULL) 87 { 88 os_memoryFree(List->hOs, List, sizeof(List_t)); 89 return NULL; 90 } 91 92 /*Allocate the Data containers*/ 93 for(index=0;index<MaxNumOfElements;index++) 94 { 95 List->ElementList[index].Container = os_memoryAlloc(hOs,ContainerSize); 96 if(List->ElementList[index].Container == NULL) 97 break; 98 List->ElementList[index].Inuse = TI_FALSE; 99 } 100 if (index != MaxNumOfElements) /*Not all the list element was allocated and*/ 101 { /*therefore we free the entire list and rap it up*/ 102 index--; 103 for(;index>=0;index--) 104 os_memoryFree(hOs,List->ElementList[index].Container,ContainerSize); 105 os_memoryFree(List->hOs, List->ElementList, (sizeof(ListElement_t)*MaxNumOfElements)); 106 os_memoryFree(List->hOs,List,(sizeof(List_t))); 107 return NULL; 108 109 } 110 111 List->MaxNumOfElements = MaxNumOfElements; 112 List->ContainerSize = ContainerSize; 113 return((TI_HANDLE)List); 114} 115 116 117/*************************************************************************** 118* List_Destroy * 119**************************************************************************** 120* DESCRIPTION: This function unload the List data module. 121* 122* INPUTS: hCtrlData - the object 123* 124* OUTPUT: 125* 126* RETURNS: TI_OK - Unload succesfull 127* TI_NOK - Unload unsuccesfull 128***************************************************************************/ 129TI_STATUS List_Destroy(TI_HANDLE hList) 130{ 131 List_t* List = (List_t*)hList; 132 int index; 133 134 if(List!=NULL) 135 { 136 if(List->ElementList != NULL) 137 { 138 for(index=0;index<List->MaxNumOfElements;index++) 139 os_memoryFree(List->hOs,List->ElementList[index].Container,List->ContainerSize); 140 141 os_memoryFree(List->hOs,List->ElementList,(sizeof(ListElement_t)*List->MaxNumOfElements)); 142 } 143 os_memoryFree(List->hOs, List, sizeof(List_t)); 144 } 145 return TI_OK; 146} 147 148/*************************************************************************** 149* List_AllocElement * 150**************************************************************************** 151* 152* 153* Fined an empty entry in the list and returns 154* a pointer to a memory that contains an element that not in use. 155* 156* Note in multi Task environment we need to add semaphore to protect the 157* Function. 158* 159***************************************************************************/ 160TI_HANDLE List_AllocElement(TI_HANDLE hList) 161{ 162 List_t* List = (List_t*)hList; 163 int index; 164 165 if (List == NULL) 166 return NULL; 167 168 for(index=0;index<List->MaxNumOfElements;index++) 169 { 170 if(!(List->ElementList[index].Inuse)) 171 { 172 List->ElementList[index].Inuse = TI_TRUE; 173 os_memoryZero(List->hOs,List->ElementList[index].Container,List->ContainerSize); 174 return((TI_HANDLE)List->ElementList[index].Container); 175 } 176 } 177 return NULL; 178} 179 180 181/*************************************************************************** 182* List_FreeElement * 183**************************************************************************** 184* 185* Marks the entry that was allocated as free. 186* An alloc process can use this space. 187* 188* 189* 190***************************************************************************/ 191TI_STATUS List_FreeElement(TI_HANDLE hList,TI_HANDLE Container) 192{ 193 List_t* List = (List_t*)hList; 194 int index; 195 196 if (List == NULL) 197 return TI_NOK; 198 199 for(index=0;index<List->MaxNumOfElements;index++) 200 { 201 if(List->ElementList[index].Container == Container) 202 { 203 if(!List->ElementList[index].Inuse) 204 return TI_NOK; /*double free not legal*/ 205 List->ElementList[index].Inuse = TI_FALSE; 206 return TI_OK; 207 } 208 } 209 return TI_NOK; 210} 211 212 213/*************************************************************************** 214* List_GetFirst * 215**************************************************************************** 216* 217* For purposes of searching the element list (going over all the element in the list) 218* Get first is used to reset an index for the search. 219* This function is work combined with GetNext. 220* 221* Note this function can't be used in multi Task environment. 222* 223***************************************************************************/ 224TI_HANDLE List_GetFirst(TI_HANDLE hList) 225{ 226 List_t* List = (List_t*)hList; 227 int index; 228 229 if (List == NULL) 230 return NULL; 231 232 for(index=0;index<List->MaxNumOfElements;index++) 233 { 234 if(List->ElementList[index].Inuse) 235 { 236 List->CurrentIndex = index; 237 return (List->ElementList[index].Container); 238 } 239 } 240 return NULL; 241} 242 243 244/*************************************************************************** 245* List_GetNext * 246**************************************************************************** 247* 248* This function returns the next element in the list till null 249* that indicate that there no more element or we have reached the end of the list. 250* This function is work combined with GetFirst. 251* 252* Note this function can't be used in multi Task environment. 253* 254***************************************************************************/ 255TI_HANDLE List_GetNext(TI_HANDLE hList) 256{ 257 List_t* List = (List_t*)hList; 258 int index; 259 260 if (List == NULL) 261 return NULL; 262 263 /* the code works fine even if the elment is the last*/ 264 for(index=List->CurrentIndex+1;index<List->MaxNumOfElements;index++) 265 { 266 if(List->ElementList[index].Inuse) 267 { 268 List->CurrentIndex = index; 269 return (List->ElementList[index].Container); 270 271 } 272 } 273 return NULL; 274} 275 276 277 278 279/*************************************************************************** 280* DISTRIBUTOR MANAGER * 281**************************************************************************** 282*************************************************************************** 283* 284 * PURPOSE:The distributor manger supplies 285 * 1. Register mechanism that has a callback function and the condition 286 * (bit mask format) that will be used to distinguish if to call this callback. 287 * 2. Event occurrence function that go over all the registered function and compare 288 * the input mask to the callback mask condition. 289 * 290 * 291 * 292***************************************************************************/ 293 294 295 296/*************************************************************************** 297* DistributorMgr_Create * 298**************************************************************************** 299* 300***************************************************************************/ 301TI_HANDLE DistributorMgr_Create(TI_HANDLE hOs , int MaxNotifReqElment) 302{ 303 DistributorMgr_t *DistributorMgr; 304 305 DistributorMgr = (DistributorMgr_t*)os_memoryAlloc(hOs, sizeof(DistributorMgr_t)); 306 if(DistributorMgr == NULL) 307 return NULL; 308 DistributorMgr->hOs = hOs; 309 DistributorMgr->DistributionList = (List_t*)List_create(hOs,MaxNotifReqElment,sizeof(NotifReqElment_t)); 310 if (DistributorMgr->DistributionList == NULL) 311 { 312 os_memoryFree(hOs, DistributorMgr, sizeof(DistributorMgr_t)); 313 return NULL; 314 } 315 return (TI_HANDLE)DistributorMgr; 316} 317 318 319 320/************************************************************************/ 321/* DistributorMgr_Destroy */ 322/************************************************************************/ 323TI_STATUS DistributorMgr_Destroy(TI_HANDLE hDistributorMgr) 324{ 325 DistributorMgr_t *DistributorMgr =(DistributorMgr_t*)hDistributorMgr; 326 327 if(DistributorMgr == NULL) 328 return TI_NOK; 329 330 List_Destroy(DistributorMgr->DistributionList); 331 332 os_memoryFree(DistributorMgr->hOs, hDistributorMgr, sizeof(DistributorMgr_t)); 333 334 return TI_OK; 335 336} 337 338/*************************************************************************** 339* DistributorMgr_Reg * 340**************************************************************************** 341* 342* Use by the client to register a callback function 343* with the mask condition that will trigger the call. 344* 345* input 346* TI_UINT16 Mask 347* TI_HANDLE CallBack 348* HANDLE Context 349* TI_UINT32 Cookie 350* 351* 352***************************************************************************/ 353TI_HANDLE DistributorMgr_Reg(TI_HANDLE hDistributorMgr,TI_UINT16 Mask,TI_HANDLE CallBack, 354 TI_HANDLE Context,TI_UINT32 Cookie) 355{ 356 DistributorMgr_t *DistributorMgr = (DistributorMgr_t*)hDistributorMgr; 357 NotifReqElment_t *NotifReqElment; 358 359 if(DistributorMgr == NULL) 360 return NULL; 361 362 NotifReqElment = (NotifReqElment_t*)List_AllocElement(DistributorMgr->DistributionList); 363 if (NotifReqElment == NULL) 364 return NULL ; 365 366 NotifReqElment->CallBack = (GeneralEventCall_t)CallBack; 367 NotifReqElment->Mask = Mask; 368 NotifReqElment->Context = Context; 369 NotifReqElment->Cookie = Cookie; 370 NotifReqElment->HaltReq = TI_FALSE; 371 return (TI_HANDLE)NotifReqElment; 372} 373 374 375/*************************************************************************** 376* DistributorMgr_ReReg * 377**************************************************************************** 378* 379***************************************************************************/ 380TI_STATUS DistributorMgr_ReReg(TI_HANDLE hDistributorMgr,TI_HANDLE ReqElmenth ,TI_UINT16 Mask,TI_HANDLE CallBack,TI_HANDLE Context,TI_UINT32 Cookie) 381{ 382 DistributorMgr_t *DistributorMgr = (DistributorMgr_t*)hDistributorMgr; 383 NotifReqElment_t *NotifReqElment = (NotifReqElment_t*)ReqElmenth; 384 385 if(DistributorMgr == NULL) 386 return TI_NOK; 387 388 if (NotifReqElment == NULL) 389 return TI_NOK; 390 391 NotifReqElment->CallBack = (GeneralEventCall_t)CallBack; 392 NotifReqElment->Mask = Mask; 393 NotifReqElment->Context = Context; 394 NotifReqElment->Cookie = Cookie; 395 return TI_OK; 396} 397 398 399/*************************************************************************** 400* DistributorMgr_AddToMask * 401**************************************************************************** 402* 403* Use this function to add mask bit to the bit mask condition that triggers the Callback 404* 405* 406***************************************************************************/ 407TI_STATUS DistributorMgr_AddToMask(TI_HANDLE hDistributorMgr,TI_HANDLE ReqElmenth,TI_UINT16 Mask) 408{ 409 DistributorMgr_t *DistributorMgr = (DistributorMgr_t*)hDistributorMgr; 410 NotifReqElment_t *NotifReqElment = (NotifReqElment_t*)ReqElmenth; 411 412 if(DistributorMgr == NULL) 413 return TI_NOK; 414 415 if (NotifReqElment == NULL) 416 return TI_NOK; 417 418 NotifReqElment->Mask |= Mask; 419 return TI_OK; 420} 421 422 423/*************************************************************************** 424* DistributorMgr_HaltNotif * 425**************************************************************************** 426* 427* Use this function to add mask bit to the bit mask condition that triggers the Callback 428* 429* 430***************************************************************************/ 431void DistributorMgr_HaltNotif(TI_HANDLE ReqElmenth) 432{ 433 NotifReqElment_t *NotifReqElment = (NotifReqElment_t*)ReqElmenth; 434 435 if (NotifReqElment == NULL) 436 return; 437 438 NotifReqElment->HaltReq = TI_TRUE; 439 440} 441 442 443/*************************************************************************** 444* DistributorMgr_RestartNotif * 445**************************************************************************** 446* 447* Use this function to add mask bit to the bit mask condition that triggers the Callback 448* 449* 450***************************************************************************/ 451void DistributorMgr_RestartNotif(TI_HANDLE ReqElmenth) 452{ 453 NotifReqElment_t *NotifReqElment = (NotifReqElment_t*)ReqElmenth; 454 455 if (NotifReqElment == NULL) 456 return; 457 458 NotifReqElment->HaltReq = TI_FALSE; 459 460} 461/*************************************************************************** 462* DistributorMgr_UnReg * 463**************************************************************************** 464* 465* 466***************************************************************************/ 467TI_STATUS DistributorMgr_UnReg(TI_HANDLE hDistributorMgr,TI_HANDLE RegEventHandle) 468{ 469 DistributorMgr_t *DistributorMgr = (DistributorMgr_t*)hDistributorMgr; 470 471 if(DistributorMgr == NULL) 472 return TI_NOK; 473 474 return List_FreeElement(DistributorMgr->DistributionList, RegEventHandle); 475} 476 477 478/*************************************************************************** 479* DistributorMgr_EventCall * 480**************************************************************************** 481* 482* When the client needs to invoke the callback calls function that corresponds 483* to a specific event mask it will call this function with the desired mask. 484* And event count that can be used to aggregate the events. 485* that way calling this function not for every event 486* 487***************************************************************************/ 488void DistributorMgr_EventCall(TI_HANDLE hDistributorMgr,TI_UINT16 Mask,int EventCount) 489{ 490 DistributorMgr_t *DistributorMgr = (DistributorMgr_t*)hDistributorMgr; 491 NotifReqElment_t *NotifReqElment; 492 493 if(DistributorMgr == NULL) 494 return; 495 496 NotifReqElment = (NotifReqElment_t*)List_GetFirst(DistributorMgr->DistributionList); 497 498 while(NotifReqElment) 499 { 500 if((NotifReqElment->Mask & Mask) && !(NotifReqElment->HaltReq)) 501 { 502 NotifReqElment->CallBack(NotifReqElment->Context,EventCount,Mask, 503 NotifReqElment->Cookie); 504 } 505 NotifReqElment = (NotifReqElment_t*)List_GetNext(DistributorMgr->DistributionList); 506 } 507} 508 509 510 511/*******************************************************/ 512