DSMCC  17.9.0
 All Data Structures Files Functions Typedefs
streamEvent.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright © 2014 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  * Copyright © 2006 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  *******************************************************************************/
26 /*---includes for this file--------------------------------------------------*/
27 #include <string.h>
28 #include <stdio.h>
29 #include "clDsmSystem.h"
30 #include "moduleData.h"
31 #include "sectionFilter.h"
32 #include "dsmObject.h"
33 #include "module.h"
34 #include "objectCarousel.h"
35 #include "cacheMgr.h"
36 
37 /*------------------------------- Local Macros -------------------------------*/
38 
39 #define MAX_EVT_LISTENERS 8
40 #define LIFECYCLE_STR "Life cycle"
41 
42 /* Stream descriptors. Ref[1] - table 8-1 p.279 */
43 #define STREAM_NPT_REF_DESC 23
44 #define STREAM_NPT_END_DESC 24
45 #define STREAM_MODE_DESC 25
46 #define STREAM_EVENT_DESC 26
47 
48 #define GEN_E_HDL(sid, eid, lid) (((U32BIT)sid << 24) | ((U32BIT)eid << 8) | (lid))
49 #define EH_TO_LID(eh) (U8BIT)(((U32BIT)eh) & 0xFF)
50 #define EH_TO_SID(eh) (U8BIT)(((U32BIT)eh) >> 24)
51 #define EH_TO_EID(eh) (U16BIT)((((U32BIT)eh) >> 8) & 0xFFFF)
52 
53 #ifdef DISABLE_SUBSCRIBE_REFRESH
54  #define NewEventListen(i, e, ps, pe, h, u1, u2) NewEventListen(i, e, h, u1, u2)
55 #endif
56 
57 #define XML_DATA1a "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" \
58  "<dsmcc:dsmcc xmlns=\"urn:dvb:mis:dsmcc:2009\" xmlns:dsmcc=\"urn:dvb:mis:dsmcc:2009\">\n" \
59  "<dsmcc:dsmcc_object dsmcc:component_tag=\""
60 #define XML_DATA1b "\">\n"
61 #define XML_DATA2a "<dsmcc:stream_event dsmcc:stream_event_id=\""
62 #define XML_DATA2b "\" dsmcc:stream_event_name=\""
63 #define XML_DATA2c "\"/>\n"
64 #define XML_DATA3 "</dsmcc:dsmcc_object>\n" \
65  "</dsmcc:dsmcc>\n"
66 
67 /*------------------------------ Exported Data -----------------------------*/
68 
69 
70 /*--------------------------------Local Types --------------------------------*/
71 
72 typedef struct s_se_info
73 {
74  struct s_se_info *next;
75  S_ObjectKey objectKey;
76  P_Module pModule;
77  U16BIT eventAssocTag;
78  U8BIT uniqueId;
79  U8BIT lstnrCount;
80  U16BIT eventCount;
81  U16BIT namesLen;
82  U16BIT serviceId;
83  U16BIT xmlLen;
84  U8BIT *namesPtr;
85  U8BIT *xmlPtr;
86 } S_SE_INFO;
87 
88 typedef struct s_listener
89 {
90  struct s_listener *next;
91  H_DsmEvent eventHandle;
92  void *userData1;
93  void *userData2;
94  U8BIT uniqueId;
95 } S_LISTENER;
96 
97 typedef struct s_dsmevent
98 {
99  P_SecFilterInfo pFilter;
100  U16BIT id;
101  U8BIT version;
102  U8BIT nlen;
103  U8BIT *name;
104  S_LISTENER *pListener;
105 #ifdef SUPPORT_SCHEDULED_EVENTS
106  U64BIT eventNpt;
107 #endif
108 } S_Event;
109 
110 
111 /*------------------------------- Local Statics ------------------------------*/
112 
113 static U8BIT unique_stream_ids = 0;
114 static U8BIT unique_listen_ids = 0;
115 
116 /*------------------- local prototypes/forward declarations ------------------*/
117 
118 static void ReleaseStreamInfo( P_DsmCoreInst idp, S_SE_INFO *dsi );
119 static E_DscError RetrieveStreamInfo( P_DsmCoreInst idp,
120  /*I*/ H_DsmObject streamObject,
121  /*O*/ S_SE_INFO **ppStreamInfo );
122 
123 /*-------------------------- Functions ---------------------------------------*/
124 
125 
126 S_SE_INFO* FindEventInfo(P_DsmCoreInst idp, H_DsmEvent eventHandle)
127 {
128  S_SE_INFO *pStreamInfo;
129  U8BIT strmId;
130  if (!eventHandle)
131  {
132  pStreamInfo = NULL;
133  }
134  else
135  {
136  strmId = EH_TO_SID(eventHandle);
137  pStreamInfo = idp->hSubscribedEventList;
138  while (pStreamInfo != NULL)
139  {
140  if (pStreamInfo->uniqueId == strmId)
141  {
142  break;
143  }
144  pStreamInfo = pStreamInfo->next;
145  }
146  }
147  return pStreamInfo;
148 }
149 
150 S_SE_INFO* FindStreamInfo(P_DsmCoreInst idp, H_DsmObject streamObject)
151 {
152  S_SE_INFO *pStreamInfo;
153  pStreamInfo = idp->hSubscribedEventList;
154  while (pStreamInfo != NULL)
155  {
156  if (pStreamInfo->pModule == streamObject->pModule &&
157  !memcmp(&pStreamInfo->objectKey, &streamObject->objectInfo.objectKey, sizeof(S_ObjectKey)))
158  {
159  break;
160  }
161  pStreamInfo = pStreamInfo->next;
162  }
163  return pStreamInfo;
164 }
165 
166 #ifndef DISABLE_SUBSCRIBE_REFRESH
167 static
168 S_Event* FindMatchingEventId( S_SE_INFO *pStreamInfo, U16BIT id )
169 {
170  S_Event *pEvent;
171  U16BIT evntNdx, evntMax;
172  if (pStreamInfo != NULL)
173  {
174  pEvent = (S_Event *)(pStreamInfo + 1);
175  evntMax = pStreamInfo->eventCount;
176  for (evntNdx = 0; evntNdx != evntMax; evntNdx++)
177  {
178  if (pEvent->id == id)
179  {
180  /*match*/
181  return pEvent;
182  }
183  pEvent++;
184  }
185  }
186  return NULL;
187 }
188 #endif
189 
190 static E_DscError UnsubscribeEvent( P_DsmCoreInst idp, S_Event *pEvent, H_DsmEvent eventHandle )
191 {
192  E_DscError err;
193  S_LISTENER **ppL, *pL;
194  U8BIT lstnId = EH_TO_LID(eventHandle);
195  ppL = &(pEvent->pListener);
196  err = CLDSM_ERR_INVALID_STREAM_EVENT_HANDLE;
197  while (*ppL != NULL)
198  {
199  pL = *ppL;
200 
201  if (pL->uniqueId == lstnId)
202  {
203  *ppL = pL->next;
204  DSC_CmMemRelease( idp, pL );
205  err = CLDSM_OK;
206  break;
207  }
208  ppL = &((*ppL)->next);
209  }
210  if (pEvent->pListener == NULL && pEvent->pFilter != NULL)
211  {
212  DBGLOG((DD_SE | DD_SF), "pFilter=%p", pEvent->pFilter)
213  DSC_SectionFilterStop( idp, (void *)&pEvent->pFilter );
214  pEvent->version = 0xff;
215  }
216  return err;
217 }
218 
219 static E_DscError NewEventListen( P_DsmCoreInst idp, S_Event *pEvent,
220  S_SE_INFO *prevSEInfo, H_DsmEvent prevEventHandle, U32BIT hdl_id, void *userData1, void *userData2 )
221 {
222  E_DscError err;
223  S_LISTENER *pL;
224 #ifndef DISABLE_SUBSCRIBE_REFRESH
225  S_Event *pPrevEvt;
226  pPrevEvt = FindMatchingEventId( prevSEInfo, pEvent->id );
227  if (pPrevEvt != NULL)
228  {
229  dsmDP2(("Previously subsribed event, id %d vers %d <- %d", pEvent->id, pEvent->version, pPrevEvt->version));
230  pEvent->version = pPrevEvt->version;
231  }
232 #endif
233  pL = pEvent->pListener;
234  while (pL != NULL)
235  {
236  DBGLOG(DD_SE, "e Lsr=%p", pL)
237  if (pL->userData1 == userData1 && pL->userData2 == userData2)
238  {
239  err = CLDSM_ERR_STREAM_EVENTS_STILL_SUBSCRIBED;
240  break;
241  }
242  pL = pL->next;
243  }
244  if (pL == NULL)
245  {
246  pL = (S_LISTENER *)DSC_CmMemGet( idp, sizeof(S_LISTENER) );
247  if (!pL)
248  {
249  err = CLDSM_ERR_MEM_HEAP_FULL;
250  }
251  else
252  {
253  err = CLDSM_OK;
254  DBGLOG(DD_SE, "e Lsr=%p", pL)
255  pL->userData1 = userData1;
256  pL->userData2 = userData2;
257  pL->uniqueId = unique_listen_ids;
258  pL->eventHandle = (H_DsmEvent)hdl_id; /* save handle for callback */
259  pL->next = pEvent->pListener;
260  pEvent->pListener = pL;
261  }
262  }
263  return err;
264 }
265 
266 static E_DscError StartSectionFilter( P_DsmCoreInst idp, S_SE_INFO *pStreamInfo, P_Event pEvent )
267 {
268  S_SfTarget target;
269  if (pEvent->pFilter == NULL)
270  {
271  DBGLOG((DD_SE | DD_SF), "serv_id=0x%x eid=%x", pStreamInfo->serviceId,pEvent->id)
272  /* Request section filter */
273  target.kind = SFK_STREAM_DESCR;
274  target.id = pEvent->id;
275  target.serviceId = pStreamInfo->serviceId;
276  target.associationTag = pStreamInfo->eventAssocTag;
277  target.u.pEvent = pEvent;
278  return DSC_SectionFilterStart( idp, &target, SF_PRIORITY_HIGH, &pEvent->pFilter );
279  }
280  return CLDSM_OK;
281 }
282 
330  /*I*/ H_DsmCoreInst dsmccInstance,
331  /*I*/ H_DsmObject streamObject,
332  /*I*/ U8BIT *eventName,
333  /*I*/ void *userData1,
334  /*I*/ void *userData2,
335  /*O*/ H_DsmEvent *pEventHandle )
336 {
337  P_DsmCoreInst idp = (P_DsmCoreInst) dsmccInstance;
338  E_DscError err;
339  S_SE_INFO *pStreamInfo;
340 #ifndef DISABLE_SUBSCRIBE_REFRESH
341  S_SE_INFO *prevStrmInfo;
342 #endif
343  S_Event *pEvent;
344  U32BIT ui32, usid;
345  U16BIT evntNdx, evntMax;
346 
347  DBGLOG(DD_SE, "( 0x%x, %s, 0x%x, 0x%x, 0x%x )",
348  streamObject, eventName, userData1, userData2, pEventHandle)
349 
350  if (idp->setup.notifyStreamEventFunc == NULL)
351  {
352  return CLDSM_ERR_NO_STREAM_EVENT_NOTIFY_CALLBACK;
353  }
354 
355  err = RetrieveStreamInfo( idp, streamObject, &pStreamInfo );
356  if (CLDSM_OK == err)
357  {
358  pEvent = (S_Event *)(pStreamInfo + 1);
359  evntMax = pStreamInfo->eventCount;
360  pStreamInfo->lstnrCount++;
361  usid = pStreamInfo->uniqueId;
362 
363  #ifndef DISABLE_SUBSCRIBE_REFRESH
364  /* See if pEventHandle is already referencing a valid StreamInfo */
365  prevStrmInfo = FindEventInfo(idp, *pEventHandle);
366  #endif
367  unique_listen_ids++;
368 
369  if (eventName == NULL)
370  {
371  ui32 = 0;
372  }
373  else
374  {
375  ui32 = strlen((char *)eventName);
376  }
377  /* initialise to invalid se name, so detect if don't find any matching */
378  err = CLDSM_ERR_INVALID_STREAM_EVENT_NAME;
379  if (ui32 == 0)
380  {
381  /* generated this event handle */
382  ui32 = GEN_E_HDL(usid, 0xFFFF, unique_listen_ids);
383 
384  /* all events for this stream */
385  for (evntNdx = 0; evntNdx != evntMax; evntNdx++)
386  {
387  if (pEvent->name != NULL)
388  {
389  err = NewEventListen( idp, pEvent, prevStrmInfo, *pEventHandle, ui32, userData1, userData2 );
390  if (err != CLDSM_OK)
391  {
392  break;
393  }
394  else
395  {
396  err = StartSectionFilter(idp, pStreamInfo, pEvent);
397  if (CLDSM_OK != err)
398  {
399  break;
400  }
401  }
402  }
403  pEvent++;
404  }
405  }
406  else
407  {
408  for (evntNdx = 0; evntNdx != evntMax; evntNdx++)
409  {
410  if (pEvent->name != NULL && pEvent->nlen == ui32 &&
411  memcmp(pEvent->name, eventName, ui32) == 0)
412  {
413  /* generated this event handle */
414  ui32 = GEN_E_HDL(usid, evntNdx, unique_listen_ids);
415 
416  /*match*/
417  err = NewEventListen( idp, pEvent, prevStrmInfo, *pEventHandle, ui32, userData1, userData2 );
418  if (err == CLDSM_OK)
419  {
420  err = StartSectionFilter(idp, pStreamInfo, pEvent);
421  }
422  break;
423  }
424  pEvent++;
425  }
426  }
427  #ifndef DISABLE_SUBSCRIBE_REFRESH
428  if (prevStrmInfo)
429  {
430  /* unsubscribe previous */
431  CDSM_StreamEventUnsubscribe( idp, *pEventHandle );
432  }
433  #endif
434  switch (err)
435  {
436  case CLDSM_OK:
437  case CLDSM_ERR_STREAM_EVENTS_STILL_SUBSCRIBED:
438  /* return new event handle to client */
439  *pEventHandle = (H_DsmEvent)ui32;
440  break;
441 
442  default:
443  if (EH_TO_EID(ui32) == 0xFFFF)
444  {
445  do
446  {
447  UnsubscribeEvent( idp, pEvent, (H_DsmEvent)ui32 );
448  pEvent--;
449  }
450  while (evntNdx--);
451  }
452  else
453  {
454  UnsubscribeEvent( idp, pEvent, (H_DsmEvent)ui32 );
455  }
456  /*fall tho*/
457  case CLDSM_ERR_INVALID_STREAM_EVENT_NAME: /*nothing to unsubscribe */
458  ReleaseStreamInfo( idp, pStreamInfo );
459  *pEventHandle = 0;
460  break;
461  }
462  }
463  return err;
464 }
465 
505  /*I*/ H_DsmCoreInst dsmccInstance,
506  /*I*/ U16BIT associationTag,
507  /*I*/ U16BIT eventId,
508  /*I*/ void *userData1,
509  /*I*/ void *userData2,
510  /*O*/ H_DsmEvent *pEventHandle )
511 {
512  P_DsmCoreInst idp = (P_DsmCoreInst) dsmccInstance;
513  E_DscError err;
514  S_SE_INFO *pStreamInfo;
515  S_Event *pEvent;
516  U32BIT hdl_id, size;
517 
518  DBGLOG(DD_SE, "( %u, %u, 0x%x, 0x%x, 0x%x )",
519  associationTag, eventId, userData1, userData2, pEventHandle)
520 
521  if (idp->setup.notifyStreamEventFunc == NULL)
522  {
523  return CLDSM_ERR_NO_STREAM_EVENT_NOTIFY_CALLBACK;
524  }
525  if (!idp->currentServiceSet || idp->dvbLocator.service_id == 0)
526  {
527  return CLDSM_ERR_NO_CURRENT_SERVICE_SET;
528  }
529  pStreamInfo = idp->hSubscribedEventList;
530  while (pStreamInfo != NULL)
531  {
532  DBGLOG(DD_SE, "pStreamInfo=%p", pStreamInfo)
533  if (pStreamInfo->eventAssocTag == associationTag)
534  {
535  pEvent = (S_Event *)(pStreamInfo + 1);
536  if (pEvent->id == eventId)
537  {
538  break;
539  }
540  }
541  pStreamInfo = pStreamInfo->next;
542  }
543 
544  if (pStreamInfo != NULL)
545  {
546  err = CLDSM_OK;
547  }
548  else
549  {
550  size = sizeof(S_SE_INFO) + sizeof(S_Event);
551  pStreamInfo = (S_SE_INFO *)DSC_CmMemGet( idp, size );
552  if (!pStreamInfo)
553  {
554  ERRPRINT("mem fail")
555  err = CLDSM_ERR_MEM_HEAP_FULL;
556  *pEventHandle = 0;
557  }
558  else
559  {
560  err = CLDSM_OK;
561  memset( pStreamInfo, 0, size );
562 
563  pEvent = (S_Event *)(pStreamInfo + 1);
564  pEvent->name = NULL;
565 
566  pEvent->id = eventId;
567  pEvent->version = 0xFF;
568 
569  DBGLOG(DD_SE, "pStreamInfo=%p", pStreamInfo)
570  pStreamInfo->eventAssocTag = associationTag;
571  pStreamInfo->uniqueId = ++unique_stream_ids;
572  pStreamInfo->eventCount = 1;
573  pStreamInfo->serviceId = idp->dvbLocator.service_id;
574 
575  pStreamInfo->next = idp->hSubscribedEventList;
576  idp->hSubscribedEventList = pStreamInfo;
577  }
578  }
579  if (!err)
580  {
581  #ifndef DISABLE_SUBSCRIBE_REFRESH
582  /* See if pEventHandle is already referencing a valid StreamInfo */
583  S_SE_INFO *prevStrmInfo = FindEventInfo(idp, *pEventHandle);
584  #endif
585  pStreamInfo->lstnrCount++;
586  hdl_id = pStreamInfo->uniqueId;
587  unique_listen_ids++;
588  /* generated this event handle */
589  hdl_id = GEN_E_HDL(hdl_id, 0, unique_listen_ids);
590  err = NewEventListen( idp, pEvent, prevStrmInfo, *pEventHandle, hdl_id, userData1, userData2 );
591  if (err == CLDSM_OK)
592  {
593  DBGLOG(DD_SE, "e ftr=%p, hdl_id=%lx", pEvent->pFilter, hdl_id)
594  err = StartSectionFilter(idp, pStreamInfo, pEvent);
595  DBGLOG(DD_SF, "err=%d pEvent->pFilter=%x", err, pEvent->pFilter)
596  }
597  #ifndef DISABLE_SUBSCRIBE_REFRESH
598  if (prevStrmInfo)
599  {
600  /* unsubscribe previous */
601  DBGLOG(DD_SE, "unsubscr %p", *pEventHandle)
602  CDSM_StreamEventUnsubscribe( idp, *pEventHandle );
603  }
604  #endif
605  switch (err)
606  {
607  case CLDSM_OK:
608  case CLDSM_ERR_STREAM_EVENTS_STILL_SUBSCRIBED:
609  /* return new event handle to client */
610  *pEventHandle = (H_DsmEvent)hdl_id;
611  break;
612 
613  default:
614  ERRPRINT("err=%d", err)
615  UnsubscribeEvent( idp, pEvent, (H_DsmEvent)hdl_id );
616  ReleaseStreamInfo( idp, pStreamInfo );
617  *pEventHandle = 0;
618  }
619  }
620  return err;
621 }
622 
639  /*I*/ H_DsmCoreInst idp,
640  /*I*/ H_DsmEvent eventHandle)
641 {
642  E_DscError err;
643  S_SE_INFO *pStreamInfo;
644  S_Event *pEvent;
645  U16BIT evtId;
646 
647  DBGLOG(DD_SE, " evHl=%p", eventHandle)
648 
649  evtId = EH_TO_EID(eventHandle);
650 
651  pStreamInfo = FindEventInfo(idp, eventHandle);
652  if (pStreamInfo == NULL)
653  {
654  err = CLDSM_ERR_INVALID_STREAM_EVENT_HANDLE;
655  }
656  else
657  {
658  pEvent = (S_Event *)(pStreamInfo + 1);
659  if (evtId == 0xFFFF)
660  {
661  /* listener interested in all events */
662  err = CLDSM_ERR_INVALID_STREAM_EVENT_HANDLE;
663  for (evtId = 0; evtId != pStreamInfo->eventCount; evtId++, pEvent++)
664  {
665  if (UnsubscribeEvent( idp, pEvent, eventHandle ) == CLDSM_OK)
666  {
667  err = CLDSM_OK;
668  }
669  }
670  }
671  else if (evtId <= pStreamInfo->eventCount)
672  {
673  pEvent += evtId;
674  err = UnsubscribeEvent( idp, pEvent, eventHandle );
675  }
676  else
677  {
678  err = CLDSM_ERR_INVALID_STREAM_EVENT_HANDLE;
679  }
680  if (err == CLDSM_OK)
681  {
682  ReleaseStreamInfo( idp, pStreamInfo );
683  }
684  }
685  return err;
686 }
687 
701  /*I*/ H_DsmCoreInst dsmccInstance,
702  /*I*/ H_DsmEvent eventHandle )
703 {
704  return CDSM_StreamEventUnsubscribe(dsmccInstance, eventHandle);
705 }
706 
707 #ifdef INC_STREAM_RESET
708 
714 E_DscError dsmStreamEventReset(
715  /*I*/ H_DsmCoreInst dsmccInstance,
716  /*I*/ void *streamObject )
717 {
718  E_DscError err;
719  S_SE_INFO *pStreamInfo;
720  S_Event *pEvent;
721  U16BIT evntNdx, evntMax;
722 
723  dsmDP2(("( 0x%x )", streamObject));
724 
725  pStreamInfo = FindStreamInfo(dsmccInstance, streamObject);
726  if (pStreamInfo != NULL)
727  {
728  dsmDP1((" no stream object "));
729  err = CLDSM_ERR_OBJECT_NOT_LOADED;
730  }
731  else
732  {
733  pEvent = (S_Event *)(pStreamInfo + 1);
734  evntMax = pStreamInfo->eventCount;
735  for (evntNdx = 0; evntNdx != evntMax; evntNdx++)
736  {
737  pEvent->version = 0xff;
738  pEvent++;
739  }
740  err = CLDSM_OK;
741  }
742 }
743 
744 #endif /*INC_STREAM_RESET*/
745 
746 E_DscError DSC_StrmEventUpdate( P_DsmCoreInst idp, U8BIT *pStreamDescrSection,
747  P_Event pEvent, U32BIT targetId )
748 {
749  E_DscError err = CLDSM_OK;
750  S_LISTENER *pL;
751 #if DSM_DATA_CHECK_LEVEL >= 2
752  U16BIT ui16;
753 #endif
754  U16BIT eventID, msg_len;
755  U8BIT ui8, version, dtag, dlen, edata_len, *edata_ptr;
756 #ifdef SUPPORT_SCHEDULED_EVENTS
757  U32BIT ui32;
758 #endif
759 
760  dsmDP3(("DSC_StrmEventUpdate()\n"));
761  dsmAssert((idp != NULL));
762  dsmAssert((pStreamDescrSection != NULL));
763 
764  /* -- table_id = 0x3D */
765  READ_UINT8( pStreamDescrSection, ui8);
766  if (ui8 != 0x3D)
767  {
768  dsmDP1(("DATA ERROR: streamEvent table_id = %x", ui8));
769  return CLDSM_ERR_INVALID_INSTANCE;
770  }
771  /* Minimum section length is 9 bytes (with message length of zero) - ie 12 byte header
772  * less three bytes for table id and length fields.
773  * Note: maximum DSMCC message length is 4084 bytes, following the last-section-number
774  field and up to the CRC_32/checksum - Ref[1] - section 9.2.2.1, pg 287
775  */
776  READ_UINT16( pStreamDescrSection, msg_len );
777  msg_len &= 0x0fff; /* got section length */
778  if (msg_len < 9)
779  {
780  dsmDP1(("DATA ERROR: section length=0x%x", msg_len));
781  return CLDSM_ERR_INVALID_INSTANCE;
782  }
783  msg_len -= 9; /* remove remaining header bytes */
784 
785  if (pEvent == NULL || pEvent->id != targetId)
786  {
787  dsmDP1(("no target for id=%x", targetId));
788  return CLDSM_ERR_INVALID_STREAM_EVENT_HANDLE;
789  }
790 
791  /*---------------------------------------------------------------------------*/
792  /* -- table_id_extension = eventID !!! */
793 
794  /* description in DTG 4.0 17.2.4.4 p. 17-15 */
795  /* [15] [14] [13...8] [7...0] */
796  /* 0 0 eventId[13..8] eventId[7..0] ===> section carries a SINGLE "do-it-now" EVENT */
797 
798  /* *** "do-it-now" EVENTs matches with eventID in the range 0x0001 .. 0x3FFF */
799  /*---------------------------------------------------------------------------*/
800 
801  /* read eventID */
802  READ_UINT16( pStreamDescrSection, eventID );
803 
804  /* EVENT IDs 0x0001-0x3FFF carries "do-it-now" event
805  * EVENT IDs 0x4000-0x7FFF carries NPT ref descriptor
806  * EVENT IDs 0x8000-0xBFFF carries other stream descriptors
807  */
808  if ((eventID != 0xFFFF) &&
809  ((eventID < 0x0001) || (eventID > 0xBFFF)))
810  {
811  dsmDP3(("DSC_StrmEventUpdate tableId ext doesnt carry a do-it-now event = %xh\n", eventID));
812  goto _return;
813  }
814 
815  if (pEvent->id != eventID)
816  {
817  dsmDP1(("pEvent->id != eventID: %x, %x", pEvent->id, eventID));
818  err = CLDSM_ERR_INVALID_STREAM_EVENT_NAME;
819  }
820  else
821  {
822  /* -- get version */
823  READ_UINT8( pStreamDescrSection, ui8);
824 
825  version = (ui8 >> 1) & 0x1F;
826  if (version != pEvent->version)
827  {
828  edata_len = 0;
829  edata_ptr = NULL;
830  dsmDP2(("newVer=%u oldVer=%u", version, pEvent->version));
831  pEvent->version = version;
832 
833  /* get sectionNumber*/
834  /* only consider section number == 0 : DTG: 4.0 paragr:17.2.4.4 p 17-15 */
835  READ_UINT8_L2CHK( pStreamDescrSection, ui8, ui8 == 0,
836  dsmDP2(("only consider section number = 0 here: %x\n", ui8)),
837  goto _return );
838  /* get lastSectionNumber*/
839  READ_UINT8_L2CHK( pStreamDescrSection, ui8, ui8 == 0,
840  dsmDP2(("only consider last section number = 0 here: %x\n", ui8)),
841  goto _return );
842  while (msg_len >= 2)
843  {
844  msg_len -= 2;
845  /* -- get descriptor tag */
846  READ_UINT8( pStreamDescrSection, dtag );
847  /* -- get descriptor len */
848  READ_UINT8( pStreamDescrSection, dlen );
849  if (dlen > msg_len)
850  {
851  dsmDP1(("Invalid lengths: msg=%x, dlen=%x", msg_len, dlen));
852  return CLDSM_ERR_END_OF_DATA;
853  }
854  msg_len -= dlen;
855  switch (dtag)
856  {
857  case STREAM_NPT_REF_DESC:
858  case STREAM_NPT_END_DESC:
859  case STREAM_MODE_DESC:
860  default: /* Ignore all other tags */
861  break;
862 
863  case STREAM_EVENT_DESC:
864  if (dlen < 10)
865  {
866  dsmDP1(("Invalid desc length: %x", dlen));
867  return CLDSM_ERR_END_OF_DATA;
868  }
869  edata_len = dlen - 10;
870  if (edata_len != 0)
871  {
872  /* point at first byte of private data for the StreamEventDecriptor */
873  edata_ptr = pStreamDescrSection + 10;
874  }
875  #if DSM_DATA_CHECK_LEVEL >= 2
876  READ_UINT16_L2CHK(pStreamDescrSection, ui16, ui16 == eventID,
877  dsmDP2(("DATA ERR: eventID mismatch %u,%u\n", eventID, ui16)),
878  goto _return );
879  #else
880  pStreamDescrSection += 2;
881  #endif
882  #ifdef SUPPORT_SCHEDULED_EVENTS
883  /* read eventNPT */
884  READ_UINT32( pStreamDescrSection, ui32);
885  ULONG_Set32(pEvent->eventNpt, ui32 & 1);
886  ULONG_ShiftLeft(pEvent->eventNpt, 32);
887  READ_UINT32( pStreamDescrSection, ui32);
888  ULONG_Set32(pEvent->eventNpt, ui32); /* TODO: use eventNPT in synchronised event handling */
889  pStreamDescrSection += edata_len;
890  #else
891  pStreamDescrSection += 8 + edata_len;
892  #endif
893  }
894  }
895  if (eventID == 0xFFFF || (eventID > 0 && eventID < 0x4000)) /* this is Lifecycle or "do-it-now" EVENT */
896  {
897  U8BIT *name = pEvent->name;
898  dlen = pEvent->nlen;
899  /* null terminate name */
900  if (name != NULL)
901  {
902  ui8 = name[dlen];
903  name[dlen] = 0;
904  }
905 
906  dsmDP2(("\nEVENT Name:%s ID:%u version Nb:%u\n", name, eventID, version));
907 
908  dsmAssert((idp->setup.notifyStreamEventFunc != NULL));
909  pL = pEvent->pListener;
910  while (pL != NULL)
911  {
912  idp->setup.notifyStreamEventFunc( pL->eventHandle,
913  SEN_TRIGGERED, pL->userData1, pL->userData2, name, edata_ptr, dlen, edata_len );
914  pL = pL->next;
915  }
916  /* restore original terminating char of name */
917  if (name != NULL)
918  {
919  name[dlen] = ui8;
920  }
921  }
922  /* else if ( eventID >= 0x8000 )
923  {}
924  else // if ( eventID >= 0x4000 && eventID <= 0x7FFF )
925  {}
926  */
927  }
928  }
929 
930 _return:
931  DEBUG_CHK( err == CLDSM_OK, dsmDP1(("ERROR: DSC_StrmEventUpdate: %u\n", err)));
932  return err;
933 }
934 
935 void DSC_StrmEventFilterReset( P_DsmCoreInst idp )
936 {
937  S_SE_INFO *pStreamInfo;
938  S_Event *pEvent;
939  U16BIT evntNdx, evntMax;
940  pStreamInfo = idp->hSubscribedEventList;
941  while (pStreamInfo != NULL)
942  {
943  pEvent = (S_Event *)(pStreamInfo + 1);
944  evntMax = pStreamInfo->eventCount;
945  for (evntNdx = 0; evntNdx != evntMax; evntNdx++, pEvent++)
946  {
947  if (pEvent->pFilter != NULL)
948  {
949  DBGLOG((DD_SE | DD_SF), "serv_id=0x%x pFilter=%p", pStreamInfo->serviceId, pEvent->pFilter)
950  DSC_SectionFilterStop( idp, &pEvent->pFilter );
951  }
952  StartSectionFilter(idp, pStreamInfo, pEvent);
953  }
954  pStreamInfo = pStreamInfo->next;
955  }
956 }
957 
958 /*----------------------------------------------------------------------------*/
959 
960 /*
961  * Free up stream event resources
962  */
963 static void FreeStreamInfo( P_DsmCoreInst idp, S_SE_INFO *pStreamInfo )
964 {
965  S_Event *pEvent;
966  U16BIT eventCount;
967  S_LISTENER *pL;
968 
969  if (pStreamInfo->xmlPtr)
970  {
971  DSC_CmMemRelease( idp, pStreamInfo->xmlPtr );
972  }
973  pEvent = (S_Event *)(pStreamInfo + 1);
974  eventCount = pStreamInfo->eventCount;
975  while (eventCount--)
976  {
977  while (pEvent->pListener != NULL)
978  {
979  pL = pEvent->pListener;
980  ERRPRINT("ERROR !Listener still subscribed! hdl=%x", pL->eventHandle)
981  pEvent->pListener = pL->next;
982  DSC_CmMemRelease( idp, pL );
983  }
984  if (pEvent->pFilter != NULL)
985  {
986  DBGLOG((DD_SE | DD_SF), "serv_id=0x%x pFilter=%p", pStreamInfo->serviceId, pEvent->pFilter)
987  DSC_SectionFilterStop( idp, &pEvent->pFilter );
988  }
989  pEvent++;
990  }
991  DSC_CmMemRelease( idp, pStreamInfo );
992 }
993 
1007 static E_DscError RetrieveStreamInfo( P_DsmCoreInst idp,
1008  /*I*/ H_DsmObject streamObject,
1009  /*O*/ S_SE_INFO **ppStreamInfo )
1010 {
1011  MemPtr mpObjectData, mpObjectDataFirstPos;
1012  MemPos hdlPos;
1013  P_Module pModule;
1014  U8BIT ui8;
1015  U16BIT ui16;
1016  U32BIT ui32;
1017  U16BIT eventCount, namesLen;
1018  U16BIT tapUse;
1019  E_DscError err;
1020  U8BIT tapsCount;
1021  S_Event *pEvent;
1022  S_SE_INFO *pStreamInfo;
1023  U8BIT *pNames;
1024 
1025  *ppStreamInfo = NULL;
1026 
1027  if (!DSM_OBJECT_CORRECT( streamObject, idp ))
1028  {
1029  dsmDP1(("API ERROR: Invalid object handle\n"));
1030  err = CLDSM_ERR_INVALID_OBJECT_HANDLE;
1031  }
1032  else if (streamObject->objectInfo.objectKind != STE_STR)
1033  {
1034  dsmDP1(("ERROR: message is not a streamEvent !! = %u\n",
1035  streamObject->objectInfo.objectKind));
1036  err = CLDSM_ERR_INVALID_OBJECT_TYPE;
1037  }
1038  else if ((pStreamInfo = FindStreamInfo(idp, streamObject)) != NULL)
1039  {
1040  *ppStreamInfo = pStreamInfo;
1041  err = CLDSM_OK;
1042  }
1043  else
1044  {
1045  pModule = streamObject->pModule;
1046  if (!moduleDataFindObject(pModule->hModuleData, pModule->moduleInfo.originalSize,
1047  &(streamObject->objectInfo.objectKey), &mpObjectData ))
1048  {
1049  dsmDP1(("failed to find object in module"));
1050  err = CLDSM_ERR_OBJECT_NOT_LOADED;
1051  }
1052  else
1053  {
1054  mpObjectDataFirstPos = mpObjectData;
1055 
1056  /* SKIP biop magic + version + byte order + msg size */
1057  SET_POS_REL(mpObjectData, 12);
1058 
1059  /* SKIP object key */
1060  READ_UINT8(mpObjectData, ui8 );
1061  SET_POS_REL(mpObjectData, ui8);
1062 
1063  /* get object kind */
1064  READ_UINT32( mpObjectData, ui32)
1065  if (ui32 != 4)
1066  {
1067  dsmDP2(("DATA ERROR: objectKindLg !=4 %u\n", ui32));
1068  err = CLDSM_ERR_INVALID_OBJECT_TYPE;
1069  }
1070  else
1071  {
1072  READ_UINT32( mpObjectData, ui32)
1073  if (ui32 != 0x73746500)
1074  {
1075  dsmDP2(("DATA ERROR: objectKind != ste %u\n", ui32));
1076  err = CLDSM_ERR_INVALID_OBJECT_TYPE;
1077  }
1078  else
1079  {
1080  /* skip objectInfo Length */
1081  SET_POS_REL(mpObjectData, 2);
1082 
1083  /* SKIP aDescriptionLg */
1084  READ_UINT8(mpObjectData, ui8); /*-- N3 */
1085  SET_POS_REL(mpObjectData, ui8);
1086 
1087  /* SKIP duration seconds, microsecs, audio, video, data (4 + 4 + 1 + 1 + 1) */
1088  SET_POS_REL(mpObjectData, 11);
1089 
1090  READ_UINT16(mpObjectData, eventCount);
1091  GET_POS( mpObjectData, hdlPos ); /* save position */
1092  namesLen = 0;
1093  for (ui16 = eventCount; ui16--; )
1094  {
1095  READ_UINT8( mpObjectData, ui8 );
1096  SET_POS_REL(mpObjectData, ui8);
1097  namesLen += ui8;
1098  }
1099  ui32 = sizeof(S_SE_INFO) + (eventCount * sizeof(S_Event)) + namesLen;
1100  pStreamInfo = (S_SE_INFO *)DSC_CmMemGet( idp, ui32 );
1101  if (!pStreamInfo)
1102  {
1103  err = CLDSM_ERR_MEM_HEAP_FULL;
1104  }
1105  else
1106  {
1107  err = CLDSM_OK;
1108  pStreamInfo->pModule = pModule;
1109  memcpy(&(pStreamInfo->objectKey), &(streamObject->objectInfo.objectKey), sizeof(S_ObjectKey));
1110  pStreamInfo->uniqueId = ++unique_stream_ids;
1111  if (memValidate(streamObject->pObjCarousel))
1112  {
1113  pStreamInfo->serviceId = streamObject->pObjCarousel->root.serviceId;
1114  }
1115  else
1116  {
1117  pStreamInfo->serviceId = idp->dvbLocator.service_id;
1118  }
1119  pStreamInfo->eventCount = eventCount;
1120  pStreamInfo->lstnrCount = 0;
1121  pEvent = (S_Event *)(pStreamInfo + 1);
1122  pNames = (U8BIT *)(pEvent + eventCount);
1123  pStreamInfo->namesPtr = pNames;
1124  pStreamInfo->namesLen = namesLen;
1125  pStreamInfo->xmlPtr = NULL;
1126 
1127  /* reset module data pointer to beginning of names */
1128  SET_POS_ABS( mpObjectData, hdlPos );
1129  for (ui16 = eventCount; ui16--; pEvent++)
1130  {
1131  /* Note: DBOOK (table 17-20) says name length includes zero terminator */
1132  READ_UINT8( mpObjectData, ui8 );
1133  pEvent->nlen = ui8 - 1; /* keep length without the terminating 'null' char */
1134  pEvent->name = pNames;
1135  while (ui8--)
1136  {
1137  READ_UINT8( mpObjectData, *pNames );
1138  pNames++;
1139  }
1140  /* replace last char ('null') with comma,
1141  * so that 'nameList' is a comma separated list */
1142  *(pNames - 1) = ',';
1143  /* initialise other event properties */
1144  pEvent->version = 0xFF; /* invalid value */
1145  pEvent->pFilter = NULL;
1146  pEvent->pListener = NULL;
1147  #ifdef SUPPORT_SCHEDULED_EVENTS
1148  pEvent->eventNpt = 0;
1149  #endif
1150  /* pEvent->id is initialised later */
1151  }
1152  /* revert last char back to 'null' (not comma) */
1153  *(pNames - 1) = 0;
1154 
1155  mpObjectData = mpObjectDataFirstPos;
1156  SET_POS_REL( mpObjectData, (S32BIT)(streamObject->objectInfo.messageBodyOffset - 4));
1157 
1158  /* get messageBody_length */
1159  READ_UINT32(mpObjectData, ui32);
1160  if (ui32 == 0)
1161  {
1162  dsmDP2(("RetrieveStreamInfo(-): msg len is zero\n"));
1163  }
1164 
1165  /* get taps_count */
1166  READ_UINT8(mpObjectData, tapsCount);
1167 
1168  pStreamInfo->eventAssocTag = 0;
1169 
1170  while (tapsCount--)
1171  {
1172  READ_UINT16(mpObjectData, ui16); /* tap id */
1173  if (ui16 != 0)
1174  {
1175  dsmDP1(("tap Id should zero, here=%d\n", ui16));
1176  }
1177  READ_UINT16(mpObjectData, tapUse);
1178  /* get assocTag */
1179  READ_UINT16(mpObjectData, ui16);
1180  dsmDP2(("TAP: use=%d assocTag=0x%x\n", tapUse, ui16));
1181  /* get selector_length */
1182  READ_UINT8(mpObjectData, ui8);
1183  if (ui8 != 0)
1184  {
1185  dsmDP1(("RetrieveStreamInfo(-): selector_length should be zero here=%d\n", ui8));
1186  }
1187  switch (tapUse)
1188  {
1189  case STR_STATUS_AND_EVENT_USE:
1190  case STR_EVENT_USE:
1191  pStreamInfo->eventAssocTag = ui16;
1192  default:;
1193  }
1194  }
1195  /* get eventIds_count */
1196  READ_UINT8(mpObjectData, ui8);
1197  if (eventCount != ui8)
1198  {
1199  dsmDP1(("eventNamesCount=%d != eventIds_count=%d\n", eventCount, ui8));
1200  }
1201  pEvent = (S_Event *)(pStreamInfo + 1);
1202  for (ui16 = eventCount; ui16--; pEvent++)
1203  {
1204  READ_UINT16(mpObjectData, pEvent->id);
1205  }
1206  /* add to list */
1207  pStreamInfo->next = idp->hSubscribedEventList;
1208  idp->hSubscribedEventList = pStreamInfo;
1209  *ppStreamInfo = pStreamInfo;
1210  err = CLDSM_OK;
1211  }
1212  }
1213  }
1214  }
1215  }
1216  return(err);
1217 }
1218 
1219 void ReleaseStreamInfo( P_DsmCoreInst idp, S_SE_INFO *sei )
1220 {
1221  S_SE_INFO **ppSEI;
1222 
1223  sei->lstnrCount--;
1224  if (!sei->lstnrCount)
1225  {
1226  ppSEI = &idp->hSubscribedEventList;
1227  while (*ppSEI != NULL)
1228  {
1229  if (*ppSEI == sei)
1230  {
1231  *ppSEI = (*ppSEI)->next;
1232  FreeStreamInfo( idp, sei );
1233  break;
1234  }
1235  ppSEI = &((*ppSEI)->next);
1236  }
1237  }
1238 }
1239 
1240 void DSC_StrmEventListReset( P_DsmCoreInst idp )
1241 {
1242  S_SE_INFO *sei, *nxt;
1243  sei = idp->hSubscribedEventList;
1244  while (sei != NULL)
1245  {
1246  nxt = sei->next;
1247  FreeStreamInfo( idp, sei );
1248  sei = nxt;
1249  }
1250  idp->hSubscribedEventList = NULL;
1251 }
1252 
1280  /*I*/ H_DsmCoreInst dsmccInstance,
1281  /*I*/ H_DsmObject streamObject,
1282  /*O*/ U8BIT **pNamesPtr, U16BIT *pNamesLen )
1283 {
1284  E_DscError err;
1285  S_SE_INFO *pStreamInfo;
1286  err = RetrieveStreamInfo( dsmccInstance, streamObject, &pStreamInfo );
1287  if (CLDSM_OK == err)
1288  {
1289  *pNamesPtr = pStreamInfo->namesPtr;
1290  *pNamesLen = pStreamInfo->namesLen;
1291  }
1292  return err;
1293 }
1294 
1311  /*I*/ H_DsmCoreInst dsmccInstance,
1312  /*I*/ H_DsmObject streamObject,
1313  /*O*/ U8BIT **pXmlData, U16BIT *pXmlLen)
1314 {
1315  E_DscError err;
1316  S_SE_INFO *pStreamInfo;
1317  S_Event *pEvent;
1318  err = RetrieveStreamInfo( dsmccInstance, streamObject, &pStreamInfo );
1319  if (CLDSM_OK == err)
1320  {
1321  if (pStreamInfo->xmlPtr == NULL)
1322  {
1323  char *data;
1324  U16BIT sz;
1325  sz = sizeof(XML_DATA2a) + sizeof(XML_DATA2b) + sizeof(XML_DATA2c) + 2; // add (5-3) to allow for max event id (65535)
1326  sz *= pStreamInfo->eventCount;
1327  sz += pStreamInfo->namesLen;
1328  sz += sizeof(XML_DATA1a) + sizeof(XML_DATA1b) + sizeof(XML_DATA3);
1329  data = (char *)DSC_CmMemGet( (P_DsmCoreInst)dsmccInstance, sz );
1330  if (data != NULL)
1331  {
1332  pStreamInfo->xmlPtr = (U8BIT *)data;
1333  strcpy(data, XML_DATA1a);
1334  data += sizeof(XML_DATA1a) - 1;
1335  data += sprintf(data, "%u", pStreamInfo->eventAssocTag);
1336  strcpy(data, XML_DATA1b);
1337  data += sizeof(XML_DATA1b) - 1;
1338  pEvent = (S_Event *)(pStreamInfo + 1);
1339  for (sz = 0; sz != pStreamInfo->eventCount; sz++, pEvent++)
1340  {
1341  strcat(data, XML_DATA2a);
1342  data += sizeof(XML_DATA2a) - 1;
1343  data += sprintf(data, "%u", pEvent->id);
1344  strcat(data, XML_DATA2b);
1345  data += sizeof(XML_DATA2b) - 1;
1346  strncpy(data, (const char *)pEvent->name, pEvent->nlen);
1347  data += pEvent->nlen;
1348  strcat(data, XML_DATA2c);
1349  data += sizeof(XML_DATA2c) - 1;
1350  }
1351  strcat(data, XML_DATA3);
1352  data += sizeof(XML_DATA3) - 1;
1353  pStreamInfo->xmlLen = (U16BIT)((U8BIT*)data - pStreamInfo->xmlPtr);
1354  }
1355  }
1356  *pXmlData = pStreamInfo->xmlPtr;
1357  *pXmlLen = pStreamInfo->xmlLen;
1358  }
1359  return err;
1360 }
1361 
E_DscError CDSM_StreamEventUnsubscribe(H_DsmCoreInst idp, H_DsmEvent eventHandle)
This function is called by the Client to let DSMCC know when a previously subscribed stream event is ...
Definition: streamEvent.c:638
General include file for clDsm library internal definitions.
E_DscError CDSM_StreamEventNameList(H_DsmCoreInst dsmccInstance, H_DsmObject streamObject, U8BIT **pNamesPtr, U16BIT *pNamesLen)
The Client uses this function to request list of event names for stream object Before calling this fu...
Definition: streamEvent.c:1279
E_DscError CDSM_StreamEventSubscribe(H_DsmCoreInst dsmccInstance, H_DsmObject streamObject, U8BIT *eventName, void *userData1, void *userData2, H_DsmEvent *pEventHandle)
The Client uses this function to request that the DSMCC notifies it when a named stream event occurs...
Definition: streamEvent.c:329
Header to the cacheMgr module.
E_DscError CDSM_SpecialEventSubscribe(H_DsmCoreInst dsmccInstance, U16BIT associationTag, U16BIT eventId, void *userData1, void *userData2, H_DsmEvent *pEventHandle)
Like clDsmStreamEventSubscribe, except that no stream object is required. This function subscribes to...
Definition: streamEvent.c:504
Header to dsmObject module - functions for managing DSM object heap.
E_DscError CDSM_SpecialEventUnsubscribe(H_DsmCoreInst dsmccInstance, H_DsmEvent eventHandle)
Same as clDsmStreamEventUnsubscribe - used in conjuction with clDsmSpecialEventSubscribe.
Definition: streamEvent.c:700
Header to the sectionFilter module.
E_DscError CDSM_StreamEventXmlData(H_DsmCoreInst dsmccInstance, H_DsmObject streamObject, U8BIT **pXmlData, U16BIT *pXmlLen)
The Client uses this function to request data in XML format for stream object and associated events...
Definition: streamEvent.c:1310
Header to the 'module' module - Functions/methods for creating/destroying and managing attributes of ...
Header to the moduleData module.