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