DSMCC  17.9.0
 All Data Structures Files Functions Typedefs
siq_pmt.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright © 2014 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  * Copyright © 2004 Ocean Blue Software Ltd
4  *
5  * This file is part of a DTVKit Software Component
6  * You are permitted to copy, modify or distribute this file subject to the terms
7  * of the DTVKit 1.0 Licence which can be found in licence.txt or at www.dtvkit.org
8  *
9  * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
10  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
11  * OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
12  *
13  * If you or your organisation is not a member of DTVKit then you have access
14  * to this source code outside of the terms of the licence agreement
15  * and you are expected to delete this and any associated files immediately.
16  * Further information on DTVKit, membership and terms can be found at www.dtvkit.org
17  *******************************************************************************/
24 /*---includes for this file--------------------------------------------------*/
25 #include <string.h>
26 
27 /* compiler library header files */
28 
29 /* third party header files */
30 
31 /* OBS header files */
32 #include "siq_debug.h"
33 #include "siq_main.h"
34 #include "siq_pmt.h"
35 
36 #include "cldsmcc.h"
37 
38 /*---constant definitions for this file--------------------------------------*/
39 
40 #define DBC_ID_SSU 0x000A
41 #define DBC_ID_MHEG5 0x0106
42 #define DBC_ID_OAD 0x0111
43 #define DBC_ID_HBBTV 0x0123
44 #define DBC_ID_MHP0 0x00F0
45 #define DBC_ID_MHP1 0x00F1
46 
47 #define DVB_OUI 0x00015A
48 
49 /*---local typedef structs for this file-------------------------------------*/
50 
51 typedef enum
52 {
53  ST_VIDEO1 = 0x01,
54  ST_VIDEO2 = 0x02,
55  ST_AUDIO1 = 0x03,
56  ST_AUDIO2 = 0x04,
57  ST_PRIVATE = 0x05,
58  ST_PES_PRV = 0x06,
59  ST_MHEG = 0x07,
60  ST_DATA_A = 0x0a,
61  ST_DATA_B = 0x0b,
62  ST_DATA_C = 0x0c,
63  ST_DATA_D = 0x0d,
64  ST_AUX = 0x0e,
65  ST_AAC = 0x0f,
66  ST_HEAAC = 0x11,
67  ST_H264 = 0x1b
68 } E_STREAM_TYPE;
69 
70 typedef enum
71 {
72  SUT_PROPRIETORY,
73  SUT_SIMPLE_SSU,
74  SUT_WITH_UNT,
75  SUT_RETURN_UNT
76 } E_SsuUpdType;
77 
78 enum
79 {
80  APP_TYP_MHEG5 = 0x0008,
81  APP_TYP_HBBTV = 0x0010,
82 };
83 
84 enum
85 {
86  CAROUSEL_ID_DESCRIPTOR = 0x13,
87  DEFERRED_ASSOC_DESCRIPTOR = 0x15,
88  STREAM_ID_DESCRIPTOR = 0x52,
89  DATA_BROADCAST_ID_DESCRIPTOR = 0x66,
90  APP_SIGNALLING_DESCRIPTOR = 0x6f
91 };
92 
93 typedef struct s_SsuInfo *P_SsuInfo;
94 
95 typedef struct s_SsuInfo
96 {
97  P_SsuInfo next;
98  U32BIT oui;
99  E_SsuUpdType type;
100  BOOLEAN hasVers;
101  U8BIT version;
102  U8BIT selectorLen;
103 } S_SsuInfo;
104 
105 typedef struct s_PmtStream
106 {
107  U16BIT pid;
108  U16BIT numtags;
109  U32BIT carouselId;
110  U16BIT bootPref;
111  U16BIT dbcId;
112  U8BIT *cTags;
113  P_SsuInfo ssuInfo;
114 } S_PmtStream;
115 
116 typedef struct s_Deferred
117 {
118  U16BIT transportId;
119  U16BIT serviceId;
120  U16BIT origNetId;
121  U16BIT numAssocTags;
122  U16BIT *assocTags;
123 } S_Deferred;
124 
125 typedef struct s_SiqPmtTable
126 {
127  U8BIT num_deferred;
128  U8BIT num_streams;
129  S_Deferred *deferreds;
130  S_PmtStream *streams;
131 } S_SiqPmtTable;
132 
133 /*---local (static) variable declarations for this file----------------------*/
134 /* (internal variables declared static to make them local) */
135 
136 /*---local function prototypes for this file---------------------------------*/
137 /* (internal functions declared static to make them local) */
138 
139 
140 /*---------------------- Local function definitions -------------------------*/
141 
142 
150 static void ParseForAitInfo( S_SiqInstance *siq, U16BIT sid,
151  U16BIT pid, U8BIT *dptr, U8BIT *dend )
152 {
153  U8BIT dlen, dtag;
154  FUNCTION_START(ParseForAitInfo)
155  while (dptr < dend)
156  {
157  dtag = *dptr++;
158  dlen = *dptr++;
159  DBGLOG(DS_PMT, " dtag=0x%x dlen=%d, data=0x%x 0x%x 0x%x 0x%x", dtag, dlen, dptr[0], dptr[1], dptr[2], dptr[3])
160  if (dtag == APP_SIGNALLING_DESCRIPTOR)
161  {
162  if (dlen == 0)
163  {
164  siq->setup.notifyAitInfo( sid, pid, UNKNOWN_AIT_TYPE, UNKNOWN_AIT_VERS );
165  }
166  else
167  {
168  while (dlen >= 3)
169  {
170  siq->setup.notifyAitInfo( sid, pid, ((dptr[0] & 0x7f) << 8) + dptr[1], dptr[2] & 0x1f );
171  dptr += 3;
172  dlen -= 3;
173  }
174  }
175  }
176  dptr += dlen;
177  }
178  FUNCTION_FINISH(ParseForAitInfo)
179 }
180 
181 void ParseSystemSoftwareUpdateInfo( S_SiqInstance *siq, S_PmtStream *pStream, U8BIT *dptr, U8BIT dlen, U8BIT **pxtr_ptr )
182 {
183  P_SsuInfo pSsuInfo;
184  U32BIT oui;
185  U8BIT slen;
186  FUNCTION_START(ParseSystemSoftwareUpdateInfo)
187  ASSERT(*pxtr_ptr)
188  pSsuInfo = (P_SsuInfo)*pxtr_ptr;
189  oui = *dptr++;
190  oui = (oui << 8) | *dptr++;
191  oui = (oui << 8) | *dptr++;
192  pSsuInfo->oui = oui;
193  pSsuInfo->type = (E_SsuUpdType)(*dptr & 0x0f);
194  dptr++;
195  pSsuInfo->hasVers = (*dptr & 0x20)? TRUE : FALSE;
196  pSsuInfo->version = *dptr & 0x1F;
197  dptr++;
198  slen = *dptr++;
199  pSsuInfo->selectorLen = slen;
200  if (slen)
201  {
202  /* store selector bytes for later */
203  memcpy(pSsuInfo+1,dptr,slen);
204  }
205  pSsuInfo->next = pStream->ssuInfo;
206  pStream->ssuInfo = pSsuInfo;
207  slen += sizeof(S_SsuInfo) + 3;
208  slen &= ~(0x03);
209  *pxtr_ptr += slen;
210  FUNCTION_FINISH(ParseSystemSoftwareUpdateInfo)
211 }
212 
218 static U16BIT ParseForDataBroadcastIds( S_SiqInstance *siq, H_PmtRef pmtref,
219  S_PmtStream *pStream, U8BIT *dptr, U8BIT *dend, U8BIT **pxtr_ptr )
220 {
221  U16BIT prefer, preferred;
222  U8BIT dlen, dtag;
223  U16BIT dbcId;
224  FUNCTION_START(ParseForDataBroadcastIds)
225  preferred = 0;
226  while (dptr < dend)
227  {
228  dtag = *dptr++;
229  dlen = *dptr++;
230  if (dtag == DATA_BROADCAST_ID_DESCRIPTOR)
231  {
232  dbcId = dptr[0] << 8 | dptr[1];
233  if (dbcId == DBC_ID_SSU)
234  {
235  pStream->dbcId = dbcId;
236  ParseSystemSoftwareUpdateInfo( siq, pStream, dptr+3, *(dptr+2), pxtr_ptr );
237  }
238  else if (pStream->carouselId != INVALID_CAROUSEL_ID &&
239  siq->setup.parseDataBroadcastId != NULL && dbcId != 0)
240  {
241  DBGLOG(DS_PMT, "numtags=%d dbcId=%x",pStream->numtags,dbcId)
242  prefer = (U16BIT)siq->setup.parseDataBroadcastId( pmtref, pStream->carouselId, dptr, dlen );
243  if (preferred < prefer)
244  {
245  preferred = prefer;
246  pStream->dbcId = dbcId;
247  }
248  }
249  }
250  dptr += dlen;
251  }
252  FUNCTION_FINISH(ParseForDataBroadcastIds)
253  return preferred;
254 }
255 
261 static U16BIT GetDataBroadcastExtraSize( U8BIT *dptr, U8BIT *dend )
262 {
263  U16BIT size = 0;
264  U16BIT dbcId;
265  U8BIT dlen, dtag, slen;
266  while (dptr < dend)
267  {
268  dtag = *dptr++;
269  dlen = *dptr++;
270  if (dtag == DATA_BROADCAST_ID_DESCRIPTOR)
271  {
272  dbcId = dptr[0] << 8 | dptr[1];
273  switch (dbcId)
274  {
275  case DBC_ID_SSU:
276  slen = sizeof(S_SsuInfo) + dptr[8] + 3;
277  slen &= ~(0x03);
278  size += slen;
279  break;
280  default:
281  break;
282  }
283  }
284  dptr += dlen;
285  }
286  return size;
287 }
288 
294 static U16BIT CountStreamIdDesc( U8BIT *dptr, U8BIT *dend )
295 {
296  U16BIT count = 0;
297  U8BIT dlen, dtag;
298  while (dptr < dend)
299  {
300  dtag = *dptr++;
301  dlen = *dptr++;
302  if (dtag == STREAM_ID_DESCRIPTOR)
303  {
304  count++;
305  }
306  dptr += dlen;
307  }
308  return count;
309 }
310 
316 static U16BIT GetComponentTags( U8BIT *dptr, U8BIT *dend, U8BIT *ctags )
317 {
318  U16BIT count = 0;
319  U8BIT dlen, dtag;
320  while (dptr < dend)
321  {
322  dtag = *dptr++;
323  dlen = *dptr++;
324  if (dtag == STREAM_ID_DESCRIPTOR)
325  {
326  ctags[count] = *dptr;
327  count++;
328  }
329  dptr += dlen;
330  }
331  return count;
332 }
333 
339 static U32BIT GetCarouselInfo( U8BIT *dptr, U8BIT *dend /*, formatId?*/)
340 {
341  U32BIT carouselId = INVALID_CAROUSEL_ID;
342  U8BIT dlen, dtag;
343  while (dptr < dend)
344  {
345  dtag = *dptr++;
346  dlen = *dptr++;
347  if (dtag == CAROUSEL_ID_DESCRIPTOR)
348  {
349  carouselId = *dptr;
350  dptr++;
351  carouselId <<= 8;
352  carouselId |= *dptr;
353  dptr++;
354  carouselId <<= 8;
355  carouselId |= *dptr;
356  dptr++;
357  carouselId <<= 8;
358  carouselId |= *dptr;
359  /* format ID is optional in HbbTv, and not required by MHEG *
360  dptr++;
361  stream_ptr->format_id = *dptr;
362  if ( stream_ptr->format_id == 0x01 )
363  {}
364  */
365  break;
366  }
367  dptr += dlen;
368  }
369  return carouselId;
370 }
371 
377 static U16BIT DeferredSize( U8BIT *dptr, U8BIT *dend, U8BIT *pNum )
378 {
379  U16BIT size = 0;
380  U8BIT dlen, dtag, num = 0;
381  while (dptr < dend)
382  {
383  dtag = *dptr++;
384  dlen = *dptr++;
385  if (dtag == DEFERRED_ASSOC_DESCRIPTOR)
386  {
387  /* add space for assoc tag array with assocTag_bytes (i.e. *dptr) */
388  size += sizeof(S_Deferred) + *dptr;
389  num++;
390  }
391  dptr += dlen;
392  }
393  *pNum = num;
394  return size;
395 }
396 
402 static U16BIT ParseDeferreds( U8BIT *dptr, U8BIT *dend, S_Deferred *pDeferred, U16BIT *atags )
403 {
404  U16BIT size = 0;
405  U16BIT i;
406  U8BIT dlen, dtag;
407  while (dptr < dend)
408  {
409  dtag = *dptr++;
410  dlen = *dptr++;
411  if (dtag == DEFERRED_ASSOC_DESCRIPTOR && dlen > 8)
412  {
413  pDeferred->numAssocTags = *dptr / 2;
414  pDeferred->assocTags = atags;
415  dptr++;
416  for (i = pDeferred->numAssocTags; i--; atags++)
417  {
418  *atags = (dptr[0] << 8) | dptr[1];
419  size += 2;
420  dptr += 2;
421  dlen -= 2;
422  }
423  pDeferred->transportId = (dptr[0] << 8) | dptr[1];
424  dptr += 2;
425  pDeferred->serviceId = (dptr[0] << 8) | dptr[1];
426  dptr += 2;
427  pDeferred->origNetId = (dptr[0] << 8) | dptr[1];
428  dptr += 2;
429  dlen -= 7;
430  pDeferred++;
431  }
432  dptr += dlen;
433  }
434  return size;
435 }
436 
437 /*---global function definitions---------------------------------------------*/
438 
444 H_SiqPmtTable SIQ_PmtCreateTable( S_SiqInstance *siq, U8BIT *data )
445 {
446  S_SiqPmtTable *pmt_table;
447  S_PmtStream *stream_ptr;
448  H_PmtRef pmtref;
449  U8BIT *dptr, *section_end, *dloop_end, *ctags, *xtr_ptr;
450  U8BIT num_streams, num_deferred;
451  U8BIT stream_type;
452  U16BIT section_len, dloop_len;
453  U16BIT pid, size, sid, cnt, xtr_size;
454 
455  FUNCTION_START(PMT_CreateTable)
456 
457  dptr = data;
458  section_len = (dptr[1] << 8 | dptr[2]) & 0xfff;
459  dloop_len = (dptr[10] << 8 | dptr[11]) & 0xfff;
460 
461  sid = dptr[3] << 8 | dptr[4]; /* service id*/
462 
463  DBGLOG(DS_PMT, "sid=0x%x tid=0x%x sec_len=%d first desc len=%d", sid,
464  *data, section_len, dloop_len )
465 
466  section_end = data + section_len - 4; // -4 for crc
467  /* Search for deferred service assoc in first descriptor loop */
468  dptr = data + 12;
469  dloop_end = dptr + dloop_len;
470 
471  size = sizeof(S_SiqPmtTable) + DeferredSize( dptr, dloop_end, &num_deferred );
472  xtr_size = 0;
473 
474  dptr = dloop_end;
475 
476  /* count number of streams of interest */
477  num_streams = 0;
478  while (dptr < section_end)
479  {
480  stream_type = *dptr;
481  // use 'pid' to temporarily hold desc loop length
482  pid = ((dptr[3] & 0x0f) << 8) | dptr[4];
483  dptr += 5;
484  dloop_end = dptr + pid;
485  switch (stream_type)
486  {
487  case ST_MHEG: case ST_DATA_A:
488  ERRLOG(" Unhandled stream type=0x%x", stream_type)
489  default:
490  case ST_PRIVATE:
491  break;
492 
493  case ST_PES_PRV:
494  /* Telefonica SSU */
495  num_streams++;
496  size += sizeof(S_PmtStream);
497  break;
498 
499  case ST_DATA_B:
500  case ST_DATA_C:
501  case ST_DATA_D:
502  {
503  U16BIT dbsz;
504  cnt = CountStreamIdDesc(dptr, dloop_end);
505  dbsz = GetDataBroadcastExtraSize(dptr, dloop_end);
506  if (cnt || dbsz)
507  {
508  size += sizeof(S_PmtStream) + cnt;
509  xtr_size += dbsz;
510  num_streams++;
511  }
512  }
513  break;
514  }
515  dptr = dloop_end;
516  }
517  size += xtr_size;
518 
519  pmt_table = (S_SiqPmtTable *)siq->setup.memAlloc( size );
520  if (pmt_table == NULL)
521  {
522  ERRLOG("Memory failure")
523  }
524  else
525  {
526  memset( pmt_table, 0, size );
527  pmt_table->deferreds = (S_Deferred *)(pmt_table + 1);
528  pmt_table->num_deferred = num_deferred;
529  stream_ptr = (S_PmtStream *)(pmt_table->deferreds + num_deferred);
530  pmt_table->streams = stream_ptr;
531  pmt_table->num_streams = num_streams;
532  xtr_ptr= (U8BIT*)(stream_ptr + num_streams);
533  ctags = xtr_ptr + xtr_size;
534 
535  if (siq->setup.parsePmtInit)
536  {
537  /* Inform client about to start */
538  pmtref = siq->setup.parsePmtInit( sid );
539  }
540  else
541  {
542  U_PARAM pr;
543  pr.ptr = NULL;
544  pr.u32 = sid;
545  pmtref = pr.ptr;
546  }
547 
548  /* Search for deferred service assoc in first descriptor loop */
549  dptr = data + 12;
550  dloop_end = dptr + dloop_len;
551 
552  ctags += ParseDeferreds( dptr, dloop_end, pmt_table->deferreds, (U16BIT *)ctags );
553 
554  dptr = dloop_end;
555 
556  /*process second descriptor loop*/
557  num_streams = 0;
558  while (dptr < section_end)
559  {
560  stream_type = *dptr;
561  pid = ((dptr[1] & 0x1f) << 8) | dptr[2];
562  dloop_len = ((dptr[3] & 0x0f) << 8) | dptr[4];
563  dptr += 5;
564  dloop_end = dptr + dloop_len;
565  switch (stream_type)
566  {
567  default:
568  DBGLOG(DS_PMT, "; strm typ=0x%x", stream_type)
569  break;
570 
571  case ST_PRIVATE:
572  DBGLOG(DS_PMT, "[%d] stream typ=PRIVATE pid=0x%x func=%p", num_streams, stream_type, pid, siq->setup.notifyAitInfo)
573  if (siq->setup.notifyAitInfo)
574  {
575  DBGLOG(DS_PMT, " bytes=%d, data=0x%x 0x%x 0x%x 0x%x", dloop_end - dptr, dptr[0], dptr[1], dptr[2], dptr[3])
576  ParseForAitInfo(siq, sid, pid, dptr, dloop_end);
577  }
578  break;
579 
580  case ST_PES_PRV:
581  /* Telefonica SSU */
582  stream_ptr->dbcId = DBC_ID_SSU;
583  stream_ptr->carouselId = INVALID_CAROUSEL_ID;
584  stream_ptr->pid = pid;
585  break;
586 
587  case ST_DATA_B:
588  case ST_DATA_C:
589  case ST_DATA_D:
590  DBGLOG(DS_PMT, "[%d] stream typ=0x%x pid=0x%x", num_streams, stream_type, pid)
591  cnt = GetComponentTags(dptr, dloop_end, ctags);
592  if (cnt != 0)
593  {
594  stream_ptr->numtags = cnt;
595  stream_ptr->cTags = ctags;
596  stream_ptr->carouselId = GetCarouselInfo( dptr, dloop_end );
597  DBGLOG(DS_PMT, "cnt=%u, ctags[0]=%u crslId=0x%x", cnt, ctags[0], stream_ptr->carouselId)
598  }
599  else
600  {
601  DBGLOG(DS_PMT, "no ctags")
602  }
603  stream_ptr->bootPref = ParseForDataBroadcastIds( siq, pmtref, stream_ptr, dptr, dloop_end, &xtr_ptr );
604  if (cnt || stream_ptr->dbcId == DBC_ID_SSU)
605  {
606  ctags += cnt;
607  stream_ptr->pid = pid;
608  DBGLOG(DS_PMT, "crsl-id=0x%x bootPref=0x%x", stream_ptr->carouselId, stream_ptr->bootPref)
609  stream_ptr++;
610  }
611  else
612  {
613  DBGLOG(DS_PMT, "dbcId=0x%x",stream_ptr->dbcId)
614  }
615  }
616  dptr = dloop_end;
617  }
618  if (siq->setup.parsePmtDone)
619  {
620  /* Inform client have finished */
621  siq->setup.parsePmtDone( pmtref );
622  }
623  DBGLOG(DS_PMT, "table=%p", pmt_table )
624  }
625  FUNCTION_FINISH(PMT_CreateTable)
626  return pmt_table;
627 }
628 
635 void SIQ_PmtDestroyTable( S_SiqInstance *siq, H_SiqPmtTable table )
636 {
637  if (table != NULL)
638  {
639  DBGLOG(DS_PMT, "table=%p", table )
640  siq->setup.memFree( table );
641  }
642 }
643 
652 static void PmtDsmccPid( S_SiqInstance *siq, S_SiqPmtTable *pmt,
653  U16BIT assocTag, P_SIQueryResult pResult )
654 {
655  S_PmtStream *sptr;
656  U16BIT cnt, i;
657  FUNCTION_START(PmtDsmccPid);
658  sptr = pmt->streams;
659  for (cnt = pmt->num_streams; cnt--; sptr++)
660  {
661  for (i = 0; i != sptr->numtags; i++)
662  {
663  if (sptr->cTags[i] == (assocTag & 0xFF))
664  {
665  pResult->kind = SIQUERY_PID;
666  pResult->data.pid = sptr->pid;
667  return;
668  }
669  }
670  }
671  FUNCTION_FINISH(PmtDsmccPid);
672 }
673 
682 static void PmtCarouselInfo( S_SiqInstance *siq, S_SiqPmtTable *pmt,
683  U8BIT cTag, P_SIQueryResult pResult )
684 {
685  S_PmtStream *sptr;
686  U16BIT cnt, i;
687  FUNCTION_START(PmtCarouselInfo);
688  sptr = pmt->streams;
689  for (cnt = pmt->num_streams; cnt--; sptr++)
690  {
691  if (sptr->dbcId != DBC_ID_SSU)
692  {
693  for (i = 0; i != sptr->numtags; i++)
694  {
695  if (sptr->cTags[i] == cTag)
696  {
697  pResult->kind = SIQUERY_CAROUSEL_INFO;
698  pResult->data.carouselInfo.pid = sptr->pid;
699  pResult->data.carouselInfo.associationTag = cTag;
700  pResult->data.carouselInfo.carouselId = sptr->carouselId;
701  pResult->data.carouselInfo.next = NULL;
702  return;
703  }
704  }
705  }
706  }
707  FUNCTION_FINISH(PmtCarouselInfo);
708 }
709 
718 static void PmtCarousel(S_SiqInstance *siq, S_SiqPmtTable *pmt,
719  U32BIT carouselId, P_SIQueryResult pResult)
720 {
721  S_PmtStream *sptr;
722  U32BIT i;
723  FUNCTION_START(PmtCarousel)
724  sptr = pmt->streams;
725  for (i = 0; i != pmt->num_streams; i++, sptr++)
726  {
727  if (sptr->carouselId == carouselId)
728  {
729  pResult->kind = SIQUERY_CAROUSEL;
730  pResult->data.carouselInfo.pid = sptr->pid;
731  pResult->data.carouselInfo.associationTag = sptr->cTags[0];
732  pResult->data.carouselInfo.carouselId = carouselId;
733  pResult->data.carouselInfo.next = NULL;
734  DBGLOG(DS_QUERY, " strm[%d] ctag=0x%x crslid=0x%x", i, sptr->cTags[0], carouselId)
735  break;
736  }
737  }
738  FUNCTION_FINISH(PmtCarousel);
739 }
740 
748 static void PmtFindCarousel(S_SiqInstance *siq, H_SiqPmtTable pmt,
749  P_SIQueryResult pResult)
750 {
751  S_PmtStream *sptr;
752  U32BIT i;
753  FUNCTION_START(PmtFindCarousel)
754  sptr = pmt->streams;
755  for (i = 0; i != pmt->num_streams; i++, sptr++)
756  {
757  if (sptr->carouselId != INVALID_CAROUSEL_ID)
758  {
759  pResult->kind = SIQUERY_FIND_CAROUSEL;
760  pResult->data.carouselInfo.pid = sptr->pid;
761  pResult->data.carouselInfo.associationTag = sptr->cTags[0];
762  pResult->data.carouselInfo.carouselId = sptr->carouselId;
763  pResult->data.carouselInfo.next = NULL;
764  DBGLOG(DS_QUERY, " strm[%d] ctag=0x%x crslid=0x%x", i, sptr->cTags[0], sptr->carouselId)
765  break;
766  }
767  }
768  FUNCTION_FINISH(PmtFindCarousel);
769 }
770 
779 static void PmtBootCarousel(S_SiqInstance *siq, S_SiqPmtTable *pmt,
780  P_SIQueryResult pResult)
781 {
782  S_PmtStream *sptr;
783  U16BIT i, bootPref = 0;
784  FUNCTION_START(PmtBootCarousel)
785  sptr = pmt->streams;
786  for (i = 0; i != pmt->num_streams; i++, sptr++)
787  {
788  if (sptr->dbcId != DBC_ID_SSU && bootPref < sptr->bootPref)
789  {
790  bootPref = sptr->bootPref;
791  ASSERT( sptr->carouselId != INVALID_CAROUSEL_ID );
792  pResult->kind = SIQUERY_BOOT_CAROUSEL;
793  pResult->data.carouselInfo.pid = sptr->pid;
794  pResult->data.carouselInfo.associationTag = sptr->cTags[0];
795  pResult->data.carouselInfo.carouselId = sptr->carouselId;
796  pResult->data.carouselInfo.next = NULL;
797  DBGLOG(DS_QUERY, " strm[%d] ctag=0x%x crslid=0x%x", i, sptr->cTags[0], sptr->carouselId)
798  }
799  }
800  FUNCTION_FINISH(PmtBootCarousel)
801 }
802 
811 static void PmtSsuCarousel(S_SiqInstance *siq, S_SiqPmtTable *pmt,
812  U32BIT oui, P_SIQueryResult pResult)
813 {
814  S_PmtStream *sptr;
815  P_SsuInfo ssuInfo;
816  U32BIT i;
817  P_CarouselInfo pCrslInfo;
818  FUNCTION_START(PmtSsuCarousel)
819  sptr = pmt->streams;
820  pCrslInfo = NULL;
821  for (i = 0; i != pmt->num_streams; i++, sptr++)
822  {
823  ssuInfo = sptr->ssuInfo;
824  while (ssuInfo != NULL)
825  {
826  /* Call client function to parse selector bytes - which can determine whether
827  * target is for correct model/version etc */
828  if ((ssuInfo->oui == oui || ssuInfo->oui == DVB_OUI) &&
829  (!ssuInfo->selectorLen || siq->setup.parseSsuSelectorBytes((U8BIT*)(ssuInfo+1),ssuInfo->selectorLen)))
830  {
831  if (pCrslInfo == NULL)
832  {
833  pResult->kind = SIQUERY_SSU_CAROUSEL;
834  pCrslInfo = &pResult->data.carouselInfo;
835  }
836  else
837  {
838  pCrslInfo->next = siq->setup.memAlloc( sizeof(S_CarouselInfo) );
839  if (pCrslInfo->next == NULL)
840  {
841  ERRLOG("mem fail for extra carousel info")
842  return;
843  }
844  pCrslInfo = pCrslInfo->next;
845  }
846  pCrslInfo->pid = sptr->pid;
847  pCrslInfo->carouselId = ssuInfo->oui;
848  pCrslInfo->next = NULL;
849  if (sptr->numtags == 0)
850  {
851  pCrslInfo->associationTag = INVALID_ASSOCIATION_TAG;
852  }
853  else
854  {
855  pCrslInfo->associationTag = sptr->cTags[0];
856  }
857  DBGLOG(DS_QUERY, " strm[%d] ctag=0x%x crslid=0x%x", i, pCrslInfo->associationTag, oui)
858  }
859  ssuInfo = ssuInfo->next;
860  }
861  }
862  if (pResult->kind == SIRESULT_FAILURE && pmt->num_streams == 1)
863  {
864  sptr = pmt->streams;
865  if (sptr->dbcId == DBC_ID_SSU && sptr->carouselId == INVALID_CAROUSEL_ID && sptr->ssuInfo == NULL)
866  {
867  pResult->kind = SIQUERY_SSU_CAROUSEL;
868  pResult->data.carouselInfo.pid = sptr->pid;
869  pResult->data.carouselInfo.carouselId = oui;
870  pResult->data.carouselInfo.associationTag = INVALID_ASSOCIATION_TAG;
871  pResult->data.carouselInfo.next = NULL;
872  }
873  }
874  FUNCTION_FINISH(PmtSsuCarousel);
875 }
876 
885 static void PmtDeferredService(S_SiqInstance *siq, S_SiqPmtTable *pmt, U16BIT assocTag,
886  P_SIQueryResult pResult)
887 {
888  S_Deferred *ds;
889  U16BIT *atags, ndx;
890  U8BIT num_deferred;
891 
892  FUNCTION_START(PmtDeferredService)
893  num_deferred = pmt->num_deferred;
894  for (ds = pmt->deferreds; num_deferred--; ds++)
895  {
896  atags = ds->assocTags;
897  for (ndx = ds->numAssocTags; ndx--; atags++)
898  {
899  if (*atags == assocTag)
900  {
901  pResult->kind = SIQUERY_DEFERRED_SERVICE;
902  pResult->data.deferredService.transport_stream_id = ds->transportId;
903  pResult->data.deferredService.service_id = ds->serviceId;
904  pResult->data.deferredService.original_network_id = ds->origNetId;
905  num_deferred = 0; //break out of outer loop
906  break;
907  }
908  }
909  }
910  FUNCTION_FINISH(PmtDeferredService)
911 }
912 
921 void SIQ_PmtProcessQuery(S_SiqInstance *siq, P_SIQueryRequest pQuery, H_SiqPmtTable hpmt,
922  P_SIQueryResult pResult )
923 {
924  pResult->kind = SIRESULT_FAILURE;
925  switch (pQuery->kind)
926  {
927  case SIQUERY_PID:
928  DBGLOG(DS_QUERY, "PID serviceId=0x%x assocTag=0x%x", pQuery->serviceId, pQuery->associationTag)
929  PmtDsmccPid(siq, hpmt, pQuery->associationTag, pResult);
930  break;
931 
932  case SIQUERY_BOOT_CAROUSEL:
933  DBGLOG(DS_QUERY, "Boot Carousel serviceId=0x%x", pQuery->serviceId)
934  PmtBootCarousel(siq, hpmt, pResult);
935  break;
936 
937  case SIQUERY_FIND_CAROUSEL:
938  DBGLOG(DS_QUERY, "Find Carousel serviceId=0x%x", pQuery->serviceId)
939  PmtFindCarousel(siq, hpmt, pResult);
940  break;
941 
942  case SIQUERY_CAROUSEL_INFO:
943  DBGLOG(DS_QUERY, "Carousel id=0x%x serviceId=0x%x", (int)pQuery->dataId, pQuery->serviceId)
944  PmtCarouselInfo(siq, hpmt, (U8BIT)pQuery->dataId, pResult);
945  break;
946 
947  case SIQUERY_CAROUSEL:
948  DBGLOG(DS_QUERY, "Carousel id=0x%x serviceId=0x%x", (int)pQuery->dataId, pQuery->serviceId)
949  PmtCarousel(siq, hpmt, pQuery->dataId, pResult);
950  break;
951 
952  case SIQUERY_DEFERRED_SERVICE:
953  DBGLOG(DS_QUERY, "Deferred serviceId=0x%x assocTag=0x%x", pQuery->serviceId, pQuery->associationTag)
954  PmtDeferredService(siq, hpmt, pQuery->associationTag, pResult);
955  break;
956 
957  case SIQUERY_SSU_CAROUSEL:
958  DBGLOG(DS_QUERY, "Carousel id=0x%x serviceId=0x%x", (int)pQuery->dataId, pQuery->serviceId)
959  PmtSsuCarousel(siq, hpmt, pQuery->dataId, pResult);
960  break;
961 
962  case SIQUERY_SSU_PID:
963  /* Special case of ssu PID being given to DSMCC API (and held in service id field) */
964  pResult->kind = SIQUERY_SSU_PID;
965  pResult->data.carouselInfo.pid = pQuery->serviceId;
966  pResult->data.carouselInfo.carouselId = INVALID_CAROUSEL_ID;
967  pResult->data.carouselInfo.associationTag = INVALID_ASSOCIATION_TAG;
968  break;
969 
970  default:
971  case SIQUERY_PIDLIST:
972  ERRLOG("NOT supported %d", pQuery->kind);
973  break;
974  }
975 }
976 
987 void SIQ_PmtCheckTableChange( S_SiqInstance *siq, H_SiqPmtTable pOldTable,
988  H_SiqPmtTable pNewTable, U16BIT serviceId )
989 {
990  S_PmtStream *pOldStream, *pNewStream;
991  U16BIT i, j;
992  U32BIT carouselId;
993 
994  FUNCTION_START(SIQ_PmtCheckTableChange)
995  ASSERT(pOldTable != NULL)
996  ASSERT(pNewTable != NULL)
997 
998  pOldStream = pOldTable->streams;
999  for (i = pOldTable->num_streams; i--; pOldStream++)
1000  {
1001  carouselId = pOldStream->carouselId;
1002  pNewStream = pNewTable->streams;
1003  for (j = pNewTable->num_streams; j--; pNewStream++)
1004  {
1005  if (carouselId == pNewStream->carouselId)
1006  {
1007  /* found carousel in new one as well - OK */
1008  carouselId = INVALID_CAROUSEL_ID;
1009  break;
1010  }
1011  }
1012  if (carouselId != INVALID_CAROUSEL_ID)
1013  {
1014  CDSM_SysProcessSIChangeEvent( siq->dsmInstance, SICHANGE_CAROUSEL_DELETED, serviceId, carouselId );
1015  }
1016  }
1017 
1018  CDSM_SysProcessSIChangeEvent( siq->dsmInstance, SICHANGE_SERVICE_UPDATED, serviceId, 0 );
1019 
1020  FUNCTION_FINISH(SIQ_PmtCheckTableChange)
1021 }
1022 
H_SiqPmtTable SIQ_PmtCreateTable(S_SiqInstance *siq, U8BIT *data)
Create PMT structure for monitoring (life-cycle, NB_Info)
Definition: siq_pmt.c:444
void SIQ_PmtDestroyTable(S_SiqInstance *siq, H_SiqPmtTable table)
Destroy PMT structure created by PMT_CreateTable.
Definition: siq_pmt.c:635
Main API to DSM-CC core layer (provided functions and required callbacks).
Service Information Query: debug definitions.
void SIQ_PmtCheckTableChange(S_SiqInstance *siq, H_SiqPmtTable pOldTable, H_SiqPmtTable pNewTable, U16BIT serviceId)
For each carousel Id in old table, search through new table to see if it still exists. If not, tell DSM-CC. Then tell DSM-CC that PMT has been updated.
Definition: siq_pmt.c:987
Service Information Query: PMT parsing functions.
void SIQ_PmtProcessQuery(S_SiqInstance *siq, P_SIQueryRequest pQuery, H_SiqPmtTable hpmt, P_SIQueryResult pResult)
Retrieve Information required by Query request from SIQ's PMT table.
Definition: siq_pmt.c:921
Service Information Query: main definitions.
E_DscError CDSM_SysProcessSIChangeEvent(H_DsmCoreInst instance, E_SIChangeEvent evnt, U16BIT service_id, U32BIT carousel_id)
Notify that the SI for the indicated service has changed Changes should be notified in the following ...
Definition: clDsmMain.c:1113