DVBCore  20.3.0
DVBCore Documentation
stbcica.c
1 /*******************************************************************************
2  * Copyright © 2016 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  * Copyright © 2009 Ocean Blue Software Ltd
4  *
5  * This file is part of a DTVKit Software Component
6  * You are permitted to copy, modify or distribute this file subject to the terms
7  * of the DTVKit 1.0 Licence which can be found in licence.txt or at www.dtvkit.org
8  *
9  * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
10  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
11  * OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
12  *
13  * If you or your organisation is not a member of DTVKit then you have access
14  * to this source code outside of the terms of the licence agreement
15  * and you are expected to delete this and any associated files immediately.
16  * Further information on DTVKit, membership and terms can be found at www.dtvkit.org
17  *******************************************************************************/
24 //#define DEBUG_PRINTING_ENABLED
25 
26 /*---includes for this file--------------------------------------------------*/
27 
28 /* compiler library header files */
29 #include <string.h>
30 
31 /* third party header files */
32 
33 /* DVBCore header files */
34 #include "techtype.h"
35 #include "dbgfuncs.h"
36 #include "stbhwos.h"
37 #include "stbci.h"
38 #include "stberc.h"
39 #include "stbdpc.h"
40 #include "stbpvr.h"
41 #include "stbheap.h"
42 
43 #include "stbcica.h"
44 #include "stbci_int.h"
45 
46 /*---constant definitions for this file--------------------------------------*/
47 
48 //#define DEBUG_CA
49 #ifdef DEBUG_CA
50  #define DBG_CA(x, ...) STB_SPDebugWrite( "%s:%d " x, __FUNCTION__, __LINE__, ##__VA_ARGS__);
51 #else
52  #define DBG_CA(x, ...)
53 #endif
54 
55 /*---local typedef enums for this file-------------------------------------*/
56 
57 /*---local typedef structs for this file-------------------------------------*/
58 
59 typedef struct s_ca_info
60 {
61  struct s_ca_info *next;
62  U32BIT module;
63  BOOLEAN disabled;
64  U8BIT slot_id;
65  U8BIT num_ca_ids;
66  U8BIT last_pmt_version;
67  U16BIT last_pmt_program;
68 } S_CA_INFO;
69 
70 /*---local (static) variable declarations for this file----------------------*/
71 /* (internal variables declared static to make them local) */
72 
73 static S_CA_INFO *cica_slots = NULL;
74 static void *cica_mutex;
75 
76 static S_CA_INFO *FindSlot(U8BIT slot_id);
77 static BOOLEAN UpdateCASystemInfo(S_CA_INFO *slot_info, U8BIT *pmt);
78 
79 /*---global function definitions---------------------------------------------*/
80 
85 {
86  cica_mutex = STB_OSCreateMutex();
87 }
88 
93 void STB_CiCaDisable(U8BIT slot_id)
94 {
95  S_CA_INFO *slot_info;
96 
97  FUNCTION_START(STB_CiKeysDisable);
98 
99  DBG_CA("(slot=%u)", slot_id)
100 
101  slot_info = FindSlot(slot_id);
102  if (slot_info != NULL)
103  {
104  slot_info->disabled = TRUE;
105  }
106  FUNCTION_FINISH(STB_CiKeysDisable);
107 }
108 
113 void STB_CiCaRemove(U8BIT slot_id)
114 {
115  S_CA_INFO *slot;
116  S_CA_INFO **pslot;
117 
118  FUNCTION_START(STB_CiCaRemove);
119  DBG_CA("(slot=%u)", slot_id)
120  pslot = &cica_slots;
121  STB_OSMutexLock(cica_mutex);
122  slot = cica_slots;
123  while (slot != NULL)
124  {
125  if (slot->slot_id == slot_id)
126  {
127  *pslot = slot->next;
128  STB_FreeMemory(slot);
129  break;
130  }
131  pslot = &(slot->next);
132  slot = slot->next;
133  }
134  STB_OSMutexUnlock(cica_mutex);
135 
136  FUNCTION_FINISH(STB_CiCaRemove);
137 }
138 
145 void STB_CINotifyCaSystems(U32BIT module, U16BIT *ca_ids, U8BIT num_ca_ids)
146 {
147  S_CA_INFO *slot;
148  U8BIT slot_id;
149 
150  FUNCTION_START(STB_CINotifyCaSystems);
151 
152  DBG_CA("mod=%x slot=%u", module, STB_GetCIConditionalAccessSlotId(module))
153 
154  slot_id = STB_GetCIConditionalAccessSlotId(module);
155  slot = FindSlot(slot_id);
156  if (slot != NULL && num_ca_ids > slot->num_ca_ids)
157  {
158  STB_CiCaRemove(slot_id);
159  slot = NULL;
160  }
161  if (slot == NULL)
162  {
163  slot = STB_GetMemory(sizeof(S_CA_INFO)+ (num_ca_ids * sizeof(U16BIT)));
164  if (slot != NULL)
165  {
166  slot->slot_id = slot_id;
167  slot->disabled = FALSE;
168  STB_OSMutexLock(cica_mutex);
169  slot->next = cica_slots;
170  cica_slots = slot;
171  STB_OSMutexUnlock(cica_mutex);
172  }
173  }
174  if (slot != NULL)
175  {
176  slot->module = module;
177  slot->num_ca_ids = num_ca_ids;
178  memcpy(&slot[1], ca_ids, num_ca_ids * sizeof(U16BIT));
179 
180  /* Force resending of PMT */
181  slot->last_pmt_version = 0xFF;
182  slot->last_pmt_program = 0xFFFF;
183 
184  STB_ERSendEvent(FALSE, FALSE, EV_CLASS_CI, EV_TYPE_CI_SLOT_STATUS_UPDATED, &slot_id, sizeof slot_id);
185  }
186 
187  FUNCTION_FINISH(STB_CINotifyCaSystems);
188 }
189 
190 void STB_CINotifyPmtReply(U32BIT module, U16BIT program_number, U8BIT version_number,
191  U8BIT current_next_indicator, E_STB_CI_DESC ca_enable)
192 {
193  FUNCTION_START(STB_CINotifyPmtReply);
194  USE_UNWANTED_PARAM(module);
195  USE_UNWANTED_PARAM(program_number);
196  USE_UNWANTED_PARAM(version_number);
197  USE_UNWANTED_PARAM(current_next_indicator);
198  USE_UNWANTED_PARAM(ca_enable);
199  FUNCTION_FINISH(STB_CINotifyPmtReply);
200 }
201 
207 void STB_CiCaReportPmt(U8BIT slot_id, U8BIT *pmt)
208 {
209  S_CA_INFO *slot_info;
210  U16BIT program_number;
211  U8BIT version_number;
212 
213  FUNCTION_START(STB_CiCaReportPmt);
214 
215  DBG_CA("(slot=%u)", slot_id)
216  slot_info = FindSlot(slot_id);
217  if (slot_info != NULL )
218  {
219  if (slot_info->num_ca_ids != 0)
220  {
221  /* CAM is ready and intereseted, report PMT if necessary */
222  program_number = pmt[3] << 8 | pmt[4];
223  version_number = (pmt[5] >> 1) & 0x1f;
224 
225  if ((slot_info->last_pmt_program != program_number) ||
226  (slot_info->last_pmt_version != version_number))
227  {
228  slot_info->last_pmt_program = program_number;
229  slot_info->last_pmt_version = version_number;
230 
231  DBG_CA("mod=%x p_num=%x v_num=%x", slot_info->module, program_number, version_number)
232  STB_CIUpdatePmt(slot_info->module, pmt, TRUE, STB_CI_PMT_CMD_OK_DESCRAMBLE);
233  }
234  }
235  }
236 
237  FUNCTION_FINISH(STB_CiCaReportPmt);
238 }
239 
247 BOOLEAN STB_CiCaSystemSupported(U8BIT slot_id, U8BIT *pmt_data)
248 {
249  S_CA_INFO *slot_info;
250  BOOLEAN supported;
251 
252  FUNCTION_START(STB_CiCaSystemSupported);
253 
254  DBG_CA("(slot=%u)", slot_id)
255  slot_info = FindSlot(slot_id);
256  if (slot_info != NULL )
257  {
258  supported = UpdateCASystemInfo(slot_info, pmt_data);
259  }
260  else
261  {
262  supported = FALSE;
263  }
264 
265  FUNCTION_FINISH(STB_CiCaSystemSupported);
266 
267  return supported;
268 }
269 
270 /*---local function definitions----------------------------------------------*/
271 
272 static S_CA_INFO *FindSlot(U8BIT slot_id)
273 {
274  S_CA_INFO *slot_info;
275  STB_OSMutexLock(cica_mutex);
276  slot_info = cica_slots;
277  while (slot_info != NULL)
278  {
279  if (slot_info->slot_id == slot_id)
280  {
281  if (slot_info->disabled)
282  {
283  slot_info = NULL;
284  }
285  break;
286  }
287  slot_info = slot_info->next;
288  }
289  STB_OSMutexUnlock(cica_mutex);
290  return slot_info;
291 }
292 
305 static BOOLEAN UpdateCASystemInfo(S_CA_INFO *slot_info, U8BIT *pmt)
306 {
307  U16BIT ca_system_id;
308  U16BIT section_length;
309  U16BIT program_info_length;
310  U16BIT es_info_length;
311  U16BIT es_offset;
312  U16BIT offset;
313  U16BIT i;
314  U16BIT *ca_ids;
315  U8BIT desc_tag;
316  U8BIT desc_len;
317  BOOLEAN ca_found;
318  BOOLEAN supported;
319 
320  FUNCTION_START(UpdateCASystemInfo);
321 
322  supported = FALSE;
323  ca_found = FALSE;
324 
325  if (pmt != NULL && pmt[0] == 0x02)
326  {
327  /* Assuming that the PMT is valid */
328  section_length = (pmt[1] << 8 | pmt[2]) & 0xfff;
329 
330  /* Program info */
331  program_info_length = (pmt[10] << 8 | pmt[11]) & 0xfff;
332  offset = 12;
333  while (!supported && offset < 12 + program_info_length)
334  {
335  desc_tag = pmt[offset];
336  desc_len = pmt[offset + 1];
337  if (desc_tag == 0x09)
338  {
339  /* CA_descriptor() */
340  ca_system_id = pmt[offset + 2] << 8 | pmt[offset + 3];
341  ca_found = TRUE;
342  ca_ids = (U16BIT*)(slot_info + 1);
343  DBG_CA("Found CA system %04x in program info", ca_system_id)
344  for (i = 0; i != slot_info->num_ca_ids; i++)
345  {
346  if (ca_ids[i] == ca_system_id)
347  {
348  DBG_CA("CA system is supported")
349  supported = TRUE;
350  break;
351  }
352  }
353  }
354  offset += 2 + desc_len;
355  }
356 
357  /* ES info */
358  while (!supported && offset < section_length - 1)
359  {
360  offset += 3;
361  es_info_length = (pmt[offset] << 8 | pmt[offset + 1]) & 0xfff;
362  offset += 2;
363  es_offset = offset;
364  while (!supported && offset < es_offset + es_info_length)
365  {
366  desc_tag = pmt[offset];
367  desc_len = pmt[offset + 1];
368  if (desc_tag == 0x09)
369  {
370  /* CA_descriptor() */
371  ca_system_id = pmt[offset + 2] << 8 | pmt[offset + 3];
372  ca_found = TRUE;
373  ca_ids = (U16BIT*)(slot_info + 1);
374  DBG_CA("Found CA system %04x in ES info", ca_system_id)
375  for (i = 0; i != slot_info->num_ca_ids; i++)
376  {
377  if (ca_ids[i] == ca_system_id)
378  {
379  DBG_CA("CA system is supported")
380  supported = TRUE;
381  break;
382  }
383  }
384  }
385  offset += 2 + desc_len;
386  }
387  }
388  }
389 
390  if (ca_found)
391  {
392  DBG_CA("CA is used")
393  if (supported)
394  {
395  DBG_CA("CA system is support")
396  }
397  }
398 
399  FUNCTION_FINISH(UpdateCASystemInfo);
400 
401  return supported;
402 }
void STB_CiKeysDisable(U8BIT slot_id)
Disable CC keys for slot, as CAM is being removed.
Definition: stbcikeys.c:113
void * STB_GetMemory(U32BIT bytes)
Attempts to allocate memory from the heap.
Definition: stbheap.c:221
Header file - macros and function prototypes for public use.
void STB_CiCaReportPmt(U8BIT slot_id, U8BIT *pmt)
Report PMT to CI stack.
Definition: stbcica.c:207
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
CI Conditional Access.
void STB_OSMutexUnlock(void *mutex)
Unlock a mutex (a.k.a. &#39;leave&#39;, &#39;signal&#39; or &#39;release&#39;)
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
void STB_FreeMemory(void *addr)
Releases previously allocated heap memory.
Definition: stbheap.c:336
Debug functions header file.
void STB_OSMutexLock(void *mutex)
Lock a mutex (a.k.a. &#39;enter&#39;, &#39;wait&#39; or &#39;get&#39;).
void STB_CiCaInitialise(void)
CI conditional access support initialise.
Definition: stbcica.c:84
Header file - Function prototypes for Event Reporting.
CI Content Control support - internal header.
void STB_CiCaDisable(U8BIT slot_id)
Disable CA for slot, as CAM is being removed.
Definition: stbcica.c:93
Header file - Function prototypes for operating system.
System Wide Global Technical Data Type Definitions.
void STB_CiCaRemove(U8BIT slot_id)
Process CAM removal from slot for CA support.
Definition: stbcica.c:113
Header file - Function prototypes for heap memory.
void * STB_OSCreateMutex(void)
Create a mutex.