| 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_nit.c |
|---|
| 12 | ** Description: function that parses the NIT table section. |
|---|
| 13 | ** |
|---|
| 14 | ** Created: 03/08/2001 |
|---|
| 15 | ** |
|---|
| 16 | ** REVISION: |
|---|
| 17 | ** |
|---|
| 18 | ** $Log: $ |
|---|
| 19 | ** |
|---|
| 20 | ** |
|---|
| 21 | ****************************************************************/ |
|---|
| 22 | |
|---|
| 23 | #include "si.h" |
|---|
| 24 | #include "si_os.h" |
|---|
| 25 | #include "si_dbg.h" |
|---|
| 26 | #include "si_util.h" |
|---|
| 27 | #include "si_nit_cds.h" |
|---|
| 28 | #include "si_nit_mms.h" |
|---|
| 29 | #include "si_nit.h" |
|---|
| 30 | #include "si_descriptors.h" |
|---|
| 31 | |
|---|
| 32 | unsigned char NIT_Version_Number; |
|---|
| 33 | unsigned char NIT_CDS_Version_Number; |
|---|
| 34 | unsigned char NIT_MMS_Version_Number; |
|---|
| 35 | unsigned char NIT_last_section_number; |
|---|
| 36 | unsigned long NIT_Section_Mask[8]; |
|---|
| 37 | |
|---|
| 38 | unsigned char NIT_CDS_last_section_number; |
|---|
| 39 | unsigned char NIT_MMS_last_section_number; |
|---|
| 40 | unsigned long NIT_CDS_Section_Mask[8]; |
|---|
| 41 | unsigned long NIT_MMS_Section_Mask[8]; |
|---|
| 42 | static SI_CDS_Callback_t *s_cds_cb; |
|---|
| 43 | static SI_MMS_Callback_t *s_mms_cb; |
|---|
| 44 | |
|---|
| 45 | void SI_NIT_Init (SI_CDS_Callback_t *p_cds_cb,SI_MMS_Callback_t *p_mms_cb,unsigned char iNIT_CDS_Version_Number, |
|---|
| 46 | unsigned char iNIT_MMS_Version_Number) |
|---|
| 47 | { |
|---|
| 48 | int i; |
|---|
| 49 | |
|---|
| 50 | s_cds_cb = p_cds_cb; |
|---|
| 51 | s_mms_cb = p_mms_cb; |
|---|
| 52 | SI_NIT_CDS_Init(s_cds_cb); |
|---|
| 53 | SI_NIT_MMS_Init(s_mms_cb); |
|---|
| 54 | |
|---|
| 55 | NIT_CDS_Version_Number = iNIT_CDS_Version_Number; |
|---|
| 56 | NIT_MMS_Version_Number = iNIT_MMS_Version_Number; |
|---|
| 57 | for (i=0; i<8; i++) |
|---|
| 58 | { |
|---|
| 59 | NIT_Section_Mask[i] = NIT_CDS_Section_Mask[i] = NIT_MMS_Section_Mask[i] = 0; |
|---|
| 60 | } |
|---|
| 61 | } |
|---|
| 62 | |
|---|
| 63 | /********************************************************************* |
|---|
| 64 | Function : SI_NIT_CDS_Complete |
|---|
| 65 | Description : Return true if the complete CDS section is received. |
|---|
| 66 | Input : none. |
|---|
| 67 | Output : none. |
|---|
| 68 | **********************************************************************/ |
|---|
| 69 | bool SI_NIT_CDS_Complete() |
|---|
| 70 | { |
|---|
| 71 | return (SI_Chk_Section_complete(NIT_CDS_Section_Mask,NIT_CDS_last_section_number) == SI_SUCCESS); |
|---|
| 72 | } |
|---|
| 73 | |
|---|
| 74 | /********************************************************************* |
|---|
| 75 | Function : SI_NIT_MMS_Complete |
|---|
| 76 | Description : Return true if the complete MMS section is received. |
|---|
| 77 | Input : none. |
|---|
| 78 | Output : none. |
|---|
| 79 | **********************************************************************/ |
|---|
| 80 | bool SI_NIT_MMS_Complete() |
|---|
| 81 | { |
|---|
| 82 | return (SI_Chk_Section_complete(NIT_MMS_Section_Mask,NIT_MMS_last_section_number) == SI_SUCCESS); |
|---|
| 83 | } |
|---|
| 84 | |
|---|
| 85 | /********************************************************************* |
|---|
| 86 | Function : SI_NIT_parse |
|---|
| 87 | Description : Function to parse the NIT table. |
|---|
| 88 | Input : nit_table, point to the current NIT table section. |
|---|
| 89 | Output : SI_RET_CODE. |
|---|
| 90 | **********************************************************************/ |
|---|
| 91 | SI_RET_CODE SI_NIT_parse (unsigned char * nit_table) |
|---|
| 92 | { |
|---|
| 93 | unsigned long temp; |
|---|
| 94 | unsigned long section_length, offset, subtable_len; |
|---|
| 95 | unsigned char first_index, number_of_records, table_subtype; |
|---|
| 96 | unsigned char desc_count, desc_tag, desc_len; |
|---|
| 97 | unsigned char version_number, section_number, last_section_number; |
|---|
| 98 | int i, j, found_rdd; |
|---|
| 99 | |
|---|
| 100 | found_rdd = 0; |
|---|
| 101 | |
|---|
| 102 | SI_DBG_PRINT(E_SI_DBG_MSG,("NIT Table received.\n")); |
|---|
| 103 | |
|---|
| 104 | temp = *nit_table; |
|---|
| 105 | if (temp != SI_NIT_TABLE_ID) |
|---|
| 106 | { |
|---|
| 107 | SI_DBG_PRINT(E_SI_ERR_MSG,("NIT Table ID error!!! %x\n", temp)); |
|---|
| 108 | return SI_TABLE_ID_ERROR; |
|---|
| 109 | } |
|---|
| 110 | |
|---|
| 111 | /* calculate and check section length. */ |
|---|
| 112 | section_length = SI_Construct_Data(nit_table, |
|---|
| 113 | NIT_SECTION_LENGTH_BYTE_INDX, |
|---|
| 114 | NIT_SECTION_LENGTH_BYTE_NUM, |
|---|
| 115 | NIT_SECTION_LENGTH_SHIFT, |
|---|
| 116 | NIT_SECTION_LENGTH_MASK); |
|---|
| 117 | section_length += NIT_SECTION_LENGTH_BYTE_INDX+NIT_SECTION_LENGTH_BYTE_NUM; |
|---|
| 118 | if (section_length > SI_NORMAL_SECTION_LENGTH) |
|---|
| 119 | { |
|---|
| 120 | SI_DBG_PRINT(E_SI_ERR_MSG,("NIT Table section length error!!! %x\n", section_length)); |
|---|
| 121 | return SI_SECTION_LENGTH_ERROR; |
|---|
| 122 | } |
|---|
| 123 | /* We do the CRC check here to verify the contents of this section. */ |
|---|
| 124 | if (SI_CRC32_Check(nit_table, section_length) != SI_SUCCESS) |
|---|
| 125 | { |
|---|
| 126 | SI_DBG_PRINT(E_SI_ERR_MSG,("NIT Table section CRC error!!!\n")); |
|---|
| 127 | return SI_CRC_ERROR; |
|---|
| 128 | } |
|---|
| 129 | |
|---|
| 130 | /* check protocol version. It should be zero for now. */ |
|---|
| 131 | temp = SI_Construct_Data(nit_table, |
|---|
| 132 | NIT_PROTOCOL_VERSION_BYTE_INDX, |
|---|
| 133 | NIT_PROTOCOL_VERSION_BYTE_NUM, |
|---|
| 134 | NIT_PROTOCOL_VERSION_SHIFT, |
|---|
| 135 | NIT_PROTOCOL_VERSION_MASK); |
|---|
| 136 | if (temp != SI_CURRENT_PROTOCOL_VERSION) |
|---|
| 137 | { |
|---|
| 138 | SI_DBG_PRINT(E_SI_ERR_MSG,("NIT Table PROTOCOL version error!!! %x\n", temp)); |
|---|
| 139 | return SI_PROTOCOL_VER_ERROR; |
|---|
| 140 | } |
|---|
| 141 | |
|---|
| 142 | first_index = SI_Construct_Data(nit_table, |
|---|
| 143 | NIT_FIRST_INDEX_BYTE_INDX, |
|---|
| 144 | NIT_FIRST_INDEX_BYTE_NUM, |
|---|
| 145 | NIT_FIRST_INDEX_SHIFT, |
|---|
| 146 | NIT_FIRST_INDEX_MASK); |
|---|
| 147 | /* make sure the first_index not zero */ |
|---|
| 148 | if (first_index == 0) |
|---|
| 149 | { |
|---|
| 150 | SI_DBG_PRINT(E_SI_ERR_MSG,("NIT Table first index zero!!!")); |
|---|
| 151 | return SI_OTHER_ERROR; |
|---|
| 152 | } |
|---|
| 153 | number_of_records = SI_Construct_Data(nit_table, |
|---|
| 154 | NIT_NUMBER_OF_RECORDS_BYTE_INDX, |
|---|
| 155 | NIT_NUMBER_OF_RECORDS_BYTE_NUM, |
|---|
| 156 | NIT_NUMBER_OF_RECORDS_SHIFT, |
|---|
| 157 | NIT_NUMBER_OF_RECORDS_MASK); |
|---|
| 158 | table_subtype = SI_Construct_Data(nit_table, |
|---|
| 159 | NIT_TABLE_SUBTYPE_BYTE_INDX, |
|---|
| 160 | NIT_TABLE_SUBTYPE_BYTE_NUM, |
|---|
| 161 | NIT_TABLE_SUBTYPE_SHIFT, |
|---|
| 162 | NIT_TABLE_SUBTYPE_MASK); |
|---|
| 163 | |
|---|
| 164 | /* Now we need to check for the revision descriptors(if there is any) to get the section |
|---|
| 165 | number and revision info. This descriptor should be at the end of the table section just |
|---|
| 166 | before the CRC bytes. NOT at the end of each table subtype. */ |
|---|
| 167 | offset = NIT_TABLE_SUBTYPE_BYTE_INDX + NIT_TABLE_SUBTYPE_BYTE_NUM; |
|---|
| 168 | switch (table_subtype) |
|---|
| 169 | { |
|---|
| 170 | case CDS_SUBTYPE: |
|---|
| 171 | subtable_len = NIT_CDS_SUBTABLE_SIZE; |
|---|
| 172 | break; |
|---|
| 173 | case MMS_SUBTYPE: |
|---|
| 174 | subtable_len = NIT_MMS_SUBTABLE_SIZE; |
|---|
| 175 | break; |
|---|
| 176 | default: |
|---|
| 177 | SI_DBG_PRINT(E_SI_ERR_MSG,("NIT Table subtype error!!!\n")); |
|---|
| 178 | return SI_TABLE_ID_ERROR; |
|---|
| 179 | break; |
|---|
| 180 | } |
|---|
| 181 | /* go through all subtables and subtable descriptors to get to the NIT table descriptor. */ |
|---|
| 182 | for (i=0; i<number_of_records; i++) |
|---|
| 183 | { |
|---|
| 184 | offset += subtable_len; |
|---|
| 185 | desc_count = *(nit_table + offset++); |
|---|
| 186 | for (j=0; j<desc_count; j++) |
|---|
| 187 | { |
|---|
| 188 | desc_tag = *(nit_table + offset++); |
|---|
| 189 | desc_len = *(nit_table + offset++); |
|---|
| 190 | offset += desc_len; |
|---|
| 191 | } |
|---|
| 192 | } |
|---|
| 193 | if (offset == section_length-SI_CRC_LENGTH) |
|---|
| 194 | { |
|---|
| 195 | SI_DBG_PRINT(E_SI_DBG_MSG,("NIT no table level descriptors found.\n")); |
|---|
| 196 | } |
|---|
| 197 | else if (offset > section_length-SI_CRC_LENGTH) |
|---|
| 198 | { |
|---|
| 199 | SI_DBG_PRINT(E_SI_ERR_MSG,("NIT Table length error!!!\n")); |
|---|
| 200 | return SI_SECTION_LENGTH_ERROR; |
|---|
| 201 | } |
|---|
| 202 | else |
|---|
| 203 | { |
|---|
| 204 | /* we got more descriptors. */ |
|---|
| 205 | while (offset < section_length-SI_CRC_LENGTH) |
|---|
| 206 | { |
|---|
| 207 | desc_tag = *(nit_table + offset++); |
|---|
| 208 | desc_len = *(nit_table + offset++); |
|---|
| 209 | if (desc_tag == SI_DESC_REVISION_DETECTION) |
|---|
| 210 | { |
|---|
| 211 | found_rdd = 1; |
|---|
| 212 | /* we got a revision dectection descriptor. */ |
|---|
| 213 | SI_DBG_PRINT(E_SI_DBG_MSG,("NIT revision detection descriptors found.\n")); |
|---|
| 214 | if (desc_len != DESC_REV_DECTECT_LEN) |
|---|
| 215 | { |
|---|
| 216 | SI_DBG_PRINT(E_SI_ERR_MSG,("NIT Table Rev detect descriptor length error!!!\n")); |
|---|
| 217 | return SI_SECTION_LENGTH_ERROR; |
|---|
| 218 | } |
|---|
| 219 | version_number = SI_Construct_Data( (nit_table + offset), |
|---|
| 220 | DESC_REV_DECTECT_VER_NUM_BYTE_INDEX, |
|---|
| 221 | DESC_REV_DECTECT_VER_NUM_BYTE_NUM, |
|---|
| 222 | DESC_REV_DECTECT_VER_NUM_SHIFT, |
|---|
| 223 | DESC_REV_DECTECT_VER_NUM_MASK); |
|---|
| 224 | section_number = SI_Construct_Data( (nit_table + offset), |
|---|
| 225 | DESC_REV_DECTECT_SEC_NUM_BYTE_INDEX, |
|---|
| 226 | DESC_REV_DECTECT_SEC_NUM_BYTE_NUM, |
|---|
| 227 | DESC_REV_DECTECT_SEC_NUM_SHIFT, |
|---|
| 228 | DESC_REV_DECTECT_SEC_NUM_MASK); |
|---|
| 229 | last_section_number = SI_Construct_Data( (nit_table + offset), |
|---|
| 230 | DESC_REV_DECTECT_LAST_SEC_NUM_BYTE_INDEX, |
|---|
| 231 | DESC_REV_DECTECT_LAST_SEC_NUM_BYTE_NUM, |
|---|
| 232 | DESC_REV_DECTECT_LAST_SEC_NUM_SHIFT, |
|---|
| 233 | DESC_REV_DECTECT_LAST_SEC_NUM_MASK); |
|---|
| 234 | |
|---|
| 235 | NIT_last_section_number = last_section_number; |
|---|
| 236 | if (version_number == NIT_Version_Number) |
|---|
| 237 | { |
|---|
| 238 | /* same version number, check section mask. */ |
|---|
| 239 | if (SI_Chk_Section_mask(NIT_Section_Mask, section_number)) |
|---|
| 240 | ; // return SI_SUCCESS; /* no need to update. */ |
|---|
| 241 | } |
|---|
| 242 | else |
|---|
| 243 | { |
|---|
| 244 | /* different CDS version, init the CDS table and section mask .*/ |
|---|
| 245 | NIT_Version_Number = version_number; |
|---|
| 246 | SI_Init_Section_Mask(NIT_Section_Mask, last_section_number); |
|---|
| 247 | } |
|---|
| 248 | SI_Set_Section_mask(NIT_Section_Mask, section_number); |
|---|
| 249 | |
|---|
| 250 | if (table_subtype == CDS_SUBTYPE) |
|---|
| 251 | { |
|---|
| 252 | NIT_CDS_last_section_number = last_section_number; |
|---|
| 253 | /* CDS subtable. */ |
|---|
| 254 | if (version_number == NIT_CDS_Version_Number) |
|---|
| 255 | { |
|---|
| 256 | /* same version number, check section mask. */ |
|---|
| 257 | if (SI_Chk_Section_mask(NIT_CDS_Section_Mask, section_number)) |
|---|
| 258 | return SI_SUCCESS; /* no need to update. */ |
|---|
| 259 | } |
|---|
| 260 | else |
|---|
| 261 | { |
|---|
| 262 | /* different CDS version, init the CDS table and section mask .*/ |
|---|
| 263 | SI_NIT_CDS_Init(s_cds_cb); |
|---|
| 264 | NIT_CDS_Version_Number = version_number; |
|---|
| 265 | SI_Init_Section_Mask(NIT_CDS_Section_Mask, last_section_number); |
|---|
| 266 | } |
|---|
| 267 | /* update the mask */ |
|---|
| 268 | SI_Set_Section_mask(NIT_CDS_Section_Mask, section_number); |
|---|
| 269 | } |
|---|
| 270 | else |
|---|
| 271 | { |
|---|
| 272 | NIT_MMS_last_section_number = last_section_number; |
|---|
| 273 | /* MMS subtable. */ |
|---|
| 274 | if (version_number == NIT_MMS_Version_Number) |
|---|
| 275 | { |
|---|
| 276 | /* same version number, check section mask. */ |
|---|
| 277 | if (SI_Chk_Section_mask(NIT_MMS_Section_Mask, section_number)) |
|---|
| 278 | return SI_SUCCESS; /* no need to update. */ |
|---|
| 279 | } |
|---|
| 280 | else |
|---|
| 281 | { |
|---|
| 282 | /* different MMS version, init the MMS table and section mask .*/ |
|---|
| 283 | SI_NIT_MMS_Init(s_mms_cb); |
|---|
| 284 | NIT_MMS_Version_Number = version_number; |
|---|
| 285 | SI_Init_Section_Mask(NIT_MMS_Section_Mask, last_section_number); |
|---|
| 286 | } |
|---|
| 287 | /* update the mask */ |
|---|
| 288 | SI_Set_Section_mask(NIT_MMS_Section_Mask, section_number); |
|---|
| 289 | } |
|---|
| 290 | } |
|---|
| 291 | else if (desc_tag != SI_DESC_STUFFING) |
|---|
| 292 | SI_DBG_PRINT(E_SI_WRN_MSG,("NIT table level descriptor %x we can not handle!\n", desc_tag)); |
|---|
| 293 | /* we just don't handle it. */ |
|---|
| 294 | |
|---|
| 295 | offset += desc_len; |
|---|
| 296 | } |
|---|
| 297 | } |
|---|
| 298 | #ifdef CONFIG_RDD_REQUIRED |
|---|
| 299 | if (found_rdd == 0) |
|---|
| 300 | { |
|---|
| 301 | SI_DBG_PRINT(E_SI_ERR_MSG,("Revistion Detection Descriptor is required!!!\n")); |
|---|
| 302 | return SI_DESCRIPTOR_ERROR; |
|---|
| 303 | } |
|---|
| 304 | #endif |
|---|
| 305 | |
|---|
| 306 | if (offset != section_length-SI_CRC_LENGTH) |
|---|
| 307 | { |
|---|
| 308 | SI_DBG_PRINT(E_SI_ERR_MSG,("NIT Table descriptor length error!!!(%d, %d, %d)\n",offset,section_length,section_length-SI_CRC_LENGTH)); |
|---|
| 309 | return SI_SECTION_LENGTH_ERROR; |
|---|
| 310 | } |
|---|
| 311 | |
|---|
| 312 | |
|---|
| 313 | /* now just update the table. */ |
|---|
| 314 | offset = NIT_TABLE_SUBTYPE_BYTE_INDX + NIT_TABLE_SUBTYPE_BYTE_NUM; |
|---|
| 315 | for (i=0; i<number_of_records; i++) |
|---|
| 316 | { |
|---|
| 317 | if (table_subtype == CDS_SUBTYPE) |
|---|
| 318 | first_index += SI_NIT_CDS_parse( (nit_table + offset), first_index ); |
|---|
| 319 | else |
|---|
| 320 | SI_NIT_MMS_parse ( (nit_table + offset), first_index++ ); |
|---|
| 321 | |
|---|
| 322 | offset += subtable_len; |
|---|
| 323 | desc_count = *(nit_table + offset++); |
|---|
| 324 | for (j=0; j<desc_count; j++) |
|---|
| 325 | { |
|---|
| 326 | desc_tag = *(nit_table + offset++); |
|---|
| 327 | if (desc_tag != SI_DESC_STUFFING) |
|---|
| 328 | SI_DBG_PRINT(E_SI_WRN_MSG,("NIT Subtable descriptor %x we can not handle!\n", desc_tag)); |
|---|
| 329 | /* we just don't handle it. */ |
|---|
| 330 | desc_len = *(nit_table + offset++); |
|---|
| 331 | offset += desc_len; |
|---|
| 332 | } |
|---|
| 333 | } |
|---|
| 334 | |
|---|
| 335 | return SI_SUCCESS; |
|---|
| 336 | } |
|---|
| 337 | |
|---|
| 338 | |
|---|