source: svn/trunk/newcon3bcm2_21bu/BSEAV/lib/scte65/aett/si_aett.c

Last change on this file was 2, checked in by jglee, 11 years ago

first commit

  • Property svn:executable set to *
File size: 16.7 KB
Line 
1/***************************************************************
2**
3** Broadcom Corp. Confidential
4** Copyright 2003-2008 Broadcom Corp. All Rights Reserved.
5**
6** THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED
7** SOFTWARE LICENSE AGREEMENT BETWEEN THE USER AND BROADCOM.
8** YOU HAVE NO RIGHT TO USE OR EXPLOIT THIS MATERIAL EXCEPT
9** SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
10**
11** File:                si_aett.c
12** Description: function that parses the AETT
13**              table section. And keeps track of all the events.
14**
15** Created: 03/08/2001
16**
17** REVISION:
18**
19** $Log: $
20**
21**
22****************************************************************/
23
24#include "si.h"
25#include "si_os.h"
26#include "si_dbg.h"
27#include "si_util.h"
28#include "si_list.h"
29#include "si_aett.h"
30#include "si_mgt.h"
31#include "si_descriptors.h"
32
33/* local function prototypes. */
34static SI_AETT_SOURCE *SI_AETT_Create_Source (void);
35static SI_AETT_TEXT *SI_AETT_Create_Text (void);
36static SI_RET_CODE SI_AETT_Ins_Source_Text (SI_AETT_SLOT *slot, unsigned short srcid, SI_AETT_TEXT *new_text);
37
38
39extern struct aett_slot_list head_aett_slot, current_aett0_slot;                /* always point to AETT-0 */
40extern SI_mutex m_aett;
41
42
43
44/*********************************************************************/
45/* Function : SI_AETT_Create_Slot                                                                        */
46/* Description : Function to allocate the space for an instance of   */
47/*                               AETT-n. Corresponding to text for events happening      */
48/*               in different channels(source) during a particular 3 */
49/*                               hour period of a day.                                                           */
50/* Input : None.                                                                                                 */
51/* Output : pointer to the AETT-n instance structure allocated. Will */
52/*                      return NULL if out of memory.                                                    */
53/*********************************************************************/
54SI_AETT_SLOT *SI_AETT_Create_Slot (void)
55{
56        SI_AETT_SLOT * slot;
57        int     i;
58       
59        slot = (SI_AETT_SLOT *)SI_alloc(sizeof(SI_AETT_SLOT));
60        if (slot == NULL)
61        {
62                SI_DBG_PRINT(E_SI_ERR_MSG,("Failed to allocate an AETT slot!!!\n"));
63                return NULL;
64        }
65
66        SI_LST_D_INIT_ENTRY(&(slot->slot_link));
67        SI_LST_D_INIT(&(slot->aett_source));
68
69        for (i=0; i<8; i++)
70                slot->section_mask[i] = 0;
71
72        slot->version_number = 0xff;
73               
74        return slot;
75}
76
77/*********************************************************************/
78/* Function : SI_AETT_Create_Source                                                                      */
79/* Description : Function to allocate the space for the event text       */
80/*                               link list of a paticular channel(source) within an  */
81/*                               instance (slot) of AETT-n.                                                      */
82/* Input : None.                                                                                                 */
83/* Output : pointer to the channel (source) structure within an          */
84/*                      AETT-n instance (slot). Will return NULL if out of               */
85/*                      memory.                                                                                                  */
86/*********************************************************************/
87static SI_AETT_SOURCE *SI_AETT_Create_Source (void)
88{
89        SI_AETT_SOURCE * source;
90       
91        source = (SI_AETT_SOURCE *)SI_alloc(sizeof(SI_AETT_SOURCE));
92        if (source == NULL)
93        {
94                SI_DBG_PRINT(E_SI_ERR_MSG,("Failed to allocate an AETT source!!!\n"));
95                return NULL;
96        }
97
98        SI_LST_D_INIT_ENTRY(&(source->source_link));
99        SI_LST_D_INIT(&(source->aett_text));
100
101        return source;
102}
103
104/*********************************************************************/
105/* Function : SI_AETT_Create_Text                                                                        */
106/* Description : Function to allocate the space for an actual event  */
107/*                               text structure that forms the event text link           */
108/*                               list of a paticular channel(source) within an           */
109/*                               instance (slot) of AETT-n.                                                      */
110/* Input : None.                                                                                                 */
111/* Output : pointer to the event text structure for a channel            */
112/*                      (source) within an AETT-n instance (slot). Will return   */
113/*                      NULL if out of memory.                                                                   */
114/*********************************************************************/
115static SI_AETT_TEXT *SI_AETT_Create_Text (void)
116{
117        SI_AETT_TEXT * text;
118       
119        text = (SI_AETT_TEXT *)SI_alloc(sizeof(SI_AETT_TEXT));
120        if (text == NULL)
121        {
122                SI_DBG_PRINT(E_SI_ERR_MSG,("Failed to allocate an AETT event text!!!\n"));
123                return NULL;
124        }
125
126        text->extended_text_message = NULL;
127        SI_LST_D_INIT_ENTRY(&(text->text_link));
128
129        return text;
130}
131
132
133/*********************************************************************/
134/* Function : SI_AETT_Clear_Slot                                                                         */
135/* Description : Function to claer the contents for an instance of   */
136/*                               AETT-n. This is used when a new version of AETT-n       */
137/*                               is received. It shall free all the structure            */
138/*                               allocated for the source and events. But not free       */
139/*                               the slot itself                                                                         */
140/* Input : Slot structure pointer allocated for AETT-n.                          */
141/* Output : SI_RET_CODE                                                                                          */
142/*********************************************************************/
143SI_RET_CODE SI_AETT_Clear_Slot (SI_AETT_SLOT * slot)
144{
145        struct aett_source_list  *source_list; /* head of source list. */
146        struct aett_text_list  *text_list; /* head of text list. */
147        SI_AETT_SOURCE *source;
148        SI_AETT_TEXT *text;
149        unsigned long i;
150       
151        if (slot)
152        {
153                /* recursively free all sources in slot. */
154                source_list = &(slot->aett_source);
155                while ((source = SI_LST_D_FIRST(source_list)))
156                {
157                        /* recursively free all texts in sources. */
158                        text_list = &(source->aett_text);
159                        while ((text = SI_LST_D_FIRST(text_list)))
160                        {
161                                SI_free(text->extended_text_message);
162                                SI_LST_D_REMOVE_HEAD(text_list, text_link); /* text_list will be updated. */
163                                SI_free(text);
164                        }
165                        SI_LST_D_REMOVE_HEAD(source_list, source_link);  /* source_list will be updated. */
166                        SI_free(source);
167                }
168
169                /* just to be sure. Should not need to do it. */
170                SI_LST_D_INIT(&(slot->aett_source));
171
172                for (i=0; i<8; i++)
173                        slot->section_mask[i] = 0;
174
175                slot->version_number = 0xff;
176        }
177       
178        return SI_SUCCESS;
179}
180
181
182/*********************************************************************/
183/* Function : SI_AETT_Ins_Source_Text                                                            */
184/* Description : Function to insert a newly received event text          */
185/*                               structure for a channel(source) into the text link  */
186/*                               list for a paticular channel(source) within an          */
187/*                               instance (slot) of AETT-n. The link list of text        */
188/*                               is sorted by the event ID of an event in                        */
189/*                               incremental order.                                                                      */
190/* Input : SI_AETT_SLOT *slot : points to the existing AETT-n            */
191/*                                      instance for a particular time slot.                     */
192/*                 unsigned short srcid : source_ID for the text                         */
193/*                 SI_AETT_TEXT *new_text : points to the newly received         */
194/*                                      text structure for a channel(source) to be               */
195/*                                      inserted into the source corresponding to the    */
196/*                                      srcid of the above AETT-n slot.                                  */
197/* Output : SI_RET_CODE.                                                                                         */
198/*********************************************************************/
199static SI_RET_CODE SI_AETT_Ins_Source_Text (SI_AETT_SLOT *slot, unsigned short srcid, SI_AETT_TEXT *new_text)
200{
201        struct aett_source_list  *source_list; /* head of source list. */
202        struct aett_text_list  *text_list; /* head of text list. */
203        SI_AETT_SOURCE *source, *new_source;
204        SI_AETT_TEXT *text;
205       
206        if (slot == NULL)
207        {
208                SI_DBG_PRINT(E_SI_ERR_MSG,("AETT slot is not yet allocated!!!\n"));
209                return SI_NULL_POINTER;
210        }
211
212        if (new_text == NULL)
213        {
214                SI_DBG_PRINT(E_SI_ERR_MSG,("new text is not yet allocated!!!\n"));
215                return SI_NULL_POINTER;
216        }
217
218        /* first we create a new source structure for the new text. We may need to free it later. */
219        new_source = SI_AETT_Create_Source();
220        if (new_source == NULL)
221                return SI_NO_MEMORY;
222
223        /* insert the text into new source. */
224        new_source->source_ID = srcid;
225        SI_LST_D_INSERT_HEAD(&(new_source->aett_text), new_text, text_link);
226
227        /* if we don't have a channel allocated yet, simply create it. and copy the text.*/
228        source_list = &(slot->aett_source);
229        if ( (source = SI_LST_D_FIRST(source_list)) == NULL)
230        {
231                /* simply insert the new source structure to the head of list. */
232                SI_LST_D_INSERT_HEAD(source_list, new_source, source_link);
233                return SI_SUCCESS;
234        }
235
236        /* try to see where we going to insert the source of if the source is there already. */
237        while (source->source_ID < srcid)
238        {
239                if (SI_LST_D_NEXT(source, source_link) == NULL)   /* end of list. */
240                {
241                        /* last source in AETT-n. create and insert at the end. */
242                        SI_LST_D_INSERT_AFTER(source, new_source, source_link);
243                        return SI_SUCCESS;
244                }
245
246                source = SI_LST_D_NEXT(source, source_link);
247        }
248
249        /* check to see if the same source has already been created. */
250        if (source->source_ID == srcid)
251        {
252                /* we don't need this new source anymore. */
253                SI_free(new_source);
254
255                /* the channel(source) is already allocated. just insert the text. */
256                text_list = &(source->aett_text);       
257                if ( (text = SI_LST_D_FIRST(text_list)) == NULL)
258                {
259                        /* this condition SHOULD NOT HAPPEN! */
260                        SI_DBG_PRINT(E_SI_WRN_MSG,("AETT text is missing from a channel!!!\n"));
261                        /* we just put the new text in. */
262                        SI_LST_D_INSERT_HEAD(text_list, new_text, text_link);
263                        return SI_SUCCESS;
264                }
265
266                /* recurse through the text list to find the insertion point. */
267                while (text->event_ID < new_text->event_ID)
268                {
269                        /* see if we reach the end of list. */
270                        if (SI_LST_D_NEXT(text, text_link) == NULL)
271                        {
272                                /* insert new text at the end of list. */
273                                SI_LST_D_INSERT_AFTER(text, new_text, text_link);
274                                return SI_SUCCESS;
275                        }
276                        text = SI_LST_D_NEXT(text, text_link);
277                }
278
279                /* at this point, we just insert before the current text. */
280                SI_LST_D_INSERT_BEFORE(text_list, text, new_text, text_link);
281
282                return SI_SUCCESS;
283        }
284       
285        /* if source is not already allocated, Create the source, insert the text and
286           insert the source into the source list BEFORE the current source for the slot. */
287        SI_LST_D_INSERT_BEFORE(source_list, source, new_source, source_link);
288       
289        return SI_SUCCESS;
290}
291
292/*********************************************************************
293 Function : SI_AETT_Parse       
294 Description : Function to parse a newly received AETT-n table and put
295                                it into the AETT-n slot link list created by MGT parse.
296                                Before we create the AETT-n slot from MGT, we simply
297                                ignore the AETT-n table.
298 Input : unsigned char *aett_table : newly received aett table data.                                             
299 Output : SI_RET_CODE.                                                                                   
300**********************************************************************/
301SI_RET_CODE SI_AETT_Parse (unsigned char *aett_table)
302{
303        unsigned long temp, i, j;
304        unsigned long section_length, ETM_ID, source_ID, version_number;
305        unsigned long MGT_tag, section_number, last_section_number, num_blocks_in_section, num_events;
306        unsigned long desc_start;
307        unsigned long desc_tag, desc_len;
308        unsigned char *current, desc;
309        SI_AETT_SLOT *slot;
310        SI_AETT_TEXT *text;
311        SI_RET_CODE result;
312
313        temp = *aett_table;
314        if (temp != SI_AETT_TABLE_ID)
315        {
316                SI_DBG_PRINT(E_SI_ERR_MSG,("AETT Table ID error!!! %x\n", temp));
317                return SI_TABLE_ID_ERROR;
318        }
319
320        /* calculate and check section length. */
321        section_length = SI_Construct_Data(aett_table, 
322                                AETT_SECTION_LENGTH_BYTE_INDX,
323                                AETT_SECTION_LENGTH_BYTE_NUM,
324                                AETT_SECTION_LENGTH_SHIFT,
325                                AETT_SECTION_LENGTH_MASK);
326        section_length += AETT_SECTION_LENGTH_BYTE_INDX+AETT_SECTION_LENGTH_BYTE_NUM;
327        if (section_length > SI_LONG_SECTION_LENGTH)
328        {
329                SI_DBG_PRINT(E_SI_ERR_MSG,("AETT Table section length error!!! %x\n", section_length));
330                return SI_SECTION_LENGTH_ERROR;
331        }
332       
333        /* We do the CRC check here to verify the contents of this section. */
334        if (SI_CRC32_Check(aett_table, section_length) != SI_SUCCESS)
335        {
336                SI_DBG_PRINT(E_SI_ERR_MSG,("AETT Table section CRC error!!!\n"));
337                return SI_CRC_ERROR;
338        }
339
340        /* check to make sure AETT_subtype is zero. */
341        temp = SI_Construct_Data(aett_table, 
342                                AETT_AETT_SUBTYPE_BYTE_INDX,
343                                AETT_AETT_SUBTYPE_BYTE_NUM,
344                                AETT_AETT_SUBTYPE_SHIFT,
345                                AETT_AETT_SUBTYPE_MASK);
346        if (temp != SI_CURRENT_AETT_SUBTYPE)
347        {
348                SI_DBG_PRINT(E_SI_ERR_MSG,("AETT Table AETT_subtype Not what we can handle, Ignore the table!!! %x\n", temp));
349                return SI_PROTOCOL_VER_ERROR;
350        }
351       
352        /* get MGT_tag. */
353        MGT_tag = SI_Construct_Data(aett_table, 
354                                AETT_MGT_TAG_BYTE_INDX,
355                                AETT_MGT_TAG_BYTE_NUM,
356                                AETT_MGT_TAG_SHIFT,
357                                AETT_MGT_TAG_MASK);
358
359        /* lock mutex for AETT table access. */
360        SI_mutex_lock(m_aett);
361
362        /* search for the AETT-n slot link list for the MGT_tag. */
363        if ((slot = SI_LST_D_FIRST(&current_aett0_slot)) ==NULL)
364        {
365                SI_mutex_unlock(m_aett);
366                SI_DBG_PRINT(E_SI_ERR_MSG,("AETT-n slot link list not generated from MGT yet, Ignore the table!!!\n"));
367                return SI_AETT_LIST_NOT_READY;
368        }
369        while (slot)
370        {
371                if (slot->MGT_tag == MGT_tag)
372                        break;
373                slot = SI_LST_D_NEXT(slot, slot_link);
374        }
375
376        if (slot == NULL)
377        {
378                SI_mutex_unlock(m_aett);
379                SI_DBG_PRINT(E_SI_ERR_MSG,("AETT-n slot link list does not contain the slot that matches the MGT_tag, Ignore the table!!\n"));
380                return SI_AETT_LIST_NOT_READY;
381        }
382
383        /* look at current_next_indicator. It should be 1 for AETT. */
384        temp = SI_Construct_Data(aett_table, 
385                                AETT_CURRENT_NEXT_INDICATOR_BYTE_INDX,
386                                AETT_CURRENT_NEXT_INDICATOR_BYTE_NUM,
387                                AETT_CURRENT_NEXT_INDICATOR_SHIFT,
388                                AETT_CURRENT_NEXT_INDICATOR_MASK);
389        if (temp != 1)
390        {
391                SI_mutex_unlock(m_aett);
392                SI_DBG_PRINT(E_SI_ERR_MSG,("AETT Table current_next_indicator not one!!! %x\n", temp));
393                return SI_CURRENT_NEXT_INDICATOR_ERROR;
394        }
395
396        /* now we know where the slot is in the link list, See if we need to update. */
397        version_number = SI_Construct_Data(aett_table, 
398                                                AETT_VERSION_NUMBER_BYTE_INDX,
399                                                AETT_VERSION_NUMBER_BYTE_NUM,
400                                                AETT_VERSION_NUMBER_SHIFT,
401                                                AETT_VERSION_NUMBER_MASK);
402        section_number = SI_Construct_Data(aett_table, 
403                                                AETT_SECTION_NUMBER_BYTE_INDX,
404                                                AETT_SECTION_NUMBER_BYTE_NUM,
405                                                AETT_SECTION_NUMBER_SHIFT,
406                                                AETT_SECTION_NUMBER_MASK);
407        if (slot->version_number == version_number)
408        {
409                /* the same version number. Now check if the section number has already be processed. */
410                if (SI_Chk_Section_mask(&(slot->section_mask[0]), section_number))
411                {
412                        /* section already processed, we are done! */
413                        SI_mutex_unlock(m_aett);
414                        return SI_SUCCESS;
415                }
416        }
417        else
418        {
419                /* different version number. The slot should have already been init by MGT parse. */
420                SI_DBG_PRINT(E_SI_DBG_MSG,("New AETT Table received!\n"));
421                if (slot->MGT_version_number != version_number)
422                {
423                        /* this should not happen, but what the heck..... */
424                        SI_DBG_PRINT(E_SI_WRN_MSG,("AETT-n slot mgt version does not match new version, reinit slot!!\n"));
425                        temp = slot->pid; /* at least trust the pid. */
426                        SI_AETT_Clear_Slot(slot);
427                        slot->MGT_tag = MGT_tag;
428                        slot->MGT_version_number = version_number;
429                        slot->pid = temp;
430                }
431                slot->version_number = version_number;
432                /* init section mask. */
433                last_section_number = SI_Construct_Data(aett_table, 
434                                                        AETT_LAST_SECTION_NUMBER_BYTE_INDX,
435                                                        AETT_LAST_SECTION_NUMBER_BYTE_NUM,
436                                                        AETT_LAST_SECTION_NUMBER_SHIFT,
437                                                        AETT_LAST_SECTION_NUMBER_MASK);
438                SI_Init_Section_Mask(&(slot->section_mask[0]), last_section_number);
439        }
440
441        /* update section mask here. */
442        SI_Set_Section_mask(&(slot->section_mask[0]), section_number);
443       
444        /* new AETT table section received!!! */
445        SI_DBG_PRINT(E_SI_DBG_MSG,("New AETT Table section received!\n"));
446
447        num_blocks_in_section = SI_Construct_Data(aett_table, 
448                                                        AETT_NUM_BLOCKS_IN_SECTION_BYTE_INDX,
449                                                        AETT_NUM_BLOCKS_IN_SECTION_BYTE_NUM,
450                                                        AETT_NUM_BLOCKS_IN_SECTION_SHIFT,
451                                                        AETT_NUM_BLOCKS_IN_SECTION_MASK);
452
453        current = aett_table + AETT_NUM_BLOCKS_IN_SECTION_BYTE_INDX + 
454                                                        AETT_NUM_BLOCKS_IN_SECTION_BYTE_NUM; /* points to first block byte. */
455
456        for (i=0; i<num_blocks_in_section; i++)
457        {
458                /* create and stuff the text structure. */
459                if ((text = SI_AETT_Create_Text()) == NULL)
460                {
461                        SI_mutex_unlock(m_aett);
462                        SI_DBG_PRINT(E_SI_ERR_MSG,("AETT cannot create text structure!!!\n"));
463                        return SI_NO_MEMORY;
464                }
465                ETM_ID = SI_Construct_Data(current, 
466                                                                AETT_ETM_ID_BYTE_INDX,
467                                                                AETT_ETM_ID_BYTE_NUM,
468                                                                AETT_ETM_ID_SHIFT,
469                                                                AETT_ETM_ID_MASK);
470                source_ID = ((ETM_ID>>16)&0xffff);
471                text->event_ID = (ETM_ID&0xffff);
472                text->extended_text_length = SI_Construct_Data(current, 
473                                                                AETT_ETT_LENGTH_BYTE_INDX,
474                                                                AETT_ETT_LENGTH_BYTE_NUM,
475                                                                AETT_ETT_LENGTH_SHIFT,
476                                                                AETT_ETT_LENGTH_MASK);
477                current += AETT_ETT_LENGTH_BYTE_INDX+AETT_ETT_LENGTH_BYTE_NUM; /* points to text. */
478                if ((text->extended_text_message = (unsigned char *)SI_alloc(text->extended_text_length)) == NULL)
479                {
480                        SI_mutex_unlock(m_aett);
481                        SI_DBG_PRINT(E_SI_ERR_MSG,("AETT cannot allocate mem for text!!!\n"));
482                        return SI_NO_MEMORY;
483                }
484                SI_memcpy(text->extended_text_message, current, text->extended_text_length);
485                current += text->extended_text_length; /* points to next block. */
486
487                /* insert the text into the AETT-n source link list. */
488                if ((result = SI_AETT_Ins_Source_Text(slot,source_ID, text)) != SI_SUCCESS)
489                {
490                        SI_mutex_unlock(m_aett);
491                        SI_DBG_PRINT(E_SI_ERR_MSG,("AETT cannot insert source!!!\n"));
492                        return result;
493                }
494        }
495
496        /* lock mutex for AETT table access. */
497        SI_mutex_unlock(m_aett);
498       
499        /* verify section length. */
500        if (((unsigned long)current - (unsigned long)aett_table) != (section_length - SI_CRC_LENGTH))
501        {
502                SI_DBG_PRINT(E_SI_ERR_MSG,("AETT Table length error!\n"));
503                return SI_SECTION_LENGTH_ERROR;
504        }
505       
506        return SI_SUCCESS;
507}
508
Note: See TracBrowser for help on using the repository browser.