DSMCC  17.9.0
 All Data Structures Files Functions Typedefs
dsm_si.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright © 2014 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  *
4  * This file is part of a DTVKit Software Component
5  * You are permitted to copy, modify or distribute this file subject to the terms
6  * of the DTVKit 1.0 Licence which can be found in licence.txt or at www.dtvkit.org
7  *
8  * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
9  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
10  * OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
11  *
12  * If you or your organisation is not a member of DTVKit then you have access
13  * to this source code outside of the terms of the licence agreement
14  * and you are expected to delete this and any associated files immediately.
15  * Further information on DTVKit, membership and terms can be found at www.dtvkit.org
16  *******************************************************************************/
23 /*---includes for this file--------------------------------------------------*/
24 #include <string.h>
25 
26 #include "stb_os.h"
27 #include "stb_filter.h"
28 #include "dsm_control.h"
29 #include "dm_debug.h"
30 #include "dsm_si.h"
31 
32 /*---constant definitions for this file--------------------------------------*/
33 
34 #define PAT_PID 0
35 #define PAT_TID 0
36 #define PMT_TID 2
37 #define TIMEOUT_PAT 700
38 #define TIMEOUT_PMT 1000
39 #define TIMEOUT_DEFAULT 0x7FFF
40 
41 #define DSI_RQST_MAGIC 0xBA000000
42 
43 #ifndef NDEBUG
44 #define dsmctrl dsi->ctrl
45 #endif
46 
47 /*---local typedef structs for this file-------------------------------------*/
48 
49 typedef struct s_tablerequest
50 {
51  struct s_tablerequest *next;
52  U16BIT pid;
53  U16BIT xid;
54  U8BIT tid;
55  U8BIT version;
56  U32BIT timeout;
57 } S_TableRequest;
58 
59 typedef struct s_DsiInstance
60 {
61  F_MemAlloc memAlloc;
62  F_MemFree memFree;
63  H_DsmControl ctrl;
64  F_FILTER_CALLBACK cbfunc;
65  void *mutex;
66  S_TableRequest *tables;
67  PIDFILT pflt;
68  SECFILT sflt;
69  U32BIT rid;
70  DMXREF dmxref;
71  U8BIT version;
72 } S_DsiInstance;
73 
74 /*---local (static) variable declarations for this file----------------------*/
75 /* (internal variables declared static to make them local) */
76 
77 /*------------------- Local function definitions ----------------------------*/
78 
79 U32BIT TimeoutPeriod(U8BIT tid)
80 {
81  switch (tid)
82  {
83  case PAT_TID:
84  return TIMEOUT_PAT;
85 
86  case PMT_TID:
87  return TIMEOUT_PMT;
88 
89  default:
90  return TIMEOUT_DEFAULT;
91  }
92 }
93 
106 static SECFILT SectionFilterAdd( DMXREF dmx, PIDFILT pfid, U8BIT tid,
107  U8BIT tidMask, U16BIT tidExt, U16BIT tidExtMask )
108 {
109  U8BIT match[SECFILT_MASK_SIZE];
110  U8BIT mmask[SECFILT_MASK_SIZE];
111  SECFILT sfid;
112  U16BIT i;
113  sfid = STB_DMXGrabSectFilter(dmx, pfid);
114  if (sfid != INVALID_SECFILT)
115  {
116  match[0] = tid;
117  match[1] = (U8BIT)(tidExt >> 8);
118  match[2] = (U8BIT)(tidExt & 0x00ff);
119  mmask[0] = tidMask;
120  mmask[1] = (U8BIT)(tidExtMask >> 8);
121  mmask[2] = (U8BIT)(tidExtMask & 0x00ff);
122  for (i = 3; i != SECFILT_MASK_SIZE; i++)
123  {
124  match[i] = 0;
125  mmask[i] = 0;
126  }
127  STB_DMXSetupSectFilter(dmx, sfid, match, mmask, 0, TRUE /*crc checked*/);
128  }
129  return sfid;
130 }
131 
132 static void ReleaseSi(H_DsiInstance dsi)
133 {
134  DBGPRINT(DM_SI, "pflt=%x", dsi->pflt)
135  STB_DMXStopPIDFilter(dsi->dmxref, dsi->pflt);
136  STB_DMXReleaseSectFilter(dsi->dmxref, dsi->sflt);
137  dsi->sflt = INVALID_SECFILT;
138  STB_DMXReleasePIDFilter(dsi->dmxref, dsi->pflt);
139  dsi->pflt = INVALID_PIDFILT;
140 }
141 
142 static BOOLEAN RequestSi(H_DsiInstance dsi, U16BIT pid, U8BIT tid, U16BIT xid, U16BIT xmsk)
143 {
144  DMXREF dmxref;
145  BOOLEAN ok;
146 
147  ASSERT(dsi->pflt == INVALID_PIDFILT);
148  ASSERT(dsi->sflt == INVALID_SECFILT);
149 
150  dmxref = dsi->dmxref;
151  dsi->pflt = STB_DMXGrabPIDFilter(dmxref, pid, dsi->cbfunc);
152  if (dsi->pflt == INVALID_PIDFILT)
153  {
154  ERRPRINT("Grab PID filter fail")
155  ok = FALSE;
156  }
157  else
158  {
159  dsi->sflt = SectionFilterAdd( dmxref, dsi->pflt, tid, 0xFF, xid, xmsk);
160  if (dsi->sflt == INVALID_SECFILT)
161  {
162  ERRPRINT("Grab SEC filter fail")
163  STB_DMXReleasePIDFilter(dmxref, dsi->pflt);
164  dsi->pflt = INVALID_PIDFILT;
165  ok = FALSE;
166  }
167  else
168  {
169  STB_DMXStartPIDFilter(dmxref, dsi->pflt);
170  DBGPRINT(DM_SI, "tid=%d xid=%d pflt=%x", tid, xid, dsi->pflt)
171  ok = TRUE;
172  }
173  }
174  return ok;
175 }
176 
177 S_TableRequest* FindTableRqst(H_DsiInstance dsi, U16BIT xid, U8BIT tid)
178 {
179  S_TableRequest *rqst;
180  rqst = dsi->tables;
181  while (rqst != NULL && (rqst->xid != xid || rqst->tid != tid))
182  {
183  rqst = rqst->next;
184  }
185  return rqst;
186 }
187 
188 /*------------------- Global function definitions ---------------------------*/
189 
190 
197 H_DsiInstance DSI_CreateInstance(H_DsmControl ctrl, F_FILTER_CALLBACK cbfunc, S_DsmccConfig *config)
198 {
199  H_DsiInstance dsi;
200  dsi = config->memAlloc(sizeof(S_DsiInstance));
201  if (dsi != NULL)
202  {
203  dsi->mutex = STB_OSCreateMutex();
204  if (dsi->mutex == NULL)
205  {
206  ERRPRINT("mutex create fail")
207  config->memFree(dsi);
208  dsi = NULL;
209  }
210  else
211  {
212  dsi->memAlloc = config->memAlloc;
213  dsi->memFree = config->memFree;
214  dsi->cbfunc = cbfunc;
215  dsi->tables = NULL;
216  dsi->pflt = INVALID_PIDFILT;
217  dsi->sflt = INVALID_SECFILT;
218  dsi->ctrl = ctrl;
219  }
220  }
221  return dsi;
222 }
223 
229 void DSI_DestroyInstance( H_DsiInstance dsi )
230 {
231  STB_OSDeleteMutex(dsi->mutex);
232  dsi->memFree( dsi );
233 }
234 
242 BOOLEAN DSI_Start( H_DsiInstance dsi, U16BIT transId, DMXREF dmxref )
243 {
244  dsi->dmxref = dmxref;
245  return DSI_RequestTable( dsi, PAT_PID, transId, PAT_TID ) ? TRUE : FALSE;
246 }
247 
253 void DSI_Stop( H_DsiInstance dsi )
254 {
255  S_TableRequest *rqst, *next;
256  if (dsi->pflt != INVALID_PIDFILT)
257  {
258  ReleaseSi(dsi);
259  dsi->rid = 0;
260  }
261  STB_OSMutexLock(dsi->mutex);
262  rqst = dsi->tables;
263  while (rqst != NULL)
264  {
265  next = rqst->next;
266  dsi->memFree(rqst);
267  rqst = next;
268  }
269  dsi->tables = NULL;
270  STB_OSMutexUnlock(dsi->mutex);
271 }
272 
284 U32BIT DSI_RequestTable( H_DsiInstance dsi, U16BIT pid, U16BIT xid, U8BIT tid )
285 {
286  S_TableRequest *rqst;
287  U32BIT result;
288 
289  STB_OSMutexLock(dsi->mutex);
290  rqst = FindTableRqst(dsi, xid, tid);
291  STB_OSMutexUnlock(dsi->mutex);
292  if (rqst != NULL)
293  {
294  rqst->version = 0xFF;
295  rqst->timeout = STB_OSGetClockMilliseconds();
296  result = DSI_RQST_MAGIC | (((U32BIT)tid) << 16) | xid;
297  }
298  else
299  {
300  rqst = dsi->memAlloc(sizeof(S_TableRequest));
301  if (rqst == NULL)
302  {
303  ERRPRINT("memory fail for serviceId=%d", xid);
304  result = 0;
305  }
306  else
307  {
308  rqst->xid = xid;
309  rqst->pid = pid;
310  rqst->tid = tid;
311  rqst->version = 0xFF;
312  rqst->timeout = STB_OSGetClockMilliseconds();
313  STB_OSMutexLock(dsi->mutex);
314  rqst->next = dsi->tables;
315  dsi->tables = rqst;
316  STB_OSMutexUnlock(dsi->mutex);
317  result = DSI_RQST_MAGIC | (((U32BIT)tid) << 16) | xid;
318  }
319  }
320  if (result && dsi->pflt == INVALID_PIDFILT)
321  {
322  if ( RequestSi(dsi, pid, tid, xid, 0xFFFF) )
323  {
324  dsi->rid = result;
325  }
326  rqst->timeout += TimeoutPeriod(tid);
327  }
328  return result;
329 }
330 
337 void DSI_CancelTable( H_DsiInstance dsi, U32BIT rid )
338 {
339  S_TableRequest **pprqst, *rqst;
340  U16BIT xid;
341  U8BIT tid;
342  ASSERT((rid & 0xFF000000) == DSI_RQST_MAGIC);
343  if (rid == dsi->rid)
344  {
345  ASSERT(dsi->pflt != INVALID_PIDFILT);
346  ReleaseSi(dsi);
347  dsi->rid = 0;
348  }
349  tid = (rid >> 16) & 0xFF;
350  xid = rid & 0xFFFF;
351  STB_OSMutexLock(dsi->mutex);
352  pprqst = &(dsi->tables);
353  while (*pprqst != NULL)
354  {
355  rqst = *pprqst;
356  if (rqst->xid == xid && rqst->tid == tid)
357  {
358  *pprqst = rqst->next;
359  dsi->memFree(rqst);
360  break;
361  }
362  pprqst = &(rqst->next);
363  }
364  STB_OSMutexUnlock(dsi->mutex);
365 }
366 
373 U32BIT DSI_CheckRequests( H_DsiInstance dsi, U32BIT now )
374 {
375  U32BIT tdiff, least, tout;
376  S_TableRequest *rqst;
377  U16BIT pid, xid;
378  U8BIT tid;
379  DBGPRINT(DM_SI, "rid=%x pflt=%x", dsi->rid, dsi->pflt)
380  if (!dsi->rid && dsi->pflt != INVALID_PIDFILT)
381  {
382  ReleaseSi(dsi);
383  }
384  if (dsi->pflt == INVALID_PIDFILT)
385  {
386  STB_OSMutexLock(dsi->mutex);
387  rqst = dsi->tables;
388  while (rqst != NULL)
389  {
390  if (rqst->timeout <= now)
391  {
392  pid = rqst->pid;
393  xid = rqst->xid;
394  tid = rqst->tid;
395  break;
396  }
397  rqst = rqst->next;
398  }
399  STB_OSMutexUnlock(dsi->mutex);
400  if (rqst != NULL)
401  {
402  if (RequestSi(dsi, pid, tid, xid, 0xFFFF))
403  {
404  dsi->rid = DSI_RQST_MAGIC | (((U32BIT)tid) << 16) | xid;
405  rqst->timeout = now + TimeoutPeriod(tid);
406  }
407  }
408  }
409  least = TIMEOUT_DEFAULT;
410  STB_OSMutexLock(dsi->mutex);
411  rqst = dsi->tables;
412  while (rqst != NULL)
413  {
414  tdiff = rqst->timeout - now;
415  tout = TimeoutPeriod(rqst->tid);
416  if (least > tdiff)
417  {
418  least = tdiff;
419  }
420  else if (tdiff > tout)
421  {
422  /*time wrap*/
423  rqst->timeout = now + tout;
424  }
425  rqst = rqst->next;
426  }
427  STB_OSMutexUnlock(dsi->mutex);
428  return now + least;
429 }
430 
439 BOOLEAN DSI_RequireTable( H_DsiInstance dsi, U8BIT *hdr, U16BIT *pXid, U8BIT *pVer )
440 {
441  S_TableRequest *rqst;
442  BOOLEAN result;
443  U16BIT xid;
444  U8BIT tid;
445  U8BIT version;
446  tid = hdr[0];
447  version = (hdr[5] >> 1) & 0x1f;
448  xid = hdr[3] << 8 | hdr[4];
449 
450  STB_OSMutexLock(dsi->mutex);
451  rqst = FindTableRqst(dsi, xid, tid);
452  if (rqst != NULL && rqst->version != version)
453  {
454  DBGPRINT(DM_SI, "PMT xid=%d pflt=%x ver=%d", xid, dsi->pflt, version)
455  result = TRUE;
456  *pXid = xid;
457  *pVer = version;
458  rqst->version = version;
459  rqst->timeout = STB_OSGetClockMilliseconds() + TimeoutPeriod(tid);
460  }
461  else
462  {
463  result = FALSE;
464  }
465  dsi->rid = 0;
466  STB_OSMutexUnlock(dsi->mutex);
467 
468  return result;
469 }
470 
U32BIT STB_OSGetClockMilliseconds(void)
Get Current Computer Clock Time.
PIDFILT STB_DMXGrabPIDFilter(DMXREF dmx, U16BIT pid, F_FILTER_CALLBACK func)
Get a New PID Filter & Setup Associated Buffer and Callback Function Address.
DSM-CC API functions to control DSM-CC instance.
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.
U32BIT DSI_RequestTable(H_DsiInstance dsi, U16BIT pid, U16BIT xid, U8BIT tid)
Request Table data. It supplies Table soon after the call to this function, and then, whenever the Table version changes. This state continues until DSI_CancelTable is called.
Definition: dsm_si.c:284
Internal header for DSM-CC si support.
void STB_OSDeleteMutex(void *mutex)
Delete a mutex.
void STB_DMXStopPIDFilter(DMXREF dmx, PIDFILT pfid)
Stop Specified PID Filter Collecting Data.
BOOLEAN DSI_RequireTable(H_DsiInstance dsi, U8BIT *hdr, U16BIT *pXid, U8BIT *pVer)
Check whether SI table section data is required.
Definition: dsm_si.c:439
void DSI_CancelTable(H_DsiInstance dsi, U32BIT rid)
Cancel request for table data made by DSI_RequestTable()
Definition: dsm_si.c:337
U32BIT DSI_CheckRequests(H_DsiInstance dsi, U32BIT now)
Check outstanding PMT (and PAT) requests to see whether any need to be refreshed. ...
Definition: dsm_si.c:373
void DSI_Stop(H_DsiInstance dsi)
Stop getting SI data from Demux.
Definition: dsm_si.c:253
void STB_OSMutexUnlock(void *mutex)
Unlock a mutex (a.k.a. 'leave', 'signal' or 'release')
void * STB_OSCreateMutex(void)
Create a mutex.
void STB_DMXReleasePIDFilter(DMXREF dmx, PIDFILT pfid)
Releases a previously allocated PID filter.
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 STB_DMXReleaseSectFilter(DMXREF dmx, SECFILT sfid)
Releases a previously allocated section filter.
void STB_OSMutexLock(void *mutex)
Lock a mutex (a.k.a. 'enter', 'wait' or 'get').
H_DsiInstance DSI_CreateInstance(H_DsmControl ctrl, F_FILTER_CALLBACK cbfunc, S_DsmccConfig *config)
Create instance of DSI.
Definition: dsm_si.c:197
Interface to Platform Section Filtering.
void DSI_DestroyInstance(H_DsiInstance dsi)
Destroy instance created by SIQ_CreateInstance.
Definition: dsm_si.c:229
BOOLEAN DSI_Start(H_DsiInstance dsi, U16BIT transId, DMXREF dmxref)
Start getting SI data from Demux.
Definition: dsm_si.c:242
Function prototypes for operating system.