DSMCC  17.9.0
 All Data Structures Files Functions Typedefs
sectionFilter.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  * Copyright © 2001 Koninklijke Philips Electronics N.V
5  *
6  * This file is part of a DTVKit Software Component
7  * You are permitted to copy, modify or distribute this file subject to the terms
8  * of the DTVKit 1.0 Licence which can be found in licence.txt or at www.dtvkit.org
9  *
10  * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
11  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
12  * OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
13  *
14  * If you or your organisation is not a member of DTVKit then you have access
15  * to this source code outside of the terms of the licence agreement
16  * and you are expected to delete this and any associated files immediately.
17  * Further information on DTVKit, membership and terms can be found at www.dtvkit.org
18  *******************************************************************************/
25 /*---includes for this file--------------------------------------------------*/
26 #include "clDsmSystem.h"
27 #include "sectionFilter.h"
28 
29 #include "objectCarousel.h"
30 #include "dataCarousel.h"
31 #include "module.h"
32 #include "siQuery.h"
33 #include "loadMgr.h"
34 #include "sectionTimer.h"
35 #include "streamEvent.h"
36 
37 /*------------------------------- Local Macros -------------------------------*/
38 
39 #define HASH_SHIFT 3
40 #define HASH_NUM (1 << HASH_SHIFT)
41 #define HASH_MASK (HASH_NUM - 1)
42 #define HNDL_MAGIC 0xABBA0000
43 #define HNDL_MASK 0xFFFF0000
44 
45 /*------------------------------ Exported Data -----------------------------*/
46 
47 
48 /*--------------------------------Local Types --------------------------------*/
49 
50 typedef struct s_SectionFilterHeap
51 {
52  /* -- Section filter heap control */
53  P_SecFilterInfo sfFreeListHead;
54  P_SecFilterInfo sfFreeListTail;
55  U16BIT sectionFiltersInUse;
56 
57  P_SecFilterInfo sfActiveHeads[HASH_NUM];
58  U16BIT activeCounter;
59 
60  /* -- Section filter heap memory */
61  U32BIT totalFilters;
62  P_SecFilterInfo sectionFilters;
63 } S_SecFilterHeap, *P_SecFilterHeap;
64 
65 
66 /*------------------------------- Local Statics ------------------------------*/
67 #ifdef ACCELERATE_CAROUSEL_LOADING
68 P_SecFilterInfo wideOpenFilter;
69 
70 typedef struct _accelerate_carousel_loading_struct
71 {
72  U16BIT storeWritePos;
73  U16BIT storeReadPos;
74  U16BIT storedSectionsNB;
75  U16BIT SectionsReinjection;
76  BOOLEAN bLargeDDBFilterSet;
77  U16BIT requestedModidPos;
78  P_SecFilterInfo largeDDBFilter;
79 } accelerateCarouselLoading_t;
80 
81 extern accelerateCarouselLoading_t accCarouselLoadingInfos;
82 #endif
83 
84 #ifdef SF_STATS
85 static U32BIT sfStatsNum = 0;
86 static U32BIT sfStatsMax = 0;
87 #endif
88 
89 /*------------------- local prototypes/forward declarations ------------------*/
90 
91 static void SectionFilterHeapInit( P_SecFilterHeap pSfHeap );
92 
93 static P_SecFilterInfo AllocSectionFilterBlock( P_DsmCoreInst idp );
94 
95 static void FreeSectionFilterBlock( P_DsmCoreInst idp,
96  /*I*/ P_SecFilterInfo pSectionFilter );
97 
98 #ifdef ACCELERATE_CAROUSEL_LOADING
99 E_DscError sectionLargeDDBFilterStart( P_DsmCoreInst idp,
100  E_SecFiltKind sfKind,
101  U16BIT service_id,
102  E_SFPriority sfPriority,
103  P_SecFilterInfo *pSectionFilter,
104  U16BIT assoctag);
105 
106 extern E_DscError requestedModuleIdSet(U16BIT moduleID);
107 
108 extern E_DscError requestedModuleIdReset(U16BIT moduleID);
109 
110 #endif
111 
112 /*---------------------------- Exported Functions ----------------------------*/
113 
114 /*
115 -- NOTES:
116 -- The heap of section filter memory blocks is managed so that new filters
117 -- are assigned from the oldest free block in the heap.
118 -- This helps with detecting sections arriving from filters after the filter
119 -- has been deleted (due to delays in the calling environment).
120 */
121 
122 
123 /*
124 -- Create section filter heap
125 */
126 E_DscError DSC_SsectionFilterHeapCreate( P_DsmCoreInst idp,
127  /*O*/ void **pSectionFilterHeap, U32BIT *pHeapSize )
128 {
129  E_DscError err = CLDSM_OK;
130  P_SecFilterHeap pSfHeap;
131  U32BIT size;
132 
133  dsmDP3(("DSC_SsectionFilterHeapCreate()\n"));
134  dsmAssert((idp != NULL));
135 
136  size = (*pHeapSize) * sizeof(S_SecFilterInfo);
137  size += sizeof(S_SecFilterHeap);
138 
139  *pSectionFilterHeap = NULL;
140 
141  pSfHeap = (P_SecFilterHeap)idp->setup.allocFunc( size );
142 
143  if (pSfHeap)
144  {
145  /* -- Output debug info about the section filter heap */
146  DBGLOG(DD_SF, "Section Filter heap size = %u bytes", size)
147 
148  pSfHeap->totalFilters = *pHeapSize;
149  pSfHeap->sectionFilters = (P_SecFilterInfo)(pSfHeap + 1);
150  pSfHeap->activeCounter = 0x0000;
151 
152  SectionFilterHeapInit( pSfHeap );
153 
154  *pSectionFilterHeap = pSfHeap;
155 
156  *pHeapSize = size;
157  }
158  else
159  {
160  ERRPRINT("Failed to get section filter heap (%u); sz=%u",*pHeapSize,size)
161  err = CLDSM_ERR_ALLOC_FAILED;
162  }
163 
164  dsmDP3(("exit DSC_SsectionFilterHeapCreate -> rtn: %u\n", err));
165  return err;
166 }
167 
168 /*
169 -- Reset section filter heap
170 */
171 void DSC_SsectionFilterHeapReset( P_DsmCoreInst idp )
172 {
173  P_SecFilterHeap pSfHeap;
174  P_SecFilterInfo pSF, *pSFHead;
175  int ndx;
176 
177  dsmDP3(("DSC_SsectionFilterHeapReset()\n"));
178 
179  ASSERT( idp != NULL )
180  pSfHeap = idp->sectionFilterHeap;
181  ASSERT( pSfHeap != NULL )
182 
183  /* -- NB. should not be any active section filters at this point */
184  if (pSfHeap->sectionFiltersInUse != 0)
185  {
186  ERRPRINT("************ Section filters still in USE! %d *************",
187  pSfHeap->sectionFiltersInUse )
188  for (ndx = 0; ndx != HASH_NUM; ndx++)
189  {
190  pSFHead = pSfHeap->sfActiveHeads + ndx;
191  while (*pSFHead != NULL)
192  {
193  pSF = *pSFHead;
194 
195  ERRPRINT( "handle=0x%x targetKind=%d status=%d targetId=0x%x", pSF->handle, pSF->target.kind, pSF->status, pSF->target.id )
196 
197  DSC_SectionFilterStop(idp, &pSF);
198  }
199  if (!pSfHeap->sectionFiltersInUse)
200  break;
201  }
202  }
203 
204  SectionFilterHeapInit( pSfHeap );
205 
206  dsmDP3(("exit DSC_SsectionFilterHeapReset\n"));
207 }
208 
209 /*
210 -- Start a section filter of the specified kind.
211 -- Make SI query to get PID.
212 -- If PID returned synchronously then commit external filter (ie. add it
213 -- via callback).
214 */
215 E_DscError DSC_SectionFilterStart( P_DsmCoreInst idp, P_SfTarget pTarget,
216  E_SFPriority sfPriority, P_SecFilterInfo *ppSF )
217 {
218  P_SecFilterInfo pSF;
219  E_DscError err = CLDSM_OK;
220  S_SIQueryRequest siQueryData;
221  S_SIQueryResult siQueryResult;
222 
223  dsmDP3(("DSC_SectionFilterStart()\n"));
224  dsmAssert((idp != NULL));
225  dsmAssert((pTarget != NULL));
226  dsmAssert((ppSF != NULL));
227 
228  *ppSF = NULL;
229 
230  pSF = AllocSectionFilterBlock( idp );
231  if (!pSF)
232  {
233  /* TODO: HANDLE LIMITED SECTION FILTERS CORRECTLY */
234  dsmDP1(("ERROR: Limited section filters not yet supported\n"));
235  dsmAssert((0));
236  err = CLDSM_ERR_SECTION_FILTER_HEAP_FULL;
237  }
238  else if (pTarget->u.pRC == NULL)
239  {
240  ERRPRINT("target ref is NULL")
241  err = CLDSM_ERR_INVALID_SI_QUERY_REF;
242  FreeSectionFilterBlock( idp, pSF );
243  }
244  else
245  {
246  switch (pTarget->kind)
247  {
248  case SFK_DSI:
249  {
250  pSF->filter.tableId = DSIDII_ID;
251  pSF->filter.tableIdExt = 0x0000;
252  pSF->filter.tableIdExtMask = 0xFFFE;
253  #ifdef ACCELERATE_CAROUSEL_LOADING
254  if (FALSE == accCarouselLoadingInfos.bLargeDDBFilterSet)
255  {
256  sectionLargeDDBFilterStart( idp, SFK_DDB, pTarget->serviceId,
257  SF_PRIORITY_LOW, &accCarouselLoadingInfos.largeDDBFilter,
258  pTarget->associationTag);
259  accCarouselLoadingInfos.bLargeDDBFilterSet = TRUE;
260  }
261  #endif /* ACCELERATE_CAROUSEL_LOADING */
262  break;
263  }
264  case SFK_DII:
265  {
266  pSF->filter.tableId = DSIDII_ID;
267  pSF->filter.tableIdExt = (U16BIT)pTarget->id;
268  pSF->filter.tableIdExtMask = 0xFFFE;
269  break;
270  }
271  #if 0
272  /* TODO: Getting next DII version only (to reduce filtering
273  reqs. when monitoring for updates) ? */
274  case SFK_DII_NEXT:
275  {
276  pSF->filter.tableId = DSIDII_ID;
277  pSF->filter.tableIdExt = (U16BIT)pTarget->id;
278  pSF->filter.tableIdExtMask = 0xFFFF;
279  break;
280  }
281  #endif
282  case SFK_DDB:
283  {
284  pSF->filter.tableId = DDB_ID;
285  pSF->filter.tableIdExt = (U16BIT)pTarget->id;
286  pSF->filter.tableIdExtMask = 0xFFFF;
287  #ifdef ACCELERATE_CAROUSEL_LOADING
288  requestedModuleIdSet(pTarget->id);
289  #endif /* ACCELERATE_CAROUSEL_LODING */
290  break;
291  }
292  case SFK_STREAM_DESCR:
293  {
294  /* Tid=0x3D (define a constant)*/
295  /* Tidex= EventId&0x3F */
296  /* (if possible target id will be eventId)*/
297  pSF->filter.tableId = STREAM_DESCR_ID;
298  pSF->filter.tableIdExt = (U16BIT)pTarget->id;
299  pSF->filter.tableIdExtMask = 0xFFFF;
300  break;
301  }
302  default:
303  {
304  ERRPRINT("section filter kind = %u", pTarget->kind)
305  err = CLDSM_ERR_INTERNAL;
306  break;
307  }
308  }
309  if (err)
310  {
311  ERRLOG(DD_SF, "setup fail: err=%d", err)
312  FreeSectionFilterBlock( idp, pSF );
313  }
314  else
315  {
316  /* clear timers */
317  pSF->tms.mainTimerHandle = NULL;
318  pSF->tms.nextTimerHandle = NULL;
319  pSF->tms.nextDuration = 0;
320 
321  pSF->filter.priority = (U8BIT)sfPriority;
322  pSF->target = *pTarget;
323 
324  if (pTarget->associationTag == INVALID_ASSOCIATION_TAG)
325  {
326  /* pTarget->serviceId is really the PID value */
327  pSF->filter.pid = pTarget->serviceId;
328  err = DSC_SectionFilterCommit( idp, pSF );
329  if (!err)
330  {
331  *ppSF = pSF;
332  }
333  else
334  {
335  ERRLOG(DD_SF, "Commit fail: err=%d", err)
336  FreeSectionFilterBlock( idp, pSF );
337  }
338  }
339  else
340  {
341  /* -- Make SI Query to get PID for section filter -- */
342  siQueryData.kind = SIQUERY_PID;
343  siQueryData.serviceId = pTarget->serviceId;
344  siQueryData.associationTag = pTarget->associationTag;
345  err = siQueryStart( idp, &siQueryData, (void *) pSF, &siQueryResult );
346  switch (err)
347  {
348  case CLDSM_PENDING:
349  {
350  /* -- Store query ref with filter */
351  DBGLOG(DD_SF, "PENDING kind=%d qhdl=%p\n", siQueryResult.kind, siQueryResult.data.queryHandle);
352  pSF->u.pPendingSiQueryRef = siQueryResult.data.queryHandle;
353  pSF->status = SFA_PENDING;
354  *ppSF = pSF;
355  err = CLDSM_OK;
356  break;
357  }
358  case CLDSM_OK:
359  {
360  /* -- Store PID in filter */
361  pSF->filter.pid = siQueryResult.data.pid;
362  if (pSF->filter.pid == 0)
363  {
364  dsmDP1(("zero PID!"));
365  err = CLDSM_ERR_INVALID_SI_INFO;
366  }
367  else
368  {
369  DBGLOG(DD_SF, "kind=%d pid=0x%x\n", siQueryResult.kind, siQueryResult.data.pid);
370  err = DSC_SectionFilterCommit( idp, pSF );
371  if (!err)
372  {
373  *ppSF = pSF;
374  break;
375  }
376  dsmDP1(("DSC_SectionFilterCommit.err = %x", err));
377  }
378  }
379  default:
380  {
381  ERRLOG(DD_SF, "Query fail: err=%d", err)
382  FreeSectionFilterBlock( idp, pSF );
383  }
384  }
385  }
386  }
387  }
388  dsmDP3(("exit DSC_SectionFilterStart -> rtn: %u\n", err));
389  return err;
390 }
391 
392 /*
393 -- DSC_SsectionFilterUpdatePriority
394 --
395 -- If latchHighest is set
396 -- If new priority is HIGHER than current priority change filter priority
397 -- to new priority
398 -- Else
399 -- Always change filter priority to new priority
400 --
401 -- If filter is committed then delete current filter and add new filter using
402 -- same filter reference.
403 --
404 */
405 E_DscError DSC_SsectionFilterUpdatePriority( P_DsmCoreInst idp,
406  /*I*/ P_SecFilterInfo pSF, E_SFPriority newSfPriority,
407  BOOLEAN latchHighest )
408 {
409  E_DscError err = CLDSM_OK;
410 
411  dsmDP3(("DSC_SsectionFilterUpdatePriority()\n"));
412  dsmAssert((idp != NULL));
413  dsmAssert((pSF != NULL));
414 
415  /* update timer */
416  sectionTimerUpdate(idp, pSF, FALSE, TRUE);
417 
418  /* -- NB. Make it safe in retail mode */
419  if (pSF != NULL)
420  {
421  if ((newSfPriority != pSF->filter.priority) &&
422  !((latchHighest == TRUE) &&
423  (newSfPriority < pSF->filter.priority)))
424  {
425  /* -- Update stored filter priority */
426  pSF->filter.priority = (U8BIT)newSfPriority;
427 
428  switch (pSF->status)
429  {
430  case SFA_PENDING:
431  /*
432  -- In this state, the section filter has not yet been
433  -- added (committed) since it is waiting for an
434  -- pending SI Query to complete, so nothing specific to do.
435  */
436  break;
437 
438 
439  case SFA_COMMITTED:
440  DBGLOG(DD_SF, "pSF->u.filterHandle=%p", pSF->u.filterHandle)
441  /* -- In this state, the section filter is actually started
442  -- in the calling env. so delete it and restart it with
443  -- the same filter ref */
444  if (idp->setup.sfPriorityChangeFunc != NULL)
445  {
446  idp->setup.sfPriorityChangeFunc( idp->setup.sfmInstance,
447  pSF->u.filterHandle, (H_DscSFRef)pSF->handle, newSfPriority );
448  }
449  break;
450 
451 
452  case SFA_ABORTED:
453  /* -- In this state, the section filter commit has failed so
454  -- nothing specific to do */
455  break;
456 
457  default:
458  /* -- 'Added' section filters should not be in any other state */
459  ERRPRINT( "Illegal section filter status = %u\n", pSF->status )
460  err = CLDSM_ERR_INTERNAL;
461  break;
462  }
463  }
464  }
465  DBG3(DD_SF, "exit DSC_SsectionFilterUpdatePriority -> rtn: %u\n", err)
466  return err;
467 }
468 
469 /*
470 -- Stop section filter.
471 -- If state is pending, stop associated SI Query.
472 -- If state is committed then delete external filter via callback.
473 */
474 void DSC_SectionFilterStop( P_DsmCoreInst idp,
475  /*IO*/ P_SecFilterInfo *ppSF )
476 {
477  P_SecFilterInfo pSF;
478 
479  #ifdef ACCELERATE_CAROUSEL_LOADING
480  P_Module pTargetModule;
481  #endif /* ACCELERATE_CAROUSEL_LOADING */
482 
483  dsmDP3(("DSC_SectionFilterStop()\n"));
484  dsmAssert((idp != NULL));
485  dsmAssert((ppSF != NULL));
486  //dsmAssert((*ppSF != NULL));
487 
488  pSF = *ppSF;
489 
490  /* -- NB. Make it safe in retail mode */
491  if (pSF != NULL)
492  {
493  #ifdef ACCELERATE_CAROUSEL_LOADING
494  if (pSF->target.kind == SFK_DDB)
495  {
496  pTargetModule = pSF->target.u.pModule;
497  requestedModuleIdReset(pTargetModule->moduleInfo.moduleId);
498  }
499  #endif /* ACCELERATE_CAROUSEL_LOADING */
500 
501  /* stop acquisition timer */
502  sectionTimerRemove(idp, pSF);
503 
504  switch (pSF->status)
505  {
506  case SFA_PENDING:
507  DBGLOG(DD_SF, "SFA_PENDING 0x%x", pSF->u.pPendingSiQueryRef)
508  /*
509  -- In this state, the section filter has not yet been
510  -- added (committed) since it is waiting for an
511  -- pending SI Query to complete, so abort the query.
512  */
513  dsmAssert((pSF->u.pPendingSiQueryRef != NULL));
514  siQueryAbortPending( idp, pSF->u.pPendingSiQueryRef );
515 
516  /* -- Clear Query ref in filter (finished with) */
517  pSF->u.pPendingSiQueryRef = NULL;
518  break;
519 
520 
521  case SFA_COMMITTED:
522  DBGLOG(DD_SF, "SFA_COMMITTED 0x%x", pSF->u.filterHandle)
523  /* -- In this state, the section filter is actually started
524  -- in the calling env. so delete it */
525  idp->setup.delSectionFilterFunc( idp->setup.sfmInstance, pSF->u.filterHandle,
526  (H_DscSFRef)pSF->handle );
527  break;
528 
529 
530  case SFA_ABORTED:
531  /* -- In this state, the section filter commit has failed so
532  -- nothing specific to do (just allow filter to be freed) */
533  DBGLOG(DD_SF, "SFA_ABORTED")
534  break;
535 
536  default:
537  /* -- 'Added' section filters should not be in any other state */
538  dsmDP1(("ERROR: Illegal section filter status = %u\n", pSF->status));
539  /* -- Notify an internal error here since can't return one */
540  if (idp->setup.errorFunc)
541  {
542  idp->setup.errorFunc( CLDSM_ERR_INTERNAL, NULL);
543  }
544  break;
545  }
546  FreeSectionFilterBlock( idp, pSF );
547  *ppSF = NULL;
548  }
549 
550  dsmDP3(("exit DSC_SectionFilterStop\n"));
551 }
552 
553 /*
554 -- Commit (add) an external section filter via callback (called once
555 -- PID is resolved)
556 */
557 E_DscError DSC_SectionFilterCommit( P_DsmCoreInst idp,
558  /*I*/ P_SecFilterInfo pSF )
559 {
560  E_DscError err;
561 
562  dsmAssert((idp != NULL));
563  dsmAssert((pSF != NULL));
564  dsmAssert((pSF->status != SFA_COMMITTED));
565  dsmAssert((pSF->filter.pid != 0));
566 
567  DBGLOG(DD_SF, " PID=0x%x, tid=0x%x tidExt=0x%x msk=0x%x hdl=0x%x",
568  pSF->filter.pid, pSF->filter.tableId, pSF->filter.tableIdExt,
569  pSF->filter.tableIdExtMask, pSF->handle)
570 
571  /* -- Commit section filter */
572  pSF->status = SFA_COMMITTED;
573 
574  /* u.filterHandle overwrites any previous value in union (ie. Query Ref) */
575  pSF->u.filterHandle = idp->setup.addSectionFilterFunc( idp->setup.sfmInstance,
576  &pSF->filter, pSF->handle );
577 
578  if (!pSF->u.filterHandle)
579  {
580  ERRLOG(DD_SF, "addSectionFilterFunc. returned NULL")
581  pSF->status = SFA_ABORTED;
582  err = CLDSM_ERR_SYSTEM_ADD_SECTION_FILTER;
583  }
584  else
585  {
586  /* Start acquisition timer */
587  SectionTimerArm(idp, pSF);
588  err = CLDSM_OK;
589  }
590 
591  DBGLOG(DD_SF, " rtn: %u", err)
592  return err;
593 }
594 
595 /*
596 -- Abort (and notify) anything depending on filter
597 */
598 void DSC_SectionFilterAbortDependants( P_DsmCoreInst idp,
599  /*I*/ P_SecFilterInfo pSectionFilter )
600 {
601  P_RootCarousel pRC;
602 
603  dsmDP3(("DSC_SectionFilterAbortDependants()\n"));
604  dsmAssert((idp != NULL));
605  dsmAssert((pSectionFilter != NULL));
606  dsmAssert(((pSectionFilter->status == SFA_PENDING) ||
607  (pSectionFilter->status == SFA_ABORTED)));
608 
609  pSectionFilter->status = SFA_ABORTED;
610 
611  switch (pSectionFilter->target.kind)
612  {
613  case SFK_DSI:
614  /*
615  -- In this case, a carousel load is waiting for the DSI
616  -- to arrive so notify a load error. Carousel load will then
617  -- be unloaded/aborted by client.
618  */
619  pRC = pSectionFilter->target.u.pRC;
620  dsmAssert((pRC->status == RCS_BOOTING));
621 
622  /*
623  -- In this state, the DSI section filter will have been
624  -- requested, so stop it (also Nulls reference in OC).
625  */
626  dsmAssert((pRC->pDsiSf));
627  DSC_SectionFilterStop( idp, &pRC->pDsiSf );
628 
629  /* -- Finalise and destroy carousel load request */
630  DSC_RootCrslAbortLoadRequest( idp, pRC );
631  break;
632 
633 
634  case SFK_DII:
635  /*
636  -- In this case, one or more object loads are waiting for a DII
637  -- message to arrive so they can start the module loads, so
638  -- unload the corresponding data carousel (which in turn deletes
639  -- the relevant section filter). Unloading the data carousel also
640  -- deletes all attached modules, this notifies any load requests of
641  -- a load error and corresponding object loads will subsequently
642  -- be unloaded/aborted by client
643  */
644  DSC_DataCrslDelete( idp, pSectionFilter->target.u.pDC );
645  break;
646 
647  /*
648  case SFK_DII_NEXT:
649  TODO: Abort anything depending on next DII filter
650  (maybe just marks cache content as stale?)
651  break;
652  */
653 
654  case SFK_DDB:
655  /*
656  -- In this case, one or more object loads are waiting for
657  -- a module to arrive so unload the module (which in turn deletes
658  -- relevant section filters). Unloading the module notifies all
659  -- load requests of a load error and corresponding object loads
660  -- will subsequently be unloaded/aborted by client
661  */
662  DSC_ModuleDeleteDcTidyUp( idp, pSectionFilter->target.u.pModule );
663  break;
664 
665  case SFK_STREAM_DESCR:
666  /* TODO: Abort anything depending on stream descriptor filter */
667  break;
668 
669  default:
670  dsmDP1(("ERROR: Illegal section filter kind = %u\n",
671  pSectionFilter->target.kind));
672  dsmAssert((0));
673 
674  /* -- Notify an internal error here since can't return one */
675  if (idp->setup.errorFunc)
676  {
677  idp->setup.errorFunc( CLDSM_ERR_INTERNAL, NULL);
678  }
679  break;
680  }
681 
682  dsmDP3(("exit DSC_SectionFilterAbortDependants\n"));
683 }
684 
685 /*
686 -- Retrieve filter from handle - called when section data arrives
687 */
688 P_SecFilterInfo DSC_SectionFilterRetrieve( P_DsmCoreInst idp, U32BIT handle )
689 {
690  P_SecFilterHeap pSfHeap;
691  P_SecFilterInfo pSectionFilter;
692 
693  ASSERT(idp != NULL);
694  pSfHeap = idp->sectionFilterHeap;
695 
696  pSectionFilter = pSfHeap->sfActiveHeads[handle & HASH_MASK];
697  while (pSectionFilter != NULL)
698  {
699  if (pSectionFilter->handle == handle)
700  {
701  break;
702  }
703  pSectionFilter = pSectionFilter->nextBlock;
704  }
705  return pSectionFilter;
706 }
707 
708 /*------------------------------ Local Functions -----------------------------*/
709 
710 /*
711 -- Initialise section filter heap
712 */
713 static void SectionFilterHeapInit( P_SecFilterHeap pSfHeap )
714 {
715  S_SecFilterInfo *p_secFlt;
716  U32BIT i, total;
717 
718  dsmDP3(("SectionFilterHeapInit()\n"));
719  dsmAssert((pSfHeap != NULL));
720 
721  dsmDP4(("pSfHeap->sectionFiltersInUse = %d", pSfHeap->sectionFiltersInUse));
722 
723  pSfHeap->sectionFiltersInUse = 0;
724 
725  p_secFlt = pSfHeap->sectionFilters;
726  pSfHeap->sfFreeListHead = p_secFlt;
727  total = pSfHeap->totalFilters;
728 
729  /* -- Clear all section filter blocks & setup free list */
730  for (i = 0; i != total; i++, p_secFlt++)
731  {
732  /* -- NULL filter contents */
733  p_secFlt->filter.pid = 0;
734  p_secFlt->filter.priority = (U8BIT)SF_PRIORITY_LOW;
735  p_secFlt->filter.tableId = 0;
736  p_secFlt->filter.tableIdExt = 0;
737  p_secFlt->filter.tableIdExtMask = 0x0000;
738 
739  p_secFlt->status = SFA_INITIAL;
740  p_secFlt->target.kind = SFK_NONE;
741  p_secFlt->target.id = 0;
742  p_secFlt->target.u.pRC = NULL;
743 
744  p_secFlt->handle = 0;
745 
746  /* -- Link blocks into free list */
747  p_secFlt->nextBlock = p_secFlt + 1;
748  }
749 
750  p_secFlt--;
751  p_secFlt->nextBlock = NULL;
752  pSfHeap->sfFreeListTail = p_secFlt;
753 
754  for (i = 0; i != HASH_NUM; i++)
755  {
756  pSfHeap->sfActiveHeads[i] = NULL;
757  }
758 
759  dsmDP3(("exit SectionFilterHeapInit\n"));
760 }
761 
762 /*
763 -- Allocate section filter memory block from heap
764 */
765 static P_SecFilterInfo AllocSectionFilterBlock( P_DsmCoreInst idp )
766 {
767  P_SecFilterHeap pSfHeap;
768  P_SecFilterInfo pSectionFilter = NULL;
769  U32BIT handle;
770 
771  dsmDP3(("AllocSectionFilterBlock()\n"));
772  dsmAssert((idp != NULL));
773  dsmAssert((idp->sectionFilterHeap != NULL));
774 
775  pSfHeap = idp->sectionFilterHeap;
776 
777 #ifdef SF_STATS
778  sfStatsNum++;
779  if (sfStatsMax < sfStatsNum)
780  sfStatsMax = sfStatsNum;
781  ERRPRINT("sfStatsNum=%d sfStatsMax=%d", sfStatsNum, sfStatsMax)
782 #endif
783 
784  dsmAssert((pSfHeap->sectionFiltersInUse <= pSfHeap->totalFilters));
785 
786  handle = pSfHeap->activeCounter++;
787  handle|= HNDL_MAGIC;
788 
789  if (pSfHeap->sectionFiltersInUse < pSfHeap->totalFilters)
790  {
791  ASSERT(pSfHeap->sfFreeListHead != NULL)
792 
793  pSfHeap->sectionFiltersInUse++;
794 
795  /* -- Get section filter block at head of free list */
796  pSectionFilter = pSfHeap->sfFreeListHead;
797  pSectionFilter->handle = handle;
798 
799  pSfHeap->sfFreeListHead = pSectionFilter->nextBlock;
800  if (pSfHeap->sfFreeListHead == NULL)
801  {
802  pSfHeap->sfFreeListTail = NULL;
803  }
804 
805  handle = handle & HASH_MASK;
806  pSectionFilter->nextBlock = pSfHeap->sfActiveHeads[handle];
807  pSfHeap->sfActiveHeads[handle] = pSectionFilter;
808  DBGLOG(DD_SF, "rtn: %p handle=0x%x", pSectionFilter, pSectionFilter->handle)
809  }
810  else
811  {
812  ERRPRINT("no free section filters")
813  }
814  return pSectionFilter;
815 }
816 
817 /*
818 -- Return section filter memory block to free heap
819 */
820 static void FreeSectionFilterBlock( P_DsmCoreInst idp,
821  /*I*/ P_SecFilterInfo pSectionFilter )
822 {
823  P_SecFilterHeap pSfHeap;
824  P_SecFilterInfo *ppSfActiveHead;
825 
826  DBGLOG(DD_SF, " handle=0x%x", pSectionFilter->handle)
827  dsmAssert((idp != NULL));
828  dsmAssert((pSectionFilter != NULL));
829 
830  pSfHeap = idp->sectionFilterHeap;
831 
832 #ifdef SF_STATS
833  ERRPRINT("sfStatsNum=%d sfStatsMax=%d", sfStatsNum, sfStatsMax)
834  sfStatsNum--;
835 #endif
836 
837  dsmAssert((
838  (pSectionFilter >= &pSfHeap->sectionFilters[0]) &&
839  (pSectionFilter < &pSfHeap->sectionFilters[ pSfHeap->totalFilters ])
840  ));
841  dsmAssert((pSfHeap->sectionFiltersInUse > 0));
842  dsmAssert((pSfHeap->sectionFiltersInUse <= pSfHeap->totalFilters));
843  dsmAssert(((pSectionFilter->handle&HNDL_MASK) == HNDL_MAGIC));
844  if ((pSectionFilter->handle&HNDL_MASK) == HNDL_MAGIC)
845  {
846  ppSfActiveHead = pSfHeap->sfActiveHeads + (pSectionFilter->handle & HASH_MASK);
847  while (*ppSfActiveHead != NULL)
848  {
849  if (*ppSfActiveHead == pSectionFilter)
850  {
851  *ppSfActiveHead = pSectionFilter->nextBlock;
852  break;
853  }
854  ppSfActiveHead = &((*ppSfActiveHead)->nextBlock);
855  }
856 
857  /* -- NULL contents of section filter block (helps stale filter handles
858  -- to be detected) */
859  pSectionFilter->filter.pid = 0;
860  pSectionFilter->filter.priority = (U8BIT)SF_PRIORITY_LOW;
861  pSectionFilter->filter.tableId = 0;
862  pSectionFilter->filter.tableIdExt = 0;
863  pSectionFilter->filter.tableIdExtMask = 0x0000;
864 
865  dsmDP4(("pSectionFilter = %p", pSectionFilter));
866  pSectionFilter->status = SFA_INITIAL;
867  pSectionFilter->target.kind = SFK_NONE;
868  pSectionFilter->target.id = 0;
869  pSectionFilter->target.u.pRC = NULL;
870 
871  pSectionFilter->handle = 0;
872 
873  pSectionFilter->nextBlock = NULL;
874 
875  /* -- Put block on tail of free list */
876  if (pSfHeap->sfFreeListTail == NULL)
877  {
878  ASSERT( pSfHeap->sfFreeListHead == NULL )
879  pSfHeap->sfFreeListHead = pSectionFilter;
880  }
881  else
882  {
883  pSfHeap->sfFreeListTail->nextBlock = pSectionFilter;
884  }
885  pSfHeap->sfFreeListTail = pSectionFilter;
886 
887  pSfHeap->sectionFiltersInUse--;
888  }
889  dsmDP3(("exit FreeSectionFilterBlock\n"));
890 }
891 
892 #ifdef ACCELERATE_CAROUSEL_LOADING
893 
894 E_DscError sectionLargeDDBFilterStart( P_DsmCoreInst idp,
895  E_SecFiltKind sfKind,
896  U16BIT service_id,
897  E_SFPriority sfPriority,
898  /*O*/ P_SecFilterInfo *pSectionFilter,
899  U16BIT assocTag)
900 {
901  P_SecFilterInfo pSF;
902  E_DscError err = CLDSM_OK;
903  S_SIQueryRequest siQueryData;
904  S_SIQueryResult siQueryResult;
905 
906  dsmDP3(("sectionLargeDDBFilterStart()\n"));
907  dsmAssert((idp != NULL));
908  dsmAssert((pSectionFilter != NULL));
909 
910 
911  *pSectionFilter = NULL;
912 
913  pSF = AllocSectionFilterBlock( idp );
914 
915  if (!pSF)
916  {
917  /* TODO: HANDLE LIMITED SECTION FILTERS CORRECTLY */
918  dsmDP1(("ERROR: Limited section filters not yet supported\n"));
919  dsmAssert((0));
920  err = CLDSM_ERR_SECTION_FILTER_HEAP_FULL;
921  goto _return; /* EXIT */
922  }
923 
924  pSF->target.kind = sfKind;
925  pSF->target.u.pRC = 0;
926  pSF->hCarousel = NULL;
927 
928  pSF->target.id = 145;
929 
930 
931  pSF->filter.tableId = DDB_ID;
932  pSF->filter.tableIdExt = 0xFFFF;
933 
934  pSF->filter.tableIdExtMask = 0x0000;
935 
936  if (!err)
937  {
938  pSF->filter.priority = sfPriority;
939 
940  /* -- Make SI Query to get PID for section filter -- */
941  siQueryData.kind = SIQUERY_PID;
942  siQueryData.service_id = service_id;
943  siQueryData.data.association_tag = assocTag;
944 
945  err = siQueryStart( idp, &siQueryData, (void *) pSF, &siQueryResult );
946  switch (err)
947  {
948  case CLDSM_PENDING:
949  /* -- Store query ref with filter */
950  pSF->u.pPendingSiQueryRef = siQueryResult.data.queryHandle;
951  pSF->status = SFA_PENDING;
952  *pSectionFilter = pSF;
953  err = CLDSM_OK;
954  break;
955 
956  case CLDSM_OK:
957  /* -- Store PID in filter */
958  pSF->filter.PID = siQueryResult.data.PID;
959  err = DSC_SectionFilterCommit( idp, pSF );
960  if (!err)
961  {
962  *pSectionFilter = pSF;
963  break;
964  }
965 
966  default:
967  FreeSectionFilterBlock( idp, pSF );
968  }
969  }
970 
971  if (err)
972  {
973  /* -- NB. Cannot get here if add section filter successful so
974  -- no requirement to stop section filter */
975  }
976  else
977  {
978  }
979 
980 _return:
981  DEBUG_CHK( err == CLDSM_OK,
982  dsmDP1(("ERROR: sectionLargeDDBFilterStart %u\n", err)));
983 
984  return err;
985 }
986 
987 void largeDDBsectionFilterStop( P_DsmCoreInst idp)
988 {
989  P_SecFilterInfo pSF;
990 
991  P_SecFilterInfo *pSectionFilter = &accCarouselLoadingInfos.largeDDBFilter;
992 
993  dsmDP3(("largeDDBsectionFilterStop()\n"));
994  dsmAssert((idp != NULL));
995  dsmAssert((pSectionFilter != NULL));
996  dsmAssert((*pSectionFilter != NULL));
997 
998  pSF = *pSectionFilter;
999 
1000 
1001  /* -- NB. Make it safe in retail mode */
1002  if (pSF != NULL)
1003  {
1004  switch (pSF->status)
1005  {
1006  case SFA_PENDING:
1007  /*
1008  -- In this state, the section filter has not yet been
1009  -- added (committed) since it is waiting for an
1010  -- pending SI Query to complete, so abort the query.
1011  */
1012  dsmAssert((pSF->u.pPendingSiQueryRef != NULL));
1013  siQueryAbortPending( idp, &pSF->u.pPendingSiQueryRef );
1014 
1015  /* -- Clear Query ref in filter (finished with) */
1016  pSF->u.pPendingSiQueryRef = NULL;
1017  break;
1018 
1019 
1020  case SFA_COMMITTED:
1021  /* -- In this state, the section filter is actually started
1022  -- in the calling env. so delete it */
1023  idp->setup.delSectionFilterFunc( pSF->u.filterHandle, (H_DscSFRef)pSF,
1024  (P_SecFilter)pSF );
1025  break;
1026 
1027 
1028  case SFA_ABORTED:
1029  /* -- In this state, the section filter commit has failed so
1030  -- nothing specific to do (just allow filter to be freed) */
1031  break;
1032 
1033 
1034  default:
1035  /* -- 'Added' section filters should not be in any other state */
1036  dsmDP1(("ERROR: Illegal section filter status = %u\n",
1037  pSF->status));
1038  dsmAssert((0));
1039 
1040  /* -- Notify an internal error here since can't return one */
1041  if (idp->setup.errorFunc)
1042  {
1043  idp->setup.errorFunc( CLDSM_ERR_INTERNAL, NULL);
1044  }
1045  break;
1046  }
1047  FreeSectionFilterBlock( idp, pSF );
1048  *pSectionFilter = NULL;
1049  }
1050 
1051  dsmDP3(("exit largeDDBsectionFilterStop\n"));
1052 }
1053 
1054 #endif /* ACCELERATE_CAROUSEL_LOADING */
1055 
1056 
1057 /*----------------------------------------------------------------------------*/
General include file for clDsm library internal definitions.
Header to the loadMgr module.
Header to the sectionTimer module.
void DSC_ModuleDeleteDcTidyUp(P_DsmCoreInst idp, P_Module pModule)
Delete module and destroy parent DC if now empty.
Definition: module.c:388
void siQueryAbortPending(P_DsmCoreInst idp, P_SiQuery pSiQueryRef)
Aborts the specified SI Query before completion. Stops/destroys duplicate queries. For original queries or duplicate queries that have expired parents (and no further duplicates) calls stop SI Query callback on relevant query.
Definition: siQuery.c:350
Header to dsmStreamEvent module - functions for managing DSM streamEvent.
Header to the sectionFilter module.
E_DscError siQueryStart(P_DsmCoreInst idp, P_SIQueryRequest pQueryData, void *queryTarget, P_SIQueryResult pResult)
Starts an SI Query. First tests if we have already made this query and the results are stored or stil...
Definition: siQuery.c:76
Header to siQuery module - functions for managing SI queries.
Header to the 'module' module - Functions/methods for creating/destroying and managing attributes of ...