DVBCore  20.3.0
DVBCore Documentation
ap_ci.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright © 2014 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  * Copyright © 2011 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  *******************************************************************************/
25 /*#define CI_DEBUG*/
26 
27 //---includes for this file----------------------------------------------------
28 // compiler library header files
29 
30 #include <stdio.h>
31 #include <string.h>
32 
33 // third party header files
34 
35 // Ocean Blue Software header files
36 
37 #include "techtype.h"
38 #include "dbgfuncs.h"
39 
40 #include "stbhwci.h"
41 #include "stbhwos.h"
42 #include "stbhwtun.h"
43 
44 #include "stbdpc.h"
45 #include "stbpvr.h"
46 #include "stberc.h"
47 #include "stbheap.h"
48 #include "stbsiflt.h"
49 #include "stbsitab.h"
50 #include "stbgc.h"
51 #include "stberc.h"
52 #include "ap_tmr.h"
53 
54 #include "dba.h"
55 
56 #include "app.h"
57 #include "ap_cfg.h"
58 #include "ap_events.h"
59 #include "ap_dbacc.h"
60 #include "ap_dbdef.h"
61 #include "ap_ci.h"
62 #include "ap_cntrl.h"
63 #include "ap_state.h"
64 #include "ap_pvr.h"
65 #include "app_nvm.h"
66 
67 #include "stbci.h"
68 #include "stbcica.h"
69 #include "stbcicc.h"
70 #include "stbcikeys.h"
71 #include "ap_ci_int.h"
72 #include "ap_cihc.h"
73 #include "ap_ciop.h"
74 
75 //---constant definitions for this file----------------------------------------
76 #ifdef CI_DEBUG
77  #define AP_CI_PRINT(x) STB_SPDebugWrite x
78 #else
79  #define AP_CI_PRINT(x)
80 #endif
81 
82 #define MAX_EVENTS 100
83 
84 #define TASK_STACK_SIZE 4096
85 #define TASK_PRIORITY 11
86 
87 //---local typedefs, structs, enumerations for this file--------------------------------------------
88 
89 typedef enum
90 {
91  CIPLUS_TUNE_TYPE_SERVICE,
92  CIPLUS_TUNE_TYPE_TRANSPORT,
93  CIPLUS_TUNE_TYPE_CI_SERVICE
94 } E_CIPLUS_TUNE_TYPE;
95 
97 {
98  void *t_ptr;
99  E_ACTL_SI_SRCH_REQD reqd_si;
100 };
101 
103 {
104  void *s_ptr;
105  E_ACTL_SI_SRCH_REQD reqd_si;
106  U8BIT *pmt;
107 };
108 
109 typedef struct
110 {
111  U32BIT module;
112  E_CIPLUS_TUNE_TYPE type;
113  E_CIP_TUNE_FLAGS flags;
114  union
115  {
116  struct s_ciplus_tune_service service;
117  struct s_ciplus_tune_transport transport;
118  } u;
120 
121 
122 //---local (static) variable declarations for this file------------------------
123 // (internal variables declared static to make them local)
124 static U8BIT cam_upgrade_mode = STB_CI_UPGRADE_REPLY_ASK;
125 static E_CIP_START_OPERATOR_SEARCH operator_search_mode = CIP_START_OPERATOR_SEARCH_ASK;
126 static BOOLEAN operator_search_required = FALSE;
127 static U32BIT operator_search_module;
128 static void *operator_search_service = NULL;
129 static void *ciplus_event_queue = NULL;
130 static F_NotifyStartTuning NotifyStartTuning = NULL;
131 
132 
133 //---local function prototypes for this file-----------------------------------
134 // (internal functions declared static to make them local)
135 
141 static void ApplyUsageRules(U8BIT path, void *s_ptr)
142 {
143  U8BIT slot_id;
144  U16BIT service_id;
145  U8BIT *pmt_data;
146  U16BIT data_len;
147  U8BIT uri[CIP_URI_LEN] = { 0 };
148 
149  FUNCTION_START(ApplyUsageRules);
150 
151  AP_CI_PRINT(("[ACI] ApplyUsageRules: path=%d, service_id=0x%x", path, ADB_GetServiceId(s_ptr)));
152 
153  if (STB_DPIsDecodingPath(path))
154  {
155  slot_id = STB_DPGetPathCISlot(path);
156  if (slot_id != INVALID_RES_ID && STB_CiCcAuthenticated(slot_id))
157  {
158  AP_CI_PRINT(("[ACI] Slot %u is used on path", slot_id));
159  pmt_data = ADB_GetServicePMTData(s_ptr, &data_len);
160  if (STB_CiCaSystemSupported(slot_id, pmt_data))
161  {
162  /* Service is scrambled, CAS supported and CAM is CI+, so
163  * need to get the URI and apply it */
164  AP_CI_PRINT(("[ACI] Service scrambled, CAS supported, CI+ CAM"));
165  service_id = ADB_GetServiceId(s_ptr);
166  STB_CiCcGetUsageRulesInfo(slot_id, service_id, uri);
167  }
168  }
169 
170  /* Apply the URI to the AV outputs (regardless of slot status) */
172  }
173 
174  FUNCTION_FINISH(ApplyUsageRules);
175 }
176 
182 static void UpdateRecordingURI(U8BIT path, void *s_ptr)
183 {
184  U32BIT rec_handle;
185  U8BIT slot_id;
186  U16BIT service_id;
187  U8BIT *pmt_data;
188  U16BIT data_len;
189  U8BIT uri[CIP_URI_LEN] = { 0 };
190 
191  FUNCTION_START(UpdateRecordingURI);
192 
193  AP_CI_PRINT(("[ACI] UpdateRecordingURI: path = %d", path));
194 
195  /* Check recordings on the path */
196  if (STB_DPIsRecording(path, &rec_handle))
197  {
198  AP_CI_PRINT(("[ACI] Recording on the path"));
199  slot_id = STB_DPGetPathCISlot(path);
200  if (slot_id != INVALID_RES_ID && STB_CiCcAuthenticated(slot_id))
201  {
202  AP_CI_PRINT(("[ACI] Slot %u used for recording", slot_id));
203  pmt_data = ADB_GetServicePMTData(s_ptr, &data_len);
204  if (STB_CiCaSystemSupported(slot_id, pmt_data))
205  {
206  /* Service is scrambled, CAS supported and CAM is CI+, so
207  * need to get the URI and store it with the recording */
208  AP_CI_PRINT(("[ACI] URI stored with recording"));
209  service_id = ADB_GetServiceId(s_ptr);
210  STB_CiCcGetUsageRulesInfo(slot_id, service_id, uri);
211  STB_PVRRecordingAddURI(rec_handle, uri);
212  }
213  }
214  }
215 
216  FUNCTION_FINISH(UpdateRecordingURI);
217 }
218 
223 static void OperatorSearchFinished(void)
224 {
225  U8BIT path;
226 
227  FUNCTION_START(OperatorSearchFinished);
228 
229  /* The live path used for searching will be owned by CI+, so release it before returning
230  * to the previous service */
231  for (path = 0; path < STB_DPGetNumPaths(); path++)
232  {
233  if (STB_DPIsOwnedBy(path, RES_OWNER_CIPLUS))
234  {
235  (void)STB_DPReleasePath(path, RES_OWNER_CIPLUS);
236  }
237  }
238 
239  if (operator_search_service != NULL)
240  {
241  ACTL_TuneToService(INVALID_RES_ID, NULL, operator_search_service, FALSE, TRUE);
242  operator_search_service = NULL;
243  }
244 
245  FUNCTION_FINISH(OperatorSearchFinished);
246 }
247 
252 static void ApplyCCKeys(U8BIT slot_id)
253 {
254  U8BIT path;
255  void *s_ptr;
256  U8BIT *pmt_data;
257  U16BIT data_len;
258 
259  FUNCTION_START(ApplyCCKeys);
260  AP_CI_PRINT(("[ACI] ApplyCCKeys(%u)", slot_id));
261  if (slot_id != INVALID_RES_ID && STB_CiCcAuthenticated(slot_id))
262  {
263  /* A slot can be shared with more than one path,
264  * so handle this event for all paths using this slot */
265  path = INVALID_RES_ID;
266  while ((path = STB_DPIsCISlotInUse(path, slot_id, path)) != INVALID_RES_ID)
267  {
268  s_ptr = ADB_GetTunedService(path);
269  if (s_ptr != NULL)
270  {
271  pmt_data = ADB_GetServicePMTData(s_ptr, &data_len);
272  if (STB_CiCaSystemSupported(slot_id, pmt_data))
273  {
274  /* Apply content control keys (if any) on path */
275  STB_CiKeysApply(path, slot_id);
276  }
277  }
278  }
279  }
280  FUNCTION_FINISH(ApplyCCKeys);
281 }
282 
283 static void ReleaseCISlotFromPath(U8BIT path)
284 {
285  void *service;
286  U16BIT service_id;
287  U8BIT other, slot_id;
288 
289  FUNCTION_START(ReleaseCISlotFromPath);
290 
292  ACTL_ReleasePathOwnership(path, RES_OWNER_CIPLUS);
293 
294  /* The CI slot is being used by at least one other path. The slot may have just been
295  * released from a live path but is still in use on a recording path, so the recording
296  * mode would need to be changed to indicate it is now unattended */
297  slot_id = STB_DPGetPathCISlot(path);
298  other = STB_DPIsCISlotInUse(0, slot_id, path);
299  if (other != INVALID_RES_ID)
300  {
301  service = STB_DPGetTunedService(path);
302  if (service != NULL)
303  {
304  service_id = ADB_GetServiceId(service);
305  }
306  else
307  {
308  service_id = 0xffff;
309  }
311  STB_CI_MODE_WATCH_AND_BUFFER : STB_CI_MODE_UNATTENDED_RECORDING, service_id);
312  }
313 
314  /* And clear any CI+ keys */
315  STB_CiKeysClear(path, slot_id);
316 
317  FUNCTION_FINISH(ReleaseCISlotFromPath);
318 }
319 
324 static void CISlotRemoved(U8BIT slot_id)
325 {
326  U8BIT path;
327  FUNCTION_START(CISlotRemoved);
328  if (slot_id != INVALID_RES_ID)
329  {
330  ACI_OpSlotRemove(slot_id);
331  path = INVALID_RES_ID;
332  while ((path = STB_DPIsCISlotInUse(path, slot_id, path)) != INVALID_RES_ID)
333  {
334  /* Slot is being used but shouldn't be anymore */
336  ACTL_ReleasePathOwnership(path, RES_OWNER_CIPLUS);
337  STB_CiKeysClear(path, slot_id);
338  }
339  STB_CiCcRemove(slot_id);
340  }
341  FUNCTION_FINISH(CISlotRemoved);
342 }
343 
348 static void CISlotStatusChanged(U8BIT slot_id)
349 {
350  U8BIT path;
351  void *s_ptr;
352  U8BIT *pmt_data, *ci_prot;
353  U16BIT data_len;
354 
355  FUNCTION_START(CISlotStatusChanged);
356 
357  if (slot_id != INVALID_RES_ID)
358  {
359  AP_CI_PRINT(("CISlotStatusChanged(%u)", slot_id));
360 
361  if (STB_CiCcIsSlotReady(slot_id))
362  {
363  /* See if the slot is being used */
364  path = STB_DPIsCISlotInUse(INVALID_RES_ID, slot_id, INVALID_RES_ID);
365  if (path != INVALID_RES_ID)
366  {
367  /* A slot can be shared with more than one path,
368  * so handle this event for all paths using this slot */
369  path = INVALID_RES_ID;
370  while ((path = STB_DPIsCISlotInUse(path, slot_id, path)) != INVALID_RES_ID)
371  {
372  s_ptr = STB_DPGetTunedService(path);
373  if (s_ptr != NULL)
374  {
375  ci_prot = ADB_GetServiceCIProtectionDesc(s_ptr);
376  if (!STB_CiCcIsServiceAllowed(slot_id,ci_prot))
377  {
378  /* TS isn't allowed to be routed through this slot anymore */
379  ReleaseCISlotFromPath(path);
380  }
381  else if (STB_CiCcAuthenticated(slot_id))
382  {
383  pmt_data = ADB_GetServicePMTData(s_ptr, &data_len);
384  /* Check whether the keys need to be applied */
385  if (STB_CiCaSystemSupported(slot_id,pmt_data))
386  {
387  /* Apply content control keys (if any) on path */
388  STB_CiKeysApply(path, slot_id);
389  }
390  }
391  }
392  }
393  }
394  else
395  {
396  /* CAM inserted, check whether TS can be routed through it */
397  if (STB_CiCcIsServiceAllowed(slot_id,NULL))
398  {
399  /* If recording of scrambled services is to be allowed then all paths should
400  * be checked to see if any of them are being used for recording, whether they
401  * are already using a CI slot, and if not, whether the CAM in this slot supports
402  * the CA system for the service being recorded. If all this is true then the
403  * slot should be assigned to that path, but is it valid to do this if a recording
404  * has already been started?
405  * Not being done at the moment, just apply it to the live path */
406  if ((path = STB_DPGetLivePath()) != INVALID_RES_ID)
407  {
408  if ((s_ptr = ADB_GetTunedService(path)) != NULL)
409  {
410  /* Route live path through the slot */
411  ACI_AcquireCISlot(path, s_ptr);
412  }
413  }
414  }
415  }
416  }
417  else
418  {
419  /* CAM may have been removed from slot, check if any paths are using this slot */
420  path = INVALID_RES_ID;
421  while ((path = STB_DPIsCISlotInUse(path, slot_id, path)) != INVALID_RES_ID)
422  {
423  /* Slot is being used but shouldn't be anymore */
424  ReleaseCISlotFromPath(path);
425  }
426  }
427  }
428 
429  FUNCTION_FINISH(CISlotStatusChanged);
430 }
431 
438 static void RecordLicenceChanged(U8BIT path, U8BIT slot_id)
439 {
440  U32BIT handle;
441  U8BIT cicam_id[CIP_CICAM_ID_LEN];
442  E_STB_CI_LICENSE_RCVD_STATUS status;
443  U8BIT *licence;
444  U16BIT licence_len;
445  U8BIT licence_status;
446  void *s_ptr;
447  U8BIT *pmt_data;
448  U16BIT data_len;
449  U8BIT uri[CIP_URI_LEN];
450 
451  FUNCTION_START(RecordLicenceChanged);
452 
453  if (STB_DPIsRecording(path, &handle))
454  {
455  AP_CI_PRINT(("%s(path=%u, slot=%u): Updating recording 0x%08lx", __FUNCTION__, path,
456  slot_id, handle));
457 
458  status = STB_CI_LICENSE_RCVD_OK;
459 
460  if (STB_CIGetCicamId(slot_id, cicam_id))
461  {
462  /* Store the CICAM id with the recording */
463  if (!STB_PVRRecordingSetCicamId(handle, cicam_id, sizeof(cicam_id)))
464  {
465  status = STB_CI_LICENSE_RCVD_HOST_ERROR;
466  }
467  }
468 
469  if (status == STB_CI_LICENSE_RCVD_OK)
470  {
471  if ((licence = STB_CiCcGetRecordingLicence(slot_id, &licence_status, &licence_len, uri)) != NULL)
472  {
473  s_ptr = ADB_GetTunedService(path);
474  if (s_ptr != NULL)
475  {
476  if (STB_DPIsDecodingPath(path))
477  {
478  /* Check the licence status to make sure it's still
479  * valid for the output to be viewed */
480  if (licence_status == STB_CI_LICENSE_OK)
481  {
482  /* In watch and buffer mode, the service can be viewed */
483  STB_AVBlankVideo(0, FALSE);
484  }
485  else
486  {
487  /* Problem with the licence, ensure the video is blanked and inform the app */
488  STB_AVBlankVideo(0, TRUE);
489  }
490  }
491 
492  if (STB_CiCcAuthenticated(slot_id))
493  {
494  pmt_data = ADB_GetServicePMTData(s_ptr, &data_len);
495  if (STB_CiCaSystemSupported(slot_id, pmt_data))
496  {
497  /* Service is scrambled, CAS supported and CAM is CI+, so
498  * URI needs to be applied and saved with the recording */
499  if (STB_DPIsDecodingPath(path))
500  {
502  }
503 
504  AP_CI_PRINT(("%s(%u, %u): Adding URI to recording 0x%08lx", __FUNCTION__, path,
505  slot_id, handle));
506 
507  if (!STB_PVRRecordingAddURI(handle, uri))
508  {
509  status = STB_CI_LICENSE_RCVD_HOST_ERROR;
510  AP_CI_PRINT(("%s(%u, %u): Failed to save URI with recording 0x%08lx",
511  __FUNCTION__, path, slot_id, handle));
512  }
513  }
514  }
515  }
516 
517  /* Store the licence with the recording */
518  AP_CI_PRINT(("%s(%u, %u): Adding licence, len %u, to recording 0x%08lx", __FUNCTION__,
519  path, slot_id, licence_len, handle));
520 
521  if ((status == STB_CI_LICENSE_RCVD_OK) &&
522  !STB_PVRRecordingAddLicence(handle, licence, licence_len))
523  {
524  status = STB_CI_LICENSE_RCVD_HOST_ERROR;
525  AP_CI_PRINT(("%s(%u, %u): Failed to save licence with recording 0x%08lx",
526  __FUNCTION__, path, slot_id, handle));
527  }
528  }
529  else
530  {
531  status = STB_CI_LICENSE_RCVD_HOST_ERROR;
532  AP_CI_PRINT(("%s(%u, %u): Failed to get licence data from slot", __FUNCTION__, path, slot_id));
533  }
534  }
535 
536  /* Reply to the receipt of the licence */
537  STB_CISendLicenseReceivedStatus(slot_id, status);
538  }
539 
540  FUNCTION_FINISH(RecordLicenceChanged);
541 }
542 
548 static void PlaybackLicenceChanged(U8BIT slot_id)
549 {
550  U8BIT path;
551  U32BIT handle;
552  U8BIT cicam_id[CIP_CICAM_ID_LEN];
553  E_STB_CI_LICENSE_RCVD_STATUS status;
554  U8BIT *licence;
555  U16BIT licence_len;
556  U8BIT licence_status;
557  U8BIT uri[CIP_URI_LEN];
558 
559  FUNCTION_START(PlaybackLicenceChanged);
560 
561  if ((path = STB_DPGetPlaybackPath()) != INVALID_RES_ID)
562  {
563  handle = APVR_GetPlaybackHandle();
564 
565  /* Check that the CICAM id stored with the recording is the same
566  * as the CICAM id that's provided the licence */
567  if (STB_PVRRecordingGetCicamId(handle, cicam_id, sizeof(cicam_id)))
568  {
569  if (STB_CiCcFindSlotForCicamId(cicam_id) == slot_id)
570  {
571  AP_CI_PRINT(("%s(slot=%u): Playback path %u, recording 0x%08lx", __FUNCTION__, slot_id, path, handle));
572 
573  if ((licence = STB_CiCcGetPlaybackLicence(slot_id, &licence_status, &licence_len, uri)) != NULL)
574  {
575  /* Update the URI and licence stored with the recording */
576  if (!STB_PVRRecordingUpdateURI(handle, uri) ||
577  !STB_PVRRecordingUpdateLicence(handle, licence, licence_len))
578  {
579  status = STB_CI_LICENSE_RCVD_HOST_ERROR;
580  }
581  else
582  {
583  if (licence_status != STB_CI_LICENSE_OK)
584  {
585  /* Playback isn't allowed, so send an event to the UI app to inform it of the
586  * playback status. It would be nice if the user was offered the option of jumping
587  * to the start of the next licenced section, if any, but this is up to the app */
588  AP_CI_PRINT(("%s(%u): Licence status %u", __FUNCTION__, path, licence_status));
589  STB_ERSendEvent(FALSE, FALSE, EV_CLASS_CI, EV_TYPE_CI_PLAYBACK_LICENCE_STATUS,
590  &licence_status, sizeof(licence_status));
591  }
592  else
593  {
594  /* Apply the URI in the recording to the outputs */
596  }
597 
598  status = STB_CI_LICENSE_RCVD_OK;
599  }
600  }
601  else
602  {
603  status = STB_CI_LICENSE_RCVD_HOST_ERROR;
604  }
605  }
606  else
607  {
608  status = STB_CI_LICENSE_RCVD_INVALID_DATA;
609  }
610  }
611  else
612  {
613  status = STB_CI_LICENSE_RCVD_HOST_ERROR;
614  AP_CI_PRINT(("%s(%u): Failed to read CICAM id from recording 0x%08lx", __FUNCTION__,
615  slot_id, handle));
616  }
617 
618  /* Reply to the receipt of the licence */
619  STB_CISendLicenseReceivedStatus(slot_id, status);
620  }
621 
622  FUNCTION_FINISH(PlaybackLicenceChanged);
623 }
624 
631 static void RecordPin(U8BIT path, U8BIT slot_id)
632 {
633  U32BIT handle;
634  U8BIT cicam_id[CIP_CICAM_ID_LEN];
635  U8BIT status;
636  U8BIT age_rating;
637  U8BIT *pin_private_data;
638  U16BIT date_code;
639  U8BIT hour, min, secs;
640 
641  FUNCTION_START(RecordPin);
642 
643  if (STB_DPIsRecording(path, &handle))
644  {
645  AP_CI_PRINT(("%s(%u): Updating recording 0x%08lx", __FUNCTION__, path, handle));
646 
647  if (STB_CIGetCicamId(slot_id, cicam_id))
648  {
649  /* Store the CICAM id with the recording */
650  STB_PVRRecordingSetCicamId(handle, cicam_id, sizeof(cicam_id));
651 
652  /* Get the pin info to be stored with the recording */
653  if (STB_CiCcGetRecordingPinInfo(slot_id, &status, &age_rating, &pin_private_data,
654  &date_code, &hour, &min, &secs))
655  {
656  /* If the CAM is unable to descramble the content then the pin event doesn't
657  * need to be saved with the recording (11.3.2.3 of CI+ v1.3.1 spec) */
658  if (status != STB_CI_PIN_CONTENT_SCRAMBLED)
659  {
660  STB_PVRRecordingAddPin(handle, age_rating, pin_private_data,
661  date_code, hour, min, secs);
662  }
663  }
664  }
665  }
666  FUNCTION_FINISH(RecordPin);
667 }
668 
675 static void CIPlusEventHandler(U32BIT event_code, void *event_data, U32BIT event_size)
676 {
677  BOOLEAN retval;
678  S_EVENT_INFO event_info;
679 
680  FUNCTION_START(CIPlusEventHandler);
681 
682  retval = TRUE;
683 
684  if ((event_data != NULL) && (event_size > 0))
685  {
686  /* Allocate memory for the event data to be passed on */
687  if ((event_info.data = STB_AppGetMemory(event_size)) != NULL)
688  {
689  memcpy(event_info.data, event_data, event_size);
690  event_info.data_size = event_size;
691  }
692  else
693  {
694  retval = FALSE;
695  }
696  }
697  else
698  {
699  event_info.data = NULL;
700  event_info.data_size = 0;
701  }
702 
703  if (retval)
704  {
705  event_info.event_code = event_code;
706 
707  /* Send the event to the queue */
708  STB_OSWriteQueue(ciplus_event_queue, (void *)&event_info, sizeof(S_EVENT_INFO), TIMEOUT_NEVER);
709  }
710 
711  FUNCTION_FINISH(CIPlusEventHandler);
712 }
713 
714 static void CIPlusEventTask(void *param)
715 {
716  S_CIPLUS_TUNE_DATA *tune_data;
717  S_CIP_RELEASE_REPLY *reply_data;
718  S_ACTL_OWNER_INFO owner_info;
719  void *serv_ptr;
720  void *owner_data;
721  U32BIT data_size;
722  U8BIT slot_id, path;
723  U8BIT *ciplus_pmt = NULL;
724  S_EVENT_INFO event_info;
725  U16BIT onet_id, trans_id, serv_id;
726 
727  FUNCTION_START(CIPlusEventTask);
728  USE_UNWANTED_PARAM(param);
729 
730  while (1)
731  {
732  if (STB_OSReadQueue(ciplus_event_queue, (void *)&event_info, sizeof(S_EVENT_INFO), TIMEOUT_NEVER))
733  {
734  switch (event_info.event_code)
735  {
736  case STB_EVENT_CI_SLOT_STATUS_CHANGED:
737  {
738  CISlotStatusChanged(*(U8BIT *)event_info.data);
739  break;
740  }
741 
742  case STB_EVENT_CI_REMOVE:
743  {
744  CISlotRemoved(*(U8BIT *)event_info.data);
745  break;
746  }
747 
748  case STB_EVENT_CI_URI_CHANGED:
749  {
750  slot_id = *(U8BIT *)event_info.data;
751 
752  /* A slot can be shared with more than one path,
753  * so handle this event for all paths using this slot */
754  path = INVALID_RES_ID;
755  while ((path = STB_DPIsCISlotInUse(path, slot_id, path)) != INVALID_RES_ID)
756  {
758  }
759  break;
760  }
761 
762  case STB_EVENT_CI_KEYS_CHANGED:
763  {
764  slot_id = *(U8BIT *)event_info.data;
765 
766  ApplyCCKeys(slot_id);
767  break;
768  }
769 
770  case STB_EVENT_CI_RECORD_LICENCE_CHANGED:
771  {
772  slot_id = *(U8BIT *)event_info.data;
773 
774  /* A slot can be shared with more than one path,
775  * so handle this event for all paths using this slot */
776  path = INVALID_RES_ID;
777  while ((path = STB_DPIsCISlotInUse(path, slot_id, path)) != INVALID_RES_ID)
778  {
779  RecordLicenceChanged(path, slot_id);
780  }
781  break;
782  }
783 
784  case STB_EVENT_CI_RECORD_PIN:
785  {
786  slot_id = *(U8BIT *)event_info.data;
787 
788  /* A slot can be shared with more than one path,
789  * so handle this event for all paths using this slot */
790  path = INVALID_RES_ID;
791  while ((path = STB_DPIsCISlotInUse(path, slot_id, path)) != INVALID_RES_ID)
792  {
793  RecordPin(path, slot_id);
794  }
795  break;
796  }
797 
798  case STB_EVENT_CI_PLAYBACK_LICENCE_CHANGED:
799  {
800  PlaybackLicenceChanged(*(U8BIT *)event_info.data);
801  break;
802  }
803 
804  case STB_EVENT_CI_PLAYBACK_BLANK_VIDEO:
805  {
806  /* Have to blank the video until the pin reply is received from the CAM */
807  STB_AVBlankVideo(0, TRUE);
808  break;
809  }
810 
811  case STB_EVENT_CI_PLAYBACK_PIN_STATUS:
812  {
813  switch (*(E_STB_CI_PIN_STATUS *)event_info.data)
814  {
815  case STB_CI_PIN_CODE_CORRECT:
816  case STB_CI_PIN_BLANK_NOT_REQUIRED:
817  {
818  /* Playback can continue */
819  STB_AVBlankVideo(0, FALSE);
820  break;
821  }
822 
823  default:
824  {
825  /* Continue to blank the AV for any other pin status */
826  break;
827  }
828  }
829  break;
830  }
831 
832  case STB_EVENT_CI_TUNE_REQUEST:
833  {
834  tune_data = (S_CIPLUS_TUNE_DATA *)event_info.data;
835  if (tune_data != NULL)
836  {
837  owner_info.owner = RES_OWNER_CIPLUS;
838  owner_info.data = &tune_data->module;
839  owner_info.data_size = sizeof(tune_data->module);
840 
841  switch (tune_data->type)
842  {
843  case CIPLUS_TUNE_TYPE_TRANSPORT:
844  {
845  onet_id = ADB_GetTransportOriginalNetworkId(tune_data->u.transport.t_ptr);
846  trans_id = ADB_GetTransportTid(tune_data->u.transport.t_ptr);
847  if (NotifyStartTuning != NULL)
848  {
849  NotifyStartTuning(tune_data->module, onet_id, trans_id, 0, tune_data->flags);
850  }
851 
852  AP_CI_PRINT(("%s: CIPLUS_TUNE_TYPE_TRANSPORT", __FUNCTION__));
853  /* Tune the live path to the transport requested by CI+ */
854  ACTL_TuneToTransport(INVALID_RES_ID, &owner_info, tune_data->u.transport.t_ptr,
855  APP_SI_MODE_NO_SI, TRUE);
856  break;
857  }
858 
859  case CIPLUS_TUNE_TYPE_SERVICE:
860  {
861  ADB_GetServiceIds(tune_data->u.service.s_ptr, &onet_id, &trans_id, &serv_id);
862  if (NotifyStartTuning != NULL)
863  {
864  NotifyStartTuning(tune_data->module, onet_id, trans_id, serv_id, tune_data->flags);
865  }
866 
867  AP_CI_PRINT(("%s: CIPLUS_TUNE_TYPE_SERVICE", __FUNCTION__));
868  /* Tune the live path to the service requested by CI+ */
869  ACTL_TuneToService(INVALID_RES_ID, &owner_info, tune_data->u.service.s_ptr, FALSE, TRUE);
870  break;
871  }
872 
873  case CIPLUS_TUNE_TYPE_CI_SERVICE:
874  {
875  ADB_GetServiceIds(tune_data->u.service.s_ptr, &onet_id, &trans_id, &serv_id);
876  if (NotifyStartTuning != NULL)
877  {
878  NotifyStartTuning(tune_data->module, onet_id, trans_id, serv_id, tune_data->flags);
879  }
880 
881  AP_CI_PRINT(("%s: CIPLUS_TUNE_TYPE_CI_SERVICE", __FUNCTION__));
882  if (ciplus_pmt != NULL)
883  {
884  STB_AppFreeMemory(ciplus_pmt);
885  ciplus_pmt = NULL;
886  }
887 
888  if (tune_data->u.service.pmt != NULL)
889  {
890  /* Space for the PMT data was allocated when the event was sent
891  * and as it's stored as a pointer in the structure received with the
892  * event, the pointer just needs to be copied to ensure the data
893  * isn't lost. The PMT will be freed when the tune completes or when
894  * the next tune request is received (i.e. above). */
895  ciplus_pmt = tune_data->u.service.pmt;
896  }
897  /* Tune the live path to the service requested by CI+ */
898  ACTL_TuneToCIService(INVALID_RES_ID, &owner_info, tune_data->u.service.s_ptr,
899  tune_data->u.service.reqd_si);
900  break;
901  }
902  }
903  }
904  break;
905  }
906 
907  case APP_EVENT_CIPLUS_TUNE_COMPLETED:
908  {
909  path = *(U8BIT *)event_info.data;
910  if ((owner_data = STB_DPGetOwnerData(path, &data_size)) != NULL)
911  {
912  ACI_TuneReply(path, *(U32BIT *)owner_data, CIP_TUNER_LOCKED);
913  }
914 
915  if (ciplus_pmt != NULL)
916  {
917  if ((serv_ptr = ADB_GetTunedService(path)) != NULL)
918  {
919  /* The PMT was provided by CI+, so it's now time to use it */
920  ASI_ProcessPmt(path, serv_ptr, ciplus_pmt);
921  }
922 
923  /* PMT no longer required, so release it */
924  STB_AppFreeMemory(ciplus_pmt);
925  ciplus_pmt = NULL;
926  }
927 
928  /* Inform the UI that the service has changed */
929  if ((serv_ptr = ADB_GetTunedService(path)) != NULL)
930  {
931  STB_ERSendEvent(FALSE, FALSE, EV_CLASS_APPLICATION, EV_SERVICE_CHANGED,
932  &serv_ptr, sizeof(void *));
933  }
934 
935  break;
936  }
937 
938  case STB_EVENT_CI_RELEASE_REPLY:
939  {
940  reply_data = (S_CIP_RELEASE_REPLY *)event_info.data;
941  if (reply_data != NULL)
942  {
943  AP_CI_PRINT(("%s: STB_EVENT_CI_RELEASE_REPLY %u", __FUNCTION__, reply_data->reply));
944  if (reply_data->reply == 0)
945  {
946  ACTL_ContinueCIPLUSTune(reply_data->path, TRUE);
947  }
948  else
949  {
950  ACTL_ContinueCIPLUSTune(reply_data->path, FALSE);
951  }
952  }
953  break;
954  }
955 
956  case STB_EVENT_CI_OPERATOR_SEARCH_FINISHED:
957  {
958  OperatorSearchFinished();
959  break;
960  }
961 
962  case STB_EVENT_CI_RECORD_START:
963  {
964  APVR_CIRecordReplyReceived(TRUE, *(U8BIT *)event_info.data);
965  break;
966  }
967 
968  case STB_EVENT_CI_RECORD_START_FAILED:
969  {
970  APVR_CIRecordReplyReceived(FALSE, *(U8BIT *)event_info.data);
971  break;
972  }
973  default:
974  {
975  break;
976  }
977  }
978 
979  /* The memory associated with the event can now be freed */
980  if (event_info.data != NULL)
981  {
982  STB_AppFreeMemory(event_info.data);
983  }
984  }
985  }
986 
987  FUNCTION_FINISH(CIPlusEventTask);
988 }
989 
990 //----------------------------------------------------------------------------
991 //---Global function prototypes for this file---------------------------------
992 //----------------------------------------------------------------------------
993 
994 void ACI_Initialise(void)
995 {
996  ciplus_event_queue = STB_OSCreateQueue(sizeof(S_EVENT_INFO), MAX_EVENTS);
997  STB_OSCreateTask(CIPlusEventTask, NULL, TASK_STACK_SIZE, TASK_PRIORITY, (U8BIT *)"CI+EventTask");
1000  ACI_OpInitialise();
1001  APP_RegisterDVBEventHandler(CIPlusEventHandler);
1003 }
1004 
1010 {
1011  FUNCTION_START(ACI_GetCamUpgradeMode);
1012  FUNCTION_FINISH(ACI_GetCamUpgradeMode);
1013  return(cam_upgrade_mode);
1014 }
1015 
1020 void ACI_SetCamUpgradeMode(U8BIT upgrade_mode)
1021 {
1022  FUNCTION_START(ACI_SetCamUpgradeMode);
1023  cam_upgrade_mode = upgrade_mode;
1024  FUNCTION_FINISH(ACI_SetCamUpgradeMode);
1025 }
1026 
1031 E_CIP_START_OPERATOR_SEARCH ACI_GetOperatorSearchMode(void)
1032 {
1033  FUNCTION_START(ACI_GetOperatorSearchMode);
1034  FUNCTION_FINISH(ACI_GetOperatorSearchMode);
1035  return(operator_search_mode);
1036 }
1037 
1044 void ACI_SetOperatorSearchMode(E_CIP_START_OPERATOR_SEARCH search_mode)
1045 {
1046  FUNCTION_START(ACI_SetCamUpgradeMode);
1047  operator_search_mode = search_mode;
1048  FUNCTION_FINISH(ACI_SetOperatorSearchMode);
1049 }
1050 
1056 void ACI_OperatorSearchRequired(U32BIT module, BOOLEAN required)
1057 {
1058  void *profile;
1059 
1060  FUNCTION_START(ACI_OperatorSearchRequired);
1061 
1062  if ((profile = ADB_FindProfileForModule(module)) != NULL)
1063  {
1064  ADB_SetProfileSearchRequired(profile, TRUE, 0, 0, 0);
1065  }
1066  else
1067  {
1068  /* A profile doesn't exist for this module yet (probably the initial search),
1069  * so store the info so the app can access it */
1070  operator_search_required = required;
1071 
1072  if (required)
1073  {
1074  operator_search_module = module;
1075  }
1076  }
1077 
1078  FUNCTION_FINISH(ACI_OperatorSearchRequired);
1079 }
1080 
1088 void ACI_ScheduleOperatorSearch(U32BIT cicam_id, U16BIT date, U8BIT hour, U8BIT min)
1089 {
1090  U32BIT timer_handle;
1091  S_TIMER_INFO info;
1092 
1093  FUNCTION_START(ACI_ScheduleOperatorSearch);
1094 
1095  /* Create a timer to trigger when the search is due */
1096  info.start_time = DHMS_CREATE(date, hour, min, 0);
1097  info.type = TIMER_TYPE_PRIVATE;
1098  info.frequency = TIMER_FREQ_ONCE;
1099  timer_handle = ATMR_AddTimer(&info);
1100  if (timer_handle != INVALID_TIMER_HANDLE)
1101  {
1102  /* Save the timer / CICAM association */
1103  ADB_SetProfileSearchTimer(cicam_id, timer_handle);
1104  ADB_SaveDatabase();
1105  }
1106 
1107  FUNCTION_FINISH(ACI_ScheduleOperatorSearch);
1108 }
1109 
1115 {
1116  FUNCTION_START(ACI_IsOperatorSearchRequired);
1117  FUNCTION_FINISH(ACI_IsOperatorSearchRequired);
1118  return(operator_search_required);
1119 }
1120 
1126 {
1127  FUNCTION_START(ACI_GetOperatorSearchModule);
1128  FUNCTION_FINISH(ACI_GetOperatorSearchModule);
1129  return(operator_search_module);
1130 }
1131 
1138 BOOLEAN ACI_GetFirstOperatorSearchModule(U32BIT *module)
1139 {
1140  BOOLEAN retval;
1141  void **profile_list;
1142  U16BIT num_profiles;
1143  U16BIT active_profile;
1144  U16BIT i;
1145 
1146  FUNCTION_START(ACI_GetFirstOperatorSearchModule);
1147 
1148  retval = FALSE;
1149 
1150  if ((num_profiles = ADB_GetProfileList(&profile_list, &active_profile)) > 0)
1151  {
1152  for (i = 0; (i < num_profiles) && !retval; i++)
1153  {
1154  if ((ADB_GetProfileType(profile_list[i]) == ADB_PROFILE_TYPE_CIPLUS) &&
1155  ADB_GetProfileModulePresent(profile_list[i]) &&
1156  ADB_GetProfileSearchRequired(profile_list[i]))
1157  {
1158  /* Have found a module that needs to be updated */
1159  *module = ADB_GetProfileModule(profile_list[i]);
1160  retval = TRUE;
1161  }
1162  }
1163 
1164  ADB_ReleaseProfileList(profile_list, num_profiles);
1165  }
1166 
1167  FUNCTION_FINISH(ACI_GetFirstOperatorSearchModule);
1168 
1169  return(retval);
1170 }
1171 
1181 BOOLEAN ACI_GetFirstScheduledOperatorSearch(U32BIT *module, U16BIT *date, U8BIT *hours, U8BIT *mins)
1182 {
1183  BOOLEAN retval;
1184  void **profile_list;
1185  U16BIT num_profiles;
1186  U16BIT active_profile;
1187  U16BIT i, profile_index;
1188  U16BIT min_date, profile_date;
1189  U8BIT min_hours, profile_hours;
1190  U8BIT min_mins, profile_mins;
1191 
1192  FUNCTION_START(ACI_GetFirstScheduledOperatorSearch);
1193 
1194  retval = FALSE;
1195 
1196  if ((num_profiles = ADB_GetProfileList(&profile_list, &active_profile)) > 0)
1197  {
1198  min_date = 0xffff;
1199  min_hours = 0xff;
1200  min_mins = 0xff;
1201  profile_index = num_profiles + 1;
1202 
1203  for (i = 0; i < num_profiles; i++)
1204  {
1205  if ((ADB_GetProfileType(profile_list[i]) == ADB_PROFILE_TYPE_CIPLUS) &&
1206  ADB_GetProfileModulePresent(profile_list[i]) &&
1207  ADB_GetProfileSearchDateTime(profile_list[i], &profile_date, &profile_hours, &profile_mins))
1208  {
1209  /* Have found a module that needs to be updated.
1210  * Check whether this is earlier than any previous module */
1211  if ((profile_date <= min_date) && (profile_hours <= min_hours) &&
1212  (profile_mins < min_mins))
1213  {
1214  min_date = profile_date;
1215  min_hours = profile_hours;
1216  min_mins = profile_mins;
1217  profile_index = i;
1218  }
1219  }
1220  }
1221 
1222  if (profile_index < num_profiles)
1223  {
1224  *module = ADB_GetProfileModule(profile_list[profile_index]);
1225  *date = min_date;
1226  *hours = min_hours;
1227  *mins = min_mins;
1228  retval = TRUE;
1229  }
1230 
1231  ADB_ReleaseProfileList(profile_list, num_profiles);
1232  }
1233 
1234  FUNCTION_FINISH(ACI_GetFirstScheduledOperatorSearch);
1235 
1236  return(retval);
1237 }
1238 
1244 BOOLEAN ACI_StartOperatorSearchForModule(U32BIT module)
1245 {
1246  BOOLEAN retval;
1247  void *profile;
1248  U8BIT path;
1249 
1250  FUNCTION_START(ACI_StartOperatorSearchForModule);
1251 
1252  retval = FALSE;
1253 
1254  if ((profile = ADB_FindProfileForModule(module)) != NULL)
1255  {
1256  if (ADB_GetProfileSearchRequired(profile))
1257  {
1258  /* Search is being started so clear the required flag */
1259  ADB_SetProfileSearchRequired(profile, FALSE, 0, 0, 0);
1260 
1261  retval = ACI_StartOperatorSearch(module);
1262  }
1263  }
1264  else if (operator_search_required)
1265  {
1266  /* Search is being started so clear the required flag */
1267  ACI_OperatorSearchRequired(module, FALSE);
1268 
1269  retval = ACI_StartOperatorSearch(module);
1270  }
1271 
1272  if (retval)
1273  {
1274  /* Save the tuned service so it can be returned to when the operator search has completed */
1275  if ((path = STB_DPGetLivePath()) != INVALID_RES_ID)
1276  {
1277  operator_search_service = STB_DPGetTunedService(path);
1278  }
1279  }
1280 
1281  FUNCTION_FINISH(ACI_StartOperatorSearchForModule);
1282 
1283  return(retval);
1284 }
1285 
1292 BOOLEAN ACI_HandlePrivateTimer(U32BIT timer_handle)
1293 {
1294  BOOLEAN valid, retval;
1295  U32BIT module;
1296  ADB_CICAM_TIMER_REC *t;
1297 
1298  FUNCTION_START(ACI_HandlePrivateTimer);
1299 
1300  AP_CI_PRINT(("ACI_HandlePrivateTimer(0x%x)", timer_handle));
1301 
1302  valid = FALSE;
1303  retval = FALSE;
1304 
1306  t = DBDEF_FindCicamTimerByHandle(timer_handle);
1307  if (t != NULL)
1308  {
1309  retval = TRUE;
1310  if (ACI_FindOperatorProfileModule(t->cicam_identifier, &module))
1311  {
1312  /* Found the CICAM that requested the scheduled profile update, the search can only be
1313  performed if the module is present */
1314  valid = TRUE;
1315  }
1316  }
1318 
1319  if (retval)
1320  {
1321  AP_CI_PRINT(("Timer is associated with CICAM 0x%x", t->cicam_identifier));
1322  /* Delete the timer and clear it from the profile */
1323  ATMR_DeleteTimer(timer_handle);
1324  ADB_DeleteCicamTimerbyHandle(timer_handle);
1325  }
1326 
1327  if (valid)
1328  {
1329  AP_CI_PRINT(("CI+ Operator profile module is 0x%x, search mode is %s", module,
1330  (operator_search_mode == CIP_START_OPERATOR_SEARCH_NO) ? "NO" :
1331  (operator_search_mode == CIP_START_OPERATOR_SEARCH_YES) ? "YES" :
1332  (operator_search_mode == CIP_START_OPERATOR_SEARCH_ASK) ? "ASK" : "Unexpected"));
1333  switch (operator_search_mode)
1334  {
1335  case CIP_START_OPERATOR_SEARCH_NO:
1336  {
1337  /* Search can't be started */
1338  break;
1339  }
1340 
1341  case CIP_START_OPERATOR_SEARCH_YES:
1342  {
1343  /* Search can be started, set flag to indicate a search is required */
1344  ACI_OperatorSearchRequired(module, TRUE);
1346  break;
1347  }
1348 
1349  case CIP_START_OPERATOR_SEARCH_ASK:
1350  {
1351  /* Set flag to indicate a search is required */
1352  ACI_OperatorSearchRequired(module, TRUE);
1353 
1354  if (ASTE_InStandby())
1355  {
1356  AP_CI_PRINT(("ACI_HandlePrivateTimer: in stand-by"));
1357  /* In standby so search can be started */
1359  }
1360  else
1361  {
1362  AP_CI_PRINT(("ACI_HandlePrivateTimer: ask the user"));
1363  /* Need to ask if it can be started now */
1364  STB_ERSendEvent(FALSE, FALSE, EV_CLASS_CI, EV_TYPE_CI_REQUEST_OPERATOR_SEARCH,
1365  &module, sizeof(module));
1366  }
1367  }
1368  }
1369  }
1370 
1371  FUNCTION_FINISH(ACI_HandlePrivateTimer);
1372 
1373  return (retval);
1374 }
1375 
1380 BOOLEAN ACI_SetSecureRouting(U8BIT path)
1381 {
1382  BOOLEAN retval;
1383  U8BIT slot_id, num_slots;
1384  BOOLEAN pass_through;
1385 
1386  FUNCTION_START(ACI_SetSecureRouting);
1387 
1388  retval = TRUE;
1389 
1390  /* Ensure the TS for the path isn't being routed through a CI slot unless it contains a CI+ CAM */
1391  if ((num_slots = STB_CIGetSlotCount()) > 0)
1392  {
1393  for (slot_id = 0; (slot_id < num_slots) && retval; slot_id++)
1394  {
1395  pass_through = TRUE;
1396 
1397  /* IDs for the CI stack start at 1...this needs sorting out */
1398  if (STB_CiCcAuthenticated(slot_id))
1399  {
1400  /* Check whether the slot is already being used by another path */
1401  if (STB_DPIsCISlotInUse(INVALID_RES_ID, slot_id, path) != INVALID_RES_ID)
1402  {
1403  pass_through = FALSE;
1404  }
1405  }
1406  else
1407  {
1408  /* Nothing in the slot, or not a CI+ module, so bypass it */
1409  pass_through = FALSE;
1410  }
1411 
1412  if (!pass_through)
1413  {
1414  /* Bypass the slot to ensure it isn't modified */
1415  AP_CI_PRINT(("ACI_SetSecureRouting(%u): releasing slot %u from path", path, slot_id));
1416  ReleaseCISlotFromPath(path);
1417  }
1418  }
1419  }
1420 
1421  FUNCTION_FINISH(ACI_SetSecureRouting);
1422 
1423  return(retval);
1424 }
1425 
1433 BOOLEAN ACI_AcquireCISlot(U8BIT path, void *s_ptr)
1434 {
1435  U8BIT slot_id;
1436  U8BIT *pmt_data;
1437  U16BIT service_id;
1438  U16BIT data_len;
1439  void *ci_prot;
1440  BOOLEAN retval;
1441 
1442  FUNCTION_START(ACI_AcquireCISlot);
1443 
1444  retval = FALSE;
1445 
1446  if ((STB_DPGetPathCISlot(path) != INVALID_RES_ID) && (STB_DPGetTunedService(path) != s_ptr))
1447  {
1448  AP_CI_PRINT(("ACI_AcquireCISlot(%u, %p): Releasing CAM %u", path, s_ptr,
1449  STB_DPGetPathCISlot(path)));
1450 
1451  /* Release the CAM currently associated with the path as the
1452  * requirements for the CAM may be different for the new service */
1453  ReleaseCISlotFromPath(path);
1454  }
1455 
1456  if (s_ptr != NULL)
1457  {
1458  pmt_data = ADB_GetServicePMTData(s_ptr, &data_len);
1459  ci_prot = ADB_GetServiceCIProtectionDesc(s_ptr);
1460  service_id = ADB_GetServiceId(s_ptr);
1461  }
1462  else
1463  {
1464  pmt_data = NULL;
1465  ci_prot = NULL;
1466  service_id = 0xffff;
1467  }
1468 
1469  slot_id = STB_DPAcquireCISlotForPath(path, pmt_data, ci_prot);
1470  if (slot_id != INVALID_RES_ID)
1471  {
1472  /* Set the recording mode based on whether the slot is being used on the live path */
1473  if (STB_DPIsLivePath(path) || STB_DPIsLivePath(STB_DPIsCISlotInUse(0, slot_id, path)))
1474  {
1475  AP_CI_PRINT(("%s(%u): slot %u, record mode is WATCH for service %u",
1476  __FUNCTION__, path, slot_id, service_id));
1477  STB_CiCcSetRecordOperatingMode(slot_id, STB_CI_MODE_WATCH_AND_BUFFER, service_id);
1478  }
1479  else
1480  {
1481  AP_CI_PRINT(("%s(%u): slot %u, record mode UNATTENDED for service %u",
1482  __FUNCTION__, path, slot_id, service_id));
1483  STB_CiCcSetRecordOperatingMode(slot_id, STB_CI_MODE_UNATTENDED_RECORDING, service_id);
1484  }
1485  /* Apply any CI+ keys */
1486  STB_CiKeysApply(path, slot_id);
1487  }
1488 
1489  AP_CI_PRINT(("ACI_AcquireCISlot(%u, %p): Acquired slot %u, pmt=%p, ci_prot=%p",
1490  path, s_ptr, slot_id, pmt_data, ci_prot));
1491 
1492  if (slot_id != INVALID_RES_ID)
1493  {
1494  retval = TRUE;
1495 
1496  if (path == STB_DPGetLivePath())
1497  {
1498  /* Apply URI on the newly acquired path (if live) */
1499  ApplyUsageRules(path, s_ptr);
1500  }
1501  }
1502 
1503  FUNCTION_FINISH(ACI_AcquireCISlot);
1504 
1505  return(retval);
1506 }
1507 
1515 BOOLEAN ACI_AcquireCISlotForRecording(U8BIT path, void* s_ptr)
1516 {
1517  U8BIT slot_id;
1518  U8BIT *pmt_data;
1519  U16BIT data_len;
1520  U8BIT live_path;
1521  BOOLEAN slot_acquired;
1522 
1523  FUNCTION_START(ACI_AcquireCISlotForRecording);
1524 
1525  slot_acquired = ACI_AcquireCISlot(path, s_ptr);
1526  if (!slot_acquired)
1527  {
1528  /* See whether the slot needs to be taken away from the live path */
1529  if ((live_path = STB_DPGetLivePath()) != INVALID_RES_ID)
1530  {
1531  /* CI slot may need to be taken, but only if the service is
1532  * scrambled and the CAM supports the CAS (and the live is tuned
1533  * to a different service) */
1534  slot_id = STB_DPGetPathCISlot(live_path);
1535  if (slot_id != INVALID_RES_ID)
1536  {
1537  AP_CI_PRINT(("[ACI] Slot is used by live path"));
1538  pmt_data = ADB_GetServicePMTData(s_ptr, &data_len);
1539  if (STB_CiCcIsServiceAllowed(slot_id, NULL) &&
1540  STB_CiCaSystemSupported(slot_id, pmt_data))
1541  {
1542  /* Unfortunately the recording requires the CI slot */
1543  AP_CI_PRINT(("[ACI] slot is needed for recording, so take away from live path"));
1544 
1545  /* Clear keys (not required as the CAM is taken) */
1546  STB_CiKeysClear(live_path, slot_id);
1547 
1548  /* CI slot will be used by the recording path */
1549  ReleaseCISlotFromPath(live_path);
1550 
1551  /* Now try to acquire a slot again */
1552  slot_acquired = ACI_AcquireCISlot(path, s_ptr);
1553 
1554  /* TODO: Would be nice to let the user know what just happened */
1555  }
1556  }
1557  else
1558  {
1559  /* Slot must be used for another recording */
1560  }
1561  }
1562  else
1563  {
1564  /* Slot must be used for another recording */
1565  }
1566  }
1567 
1568  FUNCTION_FINISH(ACI_AcquireCISlotForRecording);
1569 
1570  return(slot_acquired);
1571 }
1572 
1578 U8BIT ACI_FindCISlotForService(void *serv_ptr)
1579 {
1580  U8BIT slot_id;
1581  U8BIT id, num_slots;
1582  void *pmt_data;
1583  U16BIT data_len;
1584 
1585  FUNCTION_START(ACI_FindCISlotForService);
1586  slot_id = INVALID_RES_ID;
1587  if ((num_slots = STB_CIGetSlotCount()) > 0)
1588  {
1589  if (serv_ptr != NULL)
1590  {
1591  pmt_data = ADB_GetServicePMTData(serv_ptr, &data_len);
1592  for (id = 0; id != num_slots; id++)
1593  {
1594  if (STB_CiCcAuthenticated(id) &&
1595  STB_CiCaSystemSupported(id, pmt_data))
1596  {
1597  /* Found a CI+ CAM that supports this service */
1598  slot_id = id;
1599  break;
1600  }
1601  }
1602  }
1603  }
1604  FUNCTION_FINISH(ACI_FindCISlotForService);
1605  return(slot_id);
1606 }
1607 
1613 {
1614  void *s_ptr;
1615 
1616  FUNCTION_START(ACI_UsageRulesStatusChanged);
1617  if (STB_CIGetSlotCount() > 0)
1618  {
1619  /* URIs are associated with specific services, so if there is
1620  * no service, the URI is meaningless */
1621  s_ptr = ADB_GetTunedService(path);
1622  if (s_ptr != NULL)
1623  {
1624  /* The URI is applied to the CAM being used by the decoding path */
1625  ApplyUsageRules(path, s_ptr);
1626 
1627  /* Any recording on the path should be updated */
1628  UpdateRecordingURI(path, s_ptr);
1629  }
1630  }
1631  FUNCTION_FINISH(ACI_UsageRulesStatusChanged);
1632 }
1633 
1639 {
1640  U8BIT path;
1641  U8BIT num_paths;
1642  void *s_ptr;
1643  U8BIT slot_id;
1644  U16BIT service_id;
1645 
1646  FUNCTION_START(ACI_ProgramMapTableChanged);
1647 
1648  //AP_CI_PRINT(("[ACI] ACI_ProgramMapTableChanged"));
1649 
1650  if (STB_CIGetSlotCount() > 0)
1651  {
1652  num_paths = STB_DPGetNumPaths();
1653  for (path = 0; path < num_paths; path++)
1654  {
1655  slot_id = STB_DPGetPathCISlot(path);
1656  if (slot_id == INVALID_RES_ID || !STB_CiCcIsSlotReady(slot_id))
1657  {
1658  /* The path does not use the CI slot, or slot not ready, PMT is irrelevant */
1659  continue;
1660  }
1661 
1662  s_ptr = ADB_GetTunedService(path);
1663  if (s_ptr == NULL)
1664  {
1665  /* The PMT is irrelevant to the path */
1666  continue;
1667  }
1668 
1669  service_id = pmt[3] << 8 | pmt[4];
1670  if (ADB_GetServiceId(s_ptr) == service_id)
1671  {
1672  /* Update the CAM */
1673  //AP_CI_PRINT(("[ACI] Calling CIP_ReportPmt(%d, %p)", slot_id, pmt));
1674  STB_CiCaReportPmt(slot_id, pmt);
1675  }
1676  }
1677  }
1678 
1679  FUNCTION_FINISH(ACI_ProgramMapTableChanged);
1680 }
1681 
1688 BOOLEAN ACI_IsTrustedPath(U8BIT path)
1689 {
1690  BOOLEAN trusted;
1691  U8BIT slot_id;
1692 
1693  FUNCTION_START(ACI_IsTrustedPath);
1694 
1695  trusted = FALSE;
1696 
1697  slot_id = STB_DPGetPathCISlot(path);
1698 
1699  if ((slot_id == INVALID_RES_ID) || STB_CiCcAuthenticated(slot_id))
1700  {
1701  trusted = TRUE;
1702  }
1703 
1704  FUNCTION_FINISH(ACI_IsTrustedPath);
1705 
1706  return(trusted);
1707 }
1708 
1714 S32BIT ACI_ReadPinForSlot(U8BIT slot_id)
1715 {
1716  S32BIT saved_pin;
1717  U8BIT cicam_id[CIP_CICAM_ID_LEN];
1718  U8BIT id_nvm[CIP_CICAM_ID_LEN];
1719  U32BIT nvm_value;
1720  U32DHMS used_time;
1721 
1722  FUNCTION_START(ACI_ReadPinForSlot);
1723 
1724  saved_pin = -1;
1725 
1726  /* Get the cicam id for the given slot */
1727  if (STB_CIGetCicamId(slot_id, cicam_id))
1728  {
1729  /* Check this against each saved cicam id to see if the pin is available */
1730  nvm_value = APP_NvmRead(CICAM_ID0_0_NVM);
1731  memcpy(&id_nvm[0], &nvm_value, 4);
1732  nvm_value = APP_NvmRead(CICAM_ID0_1_NVM);
1733  memcpy(&id_nvm[4], &nvm_value, 4);
1734 
1735  if (memcmp(cicam_id, id_nvm, sizeof(cicam_id)) == 0)
1736  {
1737  /* This is the cicam id for the CAM in the given slot, so return this pin */
1738  saved_pin = APP_NvmRead(CICAM_PIN0_NVM);
1739 
1740  /* Update the date/time this pin was last used */
1741  used_time = STB_GCNowDHMSGmt();
1742  APP_NvmSave(CICAM_PIN0_USED_TIME_NVM, used_time, TRUE);
1743  }
1744  else
1745  {
1746  nvm_value = APP_NvmRead(CICAM_ID1_0_NVM);
1747  memcpy(&id_nvm[0], &nvm_value, 4);
1748  nvm_value = APP_NvmRead(CICAM_ID1_1_NVM);
1749  memcpy(&id_nvm[4], &nvm_value, 4);
1750 
1751  if (memcmp(cicam_id, id_nvm, sizeof(cicam_id)) == 0)
1752  {
1753  /* This is the cicam id for the CAM in the given slot, so return this pin */
1754  saved_pin = APP_NvmRead(CICAM_PIN1_NVM);
1755 
1756  /* Update the date/time this pin was last used */
1757  used_time = STB_GCNowDHMSGmt();
1758  APP_NvmSave(CICAM_PIN1_USED_TIME_NVM, used_time, TRUE);
1759  }
1760  else
1761  {
1762  nvm_value = APP_NvmRead(CICAM_ID2_0_NVM);
1763  memcpy(&id_nvm[0], &nvm_value, 4);
1764  nvm_value = APP_NvmRead(CICAM_ID2_1_NVM);
1765  memcpy(&id_nvm[4], &nvm_value, 4);
1766 
1767  if (memcmp(cicam_id, id_nvm, sizeof(cicam_id)) == 0)
1768  {
1769  /* This is the cicam id for the CAM in the given slot, so return this pin */
1770  saved_pin = APP_NvmRead(CICAM_PIN2_NVM);
1771 
1772  /* Update the date/time this pin was last used */
1773  used_time = STB_GCNowDHMSGmt();
1774  APP_NvmSave(CICAM_PIN2_USED_TIME_NVM, used_time, TRUE);
1775  }
1776  else
1777  {
1778  nvm_value = APP_NvmRead(CICAM_ID3_0_NVM);
1779  memcpy(&id_nvm[0], &nvm_value, 4);
1780  nvm_value = APP_NvmRead(CICAM_ID3_1_NVM);
1781  memcpy(&id_nvm[4], &nvm_value, 4);
1782 
1783  if (memcmp(cicam_id, id_nvm, sizeof(cicam_id)) == 0)
1784  {
1785  /* This is the cicam id for the CAM in the given slot, so return this pin */
1786  saved_pin = APP_NvmRead(CICAM_PIN3_NVM);
1787 
1788  /* Update the date/time this pin was last used */
1789  used_time = STB_GCNowDHMSGmt();
1790  APP_NvmSave(CICAM_PIN3_USED_TIME_NVM, used_time, TRUE);
1791  }
1792  }
1793  }
1794  }
1795  }
1796 
1797  FUNCTION_FINISH(ACI_ReadPinForSlot);
1798 
1799  return(saved_pin);
1800 }
1801 
1810 BOOLEAN ACI_WritePinForSlot(U8BIT slot_id, S32BIT pin)
1811 {
1812  BOOLEAN retval;
1813  U8BIT cicam_id[CIP_CICAM_ID_LEN];
1814  U8BIT id_nvm[CIP_CICAM_ID_LEN];
1815  U32BIT nvm_value;
1816  U32DHMS used_time;
1817  U32DHMS used0, used1, used2, used3;
1818 
1819  FUNCTION_START(ACI_WritePinForSlot);
1820 
1821  retval = FALSE;
1822 
1823  /* Get the cicam id for the given slot */
1824  if (STB_CIGetCicamId(slot_id, cicam_id))
1825  {
1826  /* There's a CAM in the given slot, so the pin will be saved */
1827  retval = TRUE;
1828 
1829  /* Check whether there's already an entry for this cicam id.
1830  * If the cicam id isn't found but an empty entry is then the pin for this cicam
1831  * hasn't previously been saved and the entry can be used */
1832  nvm_value = APP_NvmRead(CICAM_ID0_0_NVM);
1833  memcpy(&id_nvm[0], &nvm_value, 4);
1834  nvm_value = APP_NvmRead(CICAM_ID0_1_NVM);
1835  memcpy(&id_nvm[4], &nvm_value, 4);
1836 
1837  if ((memcmp(cicam_id, id_nvm, sizeof(cicam_id)) == 0) ||
1838  ((S32BIT)APP_NvmRead(CICAM_PIN0_NVM) < 0))
1839  {
1840  /* This entry can be used to save the pin */
1841  nvm_value = *(U32BIT *)&cicam_id[0];
1842  APP_NvmSave(CICAM_ID0_0_NVM, nvm_value, FALSE);
1843  nvm_value = *(U32BIT *)&cicam_id[4];
1844  APP_NvmSave(CICAM_ID0_1_NVM, nvm_value, FALSE);
1845 
1846  APP_NvmSave(CICAM_PIN0_NVM, pin, FALSE);
1847 
1848  /* Update the date/time this pin was last used */
1849  used_time = STB_GCNowDHMSGmt();
1850  APP_NvmSave(CICAM_PIN0_USED_TIME_NVM, used_time, TRUE);
1851  }
1852  else
1853  {
1854  nvm_value = APP_NvmRead(CICAM_ID1_0_NVM);
1855  memcpy(&id_nvm[0], &nvm_value, 4);
1856  nvm_value = APP_NvmRead(CICAM_ID1_1_NVM);
1857  memcpy(&id_nvm[4], &nvm_value, 4);
1858 
1859  if ((memcmp(cicam_id, id_nvm, sizeof(cicam_id)) == 0) ||
1860  ((S32BIT)APP_NvmRead(CICAM_PIN1_NVM) < 0))
1861  {
1862  /* This entry can be used to save the pin */
1863  nvm_value = *(U32BIT *)&cicam_id[0];
1864  APP_NvmSave(CICAM_ID1_0_NVM, nvm_value, FALSE);
1865  nvm_value = *(U32BIT *)&cicam_id[4];
1866  APP_NvmSave(CICAM_ID1_1_NVM, nvm_value, FALSE);
1867 
1868  APP_NvmSave(CICAM_PIN1_NVM, pin, TRUE);
1869 
1870  /* Update the date/time this pin was last used */
1871  used_time = STB_GCNowDHMSGmt();
1872  APP_NvmSave(CICAM_PIN1_USED_TIME_NVM, used_time, TRUE);
1873  }
1874  else
1875  {
1876  nvm_value = APP_NvmRead(CICAM_ID2_0_NVM);
1877  memcpy(&id_nvm[0], &nvm_value, 4);
1878  nvm_value = APP_NvmRead(CICAM_ID2_1_NVM);
1879  memcpy(&id_nvm[4], &nvm_value, 4);
1880 
1881  if ((memcmp(cicam_id, id_nvm, sizeof(cicam_id)) == 0) ||
1882  ((S32BIT)APP_NvmRead(CICAM_PIN2_NVM) < 0))
1883  {
1884  /* This entry can be used to save the pin */
1885  nvm_value = *(U32BIT *)&cicam_id[0];
1886  APP_NvmSave(CICAM_ID2_0_NVM, nvm_value, FALSE);
1887  nvm_value = *(U32BIT *)&cicam_id[4];
1888  APP_NvmSave(CICAM_ID2_1_NVM, nvm_value, FALSE);
1889 
1890  APP_NvmSave(CICAM_PIN2_NVM, pin, TRUE);
1891 
1892  /* Update the date/time this pin was last used */
1893  used_time = STB_GCNowDHMSGmt();
1894  APP_NvmSave(CICAM_PIN2_USED_TIME_NVM, used_time, TRUE);
1895  }
1896  else
1897  {
1898  nvm_value = APP_NvmRead(CICAM_ID3_0_NVM);
1899  memcpy(&id_nvm[0], &nvm_value, 4);
1900  nvm_value = APP_NvmRead(CICAM_ID3_1_NVM);
1901  memcpy(&id_nvm[4], &nvm_value, 4);
1902 
1903  if ((memcmp(cicam_id, id_nvm, sizeof(cicam_id)) == 0) ||
1904  ((S32BIT)APP_NvmRead(CICAM_PIN3_NVM) < 0))
1905  {
1906  /* This entry can be used to save the pin */
1907  nvm_value = *(U32BIT *)&cicam_id[0];
1908  APP_NvmSave(CICAM_ID3_0_NVM, nvm_value, FALSE);
1909  nvm_value = *(U32BIT *)&cicam_id[4];
1910  APP_NvmSave(CICAM_ID3_1_NVM, nvm_value, FALSE);
1911 
1912  APP_NvmSave(CICAM_PIN3_NVM, pin, TRUE);
1913 
1914  /* Update the date/time this pin was last used */
1915  used_time = STB_GCNowDHMSGmt();
1916  APP_NvmSave(CICAM_PIN3_USED_TIME_NVM, used_time, TRUE);
1917  }
1918  else
1919  {
1920  /* Pin for this CAM hasn't previously been saved and all entries are being
1921  * used, so find the oldest entry and overwrite that */
1922  used0 = (U32DHMS)APP_NvmRead(CICAM_PIN0_USED_TIME_NVM);
1923  used1 = (U32DHMS)APP_NvmRead(CICAM_PIN1_USED_TIME_NVM);
1924  used2 = (U32DHMS)APP_NvmRead(CICAM_PIN2_USED_TIME_NVM);
1925  used3 = (U32DHMS)APP_NvmRead(CICAM_PIN3_USED_TIME_NVM);
1926 
1927  if ((used0 < used1) && (used0 < used2) && (used0 < used3))
1928  {
1929  /* This entry can be used to save the pin */
1930  nvm_value = *(U32BIT *)&cicam_id[0];
1931  APP_NvmSave(CICAM_ID0_0_NVM, nvm_value, FALSE);
1932  nvm_value = *(U32BIT *)&cicam_id[4];
1933  APP_NvmSave(CICAM_ID0_1_NVM, nvm_value, FALSE);
1934 
1935  APP_NvmSave(CICAM_PIN0_NVM, pin, TRUE);
1936 
1937  /* Update the date/time this pin was last used */
1938  used_time = STB_GCNowDHMSGmt();
1939  APP_NvmSave(CICAM_PIN0_USED_TIME_NVM, used_time, TRUE);
1940  }
1941  else if ((used1 < used0) && (used1 < used2) && (used1 < used3))
1942  {
1943  /* This entry can be used to save the pin */
1944  nvm_value = *(U32BIT *)&cicam_id[0];
1945  APP_NvmSave(CICAM_ID1_0_NVM, nvm_value, FALSE);
1946  nvm_value = *(U32BIT *)&cicam_id[4];
1947  APP_NvmSave(CICAM_ID1_1_NVM, nvm_value, FALSE);
1948 
1949  APP_NvmSave(CICAM_PIN1_NVM, pin, TRUE);
1950 
1951  /* Update the date/time this pin was last used */
1952  used_time = STB_GCNowDHMSGmt();
1953  APP_NvmSave(CICAM_PIN1_USED_TIME_NVM, used_time, TRUE);
1954  }
1955  else if ((used2 < used0) && (used2 < used1) && (used2 < used3))
1956  {
1957  /* This entry can be used to save the pin */
1958  nvm_value = *(U32BIT *)&cicam_id[0];
1959  APP_NvmSave(CICAM_ID2_0_NVM, nvm_value, FALSE);
1960  nvm_value = *(U32BIT *)&cicam_id[4];
1961  APP_NvmSave(CICAM_ID2_1_NVM, nvm_value, FALSE);
1962 
1963  APP_NvmSave(CICAM_PIN2_NVM, pin, TRUE);
1964 
1965  /* Update the date/time this pin was last used */
1966  used_time = STB_GCNowDHMSGmt();
1967  APP_NvmSave(CICAM_PIN2_USED_TIME_NVM, used_time, TRUE);
1968  }
1969  else
1970  {
1971  /* This entry can be used to save the pin */
1972  nvm_value = *(U32BIT *)&cicam_id[0];
1973  APP_NvmSave(CICAM_ID3_0_NVM, nvm_value, FALSE);
1974  nvm_value = *(U32BIT *)&cicam_id[4];
1975  APP_NvmSave(CICAM_ID3_1_NVM, nvm_value, FALSE);
1976 
1977  APP_NvmSave(CICAM_PIN3_NVM, pin, TRUE);
1978 
1979  /* Update the date/time this pin was last used */
1980  used_time = STB_GCNowDHMSGmt();
1981  APP_NvmSave(CICAM_PIN3_USED_TIME_NVM, used_time, TRUE);
1982  }
1983  }
1984  }
1985  }
1986  }
1987  }
1988 
1989  FUNCTION_FINISH(ACI_WritePinForSlot);
1990 
1991  return(retval);
1992 }
1993 
1994 
2000 void ACI_TuneToTransport(U32BIT module, void *t_ptr)
2001 {
2002  S_CIPLUS_TUNE_DATA tune_data;
2003 
2004  FUNCTION_START(ACI_TuneToTransport);
2005 
2006  tune_data.module = module;
2007  tune_data.type = CIPLUS_TUNE_TYPE_TRANSPORT;
2008  tune_data.u.transport.t_ptr = t_ptr;
2009  STB_ERSendEvent(FALSE, FALSE, EV_CLASS_CI, EV_TYPE_CI_TUNE, &tune_data, sizeof(tune_data));
2010 
2011  FUNCTION_FINISH(ACI_TuneToTransport);
2012 }
2013 
2020 void ACI_TuneToService(U32BIT module, void *s_ptr, E_CIP_TUNE_FLAGS flags)
2021 {
2022  S_CIPLUS_TUNE_DATA tune_data;
2023 
2024  FUNCTION_START(ACI_TuneToService);
2025 
2026  tune_data.module = module;
2027  tune_data.type = CIPLUS_TUNE_TYPE_SERVICE;
2028  tune_data.flags = flags;
2029  tune_data.u.service.s_ptr = s_ptr;
2030  tune_data.u.service.reqd_si = APP_SI_MODE_UPDATE;
2031  tune_data.u.service.pmt = NULL;
2032  STB_ERSendEvent(FALSE, FALSE, EV_CLASS_CI, EV_TYPE_CI_TUNE, &tune_data, sizeof(tune_data));
2033 
2034  FUNCTION_FINISH(ACI_TuneToService);
2035 }
2036 
2044 void ACI_TuneToDelSysDesc(U32BIT module, S_CIP_TUNE_DEL_SYS_DESC *tune, E_CIP_TUNE_FLAGS flags)
2045 {
2046  ADB_TRANSPORT_REC *t_ptr;
2047  ADB_SERVICE_REC *s_ptr;
2048  S_CIPLUS_TUNE_DATA tune_data;
2049  U16BIT pmt_size;
2050 
2051  FUNCTION_START(ACI_TuneToDelSysDesc);
2052 
2054  switch (tune->type)
2055  {
2056  case SI_DEL_SYS_DESC_TYPE_TERR:
2057  {
2058  if (tune->desc->terr.is_t2)
2059  {
2060  t_ptr = NULL;
2061  }
2062  else
2063  {
2064  if ((t_ptr = DBDEF_FindTerrestrialTransportRec(tune->desc->terr.u.t1.freq_hz, 0)) == NULL)
2065  {
2066  AP_CI_PRINT(("%s: new frequency", __FUNCTION__));
2067  t_ptr = DBDEF_AddTerrestrialTransportRec(tune->desc->terr.u.t1.freq_hz, 0, NULL);
2068  }
2069  AP_CI_PRINT(("%s: Terr freq=%d t_ptr=%p", __FUNCTION__, tune->desc->terr.u.t1.freq_hz, t_ptr));
2070  }
2071  break;
2072  }
2073  case SI_DEL_SYS_DESC_TYPE_SAT:
2074  {
2075  if ((t_ptr = DBDEF_FindSatTransportRec(tune->desc->sat.freq_hz, tune->desc->sat.sym_rate,
2076  tune->desc->sat.polarity, tune->desc->sat.dvb_s2, tune->desc->sat.modulation, NULL)) == NULL)
2077  {
2078  AP_CI_PRINT(("%s: new frequency", __FUNCTION__));
2079  t_ptr = DBDEF_AddSatTransportRec(tune->desc->sat.freq_hz, tune->desc->sat.sym_rate,
2080  tune->desc->sat.polarity, tune->desc->sat.dvb_s2, tune->desc->sat.modulation, NULL);
2081  }
2082  AP_CI_PRINT(("%s: Sat freq=%d t_ptr=%p", __FUNCTION__, tune->desc->sat.freq_hz, t_ptr));
2083  break;
2084  }
2085  case SI_DEL_SYS_DESC_TYPE_CABLE:
2086  {
2087  if ((t_ptr = DBDEF_FindCableTransportRec(tune->desc->cable.freq_hz, tune->desc->cable.symbol_rate)) == NULL)
2088  {
2089  AP_CI_PRINT(("%s: new frequency", __FUNCTION__));
2090  t_ptr = DBDEF_AddCableTransportRec(tune->desc->cable.freq_hz, tune->desc->cable.symbol_rate, NULL);
2091  }
2092  AP_CI_PRINT(("%s: Cab freq=%d t_ptr=%p", __FUNCTION__, tune->desc->cable.freq_hz, t_ptr));
2093  break;
2094  }
2095  default:
2096  {
2097  /* Unrecognised tuner type */
2098  AP_CI_PRINT(("%s: Unrecognised tuner type 0x%x", __FUNCTION__, tune->type));
2099  ACI_TuneReply(INVALID_RES_ID, module, CIP_TUNER_UNSUPPORTED_SYSTEM);
2100  t_ptr = NULL;
2101  break;
2102  }
2103  }
2104 
2106 
2107  /* The delivery descriptor can now be freed */
2108  STB_SIReleaseDelSysDesc(tune->desc, tune->type);
2109 
2110  if (t_ptr != NULL)
2111  {
2112  tune_data.module = module;
2113  tune_data.u.transport.t_ptr = t_ptr;
2114 
2115  if (tune->service_id != 0)
2116  {
2118 
2119  s_ptr = DBDEF_FindServiceRecByIds(NULL, ADB_INVALID_DVB_ID,
2120  t_ptr->orig_net_id, t_ptr->tran_id, tune->service_id);
2121  if (s_ptr == NULL)
2122  {
2123  /* Create a service record */
2124  if ((s_ptr = DBDEF_AddServiceRec(tune->service_id, t_ptr)) != NULL)
2125  {
2126  AP_CI_PRINT(("%s: new service with ID 0x%x", __FUNCTION__, tune->service_id));
2127 
2128  /* Make the service hidden and non-selectable so it isn't available to the user */
2129  s_ptr->hidden = TRUE;
2130  DBA_SetFieldValue(s_ptr->dba_rec, DBA_FIELD_SERV_HIDDEN, s_ptr->hidden);
2131  s_ptr->selectable = FALSE;
2132  DBA_SetFieldValue(s_ptr->dba_rec, DBA_FIELD_SERV_SELECTABLE, s_ptr->selectable);
2133  DBA_SaveRecord(s_ptr->dba_rec);
2134 
2135  DBDEF_SetServiceType(s_ptr, tune->service_type);
2136  if (tune->service_name != NULL)
2137  {
2138  DBDEF_SetServiceName(s_ptr,tune->service_name->str_ptr);
2139  }
2140  }
2141  }
2142 
2143  AP_CI_PRINT(("%s: SID 0x%x s_ptr=%p", __FUNCTION__, tune->service_id, s_ptr));
2144 
2145  STB_SIReleaseStringDesc(tune->service_name);
2146 
2147  if ((s_ptr != NULL) && (tune->event_desc != NULL))
2148  {
2149  if (s_ptr->now_event != NULL)
2150  {
2151  /* Free the existing now event */
2152  DBDEF_DeleteEventList(s_ptr->now_event);
2153  }
2154 
2155  if ((s_ptr->now_event = STB_AppGetMemory(sizeof(ADB_EVENT_REC))) != NULL)
2156  {
2157  memset(s_ptr->now_event, 0, sizeof(ADB_EVENT_REC));
2158  s_ptr->now_event->desc_list_head = tune->event_desc;
2159  s_ptr->now_event->desc_list_tail = tune->event_desc;
2160  }
2161  }
2162 
2164 
2165  if (s_ptr != NULL)
2166  {
2167  tune_data.type = CIPLUS_TUNE_TYPE_CI_SERVICE;
2168  tune_data.flags = flags;
2169  tune_data.u.service.s_ptr = s_ptr;
2170 
2171  if (tune->pmt == NULL)
2172  {
2173  /* The PMT hasn't been provided so needs to be obtained from the broadcast */
2174  tune_data.u.service.reqd_si = APP_SI_MODE_CIPLUS_UPDATE;
2175  tune_data.u.service.pmt = NULL;
2176  }
2177  else
2178  {
2179  /* The PMT has been provided so shouldn't be obtained from the broadcast */
2180  tune_data.u.service.reqd_si = APP_SI_MODE_CIPLUS_NO_PAT_PMT;
2181 
2182  /* Copy the PMT data.
2183  * This is a bit nasty, but the PMT data is allocated here and needs to freed by
2184  * when the event is handled, or sometime after. */
2185  pmt_size = ((tune->pmt[1] & 0x0f) << 8) + tune->pmt[2];
2186  if (pmt_size > 0)
2187  {
2188  if ((tune_data.u.service.pmt = STB_AppGetMemory(pmt_size)) != NULL)
2189  {
2190  memcpy(tune_data.u.service.pmt, tune->pmt, pmt_size);
2191  }
2192  }
2193  }
2194 
2195  STB_ERSendEvent(FALSE, FALSE, EV_CLASS_CI, EV_TYPE_CI_TUNE, &tune_data, sizeof(tune_data));
2196  }
2197  else
2198  {
2199  ACI_TuneReply(INVALID_RES_ID, module, CIP_TUNER_SERVICE_NOT_FOUND);
2200  }
2201  }
2202  else
2203  {
2204  /* Just tuning to a transport */
2205  tune_data.type = CIPLUS_TUNE_TYPE_TRANSPORT;
2206  STB_ERSendEvent(FALSE, FALSE, EV_CLASS_CI, EV_TYPE_CI_TUNE, &tune_data, sizeof(tune_data));
2207  }
2208  }
2209  FUNCTION_FINISH(ACI_TuneToDelSysDesc);
2210 }
2211 
2218 BOOLEAN ACI_AskRelease(U32BIT module)
2219 {
2220  BOOLEAN retval;
2221 
2222  FUNCTION_START(ACI_AskRelease);
2223 
2224  retval = ACI_OpAskRelease(module);
2225  if (!retval)
2226  {
2227  retval = ACI_HcAskRelease(module);
2228  }
2229 
2230  FUNCTION_FINISH(ACI_AskRelease);
2231 
2232  return(retval);
2233 }
2234 
2242 void ACI_TuneReply(U8BIT path, U32BIT module, E_CIP_TUNER_STATUS status)
2243 {
2244  FUNCTION_START(ACI_TuneReply);
2245  if (!ACI_HcTuneReply(module, status))
2246  {
2247  ACI_OpTuneReply(path, module, status);
2248  }
2249  FUNCTION_FINISH(ACI_TuneReply);
2250 }
2251 
2257 void ACI_UseCiModuleOnPath(U8BIT path, U32BIT module)
2258 {
2259  void *service;
2260  U16BIT service_id;
2261  U8BIT slot_id;
2262  slot_id = STB_GetCIHostControlSlotId(module);
2263  if (slot_id != INVALID_RES_ID &&
2264  STB_DPUseCISlotWithPath(path, slot_id))
2265  {
2266  service = STB_DPGetTunedService(path);
2267  if (service != NULL)
2268  {
2269  service_id = ADB_GetServiceId(service);
2270  }
2271  else
2272  {
2273  service_id = 0xffff;
2274  }
2275  /* Set the recording mode based on whether the slot is being used on the live path */
2276  if (STB_DPIsLivePath(path) || STB_DPIsLivePath(STB_DPIsCISlotInUse(0, slot_id, path)))
2277  {
2278  AP_CI_PRINT(("%s(%u): slot %u, record mode is WATCH for service %u",
2279  __FUNCTION__, path, slot_id, service_id));
2280  STB_CiCcSetRecordOperatingMode(slot_id, STB_CI_MODE_WATCH_AND_BUFFER, service_id);
2281  }
2282  else
2283  {
2284  AP_CI_PRINT(("%s(%u): slot %u, record mode UNATTENDED for service %u",
2285  __FUNCTION__, path, slot_id, service_id));
2286  STB_CiCcSetRecordOperatingMode(slot_id, STB_CI_MODE_UNATTENDED_RECORDING, service_id);
2287  }
2288  /* Apply any CI+ keys */
2289  STB_CiKeysApply(path, slot_id);
2290  }
2291 }
2292 
2301 BOOLEAN ACI_SendPinToCam(U8BIT slot_id, U32BIT pin)
2302 {
2303  U8BIT pin_str[16];
2304  BOOLEAN retval;
2305 
2306  FUNCTION_START(ACI_SendPinToCam);
2307 
2308  /* Convert the pin value to a string */
2309  sprintf((char *)pin_str, "%lu", (unsigned long)pin);
2310 
2311  /* Send the pin value to the CAM */
2312  retval = STB_CiCcSendPin(slot_id, pin_str);
2313 
2314  FUNCTION_FINISH(ACI_SendPinToCam);
2315 
2316  return(retval);
2317 }
2318 
2324 BOOLEAN ACI_PathOwnedByModule(U8BIT path, U32BIT module)
2325 {
2326  BOOLEAN owned;
2327  void *owner_data;
2328  U32BIT data_size;
2329  if ((STB_DPIsOwnedBy(path, RES_OWNER_CIPLUS)))
2330  {
2331  owner_data = STB_DPGetOwnerData(path, &data_size);
2332  if (owner_data != NULL && module == *(U32BIT *)owner_data)
2333  {
2334  owned = TRUE;
2335  }
2336  else
2337  {
2338  owned = FALSE;
2339  }
2340  }
2341  else
2342  {
2343  owned = FALSE;
2344  }
2345  return owned;
2346 }
2347 
2354 {
2355  NotifyStartTuning = cb_func;
2356 }
BOOLEAN STB_CiCcGetRecordingPinInfo(U8BIT slot_id, U8BIT *status, U8BIT *age_rating, U8BIT **private_data, U16BIT *date_code, U8BIT *hour, U8BIT *min, U8BIT *sec)
Returns the information to be stored with a pin event when recording.
Definition: stbcicc.c:1000
Application level CI control functions.
BOOLEAN STB_DPIsRecording(U8BIT path, U32BIT *handle)
Returns status of recording on specified path.
Definition: stbdpc.c:2189
void ADB_SaveDatabase(void)
Saves the database to non-volatile memory.
Definition: ap_dbacc.c:502
void DBDEF_DeleteEventList(ADB_EVENT_REC *elist)
Deletes all events in the given list.
Definition: ap_dbdef.c:3754
void ACI_SetCamUpgradeMode(U8BIT upgrade_mode)
Sets the CAM upgrade option (Yes/No/Ask)
Definition: ap_ci.c:1020
macros and function prototypes for public use
U8BIT * STB_CiCcGetPlaybackLicence(U8BIT slot_id, U8BIT *licence_status, U16BIT *licence_len, U8BIT raw_uri[CIP_URI_LEN])
Returns the last licence received from the CAM during playback.
Definition: stbcicc.c:1443
U8BIT STB_DPGetPathCISlot(U8BIT path)
Returns the CI slot id associated with the given path.
Definition: stbdpc.c:1082
void * STB_DPGetTunedService(U8BIT path)
Returns the service saved with the given decode path.
Definition: stbdpc.c:1582
U8BIT * STB_CiCcGetRecordingLicence(U8BIT slot_id, U8BIT *licence_status, U16BIT *licence_len, U8BIT raw_uri[CIP_URI_LEN])
Returns the last licence received from the CAM when recording.
Definition: stbcicc.c:1292
BOOLEAN STB_CiCcAuthenticated(U8BIT slot_id)
Tell whether authenticated CI+ module is in the slot.
Definition: stbcicc.c:374
BOOLEAN ACI_IsTrustedPath(U8BIT path)
The given decode path is only trusted if it doesn&#39;t include a CI slot or the CI slot contains a CI+ C...
Definition: ap_ci.c:1688
U8BIT STB_DPAcquireCISlotForPath(U8BIT path, U8BIT *pmt_data, U8BIT *ci_protection_desc)
Acquire a CI slot and assign it to the given path.
Definition: stbdpc.c:956
BOOLEAN STB_DPIsLivePath(U8BIT path)
Is the given decode path being used for live viewing.
Definition: stbdpc.c:1297
void ADB_ReleaseProfileList(void **profile_list, U16BIT num_profiles)
Frees a profile list acquired using ADB_GetProfileList.
Definition: ap_dbacc.c:11393
ADB_TRANSPORT_REC * DBDEF_FindSatTransportRec(U32BIT freq_hz, U16BIT symbol_rate, E_STB_DP_POLARITY polarity, BOOLEAN dvb_s2, E_STB_DP_MODULATION modulation, void *satellite)
Find the satellite transport record in the database matching the given params.
Definition: ap_dbdef.c:5170
BOOLEAN ACI_AskRelease(U32BIT module)
Ask the host control module to restore replaced PIDs and to close the session with the host control r...
Definition: ap_ci.c:2218
Application configuration.
Application database control.
U32DHMS STB_GCNowDHMSGmt(void)
Reads the current GMT date code and time.
Definition: stbgc.c:2264
Header file - macros and function prototypes for public use.
BOOLEAN ACI_PathOwnedByModule(U8BIT path, U32BIT module)
Checks whether path is owned by CI module.
Definition: ap_ci.c:2324
Header file for NVM data handling functions.
BOOLEAN DBDEF_SetServiceType(ADB_SERVICE_REC *s_ptr, ADB_SERVICE_TYPE serv_type)
Sets the service type for the given service record.
Definition: ap_dbdef.c:5969
ADB_TRANSPORT_REC * DBDEF_FindTerrestrialTransportRec(U32BIT freq_hz, U8BIT plp_id)
Find the terrestrial transport record in the database matching the given params.
Definition: ap_dbdef.c:4952
U8BIT STB_DPIsCISlotInUse(U8BIT start_path, U8BIT slot_id, U8BIT ignore_path)
Checks whether a given CI slot is in use.
Definition: stbdpc.c:1109
void STB_CiCaReportPmt(U8BIT slot_id, U8BIT *pmt)
Report PMT to CI stack.
Definition: stbcica.c:207
void * STB_AppGetMemory(U32BIT bytes)
Attempts to allocate memory from the application heap.
Definition: stbheap.c:651
void STB_CiCcGetUsageRulesInfo(U8BIT slot_id, U16BIT service_id, U8BIT uri[CIP_URI_LEN])
Return the current URI for the given service.
Definition: stbcicc.c:449
BOOLEAN ACI_IsOperatorSearchRequired(void)
Returns whether an operator profile search has been requested.
Definition: ap_ci.c:1114
ADB_SERVICE_REC * DBDEF_FindServiceRecByIds(ADB_SERVICE_REC *servp, U32BIT net_id, U32BIT onet_id, U32BIT tran_id, U32BIT serv_id)
Search for a service with the given IDs.
Definition: ap_dbdef.c:6150
BOOLEAN ACI_StartOperatorSearchForModule(U32BIT module)
Called by the app to start an operator profile search for the given module.
Definition: ap_ci.c:1244
void DBA_SaveRecord(void *record)
Forces a record to be saved to non-volatile storage. Depending on the implementation, this function may not do anything if the data is updated to non-volatile storage as any records and/or fields are created or updated.
Definition: dba_nvm.c:1157
Definition: ap_tmr.h:97
BOOLEAN ACI_HandlePrivateTimer(U32BIT timer_handle)
Checks whether the given timer is associated with any of the CI+ profiles and starts the operator sea...
Definition: ap_ci.c:1292
void ASI_ProcessPmt(U8BIT path, void *s_ptr, U8BIT *pmt_data)
Takes data for a raw PMT for the given service and processes it as if it had been received from the d...
Definition: ap_si.c:10035
BOOLEAN DBDEF_SetServiceName(ADB_SERVICE_REC *s_ptr, U8BIT *name)
Set or change the name of a service.
Definition: ap_dbdef.c:5783
ADB_TRANSPORT_REC * DBDEF_AddSatTransportRec(U32BIT freq_hz, U16BIT symbol_rate, E_STB_DP_POLARITY polarity, BOOLEAN dvb_s2, E_STB_DP_MODULATION modulation, ADB_NETWORK_REC *network)
Adds a satellite transport record with the given frequency, symbol rate and polarity.
Definition: ap_dbdef.c:5102
void STB_CiCcApplyUsageRulesInfoForPlayback(U8BIT *uri)
Apply the given Usage Rules Information for playback.
Definition: stbcicc.c:578
BOOLEAN ACI_HcAskRelease(U32BIT module)
Ask the module to restore replaced PIDs and to close the session with the host control resource...
Definition: ap_cihc.c:236
ADB_TRANSPORT_REC * DBDEF_AddTerrestrialTransportRec(U32BIT freq_hz, U8BIT plp_id, ADB_NETWORK_REC *network)
Adds a terrestrial transport record with the given frequency and PLP id.
Definition: ap_dbdef.c:4874
U32BIT APP_NvmRead(E_NVM_ITEMS nvm_item)
Returns the current value for the given DVB setting.
Definition: app_nvm.c:562
BOOLEAN STB_CiCaSystemSupported(U8BIT slot_id, U8BIT *pmt_data)
Tell whether CA descriptors were found in PMT and that CA system is supported.
Definition: stbcica.c:247
ADB_PROFILE_TYPE ADB_GetProfileType(void *profile)
Returns the type of the given profile.
Definition: ap_dbacc.c:11407
void STB_SIReleaseStringDesc(SI_STRING_DESC *desc)
Frees the memory used by the descriptor specified.
Definition: stbsitab.c:12040
void ACI_ProgramMapTableChanged(U8BIT *pmt)
Handle PMT change.
Definition: ap_ci.c:1638
U8BIT * ADB_GetServicePMTData(void *s_ptr, U16BIT *data_len)
Returns the current PMT data for the given service.
Definition: ap_dbacc.c:11293
BOOLEAN ACI_HcTuneReply(U32BIT module, E_STB_CI_TUNE_STATUS status)
Send status of tune operation to the CAM host control module.
Definition: ap_cihc.c:591
void STB_SIReleaseDelSysDesc(SI_DELIVERY_SYS_DESC *desc, SI_DELIVERY_SYS_DESC_TYPE type)
Frees the memory used by the descriptor specified.
Definition: stbsitab.c:11989
Application timer functions and defines.
CI Conditional Access.
void APP_NvmSave(E_NVM_ITEMS nvm_item, U32BIT new_value, BOOLEAN write_to_flash_now)
Sets the current value for the given DVB setting.
Definition: app_nvm.c:634
void ACI_HcInitialise(void)
Initialise CI Host Control support.
Definition: ap_cihc.c:101
void ACI_TuneToService(U32BIT module, void *s_ptr, E_CIP_TUNE_FLAGS flags)
Schedule a tune to a service.
Definition: ap_ci.c:2020
void ACI_TuneToDelSysDesc(U32BIT module, S_CIP_TUNE_DEL_SYS_DESC *tune, E_CIP_TUNE_FLAGS flags)
Tune to a service/transport defined by a delivery system descriptor, possibly with PMT data...
Definition: ap_ci.c:2044
BOOLEAN STB_DPReleasePath(U8BIT path, E_STB_DP_RES_OWNER owner)
Releases the decode path and all resources no longer needed. The path won&#39;t be released if the path i...
Definition: stbdpc.c:785
Header file - macros and function prototypes for public use.
void STB_ERSendEvent(BOOLEAN latched, BOOLEAN repeat, U16BIT path_class, U16BIT type, void *data, U32BIT data_size)
Sends an event to event reporting control module.
Definition: stberc.c:571
Application level CI Host Control functions.
CI Content Control.
BOOLEAN STB_DPUseCISlotWithPath(U8BIT path, U8BIT slot_id)
Use the given CI slot with the given path.
Definition: stbdpc.c:1011
BOOLEAN ACI_AcquireCISlotForRecording(U8BIT path, void *s_ptr)
Acquires a CI slot for the recording path. This function may need to "steal" the CI slot from the liv...
Definition: ap_ci.c:1515
BOOLEAN ACI_FindOperatorProfileModule(U32BIT cicam_id, U32BIT *module)
Returns the Operator Profile module associated with a CICAM ID.
Definition: ap_ciop.c:355
U8BIT STB_DPGetNumPaths(void)
Returns the maximum number of decode paths.
Definition: stbdpc.c:532
void ACI_UseCiModuleOnPath(U8BIT path, U32BIT module)
Use the CI module with the given path.
Definition: ap_ci.c:2257
U8BIT STB_DPGetPlaybackPath(void)
Returns the ID of the decode path being used for playback.
Definition: stbdpc.c:1373
U8BIT ACI_FindCISlotForService(void *serv_ptr)
Looks for a CAM that&#39;s able to descramble the given service and returns its slot id.
Definition: ap_ci.c:1578
U8BIT STB_DPGetLivePath(void)
Returns the ID of the decode path being used for live viewing.
Definition: stbdpc.c:1271
U32BIT APVR_GetPlaybackHandle(void)
Returns the handle of the recording currently being played back.
Definition: ap_pvr.c:1145
BOOLEAN STB_DPIsDecodingPath(U8BIT path)
Is the given decode path being used for decoding.
Definition: stbdpc.c:1346
BOOLEAN STB_CiCcIsSlotReady(U8BIT slot_id)
Return whether CI slot is ready.
Definition: stbcicc.c:319
void STB_CiKeysClear(U8BIT path, U8BIT slot_id)
Clear CC keys (if any) from given path.
Definition: stbcikeys.c:392
U16BIT ADB_GetTransportTid(void *t_ptr)
Returns the transport id of the given transport.
Definition: ap_dbacc.c:2325
void(* F_NotifyStartTuning)(U32BIT module, U16BIT onet_id, U16BIT trans_id, U16BIT serv_id, E_CIP_TUNE_FLAGS flags)
Notify that DVB is about to tune to service or transport stream. This function would be called as a r...
Definition: ap_ci.h:64
void DBDEF_ReleaseAccess(void)
Releases access to the app&#39;s database.
Definition: ap_dbdef.c:245
BOOLEAN STB_CiCcSendPin(U8BIT slot_id, U8BIT *pin_data)
Called by the host to check whether a CAM pin is valid. An STB_EVENT_CI_PIN_STATUS event will be sent...
Definition: stbcicc.c:873
BOOLEAN STB_DPIsOwnedBy(U8BIT path, E_STB_DP_RES_OWNER owner)
Checks whether the path is owned by the given owner.
Definition: stbdpc.c:1966
Debug functions header file.
Header file - macros and function prototypes for public use.
void STB_CiCcRemove(U8BIT slot_id)
Handle CAM removal from slot.
Definition: stbcicc.c:275
Header file - macros and function prototypes for public use.
ADB_TRANSPORT_REC * DBDEF_AddCableTransportRec(U32BIT freq_hz, U32BIT symbol_rate, ADB_NETWORK_REC *network)
Adds a cable transport record with the given frequency and symbol rate.
Definition: ap_dbdef.c:4982
void * ADB_GetTunedService(U8BIT path)
Returns the tuned service for the given decode path.
Definition: ap_dbacc.c:6068
BOOLEAN ACI_SetSecureRouting(U8BIT path)
Ensures the TS is routed securely for CI+, either by setting the TS to pass through if a CI slot cont...
Definition: ap_ci.c:1380
Database access defines, structures and public functions.
BOOLEAN ACI_GetFirstOperatorSearchModule(U32BIT *module)
Checks all the CI+ profiles to see if any have requested an update search.
Definition: ap_ci.c:1138
void ACI_UsageRulesStatusChanged(U8BIT path)
Re-evaluate current state follwing a change related to usage rules.
Definition: ap_ci.c:1612
CI Content Control - descrambler keys.
ADB_TRANSPORT_REC * DBDEF_FindCableTransportRec(U32BIT freq_hz, U32BIT symbol_rate)
Find the cable transport record in the database matching the given params.
Definition: ap_dbdef.c:5040
Application level CI - internal functions.
void ACI_TuneReply(U8BIT path, U32BIT module, E_CIP_TUNER_STATUS status)
This function is called by the host to send the status of the tune operation to the module...
Definition: ap_ci.c:2242
U16BIT ADB_GetTransportOriginalNetworkId(void *t_ptr)
Returns the original network id of the given transport.
Definition: ap_dbacc.c:2385
BOOLEAN ACI_AcquireCISlot(U8BIT path, void *s_ptr)
Acquires a CI slot for the given path on the given service after releasing any slot already being use...
Definition: ap_ci.c:1433
Header file - Function prototypes for Event Reporting.
void ACI_SetOperatorSearchMode(E_CIP_START_OPERATOR_SEARCH search_mode)
Sets the operator profile search mode (Yes/No/Ask). This should be used by the app to control whether...
Definition: ap_ci.c:1044
ADB_SERVICE_REC * DBDEF_AddServiceRec(U16BIT serv_id, ADB_TRANSPORT_REC *t_ptr)
Adds a new service record to the service database with the given service ID and parent transport...
Definition: ap_dbdef.c:5598
void DBDEF_RequestAccess(void)
Requests access to the app&#39;s database.
Definition: ap_dbdef.c:235
U8BIT ACTL_TuneToService(U8BIT path, S_ACTL_OWNER_INFO *owner_info, void *s_ptr, BOOLEAN override_lock, BOOLEAN for_live)
Starts the process of tuning to the specified service. If the service is to be tuned on the live path...
Definition: ap_cntrl.c:1651
void STB_SISetCiplusPrivateDataSpecifierMode(BOOLEAN mode)
Enables or disables use of the CI+ private data specifier when parsing SI tables. ...
Definition: stbsitab.c:7657
U16BIT ADB_GetServiceId(void *s_ptr)
Returns the signalled service id of the given service.
Definition: ap_dbacc.c:4960
void ACI_OpSlotRemove(U8BIT slot_id)
Process CAM removal from slot for CA support.
Definition: ap_ciop.c:191
void ACI_OpInitialise(void)
Initialise CI Operator Profile support.
Definition: ap_ciop.c:180
Application stb layer control.
U8BIT ACTL_TuneToTransport(U8BIT path, S_ACTL_OWNER_INFO *owner_info, void *t_ptr, E_ACTL_SI_SRCH_REQD reqd_si, BOOLEAN relock_on)
Tunes to the given transport and sets the type of SI monitoring that will be started when the tuning ...
Definition: ap_cntrl.c:1584
BOOLEAN STB_OSWriteQueue(void *queue, void *msg, U16BIT msg_size, U16BIT timeout)
Write a message to the queue.
Header file - Function prototypes for operating system.
System Wide Global Technical Data Type Definitions.
BOOLEAN DBA_SetFieldValue(void *record, U32BIT field_id, U32BIT value)
Set the value of a record&#39;s field. The function will fail if the record doesn&#39;t exist, the record doesn&#39;t include the given field, or the field is a string value.
Definition: dba_nvm.c:1175
U16BIT ADB_GetProfileList(void ***profile_list, U16BIT *active_profile)
Returns an array of available profiles. The array will be allocated within the function and should be...
Definition: ap_dbacc.c:11373
void STB_AppFreeMemory(void *addr)
Releases previously allocated application heap memory.
Definition: stbheap.c:781
BOOLEAN ACI_StartOperatorSearch(U32BIT module)
Called by the app to start an operator profile search that has been requested.
Definition: ap_ciop.c:323
BOOLEAN ACI_WritePinForSlot(U8BIT slot_id, S32BIT pin)
Saves the given pin associated with the CAM in the given slot. If the pin for this CAM has previously...
Definition: ap_ci.c:1810
BOOLEAN ACTL_ReleasePathOwnership(U8BIT path, E_STB_DP_RES_OWNER owner)
Releases ownership of the path, and frees any associated data, if the given owner is the path&#39;s owner...
Definition: ap_cntrl.c:5011
BOOLEAN ACI_OpAskRelease(U32BIT module)
Ask the opertaor module to restore replaced PIDs.
Definition: ap_ciop.c:906
void STB_CiKeysApply(U8BIT path, U8BIT slot_id)
Apply stored CC keys (if any) on given path.
Definition: stbcikeys.c:297
U32BIT ACI_GetOperatorSearchModule(void)
Returns the module performing or requiring and operator search.
Definition: ap_ci.c:1125
U32BIT ATMR_AddTimer(S_TIMER_INFO *info)
Creates a new timer based on the information supplied.
Definition: ap_tmr.c:189
BOOLEAN ACI_GetFirstScheduledOperatorSearch(U32BIT *module, U16BIT *date, U8BIT *hours, U8BIT *mins)
Checks all the CI+ profiles to find the one with the earliest scheduled search. All returned values a...
Definition: ap_ci.c:1181
void ACI_TuneToTransport(U32BIT module, void *t_ptr)
Schedule a tune to a transport.
Definition: ap_ci.c:2000
BOOLEAN ACI_OpTuneReply(U8BIT path, U32BIT module, E_STB_CI_TUNE_STATUS status)
This function is called by the host to send the status of the tune operation to the module...
Definition: ap_ciop.c:952
void * STB_OSCreateTask(void(*function)(void *), void *param, U32BIT stack, U8BIT priority, U8BIT *name)
Create a New Task to the calling process. Upon success, the created task runs on its own stack...
void * STB_OSCreateQueue(U16BIT msg_size, U16BIT msg_max)
Create Queue of given number of messages and size of message.
void ACI_RegisterStartTuneNotifyCallback(F_NotifyStartTuning cb_func)
Register callback function to notify start of tuning process due to CI tune request.
Definition: ap_ci.c:2353
void ACI_Initialise(void)
Initialise CI Host Control support.
Definition: ap_ci.c:994
void * STB_DPGetOwnerData(U8BIT path, U32BIT *data_size)
Returns the owner data saved with the path. This data should not be freed.
Definition: stbdpc.c:1993
BOOLEAN ASTE_InStandby(void)
Definition: ap_state.c:117
Header file - Function prototypes for heap memory.
void ADB_GetServiceIds(void *s_ptr, U16BIT *onet_id, U16BIT *trans_id, U16BIT *serv_id)
Returns the original network id, transport id and service id for the given service.
Definition: ap_dbacc.c:4982
U8BIT STB_CiCcFindSlotForCicamId(U8BIT cicam_id[CIP_CICAM_ID_LEN])
Checks CAMs in all slots to find the one with the given CAM id.
Definition: stbcicc.c:399
BOOLEAN ATMR_DeleteTimer(U32BIT handle)
Deletes the timer with the given handle.
Definition: ap_tmr.c:436
Application header file.
U8BIT ACI_GetCamUpgradeMode(void)
Return CAM upgrade option (Yes/No/Ask)
Definition: ap_ci.c:1009
BOOLEAN STB_OSReadQueue(void *queue, void *msg, U16BIT msg_size, U16BIT timeout)
Read a message from a queue.
void STB_CiCcInitialise(void)
CI content control support initialise.
Definition: stbcicc.c:159
void STB_CiCcSetRecordOperatingMode(U8BIT slot_id, U32BIT mode, U16BIT service_id)
Sets the record operating mode for the given slot id.
Definition: stbcicc.c:1065
BOOLEAN ACI_SendPinToCam(U8BIT slot_id, U32BIT pin)
Converts the pin value to ASCII and sends it to the CAM An STB_EVENT_CI_PIN_STATUS event will be sent...
Definition: ap_ci.c:2301
void STB_AVBlankVideo(U8BIT path, BOOLEAN blank)
Blanks or unblanks the video display.
E_CIP_START_OPERATOR_SEARCH ACI_GetOperatorSearchMode(void)
Return the option for starting an operator profile search (yes/no/ask)
Definition: ap_ci.c:1031
S32BIT ACI_ReadPinForSlot(U8BIT slot_id)
Checks if a pin has been saved for the CAM in the given slot and returns it.
Definition: ap_ci.c:1714
void STB_DPReleaseCISlotFromPath(U8BIT path)
Release the CI slot associated with the given path.
Definition: stbdpc.c:1051
BOOLEAN STB_CiCcIsServiceAllowed(U8BIT slot_id, U8BIT *ci_prot_desc)
Tell whether the service is allowed. This function checks whether the CI Protection Descriptor allows...
Definition: stbcicc.c:349
void STB_CiCcApplyUsageRulesInfo(U8BIT *uri)
Apply the given Usage Rules Information.
Application database access functions.
void ACI_ScheduleOperatorSearch(U32BIT cicam_id, U16BIT date, U8BIT hour, U8BIT min)
Sets the date/time that an operator search should be started for the given module.
Definition: ap_ci.c:1088
void ACI_OperatorSearchRequired(U32BIT module, BOOLEAN required)
Sets whether an operator profile search needs to be run.
Definition: ap_ci.c:1056
Header file - macros and function prototypes for public use.
Application level CI Operator Profile functions.
BOOLEAN APP_RegisterDVBEventHandler(DVB_EVENT_HANDLER event_handler)
Register for DVB event notifications.
Definition: ap_events.c:162
Header file - Function prototypes for tuner control.