DSMCC  17.9.0
 All Data Structures Files Functions Typedefs
sfm_filter.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 #include "sfm_main.h"
28 #include "sfm_cache.h"
29 #include "sfm_filter.h"
30 #include "cldsmcc.h"
31 
32 /*---- Constant definitions for this file-------------------------------------*/
33 
34 #define INVALID_NDX 0xFF // must be U8BIT max value
35 #define INVALID_TID 0xFF
36 #define EXACT_MATCH 16
37 #define NEAR_MATCH 15
38 #define PRIORITY_SHIFT 5
39 #define PRI_EXACT_MASK ((1 << PRIORITY_SHIFT) - 1)
40 
41 /* Number of entries in Hash Table - probably best to be prime number */
42 #define HASH_SIZE 17
43 #define TOTAL_DSM_LISTS (HASH_SIZE + 1)
44 
45 /*---- Local typedef structs for this file------------------------------------*/
46 
47 typedef struct s_BitCnt
48 {
49  U16BIT zeros;
50  U16BIT ones;
51 } S_BitCnt;
52 
53 typedef struct s_Table
54 {
55  U8BIT id;
56  U8BIT mask;
57 } S_Table;
58 
59 typedef struct s_DsmResource
60 {
61  H_DsmResource next;
62  S_TableExt tex;
63  U8BIT tid;
64  U8BIT priority;
65  U8BIT dmxPidIndex;
66  U8BIT accounted;
67  H_DscSFRef dsmSfRef;
68 } S_DsmResource;
69 
70 typedef struct s_PidTable
71 {
72  S_DsmResource *dsmlists[TOTAL_DSM_LISTS];
73  S_BitCnt bitcnt[16];
74  H_CacheTable cachetable;
75  U16BIT total;
76 } S_PidTable;
77 
78 typedef struct s_DmxSecFilter
79 {
80  SECFILT sfid;
81  S_TableExt tex;
82  S_Table tbl;
83 } S_DmxSecFilter;
84 
85 typedef struct s_DmxPidFilter
86 {
87  PIDFILT pfid;
88  U16BIT pid;
89  S_PidTable pt3B;
90  S_PidTable pt3C;
91  S_PidTable pt3D;
92  U16BIT numDsmRes;
93  U16BIT pidcounter;
94  S_DmxSecFilter *dmxSecArray;
95  BOOLEAN updating;
96 } S_DmxPidFilter;
97 
98 
99 /*---- Local (static) variable declarations for this file---------------------*/
100 /* (internal variables declared static to make them local) */
101 
102 /*---- LOCAL function definitions for this file ------------------------------*/
103 /* (internal functions declared static to make them local) */
104 
105 static U8BIT ExactPriority( U16BIT mask )
106 {
107  U8BIT exactness, cnt;
108  FUNCTION_START(ExactPriority)
109  switch (mask)
110  {
111  case 0xFFFF:
112  exactness = EXACT_MATCH;
113  break;
114  case 0xFFFE:
115  exactness = NEAR_MATCH;
116  break;
117 
118  default:
119  /* for exactness, count number of bits set in mask */
120  for (cnt = 16, exactness = 0; cnt--; mask >>= 1)
121  {
122  if (mask & 1)
123  {
124  exactness++;
125  }
126  }
127  }
128  FUNCTION_FINISH(ExactPriority)
129  return exactness;
130 }
131 
132 static U8BIT FindPidFilter( S_DmxPidFilter *pDmxPid, U8BIT max, U16BIT pid )
133 {
134  U8BIT cnt;
135  FUNCTION_START(FindPidFilter)
136  for (cnt = max; cnt--; )
137  {
138  if (pDmxPid[cnt].pid == pid)
139  {
140  break;
141  }
142  }
143  if (cnt == 0xFF) // i.e. INVALID_NDX
144  {
145  U16BIT least = 0xFFFF;
146  while (max--)
147  {
148  if (pDmxPid[max].pfid == INVALID_PIDFILT &&
149  pDmxPid[max].updating == FALSE &&
150  least >= pDmxPid[max].pidcounter)
151  {
152  least = pDmxPid[max].pidcounter;
153  cnt = max;
154  }
155  }
156  }
157  FUNCTION_FINISH(FindPidFilter)
158  return cnt;
159 }
160 
161 static S_DmxPidFilter* RetrievePidFilter( S_DmxPidFilter *pDmxPid, U8BIT cnt, PIDFILT pfid )
162 {
163  FUNCTION_START(RetrievePidFilter)
164  while (cnt--)
165  {
166  if (pDmxPid->pfid == pfid)
167  {
168  return pDmxPid;
169  }
170  pDmxPid++;
171  }
172  FUNCTION_FINISH(RetrievePidFilter)
173  return NULL;
174 }
175 
176 static void IncBitcnt( S_BitCnt *bitcnt, S_TableExt tex )
177 {
178  U16BIT mbit;
179  for (mbit = 0x8000; mbit; mbit >>= 1, bitcnt++)
180  {
181  if (tex.mask & mbit)
182  {
183  if (tex.id & mbit)
184  {
185  bitcnt->ones++;
186  }
187  else
188  {
189  bitcnt->zeros++;
190  }
191  }
192  else
193  {
194  bitcnt->zeros++;
195  bitcnt->ones++;
196  }
197  }
198 }
199 
200 static void DecBitcnt( S_BitCnt *bitcnt, S_TableExt tex )
201 {
202  U16BIT mbit;
203  for (mbit = 0x8000; mbit; mbit >>= 1, bitcnt++)
204  {
205  if (tex.mask & mbit)
206  {
207  if (tex.id & mbit)
208  {
209  bitcnt->ones--;
210  }
211  else
212  {
213  bitcnt->zeros--;
214  }
215  }
216  else
217  {
218  bitcnt->zeros--;
219  bitcnt->ones--;
220  }
221  }
222 }
223 
224 static S_TableExt TableExtension( S_BitCnt *bitcnt )
225 {
226  U16BIT mbit;
227  S_TableExt tex = { 0, 0 };
228  for (mbit = 0x8000; mbit; mbit >>= 1, bitcnt++)
229  {
230  if (!bitcnt->ones)
231  {
232  tex.mask |= mbit;
233  }
234  else if (!bitcnt->zeros)
235  {
236  tex.mask |= mbit;
237  tex.id |= mbit;
238  }
239  }
240  return tex;
241 }
242 
243 static S_TableExt FindTexIdOne( S_DsmResource **ppDsmRes, U16BIT mbit )
244 {
245  S_DsmResource *pDsmRes;
246  S_TableExt tex = {0, 0};
247  U16BIT hcnt;
248  for (hcnt = TOTAL_DSM_LISTS; hcnt != 0; hcnt--, ppDsmRes++)
249  {
250  for (pDsmRes = *ppDsmRes; pDsmRes != NULL; pDsmRes = pDsmRes->next)
251  {
252  if (!pDsmRes->accounted && (pDsmRes->tex.id & mbit) == mbit)
253  {
254  pDsmRes->accounted = 1;
255  return pDsmRes->tex;
256  }
257  }
258  }
259  ASSERT(0)
260  return tex;
261 }
262 
263 static S_TableExt FindTexIdZero( S_DsmResource **ppDsmRes, U16BIT mbit )
264 {
265  S_DsmResource *pDsmRes;
266  S_TableExt tex = {0, 0};
267  U16BIT hcnt;
268  for (hcnt = TOTAL_DSM_LISTS; hcnt != 0; hcnt--, ppDsmRes++)
269  {
270  for (pDsmRes = *ppDsmRes; pDsmRes != NULL; pDsmRes = pDsmRes->next)
271  {
272  if (!pDsmRes->accounted && (pDsmRes->tex.id & mbit) == 0)
273  {
274  pDsmRes->accounted = 1;
275  return pDsmRes->tex;
276  }
277  }
278  }
279  ASSERT(0)
280  return tex;
281 }
282 
283 void ClearTexIdAccounts( S_DsmResource **ppDsmRes )
284 {
285  S_DsmResource *pDsmRes;
286  U16BIT hcnt;
287  FUNCTION_START(ClearTexIdAccounts)
288  for (hcnt = TOTAL_DSM_LISTS; hcnt != 0; hcnt--, ppDsmRes++)
289  {
290  for (pDsmRes = *ppDsmRes; pDsmRes != NULL; pDsmRes = pDsmRes->next)
291  {
292  pDsmRes->accounted = 0;
293  }
294  }
295  FUNCTION_FINISH(ClearTexIdAccounts)
296 }
297 
298 static S_DmxSecFilter* SetupSecArray( S_PidTable *pPidTbl, S_DmxSecFilter *pTmpSec, U16BIT scnt, S_Table tbl )
299 {
300  S_TableExt tex;
301  S_BitCnt bitscopy[16];
302  S_BitCnt *bitcnt;
303  U16BIT mbit;
304  ASSERT(scnt != 0)
305  if (scnt == 1)
306  {
307  pTmpSec->tex = TableExtension( pPidTbl->bitcnt );
308  }
309  else
310  {
311  memcpy(bitscopy, pPidTbl->bitcnt, 16 * sizeof(S_BitCnt));
312 
313  for (mbit = 0x8000, bitcnt = bitscopy; mbit; mbit >>= 1, bitcnt++)
314  {
315  if (bitcnt->ones == 1)
316  {
317  tex = FindTexIdOne( pPidTbl->dsmlists, mbit );
318  DecBitcnt( bitscopy, tex );
319  pTmpSec->tbl = tbl;
320  pTmpSec->tex = tex;
321  scnt--;
322  pTmpSec++;
323  if (scnt == 1)
324  break;
325  mbit = 0x8000;
326  bitcnt = bitscopy;
327  }
328  else if (bitcnt->zeros == 1)
329  {
330  tex = FindTexIdZero( pPidTbl->dsmlists, mbit );
331  DecBitcnt( bitscopy, tex );
332  pTmpSec->tbl = tbl;
333  pTmpSec->tex = tex;
334  scnt--;
335  pTmpSec++;
336  if (scnt == 1)
337  break;
338  mbit = 0x8000;
339  bitcnt = bitscopy;
340  }
341  }
342  ClearTexIdAccounts( pPidTbl->dsmlists );
343  pTmpSec->tex = TableExtension( bitscopy );
344  }
345  pTmpSec->tbl = tbl;
346  pTmpSec++;
347  return pTmpSec;
348 }
349 
357 static void SetupSecFilterArray( S_DmxPidFilter *pDmxPid, S_DmxSecFilter *pTmpSec, U16BIT scTotal )
358 {
359  S_Table tbl = { 0xFF, 0xFF };
360  U16BIT numb, numc, numd, totalbc;
361  FUNCTION_START(SetupSecFilterArray)
362 
363  numb = pDmxPid->pt3B.total;
364  numc = pDmxPid->pt3C.total;
365  numd = pDmxPid->pt3D.total;
366  switch (scTotal)
367  {
368  case 1:
369  if (numb)
370  {
371  if (numc)
372  {
373  pTmpSec->tex.id = 0;
374  pTmpSec->tex.mask = 0;
375  pTmpSec->tbl.id = 0x38;
376  pTmpSec->tbl.mask = 0xF8;
377  }
378  else if (numd)
379  {
380  pTmpSec->tex.id = 0;
381  pTmpSec->tex.mask = 0;
382  pTmpSec->tbl.id = 0x39;
383  pTmpSec->tbl.mask = 0xF9;
384  }
385  else
386  {
387  pTmpSec->tex = TableExtension(pDmxPid->pt3B.bitcnt);
388  pTmpSec->tbl.id = 0x3B;
389  pTmpSec->tbl.mask = 0xFF;
390  }
391  }
392  else if (numc)
393  {
394  if (numd)
395  {
396  pTmpSec->tex.id = 0;
397  pTmpSec->tex.mask = 0;
398  pTmpSec->tbl.id = 0x3C;
399  pTmpSec->tbl.mask = 0xFC;
400  }
401  else
402  {
403  pTmpSec->tex = TableExtension(pDmxPid->pt3C.bitcnt);
404  pTmpSec->tbl.id = 0x3C;
405  }
406  }
407  else if (numd)
408  {
409  pTmpSec->tex = TableExtension(pDmxPid->pt3D.bitcnt);
410  pTmpSec->tbl.id = 0x3D;
411  pTmpSec->tbl.mask = 0xFF;
412  }
413  else
414  {
415  pTmpSec->tbl.id = INVALID_TID;
416  }
417  break;
418 
419  case 2:
420  if (numb)
421  {
422  pTmpSec->tex = TableExtension(pDmxPid->pt3B.bitcnt);
423  pTmpSec->tbl.id = 0x3B;
424  pTmpSec->tbl.mask = 0xFF;
425  pTmpSec++;
426  }
427  if (numc)
428  {
429  if (numd)
430  {
431  pTmpSec->tex.id = 0;
432  pTmpSec->tex.mask = 0;
433  pTmpSec->tbl.id = 0x3C;
434  pTmpSec->tbl.mask = 0xFC;
435  }
436  else
437  {
438  pTmpSec->tex = TableExtension(pDmxPid->pt3C.bitcnt);
439  pTmpSec->tbl.id = 0x3C;
440  pTmpSec->tbl.mask = 0xFF;
441  }
442  }
443  else if (numd)
444  {
445  pTmpSec->tex = TableExtension(pDmxPid->pt3D.bitcnt);
446  pTmpSec->tbl.id = 0x3D;
447  pTmpSec->tbl.mask = 0xFF;
448  }
449  else
450  {
451  pTmpSec->tbl.id = INVALID_TID;
452  }
453  break;
454 
455  default:
456  if (numd)
457  {
458  pTmpSec->tex = TableExtension( pDmxPid->pt3D.bitcnt );
459  tbl.id = 0x3D;
460  pTmpSec->tbl = tbl;
461  pTmpSec++;
462  scTotal--;
463  }
464  totalbc = numb + numc;
465  if (totalbc > scTotal)
466  {
467  if (numb == 0)
468  {
469  numc = scTotal;
470  }
471  else if (numc == 0)
472  {
473  numb = scTotal;
474  }
475  else
476  {
477  numb = 1 + ((numb * scTotal) / totalbc);
478  if (numb == totalbc)
479  numb = totalbc - 1;
480  }
481  numc = scTotal - numb;
482  scTotal = 0;
483  }
484  else
485  {
486  scTotal -= numb + numc;
487  }
488  if (numb)
489  {
490  tbl.id = 0x3B;
491  pTmpSec = SetupSecArray( &pDmxPid->pt3B, pTmpSec, numb, tbl );
492  }
493  if (numc)
494  {
495  tbl.id = 0x3C;
496  pTmpSec = SetupSecArray( &pDmxPid->pt3C, pTmpSec, numc, tbl );
497  }
498  while (scTotal--)
499  {
500  pTmpSec->tbl.id = INVALID_TID;
501  pTmpSec++;
502  }
503  }
504 }
505 
513 static BOOLEAN CompareSecFilters( S_DmxSecFilter *pActive, S_DmxSecFilter *pTmpSec, U16BIT secCount )
514 {
515  BOOLEAN result = FALSE;
516  FUNCTION_START(CompareSecFilters)
517  for (; secCount--; pActive++, pTmpSec++)
518  {
519  if (pTmpSec->tbl.id != pActive->tbl.id)
520  {
521  result = TRUE;
522  break;
523  }
524  if (pTmpSec->tbl.id == INVALID_TID)
525  {
526  break;
527  }
528  if (pTmpSec->tex.mask != pActive->tex.mask ||
529  pTmpSec->tex.id != pActive->tex.id ||
530  pTmpSec->tbl.mask != pActive->tbl.mask)
531  {
532  result = TRUE;
533  break;
534  }
535  }
536  FUNCTION_FINISH(CompareSecFilters)
537  return result;
538 }
539 
549 static void RemoveOldActives( H_SfmInstance sfm, S_DmxSecFilter *pDmxSec, U16BIT secCount )
550 {
551  S_DmxSecFilter *pTmpSec;
552  U16BIT stmp, scnt;
553  FUNCTION_START(RemoveOldActives)
554  for (scnt = secCount; scnt--; pDmxSec++)
555  {
556  if (pDmxSec->sfid != INVALID_SECFILT)
557  {
558  pTmpSec = sfm->dmxSecArray;
559  for (stmp = secCount; stmp != 0; stmp--, pTmpSec++)
560  {
561  if (pTmpSec->tex.mask == pDmxSec->tex.mask &&
562  pTmpSec->tex.id == pDmxSec->tex.id &&
563  pTmpSec->tbl.mask == pDmxSec->tbl.mask &&
564  pTmpSec->tbl.id == pDmxSec->tbl.id)
565  {
566  pTmpSec->sfid = pDmxSec->sfid;
567  break;
568  }
569  }
570  if (stmp == 0)
571  {
572  DBGLOG(DF_FILTER, "%p", pDmxSec)
573  DBGLOG((DF_FILTER|DF_HWSF), "tid=0x%x tidMask=0x%x tide=0x%x tideMask=0x%x",
574  pDmxSec->tbl.id, pDmxSec->tbl.mask, pDmxSec->tex.id, pDmxSec->tex.mask)
575  STB_DMXReleaseSectFilter( sfm->demux, pDmxSec->sfid );
576  pDmxSec->sfid = INVALID_SECFILT;
577  pDmxSec->tbl.id = INVALID_TID;
578  }
579  }
580  }
581  FUNCTION_FINISH(RemoveOldActives)
582 }
583 
596 static SECFILT SectionFilterAdd( H_SfmInstance sfm, PIDFILT pfid, U8BIT tid,
597  U8BIT tidMask, U16BIT tidExt, U16BIT tidExtMask )
598 {
599  U8BIT match[SECFILT_MASK_SIZE];
600  U8BIT mmask[SECFILT_MASK_SIZE];
601  SECFILT sfid;
602  U16BIT i;
603  sfid = STB_DMXGrabSectFilter(sfm->demux, pfid);
604  if (sfid == INVALID_SECFILT)
605  {
606  ERRLOG("Failed to grab Section Filter on PFID 0x%x", pfid)
607  }
608  else
609  {
610  match[0] = tid;
611  match[1] = (U8BIT)(tidExt >> 8);
612  match[2] = (U8BIT)(tidExt & 0x00ff);
613  mmask[0] = tidMask;
614  mmask[1] = (U8BIT)(tidExtMask >> 8);
615  mmask[2] = (U8BIT)(tidExtMask & 0x00ff);
616  for (i = 3; i != SECFILT_MASK_SIZE; i++)
617  {
618  match[i] = 0;
619  mmask[i] = 0;
620  }
621  DBGLOG((DF_FILTER|DF_HWSF), "pf=%x tid=%x tidm=%x xid=%x xidm=%x", pfid, tid, tidMask, tidExt, tidExtMask)
622  STB_DMXSetupSectFilter(sfm->demux, sfid, match, mmask, 0, TRUE /*crc checked*/);
623  }
624  return sfid;
625 }
626 
635 static void RequestNewActives( H_SfmInstance sfm, PIDFILT pfid,
636  S_DmxSecFilter *pDmxSec, U16BIT secCount )
637 {
638  FUNCTION_START(RequestNewActives)
639  for (; secCount--; pDmxSec++)
640  {
641  if (pDmxSec->sfid == INVALID_SECFILT && pDmxSec->tbl.id != INVALID_TID)
642  {
643  DBGLOG(DF_FILTER, "%p", pDmxSec)
644  pDmxSec->sfid =
645  SectionFilterAdd( sfm, pfid, pDmxSec->tbl.id,
646  pDmxSec->tbl.mask, pDmxSec->tex.id, pDmxSec->tex.mask );
647  DBGLOG(DF_FILTER, "tid=0x%x tidMask=0x%x tide=0x%x tideMask=0x%x", pDmxSec->tbl.id,
648  pDmxSec->tbl.mask, pDmxSec->tex.id, pDmxSec->tex.mask)
649  }
650  }
651  FUNCTION_FINISH(RequestNewActives)
652 }
653 
662 static void RemoveAllActives( H_SfmInstance sfm, S_DmxSecFilter *pDmxSec, U16BIT secCount )
663 {
664  FUNCTION_START(RemoveAllActives)
665  for (; secCount--; pDmxSec++)
666  {
667  if (pDmxSec->sfid != INVALID_SECFILT)
668  {
669  DBGLOG(DF_FILTER, "%p", pDmxSec)
670  DBGLOG(DF_FILTER, "tid=0x%x tidMask=0x%x tide=0x%x tideMask=0x%x",
671  pDmxSec->tbl.id, pDmxSec->tbl.mask, pDmxSec->tex.id, pDmxSec->tex.mask)
672  STB_DMXReleaseSectFilter( sfm->demux, pDmxSec->sfid );
673  pDmxSec->sfid = INVALID_SECFILT;
674  pDmxSec->tbl.id = INVALID_TID;
675  }
676  }
677  FUNCTION_FINISH(RemoveAllActives)
678 }
679 
687 static void CopyAndClearTempArray( S_DmxSecFilter *pDmxSec, S_DmxSecFilter *pTmpSec, U16BIT scnt )
688 {
689  FUNCTION_START(CopyAndClearTempArray)
690  for (; scnt--; pTmpSec++, pDmxSec++)
691  {
692  *pDmxSec = *pTmpSec;
693  pTmpSec->sfid = INVALID_SECFILT;
694  pTmpSec->tbl.id = INVALID_TID;
695  }
696  FUNCTION_FINISH(CopyAndClearTempArray)
697 }
698 
707 static void UpdateDemux( H_SfmInstance sfm, S_DmxPidFilter *pDmxPid, U16BIT secCount )
708 {
709  FUNCTION_START(UpdateDemux)
710  SetupSecFilterArray( pDmxPid, sfm->dmxSecArray, secCount );
711  if (CompareSecFilters(pDmxPid->dmxSecArray, sfm->dmxSecArray, secCount))
712  {
713  STB_DMXStopPIDFilter( sfm->demux, pDmxPid->pfid );
714  RemoveOldActives( sfm, pDmxPid->dmxSecArray, secCount );
715  RequestNewActives( sfm, pDmxPid->pfid, sfm->dmxSecArray, secCount );
716  CopyAndClearTempArray( pDmxPid->dmxSecArray, sfm->dmxSecArray, secCount );
717  STB_DMXStartPIDFilter( sfm->demux, pDmxPid->pfid );
718  }
719  FUNCTION_FINISH(UpdateDemux)
720 }
721 
729 static void InsertDsmResource( H_SfmInstance sfm, S_PidTable *pPidTbl, S_DsmResource *pDsmRes )
730 {
731  H_DsmResource *phDsmRes;
732  FUNCTION_START(InsertDsmResource)
733 
734  /* remove from free list */
735  ASSERT( sfm->freeList == pDsmRes )
736  sfm->freeList = pDsmRes->next;
737 
738  if (pDsmRes->tex.mask == 0xFFFF)
739  {
740  phDsmRes = pPidTbl->dsmlists + (pDsmRes->tex.id % HASH_SIZE);
741  }
742  else
743  {
744  phDsmRes = pPidTbl->dsmlists + HASH_SIZE;
745  /* ensure tableIdExt has bits zero where mask is zero */
746  //pDsmRes->tex.id &= pDsmRes->tex.mask;
747  }
748  pPidTbl->total++;
749  IncBitcnt( pPidTbl->bitcnt, pDsmRes->tex );
750  sfm->setup.mutexLock( sfm->setup.sfmMutex );
751  while (*phDsmRes && (*phDsmRes)->priority > pDsmRes->priority)
752  {
753  phDsmRes = &(*phDsmRes)->next;
754  }
755  /* insert before existing one of same priority */
756  pDsmRes->next = *phDsmRes;
757  *phDsmRes = pDsmRes;
758  sfm->setup.mutexUnlock( sfm->setup.sfmMutex );
759  if (pPidTbl->cachetable != NULL)
760  {
761  U32BIT dsmref;
762  dsmref = pDsmRes - sfm->dmxResFirst;
763  switch (pDsmRes->priority >> PRIORITY_SHIFT)
764  {
765  case SF_PRIORITY_LOW:
766  SFMCacheSearch( sfm, pPidTbl->cachetable, pDsmRes->tex, (U16BIT)dsmref, SFM_UPDATE_LOW );
767  break;
768  case SF_PRIORITY_HIGH:
769  SFMCacheSearch( sfm, pPidTbl->cachetable, pDsmRes->tex, (U16BIT)dsmref, SFM_UPDATE_HIGH );
770  break;
771  default:
772  case SF_PRIORITY_DIRECT:
773  /*must not take from cache*/
774  break;
775  }
776  }
777  FUNCTION_FINISH(InsertDsmResource)
778 }
779 
787 static void RemoveDsmResource( H_SfmInstance sfm, S_PidTable *pPidTbl,
788  S_DsmResource *pDsmRes )
789 {
790  H_DsmResource *phDsmRes;
791  FUNCTION_START(RemoveDsmResource)
792  ASSERT( pDsmRes != NULL )
793  if (pDsmRes->tex.mask == 0xFFFF)
794  {
795  phDsmRes = pPidTbl->dsmlists + (pDsmRes->tex.id % HASH_SIZE);
796  }
797  else
798  {
799  phDsmRes = pPidTbl->dsmlists + HASH_SIZE;
800  }
801  pPidTbl->total--;
802  DecBitcnt( pPidTbl->bitcnt, pDsmRes->tex );
803  sfm->setup.mutexLock( sfm->setup.sfmMutex );
804  while (*phDsmRes)
805  {
806  if (*phDsmRes == pDsmRes)
807  {
808  *phDsmRes = pDsmRes->next;
809  break;
810  }
811  phDsmRes = &((*phDsmRes)->next);
812  }
813  sfm->setup.mutexUnlock( sfm->setup.sfmMutex );
814  /* return to free list */
815  pDsmRes->next = sfm->freeList;
816  pDsmRes->tid = INVALID_TID;
817  sfm->freeList = pDsmRes;
818  FUNCTION_FINISH(RemoveDsmResource)
819 }
820 
821 /*---- GLOBAL function definitions for this file -----------------------------*/
822 
823 
830 {
831  S_DmxPidFilter *pDmxPid;
832  S_DmxSecFilter *pDmxSec;
833  S_DsmResource *pDsmRes;
834  U16BIT dmxCount, dsmCount, secCount, cnt;
835  U32BIT size;
836  BOOLEAN result;
837 
838  FUNCTION_START(SFMFilterCreateResources)
839  dmxCount = sfm->setup.maxPidFilters;
840  dsmCount = sfm->setup.maxAvailableSectionFilters;
841  secCount = sfm->setup.maxSecFiltersPerPid;
842  ASSERT( dmxCount != 0 && secCount != 0 );
843  size = secCount * sizeof(S_DmxSecFilter);
844  size *= dmxCount + 1;
845  size += dmxCount * sizeof(S_DmxPidFilter);
846  size += (dsmCount * sizeof(S_DsmResource));
847  pDmxPid = sfm->setup.memAlloc( size );
848  if (pDmxPid == NULL)
849  {
850  result = FALSE;
851  }
852  else
853  {
854  result = TRUE;
855  memset(pDmxPid, 0, size);
856  sfm->dmxPidArray = pDmxPid;
857  pDmxSec = (S_DmxSecFilter *)(pDmxPid + dmxCount);
858  /* Initialise global demux section filter array -
859  * for temporary use in UpdateDemux */
860  sfm->dmxSecArray = pDmxSec;
861  for (cnt = secCount; cnt--; pDmxSec++)
862  {
863  pDmxSec->sfid = INVALID_SECFILT;
864  pDmxSec->tbl.id = INVALID_TID;
865  }
866  /* Initialise Demux PID filter array */
867  while (dmxCount--)
868  {
869  pDmxPid->pid = INVALID_PID;
870  pDmxPid->pfid = INVALID_PIDFILT;
871  pDmxPid->dmxSecArray = pDmxSec;
872  for (cnt = secCount; cnt--; pDmxSec++)
873  {
874  pDmxSec->sfid = INVALID_SECFILT;
875  pDmxSec->tbl.id = INVALID_TID;
876  }
877  pDmxPid++;
878  }
879  /* Initialise Dsmcc filter resource list */
880  pDsmRes = (S_DsmResource *)pDmxSec;
881  sfm->dmxResFirst = pDsmRes;
882  sfm->freeList = pDsmRes;
883  while (--dsmCount)
884  {
885  pDsmRes->next = pDsmRes + 1;
886  pDsmRes->tid = INVALID_TID;
887  pDsmRes->dmxPidIndex = INVALID_NDX;
888  pDsmRes++;
889  }
890  pDsmRes->tid = INVALID_TID;
891  pDsmRes->dmxPidIndex = INVALID_NDX;
892  pDsmRes->next = NULL;
893  sfm->dmxResLast = pDsmRes;
894  }
895  FUNCTION_FINISH(SFMFilterCreateResources)
896  return result;
897 }
898 
905 {
906  S_DmxPidFilter *pDmxPid;
907  H_SfmCache cache;
908  U16BIT dmxCount;
909 
910  FUNCTION_START(SFMFilterInitCaching)
911  pDmxPid = sfm->dmxPidArray;
912  cache = sfm->cache;
913  if (cache != NULL)
914  {
915  for (dmxCount = sfm->setup.maxPidFilters; dmxCount--; pDmxPid++)
916  {
917  pDmxPid->pt3B.cachetable = SFMCacheGetTable( cache );
918  pDmxPid->pt3C.cachetable = SFMCacheGetTable( cache );
919  }
920  }
921  FUNCTION_FINISH(SFMFilterInitCaching)
922 }
923 
930 {
931  S_DmxPidFilter *pDmxPid;
932  U16BIT total;
933 
934  FUNCTION_START(SFMDestroyDemuxResources)
935  pDmxPid = sfm->dmxPidArray;
936  for (total = sfm->setup.maxPidFilters; total--; pDmxPid++)
937  {
938  if (pDmxPid->pfid != INVALID_PIDFILT)
939  {
940  STB_DMXStopPIDFilter( sfm->demux, pDmxPid->pfid );
941  STB_DMXReleasePIDFilter( sfm->demux, pDmxPid->pfid );
942  }
943  }
944  sfm->setup.memFree( sfm->dmxPidArray );
945  FUNCTION_FINISH(SFMDestroyDemuxResources)
946 }
947 
960  H_DscSFRef dsmSfRef )
961 {
962  S_DmxPidFilter *pDmxPid;
963  S_DsmResource *pDsmRes;
964  U8BIT dmxPidIndex;
965 
966  FUNCTION_START(SFM_DsmccFilterAdd)
967  ASSERT( pFilter->priority < 8 )
968  pDsmRes = sfm->freeList;
969  if (pDsmRes == NULL)
970  {
971  ERRLOG("Eek! Dsmcc filter Resources Gone!")
972  }
973  else
974  {
975  dmxPidIndex = FindPidFilter( sfm->dmxPidArray, sfm->setup.maxPidFilters, pFilter->pid );
976  if (dmxPidIndex == INVALID_NDX)
977  {
978  ERRLOG("Eek! Demux Pid Filters Gone!")
979  pDsmRes = NULL;
980  }
981  else /* Todo?: assert that DSM-CC is not adding duplicate section filter */
982  {
983  pDmxPid = sfm->dmxPidArray + dmxPidIndex;
984  pDmxPid->pid = pFilter->pid;
985  pDsmRes->dsmSfRef = dsmSfRef;
986  pDsmRes->priority = (pFilter->priority << PRIORITY_SHIFT) |
987  ExactPriority( pFilter->tableIdExtMask );
988  pDsmRes->dmxPidIndex = dmxPidIndex;
989  pDsmRes->tid = pFilter->tableId;
990  pDsmRes->tex.id = pFilter->tableIdExt;
991  pDsmRes->tex.mask = pFilter->tableIdExtMask;
992 
993  DBGLOG(DF_FILTER, "ndx=%d PID=0x%x PFID=0x%x tid=0x%x tide=0x%x",
994  dmxPidIndex, pFilter->pid, pDmxPid->pfid, pDsmRes->tid, pDsmRes->tex.id)
995 
996  switch (pDsmRes->tid)
997  {
998  case 0x3B: InsertDsmResource( sfm, &pDmxPid->pt3B, pDsmRes ); break;
999  case 0x3C: InsertDsmResource( sfm, &pDmxPid->pt3C, pDsmRes ); break;
1000  case 0x3D: InsertDsmResource( sfm, &pDmxPid->pt3D, pDsmRes ); break;
1001  default:
1002  ASSERT(0);
1003  }
1004  pDmxPid->numDsmRes++;
1005  if (!pDmxPid->updating)
1006  {
1007  pDmxPid->updating = TRUE;
1008  sfm->setup.updateFilter(sfm, pDmxPid);
1009  }
1010  }
1011  }
1012  FUNCTION_FINISH(SFM_DsmccFilterAdd)
1013  return pDsmRes;
1014 }
1015 
1026 void SFM_DsmccFilterDelete( H_SfmInstance sfm, void *filterHandle,
1027  H_DscSFRef dsmSfRef )
1028 {
1029  S_DsmResource *pDsmRes;
1030  S_DmxPidFilter *pDmxPid;
1031  FUNCTION_START(SFM_DsmccFilterDelete)
1032  pDsmRes = (S_DsmResource *)filterHandle;
1033  ASSERT( pDsmRes->dmxPidIndex != INVALID_NDX )
1034  ASSERT( pDsmRes->dsmSfRef == dsmSfRef )
1035  if (pDsmRes->dmxPidIndex != INVALID_NDX &&
1036  pDsmRes->dsmSfRef == dsmSfRef)
1037  {
1038  pDmxPid = sfm->dmxPidArray + pDsmRes->dmxPidIndex;
1039  ASSERT( pDmxPid->numDsmRes != 0 )
1040  if (pDmxPid->numDsmRes == 0)
1041  {
1042  ERRLOG("Eek! already have zero Dsmcc filter resources allocated!")
1043  }
1044  else
1045  {
1046  DBGLOG(DF_FILTER, "num=%d PID=0x%x PFID=0x%x tid=0x%x tide=0x%x",
1047  pDmxPid->numDsmRes, pDmxPid->pid, pDmxPid->pfid, pDsmRes->tid, pDsmRes->tex.id)
1048 
1049  ASSERT( pDmxPid->pid != INVALID_PID )
1050  switch (pDsmRes->tid)
1051  {
1052  case 0x3B: RemoveDsmResource( sfm, &pDmxPid->pt3B, pDsmRes ); break;
1053  case 0x3C: RemoveDsmResource( sfm, &pDmxPid->pt3C, pDsmRes ); break;
1054  case 0x3D: RemoveDsmResource( sfm, &pDmxPid->pt3D, pDsmRes ); break;
1055  default:
1056  ASSERT(0);
1057  }
1058  pDmxPid->numDsmRes--;
1059  if (!pDmxPid->updating)
1060  {
1061  pDmxPid->updating = TRUE;
1062  sfm->setup.updateFilter(sfm, pDmxPid);
1063  }
1064  }
1065  }
1066  FUNCTION_FINISH(SFM_DsmccFilterDelete)
1067 }
1068 
1075 void SFM_FilterUpdate( H_SfmInstance sfm, H_DmxPidFilter pPF )
1076 {
1077  FUNCTION_START(SFM_FilterUpdate)
1078  ASSERT( pPF->updating != FALSE )
1079  pPF->updating = FALSE;
1080  if (pPF->pfid != INVALID_PIDFILT)
1081  {
1082  if (pPF->numDsmRes != 0)
1083  {
1084  UpdateDemux( sfm, pPF, sfm->setup.maxSecFiltersPerPid );
1085  }
1086  else
1087  {
1088  STB_DMXStopPIDFilter( sfm->demux, pPF->pfid );
1089  RemoveAllActives( sfm, pPF->dmxSecArray, sfm->setup.maxSecFiltersPerPid );
1090 
1091  DBGLOG((DF_FILTER|DF_HWSF), "DELETE PID=0x%x PFID=0x%x", pPF->pid, pPF->pfid)
1092  STB_DMXReleasePIDFilter( sfm->demux, pPF->pfid );
1093  pPF->pfid = INVALID_PIDFILT;
1094  pPF->pidcounter = sfm->pidcounter;
1095  sfm->pidcounter++;
1096  }
1097  }
1098  else if (pPF->numDsmRes != 0)
1099  {
1100  pPF->pfid = STB_DMXGrabPIDFilter( sfm->demux, pPF->pid, sfm->setup.hwFilterCallback );
1101  if (pPF->pfid == INVALID_PIDFILT)
1102  {
1103  ERRLOG("Demux PID filter failed to be added! (0x%x)", pPF->pid)
1104  }
1105  else
1106  {
1107  DBGLOG((DF_FILTER|DF_HWSF), "ADDDED PID=0x%x PFID=0x%x", pPF->pid, pPF->pfid)
1108  SetupSecFilterArray( pPF, pPF->dmxSecArray, sfm->setup.maxSecFiltersPerPid );
1109  RequestNewActives( sfm, pPF->pfid, pPF->dmxSecArray, sfm->setup.maxSecFiltersPerPid );
1110  STB_DMXStartPIDFilter( sfm->demux, pPF->pfid );
1111  }
1112  }
1113  FUNCTION_FINISH(SFM_FilterUpdate)
1114 }
1115 
1128 void SFM_DsmccFilterPriorityChange( H_SfmInstance sfm, void *filterHandle,
1129  H_DscSFRef dsmSfRef,
1130  E_SFPriority priority )
1131 {
1132  S_DsmResource *pDsmRes;
1133  FUNCTION_START(SFM_DsmccFilterPriorityChange)
1134  pDsmRes = (S_DsmResource *)filterHandle;
1135  ASSERT( pDsmRes->dmxPidIndex != INVALID_NDX )
1136  ASSERT( pDsmRes->dsmSfRef == dsmSfRef )
1137  if (pDsmRes->dmxPidIndex != INVALID_NDX &&
1138  pDsmRes->dsmSfRef == dsmSfRef)
1139  {
1140  /* Only need to lock mutex when actually changing list data */
1141  sfm->setup.mutexLock( sfm->setup.sfmMutex );
1142  pDsmRes->priority = (pDsmRes->priority & PRI_EXACT_MASK) |
1143  priority << PRIORITY_SHIFT;
1144  sfm->setup.mutexUnlock( sfm->setup.sfmMutex );
1145  }
1146 
1147  FUNCTION_FINISH(SFM_DsmccFilterPriorityChange)
1148 }
1149 
1165 E_SFM_STATUS SFMFilterRequiresSection( H_SfmInstance sfm, PIDFILT pfid,
1166  U16BIT teid, U8BIT tid, U8BIT vers,
1167  void **phBuffer )
1168 {
1169  S_DmxPidFilter *pDmxPid;
1170  S_DsmResource *pDsmRes;
1171  S_PidTable *pPidTbl;
1172  U16BIT hash;
1173  U8BIT priority = 0xFF;
1174  E_SFM_STATUS result;
1175  FUNCTION_START(SFM_FilterRequiresSection)
1176  DBGLOG(DF_HWSF, "pfid=%x tid=%x xid=%x", pfid, tid, teid)
1177  pDmxPid = RetrievePidFilter( sfm->dmxPidArray, sfm->setup.maxPidFilters, pfid );
1178  if (pDmxPid == NULL)
1179  {
1180  /* This section is for another SFM instance, and not this one */
1181  /* DBGLOG(DF_MAIN,"Unrecognised filter ID 0x%x", pfid) */
1182  *phBuffer = NULL;
1183  result = SFM_IGNORE;
1184  }
1185  else
1186  {
1187  switch (tid)
1188  {
1189  case 0x3B: pPidTbl = &pDmxPid->pt3B; break;
1190  case 0x3C: pPidTbl = &pDmxPid->pt3C; break;
1191  case 0x3D: pPidTbl = &pDmxPid->pt3D; break;
1192  default:
1193  ERRLOG("Unsupported table id 0x%x", tid) *
1194  phBuffer = NULL;
1195  return SFM_ERROR;
1196  }
1197  hash = teid % HASH_SIZE;
1198  sfm->setup.mutexLock( sfm->setup.sfmMutex );
1199  /* check exact match list */
1200  pDsmRes = pPidTbl->dsmlists[hash];
1201  while (pDsmRes != NULL)
1202  {
1203  if (pDsmRes->tex.id == teid)
1204  {
1205  priority = pDsmRes->priority;
1206  break;
1207  }
1208  pDsmRes = pDsmRes->next;
1209  }
1210  if (pDsmRes == NULL)
1211  {
1212  /* Try wild card list */
1213  pDsmRes = pPidTbl->dsmlists[HASH_SIZE];
1214  while (pDsmRes != NULL)
1215  {
1216  if (pDsmRes->tex.id == (teid & pDsmRes->tex.mask))
1217  {
1218  priority = pDsmRes->priority;
1219  break;
1220  }
1221  pDsmRes = pDsmRes->next;
1222  }
1223  }
1224  sfm->setup.mutexUnlock( sfm->setup.sfmMutex );
1225  if (pDsmRes != NULL)
1226  {
1227  switch (priority >> PRIORITY_SHIFT)
1228  {
1229  case SF_PRIORITY_LOW:
1230  case SF_PRIORITY_CLEAR:
1231  *phBuffer = pDsmRes;
1232  result = SFM_UPDATE_LOW;
1233  DBGLOG(DF_MAIN, "pfid=%x tid=%x xid=%x LOW priority", pfid, tid, teid)
1234  break;
1235  case SF_PRIORITY_HIGH:
1236  case SF_PRIORITY_DIRECT:
1237  *phBuffer = pDsmRes;
1238  result = SFM_UPDATE_HIGH;
1239  DBGLOG(DF_MAIN, "pfid=%x tid=%x xid=%x HIGH priority", pfid, tid, teid)
1240  break;
1241  default:
1242  *phBuffer = NULL;
1243  ERRLOG("Bad priority value 0x%x", priority)
1244  result = SFM_ERROR;
1245  }
1246  }
1247  else if (pPidTbl->cachetable != NULL)
1248  {
1249  *phBuffer = SFMCacheRetrieveFilter( sfm, pPidTbl->cachetable, teid, vers );
1250  result = SFM_UPDATE_CACHE;
1251  }
1252  else
1253  {
1254  DBGLOG(DF_FILTER, "Drop sec Tid=%x TEid=0x%x ver=%d", tid, teid, vers);
1255  *phBuffer = NULL;
1256  result = SFM_IGNORE;
1257  }
1258  }
1259  FUNCTION_FINISH(SFM_FilterRequiresSection)
1260  return result;
1261 }
1262 
1274 void SFMFilterProcessSection( H_SfmInstance sfm, U8BIT *pSection, H_DsmResource pDsmRes )
1275 {
1276  FUNCTION_START(SFM_FilterProcessSection)
1277  if (pDsmRes->tid == *pSection)
1278  {
1279  U16BIT txid = (U16BIT)((pSection[3] << 8) | pSection[4]);
1280  if (pDsmRes->tex.id == txid ||
1281  pDsmRes->tex.id == (txid & pDsmRes->tex.mask))
1282  {
1283  CDSM_SysProcessPrivateSection( sfm->dsmcc, pSection, pDsmRes->dsmSfRef );
1284  }
1285  }
1286  FUNCTION_FINISH(SFM_FilterProcessSection)
1287 }
1288 
1289 BOOLEAN SFMFilterValidHandle( H_SfmInstance sfm, void *hBuffer )
1290 {
1291  H_DsmResource pDsmRes;
1292  BOOLEAN result;
1293  pDsmRes = hBuffer;
1294  if (pDsmRes >= sfm->dmxResFirst && pDsmRes <= sfm->dmxResLast)
1295  {
1296  result = TRUE;
1297  }
1298  else
1299  {
1300  result = FALSE;
1301  }
1302  return result;
1303 }
1304 
1305 H_DsmResource SFMFilterDsmResource( H_SfmInstance sfm, U16BIT dsmref )
1306 {
1307  return sfm->dmxResFirst + dsmref;
1308 }
1309 
PIDFILT STB_DMXGrabPIDFilter(DMXREF dmx, U16BIT pid, F_FILTER_CALLBACK func)
Get a New PID Filter & Setup Associated Buffer and Callback Function Address.
void STB_DMXSetupSectFilter(DMXREF dmx, SECFILT sfid, U8BIT *match_ptr, U8BIT *mask_ptr, U8BIT not_equal_byte_index, BOOLEAN crc)
Configures a match and mask for a specified section filter.
H_CacheFilter SFMCacheRetrieveFilter(H_SfmInstance sfm, H_CacheTable ctable, U16BIT teid, U8BIT vers)
Search cache for section data.
Definition: sfm_cache.c:581
void SFM_DsmccFilterPriorityChange(H_SfmInstance sfm, void *filterHandle, H_DscSFRef dsmSfRef, E_SFPriority priority)
Change DSM-CC section filter priority Called by DSM-CC component, and given in clDsmSysCreate setup...
Definition: sfm_filter.c:1128
void SFM_DsmccFilterDelete(H_SfmInstance sfm, void *filterHandle, H_DscSFRef dsmSfRef)
Delete DSM-CC section filter. Called by DSM-CC component, and given in clDsmSysCreate setup...
Definition: sfm_filter.c:1026
void SFMFilterProcessSection(H_SfmInstance sfm, U8BIT *pSection, H_DsmResource pDsmRes)
Get DSM-CC filter request and pass section buffer to DSM-CC with it's filter handle This should only ...
Definition: sfm_filter.c:1274
void STB_DMXStopPIDFilter(DMXREF dmx, PIDFILT pfid)
Stop Specified PID Filter Collecting Data.
BOOLEAN SFMFilterCreateResources(H_SfmInstance sfm)
Create Filter resources for Section Filter Manager instance.
Definition: sfm_filter.c:829
Section Filter Manasger (SFM): cache definitions.
Section Filter Manager (SFM): filters.
Section Filter Manager (SFM): main definitions.
E_SFM_STATUS SFMFilterRequiresSection(H_SfmInstance sfm, PIDFILT pfid, U16BIT teid, U8BIT tid, U8BIT vers, void **phBuffer)
This function performs minimal checking of section header data to find out whether SFM requires this ...
Definition: sfm_filter.c:1165
void SFM_FilterUpdate(H_SfmInstance sfm, H_DmxPidFilter pPF)
Update SFM PID filter to configure HW for latest requirements.
Definition: sfm_filter.c:1075
Main API to DSM-CC core layer (provided functions and required callbacks).
void STB_DMXReleasePIDFilter(DMXREF dmx, PIDFILT pfid)
Releases a previously allocated PID filter.
void SFMCacheSearch(H_SfmInstance sfm, H_CacheTable ctable, S_TableExt tex, U16BIT dsmref, E_SFM_STATUS status)
Search cache for section data.
Definition: sfm_cache.c:822
SECFILT STB_DMXGrabSectFilter(DMXREF dmx, PIDFILT pfid)
Allocated a new section filter on the specified PID filter.
void STB_DMXStartPIDFilter(DMXREF dmx, PIDFILT pfid)
Start Specified PID Filter Collecting Data.
void * SFM_DsmccFilterAdd(H_SfmInstance sfm, P_SecFilter pFilter, H_DscSFRef dsmSfRef)
Add DSM-CC section filter. Called by DSM-CC component. Note for multi-tasking: this function uses mut...
Definition: sfm_filter.c:959
void STB_DMXReleaseSectFilter(DMXREF dmx, SECFILT sfid)
Releases a previously allocated section filter.
void SFMFilterDestroyResources(H_SfmInstance sfm)
Destroy Filter resources for Section Filter Manager instance.
Definition: sfm_filter.c:929
void SFMFilterInitCaching(H_SfmInstance sfm)
Initialise caching references.
Definition: sfm_filter.c:904