RDK Documentation (Open Sourced RDK Components)
simgr.cpp
1 /*
2  * If not stated otherwise in this file or this component's Licenses.txt file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2016 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18 */
19 #include <iostream>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <unistd.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <fcntl.h>
28 #include "simgr.h"
29 #include <libxml/encoding.h>
30 #include <libxml/xmlwriter.h>
31 
32 /**
33  * @addtogroup SI_CACHE_TYPES
34  * @{
35  */
36 
37 uint32_t crctab[256];
38 
39 //#if ((ULONG_MAX) == (UINT_MAX))
40 //#define IS32BIT
41 //#else
42 //#define IS64BIT
43 //#endif
44 
45 #define HERTZ 1000000
46 
47 #define DEFAULT_SI_CACHE_FILENAME "SICache"
48 
49 #define XML_DECLARATION "1.0", "", ""
50 #define XML_SIDB_ELEMENT_NAME "SIDB"
51 #define XML_PGM_ELEMENT_NAME "program"
52 #define XML_SOURCE_ID_KEY "sourceid"
53 #define XML_FREQ_KEY "carrier_frequency"
54 #define XML_MODULATION_KEY "modulation_mode"
55 #define XML_PGM_NO_KEY "program_number"
56 #define XML_VIRT_CHAN_NO_KEY "virtual_channel_number"
57 #define XML_NO_OF_ATRIBUTES 5
58 
59 SiManager::SiManager()
60 {
61  numOfServices = 0;
62 }
63 
64 /**
65  * @}
66  */
67 
68 /**
69  * @addtogroup SI_CACHE_APIS
70  * @{
71  */
72 
73 /**
74  * @brief This API parses the program id, source id, modulation, frequency information from the XML.
75  *
76  * @param[in] parent First child node of XML.
77  *
78  * @return Returns status of the operation.
79  * @retval 0 on sucess, appropiate error code otherwise.
80  */
81 int SiManager::xml_parse_attributes(xmlNodePtr parent)
82 {
83  xmlChar* pVal = NULL;
84  xmlNodePtr cur_node = parent;
85  ProgramDetails programDetails;
86 
87  while (cur_node != NULL)
88  {
89  //printf("cur_node->name: %s\n", cur_node->name);
90  if ( ( !xmlStrcmp ( cur_node->name, ( const xmlChar* ) XML_PGM_ELEMENT_NAME ) ) )
91  {
92  pVal = xmlGetProp(cur_node, (const xmlChar*)XML_SOURCE_ID_KEY);
93  if (pVal)
94  {
95  //printf("%s: %s\n", XML_SOURCE_ID_KEY, pVal);
96  programDetails.source_id = atoi((const char*)pVal);
97  xmlFree(pVal);
98  }
99  else
100  {
101  printf(XML_SOURCE_ID_KEY" pVal NULL\n");
102  }
103 
104  pVal = xmlGetProp(cur_node, (const xmlChar*)XML_PGM_NO_KEY);
105  if (pVal)
106  {
107  //printf("%s: %s\n", XML_PGM_NO_KEY, pVal);
108  programDetails.program_number = atoi((const char*)pVal);
109  xmlFree(pVal);
110  }
111  else
112  {
113  printf(XML_PGM_NO_KEY" pVal NULL\n");
114  }
115 
116  pVal = xmlGetProp(cur_node, (const xmlChar*)XML_FREQ_KEY);
117  if (pVal)
118  {
119  //printf("%s: %s\n", XML_FREQ_KEY, pVal);
120  programDetails.carrier_frequency = atoi((const char*)pVal)*HERTZ;
121  xmlFree(pVal);
122  }
123  else
124  {
125  printf(XML_FREQ_KEY" pVal NULL\n");
126  }
127 
128  pVal = xmlGetProp(cur_node, (const xmlChar*)XML_MODULATION_KEY);
129  if (pVal)
130  {
131  //printf("%s: %s\n", XML_MODULATION_KEY, pVal);
132  programDetails.modulation_mode = atoi((const char*)pVal);
133  xmlFree(pVal);
134  }
135  else
136  {
137  printf(XML_MODULATION_KEY" pVal NULL\n");
138  }
139 
140  pVal = xmlGetProp(cur_node, (const xmlChar*)XML_VIRT_CHAN_NO_KEY);
141  if (pVal)
142  {
143  //printf("%s: %s\n", XML_VIRT_CHAN_NO_KEY, pVal);
144  programDetails.virtual_channel_number = atoi((const char*)pVal);
145  xmlFree(pVal);
146  }
147  else
148  {
149  printf(XML_VIRT_CHAN_NO_KEY" pVal NULL\n");
150  }
151 
152  m_program_list.push_back(programDetails);
153  }
154 
155  cur_node = cur_node->next;
156  }
157 
158  numOfServices = m_program_list.size();
159 
160  return 0;
161 }
162 
163 /**
164  * @brief This function loads an input xml file into memory, it does the formatting related validations and parses the attributes.
165  *
166  * @param[in] xml_file XML file name.
167  *
168  * @return Returns status of the operation.
169  * @retval True on sucess, False on failure.
170  */
171 bool SiManager::load_xml_file(string xml_file)
172 {
173  xmlDocPtr doc;
174  xmlNodePtr root_element;
175  xmlNodePtr parent;
176 
177  doc = xmlParseFile ( xml_file.c_str() );
178  if ( doc == NULL )
179  {
180  fprintf ( stderr, "Document not parsed successfully. \n" );
181  return FALSE;
182  }
183 
184  root_element = xmlDocGetRootElement ( doc );
185  if ( root_element == NULL )
186  {
187  fprintf ( stderr,"empty document\n" );
188  xmlFreeDoc ( doc );
189  return FALSE;
190  }
191 
192  if ( xmlStrcmp ( root_element->name, ( const xmlChar * )XML_SIDB_ELEMENT_NAME) )
193  {
194  fprintf ( stderr, "document of the wrong type, root node != %s", XML_SIDB_ELEMENT_NAME);
195  xmlFreeDoc ( doc );
196  return FALSE;
197  }
198 
199  parent = root_element->xmlChildrenNode;
200 
201 
202  xml_parse_attributes(parent);
203 
204  xmlFreeDoc ( doc );
205  return TRUE;
206 }
207 
208 /**
209  * @brief Initializes the CRC check.
210  */
212 {
213  uint16_t i, j;
214  uint32_t crc;
215 
216  for (i = 0; i < 256; i++)
217  {
218  crc = i << 24;
219  for (j = 0; j < 8; j++)
220  {
221  if (crc & 0x80000000)
222  crc = (crc << 1) ^ SI_CACHE_CRC_QUOTIENT;
223  else
224  crc = crc << 1;
225  }
226  crctab[i] = crc;
227  }
228 } // END crc32_init()
229 
230 /**
231  * @brief Function to calculate Cyclic Redundancy Check(CRC) value.
232  * CRC is used to find the accidental changes happened to raw data. Here is the CRC flow works here.
233  * 1. Check the SICache file version.
234  * 2. If version doesnt match delete it and get a new version of SICache file and write CRC to the end of SICache file.
235  * 3. If version matches, verify the CRC.
236  * 4. If CRC doesnt match, delete it and get a new version of SICache file and write CRC to the end of SICache file.
237  * 5. if version & CRC matches, load the cache and start using it.
238  *
239  * @param[in] data Binary cache file(SICache file).
240  * @param[in] len Size of the file.
241  *
242  * @return Returns CRC value.
243  */
244 uint32_t SiManager::calc_mpeg2_crc(uint8_t * data, uint32_t len)
245 {
246  uint32_t result;
247  uint32_t i;
248 
249  if (len < 4)
250  return 0;
251 
252  result = *data++ << 24;
253  result |= *data++ << 16;
254  result |= *data++ << 8;
255  result |= *data++;
256  result = ~result;
257  len -= 4;
258 
259  for (i = 0; i < len; i++)
260  {
261  result = (result << 8 | *data++) ^ crctab[result >> 24];
262  }
263 
264  return ~result;
265 } // END calc_mpeg2_crc()
266 
267 /**
268  * @brief The <i>si_get_file_size()</i> function will get the size of the specified file.
269  *
270  * @param[in] location XML filename
271  *
272  * @return The size of the given file.
273  * @retval -1 if the file not present or any other failure.
274  */
275 unsigned int SiManager::get_file_size(const char * location)
276 {
277  struct stat buff;
278  unsigned int size;
279  if (0 == stat(location, &buff))
280  {
281  size = (unsigned int) buff.st_size;
282  return size;
283  }
284  return -1;
285 }
286 
287 /**
288  * @brief This API finds the CRC value and writes at the end of SI cache file.
289  *
290  * @param[in] sidbFileName Binary SI Cache file.
291  *
292  * @return Returns status of the operation.
293  * @retval True on sucess, False on failure.
294  */
295 bool SiManager::write_crc_for_si_cache(string sidbFileName)
296 {
297  int fd=0;
298  uint32_t sizeOfSICache = 0;
299  uint32_t crcFileSize = 0;
300  uint32_t readSISize = 0;
301  uint32_t crcValue = 0xFFFFFFFF;
302  unsigned char *pCRCData = NULL;
303 
304  init_mpeg2_crc();
305 
306  sizeOfSICache = get_file_size(sidbFileName.c_str());
307 
308  readSISize = sizeOfSICache;
309  crcFileSize = sizeOfSICache;
310 
311  pCRCData = (unsigned char*)malloc(crcFileSize*sizeof(unsigned char));
312  memset(pCRCData, 0 , (crcFileSize*sizeof(unsigned char)));
313 
314  fd = open( sidbFileName.c_str(), O_RDONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH );
315  if ( -1 == fd)
316  {
317  perror("File open failed");
318  free(pCRCData);
319  pCRCData=NULL;
320  return FALSE;
321  }
322 
323  readSISize = read(fd, pCRCData, readSISize);
324  close(fd);
325  if(readSISize < 0)
326  {
327  perror("SNS File Read Failed");
328  free(pCRCData);
329  pCRCData=NULL;
330  return FALSE;
331  }
332 
333  /* Find the CRC and write it at the end of SICache file */
334  crcValue = calc_mpeg2_crc (pCRCData, crcFileSize);
335  printf("Calculated CRC is [%u]\n", crcValue);
336  free(pCRCData);
337  pCRCData=NULL;
338 
339  fd = open( sidbFileName.c_str(), O_RDWR | O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH );
340  if ( 0 > fd)
341  {
342  perror("File open failed");
343  return FALSE;
344  }
345 
346  crcFileSize = write( fd, &crcValue, sizeof (crcValue ));
347  close(fd);
348  if ( -1 == crcFileSize)
349  {
350  perror("File append failed");
351  return FALSE;
352  }
353 
354  return TRUE;
355 
356 }
357 
358 /**
359  * @brief This finds the CRC and write it at the end of SI and SNS cache files.
360  *
361  * @param[in] sidbFileName Binary SI Cache file.
362  * @param[in] snsdbFileName Binary SNS cache file.
363  *
364  * @return Returns status of the operation.
365  * @retval True on sucess, False on failure.
366  */
367 bool SiManager::write_crc_for_si_and_sns_cache(string sidbFileName, string snsdbFileName)
368 {
369  int fd=0;
370  uint32_t sizeOfSICache = 0;
371  uint32_t sizeOfSISNSCache = 0;
372  uint32_t crcFileSize = 0;
373  uint32_t readSNSSize = 0;
374  uint32_t readSISize = 0;
375  uint32_t crcValue = 0xFFFFFFFF;
376  unsigned char *pCRCData = NULL;
377 
378  init_mpeg2_crc();
379 
380  sizeOfSICache = get_file_size(sidbFileName.c_str());
381  sizeOfSISNSCache = get_file_size(snsdbFileName.c_str());
382 
383  readSNSSize = sizeOfSISNSCache;
384  readSISize = sizeOfSICache;
385 
386  crcFileSize = sizeOfSISNSCache + sizeOfSICache;
387 
388  pCRCData = (unsigned char*)malloc(crcFileSize*sizeof(unsigned char));
389  memset(pCRCData, 0 , (crcFileSize*sizeof(unsigned char)));
390 
391  fd = open( snsdbFileName.c_str(), O_RDONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH );
392  if ( -1 == fd)
393  {
394  perror("File open failed");
395  free(pCRCData);
396  pCRCData=NULL;
397  return FALSE;
398  }
399 
400  readSNSSize = read(fd, pCRCData, readSNSSize);
401  close(fd);
402  if(readSNSSize < 0)
403  {
404  perror("SNS File Read Failed");
405  free(pCRCData);
406  pCRCData=NULL;
407  return FALSE;
408  }
409 
410  fd = open( sidbFileName.c_str(), O_RDONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH );
411  if ( -1 == fd)
412  {
413  perror("File open failed");
414  free(pCRCData);
415  pCRCData=NULL;
416  return FALSE;
417  }
418 
419  readSISize = read(fd, (pCRCData+readSNSSize), readSISize);
420  close(fd);
421  if(readSISize < 0)
422  {
423  perror("SNS File Read Failed");
424  free(pCRCData);
425  pCRCData=NULL;
426  return FALSE;
427  }
428 
429  /* Find the CRC and write it at the end of SICache file */
430  crcValue = calc_mpeg2_crc (pCRCData, crcFileSize);
431  printf("Calculated CRC is [%u]\n", crcValue);
432  free(pCRCData);
433  pCRCData=NULL;
434 
435  fd = open( sidbFileName.c_str(), O_RDWR | O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH );
436  if ( -1 == fd)
437  {
438  perror("File open failed");
439  return FALSE;
440  }
441 
442  crcFileSize = write( fd, &crcValue, sizeof (crcValue ));
443  close(fd);
444  if ( -1 == crcFileSize)
445  {
446  perror("File append failed");
447  return FALSE;
448  }
449 
450  return TRUE;
451 
452 }
453 
454 /**
455  * @brief Internal Method to initialize service entries to default values
456  * <i>init_si_entry()</i>
457  *
458  * @param[in] si_entry Service entry to set the default values for.
459  *
460  * @return None
461  */
463 {
464  // TODO: use static struct initialization
465  /* set default values as defined in OCAP spec (annex T) */
466  /* These are in the order they appear in the struct, to make it
467  easier to verify all have been initialized. --mlb */
468  si_entry->ref_count = 1;
469  si_entry->activation_time = 0;
470  si_entry->ptime_service = 0LL;
471 
472  si_entry->next = NULL;
473  si_entry->isAppType = FALSE;
474  si_entry->source_id = SOURCEID_UNKNOWN;
475  si_entry->app_id = 0;
476  si_entry->channel_type = CHANNEL_TYPE_HIDDEN; /* */
477  si_entry->video_standard = VIDEO_STANDARD_UNKNOWN;
478  si_entry->source_name_entry = NULL; /* default value */
479  si_entry->descriptions = NULL; /* default value */
480  si_entry->major_channel_number = SI_DEFAULT_CHANNEL_NUMBER; /* default value */
481  si_entry->minor_channel_number = SI_DEFAULT_CHANNEL_NUMBER; /* default value */
482  si_entry->service_type = SI_SERVICE_TYPE_UNKNOWN; /* default value */
483  si_entry->freq_index = 0;
484  si_entry->mode_index = 0;
485 
486  si_entry->state = SIENTRY_UNSPECIFIED;
487  si_entry->virtual_channel_number = VIRTUAL_CHANNEL_UNKNOWN;
488  si_entry->program_number = 0;
489  si_entry->transport_type = 0; // Default is MPEG2
490  si_entry->scrambled = FALSE;
491 }
492 
493 /**
494  * @brief This API loads the program data from binary cache file.
495  *
496  * It checks for the version information and CRC Value and proceeds further in reading modulation, frequency,
497  * program number and Virtual channel number.
498  *
499  * @param[in] sidbFileName Binary SI Cache file.
500  *
501  * @return Returns status of the operation.
502  * @retval True on sucess, False on failure.
503  */
504 bool SiManager::parse_program_details(siTableEntry **si_entry_head, uint32_t frequency[], uint32_t modulation[], int& f_index, int& m_index)
505 {
506  int i;
507  list<ProgramDetails>::iterator pProgramDetails;
508  siTableEntry* si_entry = NULL;
509  siTableEntry* si_walker = NULL;
510  bool ret = TRUE;
511 
512  for( i=0,pProgramDetails=m_program_list.begin(); i<m_program_list.size(); i++,pProgramDetails++ )
513  {
514  si_entry = (siTableEntry*)malloc(sizeof(siTableEntry));
515  init_si_entry(si_entry);
516  //memset(si_entry, 0 , sizeof(siTableEntry));
517  int foundfreq = 0;
518  int foundmod = 0;
519 
520  si_entry->virtual_channel_number = pProgramDetails->virtual_channel_number;
521  si_entry->program_number = pProgramDetails->program_number;
522  si_entry->source_id = pProgramDetails->source_id;
523  si_entry->state |= SIENTRY_MAPPED;
524 
525  for (int i = 0; i < f_index; i++)
526  {
527  if ( pProgramDetails->carrier_frequency == frequency[i])
528  {
529  si_entry->freq_index = i;
530  foundfreq = 1;
531  break;
532  }
533  }
534 
535  if ( foundfreq == 0)
536  {
537  frequency[ f_index ] = pProgramDetails->carrier_frequency;
538  si_entry->freq_index = f_index;
539  f_index++;
540  }
541 
542  for (int i = 0; i <m_index; i++)
543  {
544  if ( pProgramDetails->modulation_mode == modulation[i])
545  {
546  si_entry->mode_index = i;
547  foundmod= 1;
548  break;
549  }
550  }
551 
552  if ( foundmod == 0)
553  {
554  modulation[ m_index ] = pProgramDetails->modulation_mode;
555  si_entry->mode_index = m_index;
556  m_index++;
557  }
558 
559  if (*si_entry_head == NULL)
560  {
561  *si_entry_head = si_entry;
562  }
563  else
564  {
565  for(si_walker=*si_entry_head; si_walker->next!=NULL; si_walker = si_walker->next);
566 
567  si_walker->next = si_entry;
568  }
569 
570  }
571 
572  return ret;
573 }
574 
575 /**
576  * @brief This API write the program details like modulation, frequency, program number, VCN information to SI cache file.
577  *
578  * @param[in] sidbFileName Binary SI Cache file.
579  *
580  * @return Returns status of the operation.
581  * @retval True on sucess, False on failure.
582  */
583 bool SiManager::cache_si_data ( string sidbFileName)
584 {
585  int ret, fd;
586  uint32_t frequency[SI_CACHE_MAX_FREQUENCIES + 1];
587  uint32_t modulation[SI_CACHE_MAX_FREQUENCIES + 1];
588  int f_index = 0, m_index=0;
589  siTableEntry* si_entry, *si_entry_head = NULL;
590  unsigned char * buf = NULL;
591  uint32_t version;
592 
593 
594  buf = (unsigned char*) malloc(sizeof(version)+sizeof(frequency)+ sizeof(modulation)+ 500* sizeof(siTableEntry));
595  memset( frequency, 0, sizeof(frequency));
596  memset( modulation, 0, sizeof(modulation));
597 
598  if(!parse_program_details(&si_entry_head,frequency, modulation, f_index, m_index))
599  {
600  perror("cache_si_data() failed");
601  return FALSE;
602  }
603 
604  fd = open( sidbFileName.c_str(), O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH );
605  if ( -1 == fd)
606  {
607  perror("File open failed");
608  return FALSE;
609  }
610  version = SI_CACHE_FILE_VERSION;
611 
612  ret = write( fd, &version, sizeof (version ));
613  if ( -1 == ret)
614  {
615  perror("File write failed");
616  close(fd);
617  return FALSE;
618  }
619  memcpy(buf, &version, sizeof (version ));
620  buf+=sizeof (version );
621 
622  ret = write( fd, frequency, sizeof (frequency ));
623  if ( -1 == ret)
624  {
625  perror("File write failed");
626  close(fd);
627  return FALSE;
628  }
629  memcpy(buf, frequency, sizeof (frequency ));
630  buf+=sizeof (frequency );
631 
632  ret = write( fd, modulation, sizeof (modulation ));
633  if ( -1 == ret)
634  {
635  perror("File write failed");
636  close(fd);
637  return FALSE;
638  }
639  memcpy(buf, modulation, sizeof (modulation ));
640  buf+=sizeof (modulation );
641 
642  si_entry = si_entry_head;
643 
644  while (si_entry)
645  {
646  ret = write( fd, si_entry, sizeof (*si_entry ));
647  if ( -1 == ret)
648  {
649  perror("File write failed");
650  close(fd);
651  return FALSE;
652  }
653  memcpy(buf, si_entry, sizeof (*si_entry ));
654  buf+=sizeof (*si_entry );
655  si_entry = si_entry->next;
656  }
657 
658  close(fd);
659 
660  return TRUE;
661 }
662 
663 /**
664  * @brief This API write the program details like modulation, frequency, program number, VCN information to SI cache file.
665  * SNS cache is used to store the data available in NTT(Network Text Tables) by legacy boxes.It contains source id and corresponding source name(channel name) mappings.
666  *
667  * @param[in] snsdbFileName Binary SNS Cache file.
668  *
669  * @return Returns status of the operation.
670  * @retval True on sucess, False on failure.
671  */
672 bool SiManager::cache_sns_data ( string snsdbFileName )
673 {
674  SourceNameEntry *sn_entry=NULL, *sn_entry_head=NULL;
675  int i, fd, ret;
676  list<ProgramDetails>::iterator pProgramDetails;
677 
678  if(m_program_list.size()==0)
679  {
680  perror("File open failed");
681  return FALSE;
682  }
683 
684  for( i=0,pProgramDetails=m_program_list.begin(); i<m_program_list.size()-1; i++,pProgramDetails++ )
685  {
686  sn_entry = (SourceNameEntry*)malloc(sizeof(SourceNameEntry));
687  memset(sn_entry, 0 , sizeof(SourceNameEntry));
688  sn_entry->appType = FALSE;
689  sn_entry->mapped = false;
690  sn_entry->id = pProgramDetails->source_id;
691  sn_entry->source_long_names = NULL;
692  sn_entry->source_names = NULL;
693 
694  if (sn_entry_head == NULL)
695  {
696  sn_entry_head = sn_entry;
697  }
698  else
699  {
700  sn_entry->next = sn_entry_head;
701  sn_entry_head = sn_entry;
702  }
703  }
704 
705  fd = open( snsdbFileName.c_str(), O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH );
706  if ( -1 == fd)
707  {
708  perror("File open failed");
709  return FALSE;
710  }
711 
712 
713  sn_entry = sn_entry_head;
714 
715  while (sn_entry)
716  {
717  ret = write( fd, sn_entry, sizeof (*sn_entry ));
718  if ( -1 == ret)
719  {
720  perror("File write failed");
721  close(fd);
722  return FALSE;
723  }
724 
725  sn_entry = sn_entry->next;
726  }
727 
728  close(fd);
729 
730  return TRUE;
731 }
732 
733 /**
734  * @brief This API function loads the program data from binary cache file.
735  *
736  * It checks for the version information and CRC Value and proceeds further for reading modulation, frequency,
737  * program number and Virtual channel number.
738  *
739  * @param[in] sidbFileName Binary SI Cache file.
740  *
741  * @return Returns status of the operation.
742  * @retval True on sucess, False on failure.
743  */
744 bool SiManager::load_si_data(string sidbFileName)
745 {
746  int fd=0, version=0, count=0, size=0;
747  unsigned char *buf=(unsigned char*)malloc(sizeof(siTableEntry)*sizeof(unsigned char));
748  siTableEntry *si_entry;
749  ProgramDetails programDetails;
750  uint32_t frequency[SI_CACHE_MAX_FREQUENCIES + 1];
751  uint32_t modulation[SI_CACHE_MAX_FREQUENCIES + 1];
752 //#ifdef IS64BIT
753 // long name_count=0;
754 //#else
755 // int name_count=0;
756 //#endif
757 
758  uint32_t crcValue=0;
759  bool ret = TRUE;
760 
761  fd = open( sidbFileName.c_str(), O_RDONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH );
762  if ( -1 == fd)
763  {
764  perror("File open failed");
765  return FALSE;
766  }
767 
768  count = sizeof(version);
769  count = read(fd, (void *)&version, count);
770 
771  if (count == sizeof(version))
772  {
773  if (version != SI_CACHE_FILE_VERSION)
774  {
775  printf("Invalid cache version 0x%x, expected 0x%x\n", version, SI_CACHE_FILE_VERSION);
776  close(fd);
777  return FALSE;
778  }
779  else
780  {
781  printf("Read version 0x%x\n", version);
782  }
783  }
784  else
785  {
786  printf("reading Version [%s] failed count:%d version:0x%x\n", sidbFileName.c_str(), count, version);
787  close(fd);
788  return FALSE;
789  }
790 
791  count = sizeof(frequency);
792  count = read(fd, (void *)frequency, count);
793  if (count != sizeof(frequency))
794  {
795  printf("reading FREQ from [%s] failed\n", sidbFileName.c_str());
796  close(fd);
797  return FALSE;
798  }
799 
800  count = sizeof(modulation);
801  count = read(fd, (void *)modulation, count);
802  if (count != sizeof(modulation))
803  {
804  printf("reading MODULATION from [%s] failed\n", sidbFileName.c_str());
805  close(fd);
806  return FALSE;
807  }
808 
809  count = size = sizeof(siTableEntry);
810 
811  while(count == size)
812  {
813  count = read(fd, (void*)buf, size);
814  if (count == 0 )
815  {
816  printf("Reached end of file [%s]\n", sidbFileName.c_str());
817  ret = TRUE;
818  break;
819  }
820  else if((count < size) && (count == sizeof(crcValue)))
821  {
822  //crcValue = (uint32_t)buf;
823  crcValue = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | (buf[0] & 0xFF);
824  printf("CRC Value: [%u]\n", crcValue);
825  count=size;
826  continue;
827  }
828  else if((count < 0) || (count < size))
829  {
830  printf("Error in reading file [%s] \n", sidbFileName.c_str());
831  perror("Reason: ");
832  ret = FALSE;
833  break;
834  }
835 
836  si_entry = (siTableEntry*)buf;
837  programDetails.source_id = si_entry->source_id;
838  programDetails.program_number = si_entry->program_number;
839  programDetails.carrier_frequency = frequency[si_entry->freq_index]/HERTZ;
840  programDetails.modulation_mode = modulation[si_entry->mode_index];
841  programDetails.virtual_channel_number = si_entry->virtual_channel_number;
842 
843  m_program_list.push_back(programDetails);
844 
845  long name_count = (long)(si_entry->descriptions);
846 
847  if(name_count != 0)
848  {
849  //TODO : Skip the description data
850  for(int i=0 ; i< name_count; i++)
851  {
852  unsigned char name_len_buf[4] = {0};
853  int buf_count = sizeof(name_len_buf);
854 
855  count = read(fd, (void *)name_len_buf, buf_count);
856 
857  int name_len = (name_len_buf[0]) | (name_len_buf[1] << 8) | (name_len_buf[2] << 16) | (name_len_buf[3] << 24);
858  lseek(fd, name_len, SEEK_CUR);
859  }
860  }
861  }
862 
863  numOfServices = m_program_list.size();
864 
865  close(fd);
866  free(buf);
867  buf=NULL;
868  return ret;
869 }
870 
871 /**
872  * @brief This API is to load program data from XML file, if the operation mode selected is XML to Binary.
873  * Otherwise it will load program data from cache file.
874  *
875  * It will also display number of available services.
876  *
877  * @param[in] file_name It can be an XML file or a binary SI Cache file depending on the operation mode.
878  * @param[in] mode Operation mode. It can be one of the following:
879  * xtob - Generate SI Cache binaries from the given XML file
880  * btox - Generate SI Cache XML file from the given binary file
881  *
882  * @return Returns status of the operation.
883  * @retval True on sucess, False on failure.
884  */
885 bool SiManager::Load(string file_name, int mode)
886 {
887  bool ret = FALSE;
888  switch (mode)
889  {
890  case SI_FILETYPE_XML:
891  {
892  printf("Loading program data from XML file [%s]\n", file_name.c_str());
893  ret = load_xml_file(file_name);
894  if(ret == TRUE)
895  printf("No:of Services Available: %d\n", numOfServices);
896  }
897  break;
898  case SI_FILETYPE_BINARY:
899  {
900  printf("Loading program data from binary cache file [%s]\n", file_name.c_str());
901  ret = load_si_data(file_name);
902  if(ret == TRUE)
903  printf("No:of Services Available: %d\n", numOfServices);
904 
905  }
906  break;
907 
908  default:
909  {
910  cout<<"Mode not implemented"<<endl;
911  }
912  }
913  return ret;
914 }
915 
916 /**
917  * @brief Dump channel map information from binary SI cache to console.
918  */
920 {
921  list<ProgramDetails>::iterator p;
922  int i;
923 
924  for( i=0,p=m_program_list.begin(); i<m_program_list.size(); i++,p++ )
925  {
926  printf("RChannelVCN[%06d]-SRCID[%06x]-Freq[%09d]-Mode[%04d]-Prog[%08d]\n",p->virtual_channel_number, p->source_id, p->carrier_frequency*HERTZ,p->modulation_mode,p->program_number);
927  }
928  cout << endl;
929 }
930 
931 /**
932  * @brief Generates binary SI cache from the XML file.
933  *
934  * @param[out] sidbFileName Binary SI Cache file
935  *
936  * @return Returns status of the operation.
937  * @retval True on sucess, False on failure.
938  */
939 bool SiManager::GenerateSICache ( string sidbFileName )
940 {
941  if(!cache_si_data(sidbFileName))
942  {
943  perror("Failed to cache si data");
944  return FALSE;
945  }
946 
947  if(!write_crc_for_si_cache(sidbFileName))
948  {
949  perror("Failed to append CRC");
950  return FALSE;
951  }
952 
953  printf("Binary file [%s] generated successfully\n", sidbFileName.c_str());
954 }
955 
956 /**
957  * @brief Generate both binary SI cache and binary SNS cache from the XML file
958  *
959  * @param[out] sidbFileName Binary SI Cache file
960  * @param[out] snsdbFileName Binary SNS cache file
961  *
962  * @return Returns status of the operation.
963  * @retval True on sucess, False on failure.
964  */
965 bool SiManager::GenerateSICache ( string sidbFileName, string snsdbFileName )
966 {
967  printf("Generating SI Cache [%s] from extracted program details\n", sidbFileName.c_str());
968  if(!cache_si_data(sidbFileName))
969  {
970  perror("Failed to cache si data");
971  return FALSE;
972  }
973 
974  printf("Generating SNS Cache [%s] from extracted program details\n", snsdbFileName.c_str());
975  if(!cache_sns_data(snsdbFileName))
976  {
977  perror("Failed to cache si data");
978  return FALSE;
979  }
980 
981  if(!write_crc_for_si_and_sns_cache(sidbFileName, snsdbFileName))
982  {
983  perror("Failed to append CRC");
984  return FALSE;
985  }
986 
987  printf("Binary files [%s] and [%s] generated successfully\n", sidbFileName.c_str(), snsdbFileName.c_str());
988 }
989 
990 /**
991  * @brief Function to generate XML file(sidb.xml).
992  *
993  * It uses standard libxml2 methods for XML file creation.
994  * XML of the format:
995  * <?xml version="1.0" encoding="UTF-8"?>
996  * <SIDB>
997  * <program sourceid="162" program_number="65535" carrier_frequency="179" modulation_mode="674000000" virtual_channel_number="4"/>
998  * </SIDB>
999  *
1000  * @param[out] sixmlFileName XML file
1001  *
1002  * @return Returns status of the operation.
1003  * @retval True on sucess, False on failure.
1004  */
1005 bool SiManager::GenerateXML (string sixmlFileName)
1006 {
1007  xmlTextWriterPtr writer;
1008  list<ProgramDetails>::iterator p;
1009  int i=0;
1010 
1011  printf("Generating XML file [%s] from extracted program data\n", sixmlFileName.c_str());
1012  writer = xmlNewTextWriterFilename(sixmlFileName.c_str(), 0);
1013  xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL);
1014 
1015  xmlTextWriterStartElement(writer, BAD_CAST XML_SIDB_ELEMENT_NAME);
1016  xmlTextWriterSetIndent(writer, 1);
1017  xmlTextWriterSetIndentString(writer, BAD_CAST "");
1018 
1019  for( i=0,p=m_program_list.begin(); i<m_program_list.size(); p++, i++ )
1020  {
1021  xmlTextWriterStartElement(writer, BAD_CAST XML_PGM_ELEMENT_NAME);
1022  xmlTextWriterSetIndentString(writer, BAD_CAST "");
1023 
1024  xmlTextWriterWriteFormatAttribute(writer, BAD_CAST XML_SOURCE_ID_KEY, "%d", p->source_id);
1025  xmlTextWriterWriteFormatAttribute(writer, BAD_CAST XML_PGM_NO_KEY, "%d", p->program_number);
1026  xmlTextWriterWriteFormatAttribute(writer, BAD_CAST XML_FREQ_KEY, "%d", p->carrier_frequency);
1027  xmlTextWriterWriteFormatAttribute(writer, BAD_CAST XML_MODULATION_KEY, "%d", p->modulation_mode);
1028  xmlTextWriterWriteFormatAttribute(writer, BAD_CAST XML_VIRT_CHAN_NO_KEY, "%d",p->virtual_channel_number);
1029 
1030  xmlTextWriterEndElement(writer);
1031  }
1032  xmlTextWriterEndElement(writer);
1033  xmlTextWriterEndDocument(writer);
1034  xmlFreeTextWriter(writer);
1035  printf("XML file [%s] generated successfully\n", sixmlFileName.c_str());
1036 }
1037 
1038 /**
1039  * @}
1040  */
1041 
1042 
SiManager::cache_sns_data
bool cache_sns_data(string snsdbFileName)
This API write the program details like modulation, frequency, program number, VCN information to SI ...
Definition: simgr.cpp:672
siTableEntry::video_standard
uint32_t video_standard
SVCT (NTSC, PAL etc.)
Definition: simgr.h:188
siTableEntry::descriptions
void * descriptions
LVCT/CVCT (desc)
Definition: simgr.h:192
siTableEntry::activation_time
uint32_t activation_time
SVCT.
Definition: simgr.h:174
siTableEntry::mode_index
uint8_t mode_index
SVCT.
Definition: simgr.h:194
SiManager::DumpChannelMap
void DumpChannelMap()
Dump channel map information from binary SI cache to console.
Definition: simgr.cpp:919
SiManager::parse_program_details
bool parse_program_details(siTableEntry **si_entry_head, uint32_t frequency[], uint32_t modulation[], int &f_index, int &m_index)
This API loads the program data from binary cache file.
Definition: simgr.cpp:504
_SourceNameEntry::id
uint32_t id
if appType=FALSE, sourceID otherwise appID
Definition: simgr.h:164
siTableEntry::program_number
uint16_t program_number
SVCT.
Definition: simgr.h:198
SiManager::init_si_entry
void init_si_entry(siTableEntry *si_entry)
Internal Method to initialize service entries to default values init_si_entry()
Definition: simgr.cpp:462
SiManager::load_xml_file
bool load_xml_file(string xml_file)
This function loads an input xml file into memory, it does the formatting related validations and par...
Definition: simgr.cpp:171
SiManager::write_crc_for_si_and_sns_cache
bool write_crc_for_si_and_sns_cache(string sidbFileName, string snsdbFileName)
This finds the CRC and write it at the end of SI and SNS cache files.
Definition: simgr.cpp:367
SiManager::xml_parse_attributes
int xml_parse_attributes(xmlNodePtr parent)
This API parses the program id, source id, modulation, frequency information from the XML.
Definition: simgr.cpp:81
SIENTRY_MAPPED
@ SIENTRY_MAPPED
Mapped in VCM.
Definition: simgr.h:76
siTableEntry::next
siTableEntry * next
next service entry
Definition: simgr.h:203
_SourceNameEntry::next
struct _SourceNameEntry * next
Next source name entry.
Definition: simgr.h:168
SiManager::GenerateXML
bool GenerateXML(string sixmlFileName)
Function to generate XML file(sidb.xml).
Definition: simgr.cpp:1005
SiManager::cache_si_data
bool cache_si_data(string sidbFileName)
This API write the program details like modulation, frequency, program number, VCN information to SI ...
Definition: simgr.cpp:583
SiManager::init_mpeg2_crc
void init_mpeg2_crc(void)
Initializes the CRC check.
Definition: simgr.cpp:211
SiManager::Load
bool Load(string file_name, int mode)
This API is to load program data from XML file, if the operation mode selected is XML to Binary....
Definition: simgr.cpp:885
siTableEntry::transport_type
uint8_t transport_type
SVCT (0==MPEG2, 1==non-MPEG2)
Definition: simgr.h:199
SiManager::load_si_data
bool load_si_data(string sidbFileName)
This API function loads the program data from binary cache file.
Definition: simgr.cpp:744
_SourceNameEntry
Definition: simgr.h:161
siTableEntry::isAppType
int32_t isAppType
For DSG app.
Definition: simgr.h:181
siTableEntry::minor_channel_number
uint32_t minor_channel_number
SVCT (desc)
Definition: simgr.h:196
SiManager::get_file_size
unsigned int get_file_size(const char *location)
The si_get_file_size() function will get the size of the specified file.
Definition: simgr.cpp:275
SiManager::write_crc_for_si_cache
bool write_crc_for_si_cache(string sidbFileName)
This API finds the CRC value and writes at the end of SI cache file.
Definition: simgr.cpp:295
SiManager::GenerateSICache
bool GenerateSICache(string sidbFileName)
Generates binary SI cache from the XML file.
Definition: simgr.cpp:939
ProgramDetails_s
Definition: simgr.h:143
siTableEntry
Definition: simgr.h:171
siTableEntry::source_name_entry
void * source_name_entry
Reference to the corresponding NTT_SNS entry.
Definition: simgr.h:191
siTableEntry::channel_type
uint32_t channel_type
SVCT.
Definition: simgr.h:187
siTableEntry::scrambled
int32_t scrambled
SVCT.
Definition: simgr.h:200
siTableEntry::freq_index
uint8_t freq_index
SVCT.
Definition: simgr.h:193
siTableEntry::service_type
uint32_t service_type
SVCT (desc)
Definition: simgr.h:189
SiManager::calc_mpeg2_crc
uint32_t calc_mpeg2_crc(uint8_t *data, uint32_t len)
Function to calculate Cyclic Redundancy Check(CRC) value. CRC is used to find the accidental changes ...
Definition: simgr.cpp:244
TRUE
#define TRUE
Defines for TRUE/FALSE/ENABLE flags.
Definition: wifi_common_hal.h:199
siTableEntry::source_id
uint32_t source_id
SVCT.
Definition: simgr.h:182
_SourceNameEntry::source_long_names
void * source_long_names
NTT_SNS.
Definition: simgr.h:167