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 ************************************************************************/ 67 TI_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 ***************************************************************************/ 129 TI_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 ***************************************************************************/ 160 TI_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 ***************************************************************************/ 191 TI_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 ***************************************************************************/ 224 TI_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 ***************************************************************************/ 255 TI_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 ***************************************************************************/ 301 TI_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 /************************************************************************/ 323 TI_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 ***************************************************************************/ 353 TI_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 ***************************************************************************/ 380 TI_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 ***************************************************************************/ 407 TI_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 ***************************************************************************/ 431 void 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 ***************************************************************************/ 451 void 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 ***************************************************************************/ 467 TI_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 ***************************************************************************/ 488 void 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