DVBCore  20.3.0
DVBCore Documentation
ap_ciop.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright © 2016 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  *
4  * This file is part of a DTVKit Software Component
5  * You are permitted to copy, modify or distribute this file subject to the terms
6  * of the DTVKit 1.0 Licence which can be found in licence.txt or at www.dtvkit.org
7  *
8  * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
9  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
10  * OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
11  *
12  * If you or your organisation is not a member of DTVKit then you have access
13  * to this source code outside of the terms of the licence agreement
14  * and you are expected to delete this and any associated files immediately.
15  * Further information on DTVKit, membership and terms can be found at www.dtvkit.org
16  *******************************************************************************/
24 //---includes for this file----------------------------------------------------
25 // compiler library header files
26 
27 #include <stdio.h>
28 #include <string.h>
29 
30 // third party header files
31 
32 // Ocean Blue Software header files
33 
34 #include "techtype.h"
35 #include "dbgfuncs.h"
36 
37 #include "stbhwos.h"
38 
39 #include "stberc.h"
40 #include "stbheap.h"
41 #include "stbuni.h"
42 
43 #include "dba.h"
44 
45 #include "app.h"
46 #include "ap_dbacc.h"
47 #include "ap_dbdef.h"
48 #include "ap_ci.h"
49 #include "ap_state.h"
50 
51 #include "stbci.h"
52 #include "ci_appmmi.h"
53 #include "ap_ci_int.h"
54 #include "ap_ci_support.h"
55 #include "ap_ciop.h"
56 
57 //---constant definitions for this file----------------------------------------
58 
59 #define DEBUG_OP
60 #ifdef DEBUG_OP
61 #define DBG_OP(x, ...) STB_SPDebugWrite( "%s:%d " x, __FUNCTION__, __LINE__, ##__VA_ARGS__);
62 #else
63 #define DBG_OP(x, ...)
64 #endif
65 
66 #define CIP_SERVICE_TYPE_TV 0x00000001 /* MPEG2 TV */
67 #define CIP_SERVICE_TYPE_RADIO 0x00000002 /* MPEG1 Layer-II radio */
68 #define CIP_SERVICE_TYPE_TELETEXT 0x00000004 /* Teletext */
69 #define CIP_SERVICE_TYPE_AVC_RADIO 0x00000008 /* AVC radio */
70 #define CIP_SERVICE_TYPE_DATA 0x00000010 /* Data */
71 #define CIP_SERVICE_TYPE_HD_TV 0x00000020 /* MPEG2 HD TV */
72 #define CIP_SERVICE_TYPE_AVC_SD_TV 0x00000040 /* AVC SD TV */
73 #define CIP_SERVICE_TYPE_AVC_HD_TV 0x00000080 /* AVC HD TV */
74 
75 #define CIP_DELIVERY_TYPE_DVBT 0x0001
76 #define CIP_DELIVERY_TYPE_DVBT2 0x0002
77 #define CIP_DELIVERY_TYPE_DVBC 0x0004
78 #define CIP_DELIVERY_TYPE_DVBC2 0x0008
79 #define CIP_DELIVERY_TYPE_DVBS 0x0010
80 #define CIP_DELIVERY_TYPE_DVBS2 0x0020
81 
82 #define CIP_APP_TYPE_MHEG 0x0001
83 #define CIP_APP_TYPE_HBBTV 0x0002
84 #define CIP_APP_TYPE_OIPF 0x0004
85 
86 #define INVALID_MODULE 0xFFFFFFFF
87 
88 #define CIP_NUM_FREE_LCNS 2
89 
90 //---local typedefs, structs, enumerations for this file--------------------------------------------
91 
92 typedef enum
93 {
94  CIP_OPERATOR_SEARCH_DEFERRED,
95  CIP_OPERATOR_SEARCH_IMMEDIATE,
96  CIP_OPERATOR_SEARCH_SCHEDULED
97 } E_CIP_OPERATOR_SEARCH_REQUEST_TYPE;
98 
99 typedef struct ci_operator_nit
100 {
101  U16BIT cicam_onet_id;
102  U32BIT cicam_identifier;
103  U32BIT lang_code;
104  U8BIT profile_name_length;
105  U8BIT *profile_name;
106  SI_NIT_TABLE *table;
108 
109 typedef struct ci_host_info
110 {
111  BOOLEAN standby;
112  U8BIT num_service_types;
113  U32BIT service_types;
114  U16BIT delivery_types;
115  U16BIT app_types;
117 
118 typedef struct ci_operator_search
119 {
120  E_CIP_OPERATOR_SEARCH_REQUEST_TYPE refresh_request;
121  U16BIT refresh_date;
122  U8BIT refresh_hour;
123  U8BIT refresh_min;
128  U32BIT cicam_id;
130 
131 typedef struct s_op_status
132 {
133  struct s_op_status *next;
134  U32BIT module;
135  U8BIT slot_id;
136  U8BIT op_desc_num;
137  U16BIT host_delivery_types;
138  U16BIT op_desc_loop_len;
139  U16BIT op_current_loc_len;
140  U8BIT *op_desc_loop;
141  U8BIT *op_current_location;
142  S_STB_CI_OPERATOR_STATUS op_status;
143  S_STB_CI_OPERATOR_INFO op_info;
144  BOOLEAN tune_started;
145  BOOLEAN op_status_valid;
146  BOOLEAN op_info_valid;
147  BOOLEAN op_nit_received;
148  BOOLEAN op_search_started;
149 } S_OP_STATUS;
150 
151 //---local (static) variable declarations for this file------------------------
152 // (internal variables declared static to make them local)
153 
154 static S_OP_STATUS *ciop_list = NULL;
155 static void *ciop_mutex;
156 static U32BIT op_module;
157 static U32BIT default_und_lang = ADB_LANG_CODE_UNDEF;
158 
159 //---local function prototypes for this file-----------------------------------
160 // (internal functions declared static to make them local)
161 
162 static S_OP_STATUS *FindOpState(U32BIT module);
163 static BOOLEAN StartOperatorSearch(S_OP_STATUS *op_state);
164 static BOOLEAN PrepareSearchInfo(S_CIP_HOST_INFO *host_info, S_STB_CI_SEARCH_START_INFO *search_info);
165 static void PerformOperatorTune(S_OP_STATUS *op_state);
166 static U32BIT ConvertLangCode(U8BIT *data);
167 static U8BIT GetCharacterCodeTable(S_STB_CI_OPERATOR_INFO *op_info);
168 
169 static void ProcessNit(U32BIT module, S_CIP_OPERATOR_NIT *nit);
170 static void RequestHostInfo(S_CIP_HOST_INFO *host_info);
171 static BOOLEAN RequestOperatorSearch(U32BIT module, S_CIP_OPERATOR_SEARCH *op_search);
172 
173 //----------------------------------------------------------------------------
174 //--- Global function for this file ------------------------------------------
175 //----------------------------------------------------------------------------
176 
181 {
182  FUNCTION_START(ACI_OpInitialise);
183  ciop_mutex = STB_OSCreateMutex();
184  FUNCTION_FINISH(ACI_OpInitialise);
185 }
186 
191 void ACI_OpSlotRemove(U8BIT slot_id)
192 {
193  S_OP_STATUS *state;
194  S_OP_STATUS **pstate;
195 
196  FUNCTION_START(ACI_OpSlotRemove);
197  DBG_OP("(slot_id=%u)", slot_id)
198  pstate = &ciop_list;
199  STB_OSMutexLock(ciop_mutex);
200  state = ciop_list;
201  while (state != NULL)
202  {
203  if (state->slot_id == slot_id)
204  {
205  ADB_MarkCIModuleNotPresent(state->module);
206  *pstate = state->next;
207  STB_FreeMemory(state);
208  state = *pstate;
209  }
210  else
211  {
212  pstate = &(state->next);
213  state = state->next;
214  }
215  }
216  STB_OSMutexUnlock(ciop_mutex);
217 
218  FUNCTION_FINISH(ACI_OpSlotRemove);
219 }
220 
227 BOOLEAN ACI_RequestOperatorStatus(U32BIT module)
228 {
229  BOOLEAN retval;
230  S_OP_STATUS *op_state;
231 
232  FUNCTION_START(ACI_RequestOperatorStatus);
233 
234  DBG_OP("(%u)", module)
235 
236  if (op_module == INVALID_MODULE)
237  {
238  retval = STB_CIRequestOperatorStatus(module);
239  if (retval)
240  {
241  /* This is the module that's in operator profile */
242  op_module = module;
243  STB_OSMutexLock(ciop_mutex);
244  op_state = FindOpState(module);
245  if (op_state != NULL)
246  {
247  DBG_OP("(%u): Setting character table 0x%x", module,
248  op_state->op_info.character_code_table)
249  STB_SetDefaultAsciiTable(GetCharacterCodeTable(&(op_state->op_info)));
250 
251  if (((op_state->op_info.iso_639_language_code[0] != 'u') ||
252  (op_state->op_info.iso_639_language_code[1] != 'n') ||
253  (op_state->op_info.iso_639_language_code[2] != 'd')) &&
254  ((op_state->op_info.iso_639_language_code[0] != 'q') ||
255  (op_state->op_info.iso_639_language_code[1] != 'a') ||
256  (op_state->op_info.iso_639_language_code[2] != 'a')))
257  {
258  default_und_lang = ACFG_GetUndefinedLanguageBehaviour();
260  ConvertLangCode(op_state->op_info.iso_639_language_code));
261  }
262  }
263  STB_OSMutexUnlock(ciop_mutex);
264  }
265  else
266  {
267  DBG_OP("STB_CIRequestOperatorStatus(%u) failed", module)
268  }
269  }
270  else
271  {
272  /* Previous operator module hasn't been exited */
273  DBG_OP("Previous operator module hasn't been exited")
274  retval = FALSE;
275  }
276 
277  FUNCTION_FINISH(ACI_RequestOperatorStatus);
278 
279  return(retval);
280 }
281 
286 BOOLEAN ACI_OperatorExit(void)
287 {
288  BOOLEAN retval;
289 
290  FUNCTION_START(ACI_OperatorExit);
291 
292  DBG_OP("")
293  if (op_module != INVALID_MODULE)
294  {
295  retval = STB_CISendOperatorExit(op_module);
296  if (!retval)
297  {
298  DBG_OP("STB_CISendOperatorExit(%u) failed", op_module)
299  }
300  op_module = INVALID_MODULE;
301 
302  DBG_OP("Setting character table 0x%x (default)", 0)
304 
305  ACFG_SetUndefinedLanguageBehaviour(default_und_lang);
306  }
307  else
308  {
309  DBG_OP("no profile to exit")
310  retval = FALSE;
311  }
312 
313  FUNCTION_FINISH(ACI_OperatorExit);
314 
315  return(retval);
316 }
317 
318 /*!**************************************************************************
319  * @brief Called by the app to start an operator profile search that has been requested
320  * @param module - operator module
321  * @return TRUE if the search is started, FALSE otherwise
322  ****************************************************************************/
323 BOOLEAN ACI_StartOperatorSearch(U32BIT module)
324 {
325  BOOLEAN retval;
326  S_OP_STATUS *op_state;
327 
328  FUNCTION_START(ACI_StartOperatorSearch);
329 
330  DBG_OP("(%u):", module)
331 
332  STB_OSMutexLock(ciop_mutex);
333  op_state = FindOpState(module);
334  if (op_state != NULL)
335  {
336  retval = StartOperatorSearch(op_state);
337  }
338  else
339  {
340  retval = FALSE;
341  }
342  STB_OSMutexUnlock(ciop_mutex);
343 
344  FUNCTION_FINISH(ACI_StartOperatorSearch);
345 
346  return(retval);
347 }
348 
355 BOOLEAN ACI_FindOperatorProfileModule(U32BIT cicam_id, U32BIT *module)
356 {
357  S_OP_STATUS *op_state;
358  BOOLEAN retval = FALSE;
359 
360  FUNCTION_START(ACI_FindOperatorProfileModule);
361 
362  STB_OSMutexLock(ciop_mutex);
363  op_state = ciop_list;
364  while (op_state != NULL)
365  {
366  if (op_state->op_info_valid &&
367  op_state->op_info.cicam_identifier == cicam_id)
368  {
369  *module = op_state->module;
370  retval = TRUE;
371  break;
372  }
373  op_state = op_state->next;
374  }
375  STB_OSMutexUnlock(ciop_mutex);
376 
377  FUNCTION_FINISH(ACI_FindOperatorProfileModule);
378 
379  return retval;
380 }
381 
391 void ACI_OpNotifyOperatorStatus(U32BIT module, S_STB_CI_OPERATOR_STATUS *status)
392 {
393  S_OP_STATUS *op_state;
394  S_CIP_OPERATOR_SEARCH op_search;
395  BOOLEAN valid;
396 
397  FUNCTION_START(ACI_OpNotifyOperatorStatus);
398 
399  DBG_OP("(%u): slot_id=%u", module, STB_GetCIOperatorProfileSlotId(module))
400  DBG_OP(" info_version: %u", status->info_version)
401  DBG_OP(" nit_version: %u", status->nit_version)
402  DBG_OP(" profile_type: %u", status->profile_type)
403  DBG_OP(" initialised_flag: %u", status->initialised_flag)
404  DBG_OP(" entitlement_change: %u", status->entitlement_change_flag)
405  DBG_OP(" entitlement_valid: %u", status->entitlement_valid_flag)
406  DBG_OP(" refresh_request: %u", status->refresh_request_flag)
407  DBG_OP(" del system hint: 0x%02x", status->delivery_system_hint)
408  DBG_OP(" error: %u", status->error_flag)
409 
410  STB_OSMutexLock(ciop_mutex);
411  op_state = FindOpState(module);
412  if (op_state == NULL)
413  {
414  op_state = STB_GetMemory(sizeof(S_OP_STATUS));
415  if (op_state != NULL)
416  {
417  memset(op_state,0,sizeof(S_OP_STATUS));
418  op_state->module = module;
419  op_state->slot_id = STB_GetCIOperatorProfileSlotId(module);
420  op_state->next = ciop_list;
421  ciop_list = op_state;
422  }
423  }
424  if (op_state != NULL)
425  {
426  if (!op_state->op_status_valid || (status->initialised_flag == 0) ||
427  (op_state->op_status.info_version != status->info_version))
428  {
429  if ((status->initialised_flag != 0) && op_state->op_status_valid &&
430  (status->nit_version != op_state->op_status.nit_version))
431  {
432  /* An updated NIT is available so indicate that a new one needs to be requested */
433  op_state->op_nit_received = FALSE;
434  }
435 
436  /* Request the operator info because this is the first time the status has been received,
437  * or the profile hasn't been initialised yet, or the info has changed */
438  DBG_OP("(%u): Requesting operator info", module)
439  STB_CIRequestOperatorInfo(module);
440  }
441  else
442  {
443  /* The CAM defines its own private network */
444  if ((status->initialised_flag == 0) ||
445  (status->refresh_request_flag != STB_CI_REFRESH_NOT_REQUIRED))
446  {
447  /* A search is required to setup the private network.
448  * Check that the search can proceed */
449  memset(&op_search, 0, sizeof(op_search));
450 
451  valid = TRUE;
452 
453  if ((status->initialised_flag == 0) ||
454  (status->refresh_request_flag == STB_CI_REFRESH_REQUIRED_IMMEDIATE))
455  {
456  op_search.refresh_request = CIP_OPERATOR_SEARCH_IMMEDIATE;
457  }
458  else if (status->refresh_request_flag == STB_CI_REFRESH_REQUIRED_SCHEDULED)
459  {
460  if (status->refresh_request_date.mjd != 0)
461  {
462  op_search.refresh_request = CIP_OPERATOR_SEARCH_SCHEDULED;
463  op_search.refresh_date = status->refresh_request_date.mjd;
464  op_search.refresh_hour = status->refresh_request_time.hour;
465  op_search.refresh_min = status->refresh_request_time.minute;
466  op_search.cicam_id = op_state->op_info.cicam_identifier;
467  }
468  else
469  {
470  /* Date isn't valid so don't proceed with the request */
471  valid = FALSE;
472  }
473  }
474  else
475  {
476  op_search.refresh_request = CIP_OPERATOR_SEARCH_DEFERRED;
477  }
478 
479  if (valid)
480  {
481  if (RequestOperatorSearch(module,&op_search))
482  {
483  /* The search can be started immediately */
484  StartOperatorSearch(op_state);
485  }
486  }
487  }
488  else if ((op_state->op_status_valid &&
489  (op_state->op_status.nit_version != status->nit_version)) ||
490  (status->entitlement_change_flag &&
491  (status->refresh_request_flag == STB_CI_REFRESH_NOT_REQUIRED)))
492  {
493  /* Profile initialisation is complete and a CICAM NIT is available */
494  DBG_OP("(%u): Requesting operator NIT", module)
495  op_state->op_nit_received = FALSE;
496  STB_CIRequestOperatorNit(module);
497  }
498  }
499 
500  /* Save the status */
501  memcpy(&op_state->op_status, status, sizeof(S_STB_CI_OPERATOR_STATUS));
502  op_state->op_status_valid = TRUE;
503  }
504  else
505  {
506  DBG_OP("(%u): unrecognised operator module", module)
507  }
508  STB_OSMutexUnlock(ciop_mutex);
509 
510  FUNCTION_FINISH(ACI_OpNotifyOperatorStatus);
511 }
512 
520 void ACI_OpNotifyOperatorInfo(U32BIT module, U8BIT info_version,
521  S_STB_CI_OPERATOR_INFO *info)
522 {
523  S_OP_STATUS *op_state;
524  S_CIP_OPERATOR_SEARCH op_search;
525  BOOLEAN valid;
526 
527  FUNCTION_START(ACI_OpNotifyOperatorInfo);
528 
529  DBG_OP("(%u, version=%u)", module, info_version)
530  if (info != NULL)
531  {
532  DBG_OP(" cicam_onet_id: 0x%04x", info->cicam_original_network_id)
533  DBG_OP(" cicam_identifier: 0x%08x", info->cicam_identifier)
534  DBG_OP(" char_code_table: %u", info->character_code_table)
535  DBG_OP(" encoding_type_id: 0x%02x", info->encoding_type_id)
536  DBG_OP(" iso lang_code: %c%c%c", info->iso_639_language_code[0], info->iso_639_language_code[1],
537  info->iso_639_language_code[2])
538  DBG_OP(" eit_present_following_usage: %u", info->eit_present_following_usage)
539  DBG_OP(" eit_schedule_usage: %u", info->eit_schedule_usage)
540  DBG_OP(" profile name len: %u", info->profile_name_length)
541  if (info->profile_name != NULL)
542  {
543  DBG_OP(" profile_name: \"%.*s\"", info->profile_name_length, info->profile_name)
544  }
545  }
546 
547  STB_OSMutexLock(ciop_mutex);
548  op_state = FindOpState(module);
549  if (op_state != NULL)
550  {
551  if ((op_state->op_status.initialised_flag == 0) ||
552  (op_state->op_status.refresh_request_flag != STB_CI_REFRESH_NOT_REQUIRED))
553  {
554  /* A scan is required to setup the private network, check if it can be started now */
555  memset(&op_search, 0, sizeof(op_search));
556 
557  valid = TRUE;
558 
559  if ((op_state->op_status.initialised_flag == 0) ||
560  (op_state->op_status.refresh_request_flag == STB_CI_REFRESH_REQUIRED_IMMEDIATE))
561  {
562  op_search.refresh_request = CIP_OPERATOR_SEARCH_IMMEDIATE;
563  }
564  else if (op_state->op_status.refresh_request_flag == STB_CI_REFRESH_REQUIRED_SCHEDULED)
565  {
566  if (op_state->op_status.refresh_request_date.mjd != 0)
567  {
568  op_search.refresh_request = CIP_OPERATOR_SEARCH_SCHEDULED;
569  op_search.refresh_date = op_state->op_status.refresh_request_date.mjd;
570  op_search.refresh_hour = op_state->op_status.refresh_request_time.hour;
571  op_search.refresh_min = op_state->op_status.refresh_request_time.minute;
572  op_search.cicam_id = info->cicam_identifier;
573  }
574  else
575  {
576  /* Date isn't valid so don't proceed with the request */
577  valid = FALSE;
578  }
579  }
580  else
581  {
582  op_search.refresh_request = CIP_OPERATOR_SEARCH_DEFERRED;
583  }
584 
585  if (valid)
586  {
587  if (RequestOperatorSearch(module,&op_search))
588  {
589  /* OK to start the search */
590  StartOperatorSearch(op_state);
591  }
592  }
593  }
594 
595  if ((op_state->op_status.profile_type == 1) &&
596  (op_state->op_status.refresh_request_flag != STB_CI_REFRESH_REQUIRED_IMMEDIATE) &&
597  (op_state->op_status.initialised_flag == 1) && !op_state->op_nit_received)
598  {
599  /* If the CICAM is ready to report a profile, but we don't have the NIT yet, request it */
600  DBG_OP("(%u): No NIT, or entitlement changed, requesting operator NIT", module)
601  STB_CIRequestOperatorNit(module);
602  }
603 
604  if ((op_module != INVALID_MODULE) && op_state->op_info_valid &&
605  (op_state->op_info.character_code_table != info->character_code_table))
606  {
607  /* The character code table for the active profile has changed */
608  DBG_OP("(%u): Setting character table 0x%x", module, info->character_code_table)
609  STB_SetDefaultAsciiTable(GetCharacterCodeTable(info));
610  }
611 
612  /* Free any existing profile name */
613  if (op_state->op_info_valid && (op_state->op_info.profile_name != NULL))
614  {
615  STB_FreeMemory(op_state->op_info.profile_name);
616  op_state->op_info.profile_name = NULL;
617  op_state->op_info.profile_name_length = 0;
618  }
619 
620  if (info != NULL)
621  {
622  /* Save the operator info, including the profile name */
623  memcpy(&op_state->op_info, info, sizeof(S_STB_CI_OPERATOR_INFO));
624 
625  if (info->profile_name != NULL)
626  {
627  if (info->profile_name_length > 0)
628  {
629  if ((op_state->op_info.profile_name = STB_GetMemory(info->profile_name_length)) != NULL)
630  {
631  memcpy(op_state->op_info.profile_name, info->profile_name, info->profile_name_length);
632  }
633  else
634  {
635  op_state->op_info.profile_name_length = 0;
636  }
637  }
638  else
639  {
640  op_state->op_info.profile_name = NULL;
641  }
642  }
643 
644  if (!op_state->op_info_valid)
645  {
646  /* This should be the first time info has been received, so inform the DVB that
647  * this module is now available */
648  DBG_OP("(%u): Inform DVB that CAM is available for profile onet=0x%04x, cam_id=0x%08x",
649  module, info->cicam_original_network_id, info->cicam_identifier)
650 
651  ADB_MarkCIModulePresent(info->cicam_original_network_id, info->cicam_identifier);
652  }
653 
654  op_state->op_info_valid = TRUE;
655  }
656  else
657  {
658  op_state->op_info_valid = FALSE;
659  }
660 
661  /* Update the version of the info now held */
662  op_state->op_status.info_version = info_version;
663 
664  }
665  else
666  {
667  DBG_OP("(%u): unrecognised operator module", module)
668  }
669  STB_OSMutexUnlock(ciop_mutex);
670 
671  FUNCTION_FINISH(ACI_OpNotifyOperatorInfo);
672 }
673 
688 void ACI_OpNotifyOperatorTune(U32BIT module, U16BIT desc_loop_len, U8BIT *desc_loop)
689 {
690  S_OP_STATUS *op_state;
691 
692  FUNCTION_START(ACI_OpNotifyOperatorTune);
693 
694  DBG_OP("(%u, desc_loop_len=%u)", module, desc_loop_len)
695  STB_OSMutexLock(ciop_mutex);
696  op_state = FindOpState(module);
697  if (op_state != NULL)
698  {
699  if (op_state->op_search_started)
700  {
701  /* Tuning operations need to be performed until all descriptors have been exhausted
702  * or until a tuning operation is sucessful, so copy the descriptor data so it can
703  * be processed as needed */
704  if ((op_state->op_desc_loop = (U8BIT *)STB_GetMemory(desc_loop_len)) != NULL)
705  {
706  memcpy(op_state->op_desc_loop, desc_loop, desc_loop_len);
707  op_state->op_desc_loop_len = desc_loop_len;
708  op_state->op_desc_num = 0;
709  /* Now process the descriptor loop to perform tune operations */
710  PerformOperatorTune(op_state);
711  }
712  }
713  else
714  {
715  DBG_OP("(%u): Received operator tune request but search hasn't been started", module)
716  }
717  }
718  else
719  {
720  DBG_OP("(%u): unrecognised operator module", module)
721  }
722  STB_OSMutexUnlock(ciop_mutex);
723 
724  FUNCTION_FINISH(ACI_OpNotifyOperatorTune);
725 }
726 
734 void ACI_OpNotifyOperatorSearchStatus(U32BIT module, S_STB_CI_OPERATOR_STATUS *status)
735 {
736  S_OP_STATUS *op_state;
737 
738  FUNCTION_START(ACI_OpNotifyOperatorSearchStatus);
739 
740  DBG_OP("(%u)", module)
741  DBG_OP(" info_version: %u", status->info_version)
742  DBG_OP(" nit_version: %u", status->nit_version)
743  DBG_OP(" profile_type: %u", status->profile_type)
744  DBG_OP(" initialised_flag: %u", status->initialised_flag)
745  DBG_OP(" entitlement_change: %u", status->entitlement_change_flag)
746  DBG_OP(" entitlement_valid: %u", status->entitlement_valid_flag)
747  DBG_OP(" refresh_request: %u", status->refresh_request_flag)
748  DBG_OP(" del system hint: 0x%02x", status->delivery_system_hint)
749  DBG_OP(" error: %u", status->error_flag)
750 
751  STB_OSMutexLock(ciop_mutex);
752  op_state = FindOpState(module);
753  if (op_state != NULL)
754  {
755  /* Operator search has completed */
756  //op_state->tuner_status = CI_TUNER_UNUSED;
757 
758  if (status->error_flag != STB_CI_OPERATOR_CANCELLED)
759  {
760  /* Any current NIT is no longer valid */
761  op_state->op_nit_received = FALSE;
762  }
763 
764  /* Operator profile is only valid if there wasn't an error during the search */
765  if (status->error_flag == STB_CI_OPERATOR_NO_ERROR)
766  {
767  if (!op_state->op_info_valid || (op_state->op_status.info_version != status->info_version))
768  {
769  /* Need to request updated info */
770  DBG_OP("(%u): Requesting operator info", module)
771  STB_CIRequestOperatorInfo(module);
772  }
773  else
774  {
775  /* Info hasn't changed, so just request the CICAM NIT */
776  DBG_OP("(%u): Requesting operator NIT", module)
777  STB_CIRequestOperatorNit(module);
778  }
779  }
780 
781  /* Save the updated status */
782  memcpy(&op_state->op_status, status, sizeof(S_STB_CI_OPERATOR_STATUS));
783  op_state->op_status_valid = TRUE;
784 
785  /* Send an event to the app to indicate that the search has finished */
786  STB_ERSendEvent(FALSE, FALSE, EV_CLASS_CI, EV_TYPE_CI_OPERATOR_SEARCH_FINISHED, NULL, 0);
787  }
788  else
789  {
790  DBG_OP("(%u): unrecognised operator module", module)
791  }
792  STB_OSMutexUnlock(ciop_mutex);
793 
794  FUNCTION_FINISH(ACI_OpNotifyOperatorSearchStatus);
795 }
796 
808 void ACI_OpNotifyOperatorNit(U32BIT module, U16BIT nit_loop_length,
809  U8BIT *nit_sections)
810 {
811  S_OP_STATUS *op_state;
812  SI_TABLE_RECORD table_rec;
813  SI_SECTION_RECORD *sect, *s;
814  SI_NIT_TABLE *nit_table;
815  S_CIP_OPERATOR_NIT nit;
816  U16BIT l, section_size;
817  U8BIT *ptr;
818 
819  FUNCTION_START(ACI_OpNotifyOperatorNit);
820 
821  DBG_OP("(%u, nit_size=%u)", module, nit_loop_length)
822 
823  STB_OSMutexLock(ciop_mutex);
824  op_state = FindOpState(module);
825  if (op_state != NULL)
826  {
827  if (nit_loop_length != 0)
828  {
829  l = 0;
830  sect = NULL;
831  memset(&table_rec, 0, sizeof(SI_TABLE_RECORD));
832  while (l < nit_loop_length)
833  {
834  ptr = nit_sections + l;
835  section_size = ((ptr[1] & 0xf) << 8) + ptr[2] + 3;
836  l += section_size;
837  s = (SI_SECTION_RECORD *)STB_GetMemory(sizeof(SI_SECTION_RECORD) + section_size);
838  if (s != NULL)
839  {
840  s->next = sect;
841  sect = s;
842  sect->sect_num = ptr[6];
843  sect->data_len = section_size;
844  memcpy(&sect->data_start, ptr, section_size);
845  table_rec.num_sect++;
846  }
847  }
848 
849  /* Populate a table_rec so the NIT can be parsed using existing functions */
850  if (sect != NULL)
851  {
852  table_rec.path = INVALID_RES_ID;
853  table_rec.tid = nit_sections[0];
854  table_rec.version = (nit_sections[5] >> 1) & 0x1f;
855  table_rec.xtid = (nit_sections[3] << 8) + nit_sections[4];
856  table_rec.section_list = sect;
857 
858  if ((nit_table = STB_SIParseNitTable(&table_rec)) != NULL)
859  {
860  /* Pass the parsed table to be processed */
861  nit.table = nit_table;
862  nit.cicam_onet_id = op_state->op_info.cicam_original_network_id;
863  nit.cicam_identifier = op_state->op_info.cicam_identifier;
864  nit.lang_code = ConvertLangCode(op_state->op_info.iso_639_language_code);
865  nit.profile_name_length = op_state->op_info.profile_name_length;
866  nit.profile_name = op_state->op_info.profile_name;
867 
868  ProcessNit(module,&nit);
869 
870  if (op_state->op_status.entitlement_change_flag)
871  {
872  /* Acknowledge that the change has been handled */
873  DBG_OP("(%u): Acknowledging entitlement change", module)
874  STB_CISendEntitlementAck(module);
875  }
876  }
877 
878  /* Can now free the copied section data */
879  while (sect != NULL)
880  {
881  s = sect->next;
882  STB_FreeMemory(sect);
883  sect = s;
884  }
885  }
886  else
887  {
888  DBG_OP("(%u): Failed to allocate memory to parse the NIT", module)
889  }
890  }
891  }
892  else
893  {
894  DBG_OP("(%u): unrecognised operator module", module)
895  }
896  STB_OSMutexUnlock(ciop_mutex);
897 
898  FUNCTION_FINISH(ACI_OpNotifyOperatorNit);
899 }
900 
906 BOOLEAN ACI_OpAskRelease(U32BIT module)
907 {
908  S_OP_STATUS *op_state;
909  BOOLEAN retval;
910  U8BIT path;
911  S_CIP_RELEASE_REPLY reply_data;
912 
913  FUNCTION_START(ACI_OpAskRelease);
914 
915  STB_OSMutexLock(ciop_mutex);
916  op_state = FindOpState(module);
917  STB_OSMutexUnlock(ciop_mutex);
918  if (op_state == NULL)
919  {
920  retval = FALSE;
921  }
922  else
923  {
924  retval = TRUE;
925  DBG_OP("(%u)", module)
926  /* The CICAM does not need to be asked in this case */
927  for (path = 0; path != STB_DPGetNumPaths(); path++)
928  {
929  if (ACI_PathOwnedByModule(path, module))
930  {
931  reply_data.path = path;
932  reply_data.module = module;
933  reply_data.reply = 0;
934  STB_ERSendEvent(FALSE, FALSE, EV_CLASS_CI, EV_TYPE_CI_RELEASE_REPLY, &reply_data, sizeof(reply_data));
935  }
936  }
937  }
938 
939  FUNCTION_FINISH(ACI_OpAskRelease);
940 
941  return(retval);
942 }
943 
952 BOOLEAN ACI_OpTuneReply(U8BIT path, U32BIT module, E_STB_CI_TUNE_STATUS status)
953 {
954  S_OP_STATUS *op_state;
955  S_STB_CI_OPERATOR_TUNE_STATUS op_status;
956  U8BIT tuner;
957  BOOLEAN retval;
958 
959  FUNCTION_START(ACI_OpTuneReply);
960 
961  DBG_OP("(%u, status=%u)", module, status)
962  retval = FALSE;
963 
964  STB_OSMutexLock(ciop_mutex);
965  op_state = FindOpState(module);
966  if (op_state != NULL)
967  {
968  if (op_state->tune_started)
969  {
970  op_state->tune_started = FALSE;
971 
972  if (status == STB_CI_TUNE_OK)
973  {
974  /* Tuned successfully, pass the result to the CI+ stack */
975  op_status.descriptor_number = op_state->op_desc_num;
976  op_status.status = STB_CI_OPERATOR_TUNE_OK;
977  op_status.desc_loop = op_state->op_current_location;
978  op_status.desc_loop_len = op_state->op_current_loc_len;
979 
980  if (path != INVALID_RES_ID)
981  {
982  if ((tuner = STB_DPGetPathTuner(path)) != INVALID_RES_ID)
983  {
984  op_status.signal_strength = STB_TuneGetSignalStrength(tuner);
985  op_status.signal_quality = STB_TuneGetDataIntegrity(tuner);
986  }
987  else
988  {
989  DBG_OP("Path %u doesn't have a tuner!", path)
990  op_status.signal_strength = 0;
991  op_status.signal_quality = 0;
992  }
993  }
994  else
995  {
996  DBG_OP("Tuner locked but invalid decode path")
997  op_status.signal_strength = 0;
998  op_status.signal_quality = 0;
999  }
1000 
1001  retval = STB_CISendOperatorTuneStatus(op_state->module, &op_status);
1002 
1003  if (op_state->op_current_location != NULL)
1004  {
1005  STB_FreeMemory(op_state->op_current_location);
1006  op_state->op_current_location = NULL;
1007  op_state->op_current_loc_len = 0;
1008  }
1009  }
1010  else
1011  {
1012  /* Tuning didn't succeed, so continue processing any remaining delivery descriptors */
1013  PerformOperatorTune(op_state);
1014  }
1015  }
1016  else
1017  {
1018  DBG_OP(" The tune was not started by module %u", module)
1019  }
1020  }
1021  STB_OSMutexUnlock(ciop_mutex);
1022 
1023  FUNCTION_FINISH(ACI_OpTuneReply);
1024 
1025  return(retval);
1026 }
1027 
1028 //----------------------------------------------------------------------------
1029 //--- Local function for this file ------------------------------------------
1030 //----------------------------------------------------------------------------
1031 
1032 static S_OP_STATUS *FindOpState(U32BIT module)
1033 {
1034  S_OP_STATUS *op_state;
1035  op_state = ciop_list;
1036  while (op_state != NULL && module != op_state->module)
1037  {
1038  op_state = op_state->next;
1039  }
1040  return op_state;
1041 }
1042 
1043 /*!**************************************************************************
1044  * @brief Starts and operator search
1045  * @param op_state - slot state info
1046  ****************************************************************************/
1047 static BOOLEAN StartOperatorSearch(S_OP_STATUS *op_state)
1048 {
1049  BOOLEAN retval;
1050  S_CIP_HOST_INFO host_info;
1051  S_STB_CI_SEARCH_START_INFO search_info;
1052 
1053  FUNCTION_START(StartOperatorSearch);
1054 
1055  retval = FALSE;
1056 
1057  /* A scan is required to setup the private network. Get scan info from the host */
1058  RequestHostInfo(&host_info);
1059 
1060  if (PrepareSearchInfo(&host_info, &search_info))
1061  {
1062  /* Save the delivery types supported by the host so they can be checked when tuning */
1063  op_state->host_delivery_types = host_info.delivery_types;
1064 
1065  if (STB_CIRequestOperatorSearchStart(op_state->module, &search_info))
1066  {
1067  DBG_OP("Starting operator search to setup network")
1068 
1069  /* Tuner is now under control of operator profile until the search completes */
1070  //op_state->tuner_status = CI_TUNER_OP;
1071 
1072  op_state->op_nit_received = FALSE;
1073  op_state->op_search_started = TRUE;
1074  op_state->op_desc_loop_len = 0;
1075  op_state->op_desc_loop = NULL;
1076 
1077  retval = TRUE;
1078  }
1079  else
1080  {
1081  DBG_OP("Failed to start operator search")
1082  }
1083 
1084  if (search_info.service_type != NULL)
1085  {
1086  STB_FreeMemory(search_info.service_type);
1087  }
1088  if (search_info.delivery_capability != NULL)
1089  {
1090  STB_FreeMemory(search_info.delivery_capability);
1091  }
1092  if (search_info.application_capability != NULL)
1093  {
1094  STB_FreeMemory(search_info.application_capability);
1095  }
1096  }
1097  else
1098  {
1099  DBG_OP("PrepareSearchInfo failed")
1100  }
1101 
1102  FUNCTION_FINISH(StartOperatorSearch);
1103 
1104  return(retval);
1105 }
1106 
1107 /*!**************************************************************************
1108  * @brief Sets up the operator start search info to be passed to the CI+ stack
1109  * from info provided by the host.
1110  * @param host_info - host info
1111  * @param search_info - structure to be setup before being passed to the CI+ stack.
1112  * Memory will be allocated for the arrays in this structure
1113  * @return TRUE if the structure is setup successfully, FALSE otherwise
1114  ****************************************************************************/
1115 static BOOLEAN PrepareSearchInfo(S_CIP_HOST_INFO *host_info, S_STB_CI_SEARCH_START_INFO *search_info)
1116 {
1117  U16BIT counter;
1118  BOOLEAN retval;
1119 
1120  FUNCTION_START(PrepareSearchInfo);
1121 
1122  retval = TRUE;
1123 
1124  search_info->unattended_flag = host_info->standby;
1125 
1126  /* Setup the supported service types */
1127  if ((search_info->service_type = STB_GetMemory(host_info->num_service_types)) != NULL)
1128  {
1129  search_info->service_type_loop_length = host_info->num_service_types;
1130 
1131  counter = 0;
1132  if ((host_info->service_types & CIP_SERVICE_TYPE_TV) != 0)
1133  {
1134  search_info->service_type[counter] = 0x01; /* MPEG2 TV */
1135  counter++;
1136  }
1137  if ((host_info->service_types & CIP_SERVICE_TYPE_RADIO) != 0)
1138  {
1139  search_info->service_type[counter] = 0x02; /* MPEG1 Layer-II radio */
1140  counter++;
1141  }
1142  if ((host_info->service_types & CIP_SERVICE_TYPE_TELETEXT) != 0)
1143  {
1144  search_info->service_type[counter] = 0x03; /* Teletext */
1145  counter++;
1146  }
1147  if ((host_info->service_types & CIP_SERVICE_TYPE_AVC_RADIO) != 0)
1148  {
1149  search_info->service_type[counter] = 0x0a; /* AVC radio */
1150  counter++;
1151  }
1152  if ((host_info->service_types & CIP_SERVICE_TYPE_DATA) != 0)
1153  {
1154  search_info->service_type[counter] = 0x0c; /* Data */
1155  counter++;
1156  }
1157  if ((host_info->service_types & CIP_SERVICE_TYPE_HD_TV) != 0)
1158  {
1159  search_info->service_type[counter] = 0x11; /* MPEG2 HD TV */
1160  counter++;
1161  }
1162  if ((host_info->service_types & CIP_SERVICE_TYPE_AVC_SD_TV) != 0)
1163  {
1164  search_info->service_type[counter] = 0x16; /* AVC SD TV */
1165  counter++;
1166  }
1167  if ((host_info->service_types & CIP_SERVICE_TYPE_AVC_HD_TV) != 0)
1168  {
1169  search_info->service_type[counter] = 0x19; /* AVC HD TV */
1170  }
1171  }
1172  else
1173  {
1174  search_info->service_type_loop_length = 0;
1175  retval = FALSE;
1176  }
1177 
1178  /* Setup the supported delivery capabilities */
1179  counter = 0;
1180  if ((host_info->delivery_types & CIP_DELIVERY_TYPE_DVBT) != 0)
1181  {
1182  counter += 1;
1183  }
1184  if ((host_info->delivery_types & CIP_DELIVERY_TYPE_DVBT2) != 0)
1185  {
1186  counter += 2;
1187  }
1188  if ((host_info->delivery_types & CIP_DELIVERY_TYPE_DVBC) != 0)
1189  {
1190  counter += 1;
1191  }
1192  if ((host_info->delivery_types & CIP_DELIVERY_TYPE_DVBC2) != 0)
1193  {
1194  counter += 2;
1195  }
1196  if ((host_info->delivery_types & CIP_DELIVERY_TYPE_DVBS) != 0)
1197  {
1198  counter += 1;
1199  }
1200  if ((host_info->delivery_types & CIP_DELIVERY_TYPE_DVBS2) != 0)
1201  {
1202  counter += 1;
1203  }
1204 
1205  if ((search_info->delivery_capability = STB_GetMemory(counter)) != NULL)
1206  {
1207  search_info->delivery_capability_loop_length = counter;
1208 
1209  counter = 0;
1210  if ((host_info->delivery_types & CIP_DELIVERY_TYPE_DVBT) != 0)
1211  {
1212  search_info->delivery_capability[counter] = 0x5a;
1213  counter += 1;
1214  }
1215  if ((host_info->delivery_types & CIP_DELIVERY_TYPE_DVBT2) != 0)
1216  {
1217  search_info->delivery_capability[counter] = 0x7f;
1218  search_info->delivery_capability[counter + 1] = 0x04;
1219  counter += 2;
1220  }
1221  if ((host_info->delivery_types & CIP_DELIVERY_TYPE_DVBC) != 0)
1222  {
1223  search_info->delivery_capability[counter] = 0x44;
1224  counter += 1;
1225  }
1226  if ((host_info->delivery_types & CIP_DELIVERY_TYPE_DVBC2) != 0)
1227  {
1228  search_info->delivery_capability[counter] = 0x7f;
1229  search_info->delivery_capability[counter + 1] = 0x0d;
1230  counter += 2;
1231  }
1232  if ((host_info->delivery_types & CIP_DELIVERY_TYPE_DVBS) != 0)
1233  {
1234  search_info->delivery_capability[counter] = 0x43;
1235  counter += 1;
1236  }
1237  if ((host_info->delivery_types & CIP_DELIVERY_TYPE_DVBS2) != 0)
1238  {
1239  search_info->delivery_capability[counter] = 0x79;
1240  }
1241  }
1242  else
1243  {
1244  search_info->delivery_capability_loop_length = 0;
1245  retval = FALSE;
1246  }
1247 
1248  /* Setup the supported application capabilities */
1249  counter = 0;
1250  if ((host_info->app_types & CIP_APP_TYPE_MHEG) != 0)
1251  {
1252  counter += 2;
1253  }
1254  if ((host_info->app_types & CIP_APP_TYPE_HBBTV) != 0)
1255  {
1256  counter += 2;
1257  }
1258  if ((host_info->app_types & CIP_APP_TYPE_OIPF) != 0)
1259  {
1260  counter += 2;
1261  }
1262 
1263  if (counter > 0)
1264  {
1265  if ((search_info->application_capability = STB_GetMemory(counter)) != NULL)
1266  {
1267  search_info->application_capability_loop_length = counter;
1268 
1269  counter = 0;
1270  if ((host_info->app_types & CIP_APP_TYPE_MHEG) != 0)
1271  {
1272  search_info->application_capability[counter] = 0x01;
1273  search_info->application_capability[counter + 1] = 0x06;
1274  counter += 2;
1275  }
1276  if ((host_info->app_types & CIP_APP_TYPE_HBBTV) != 0)
1277  {
1278  search_info->application_capability[counter] = 0x01;
1279  search_info->application_capability[counter + 1] = 0x23;
1280  counter += 2;
1281  }
1282  if ((host_info->app_types & CIP_APP_TYPE_OIPF) != 0)
1283  {
1284  search_info->application_capability[counter] = 0x01;
1285  search_info->application_capability[counter + 1] = 0x50;
1286  }
1287  }
1288  else
1289  {
1290  search_info->application_capability_loop_length = 0;
1291  retval = FALSE;
1292  }
1293  }
1294  else
1295  {
1296  search_info->application_capability_loop_length = 0;
1297  search_info->application_capability = NULL;
1298  }
1299 
1300  FUNCTION_FINISH(PrepareSearchInfo);
1301 
1302  return(retval);
1303 }
1304 
1305 static BOOLEAN ValidateFrequency(SI_DELIVERY_SYS_DESC_TYPE del_type, U32BIT frequency)
1306 {
1307  BOOLEAN valid, done;
1308  U8BIT tuner, n;
1309  E_STB_TUNE_SYSTEM_TYPE type;
1310  U32BIT tnr_min_freq;
1311  U32BIT tnr_max_freq;
1312 
1313  FUNCTION_START(ValidateFrequency);
1314 
1315  valid = FALSE;
1316  done = FALSE;
1317  /* Find the first tuner supporting the type */
1318  n = STB_HWGetTunerPaths();
1319  for (tuner = 0; tuner < n; tuner++)
1320  {
1321  type = STB_TuneGetSupportedSystemType(tuner);
1322  switch (type)
1323  {
1324  case TUNE_SYSTEM_TYPE_DVBT:
1325  case TUNE_SYSTEM_TYPE_DVBT2:
1326  {
1327  if (del_type == SI_DEL_SYS_DESC_TYPE_TERR)
1328  {
1329  done = TRUE;
1330  }
1331  break;
1332  }
1333  case TUNE_SYSTEM_TYPE_DVBS:
1334  case TUNE_SYSTEM_TYPE_DVBS2:
1335  {
1336  if (del_type == SI_DEL_SYS_DESC_TYPE_SAT)
1337  {
1338  done = TRUE;
1339  }
1340  break;
1341  }
1342  case TUNE_SYSTEM_TYPE_DVBC:
1343  {
1344  if (del_type == SI_DEL_SYS_DESC_TYPE_CABLE)
1345  {
1346  done = TRUE;
1347  }
1348  break;
1349  }
1350  default:
1351  {
1352  break;
1353  }
1354  }
1355  if (done)
1356  {
1357  break;
1358  }
1359  }
1360  if (done)
1361  {
1362  tnr_min_freq = STB_TuneGetMinTunerFreqKHz(tuner);
1363  tnr_max_freq = STB_TuneGetMaxTunerFreqKHz(tuner);
1364  DBG_OP("min=%u, max=%u", tnr_min_freq, tnr_max_freq)
1365  if ((frequency > tnr_min_freq) && (frequency < tnr_max_freq))
1366  {
1367  valid = TRUE;
1368  }
1369  }
1370 
1371  DBG_OP("frequency=%u del_type=%d valid=%s", frequency, del_type,
1372  valid ? "TRUE" : "FALSE")
1373 
1374  FUNCTION_FINISH(ValidateFrequency);
1375 
1376  return valid;
1377 }
1378 
1384 static void PerformOperatorTune(S_OP_STATUS *op_state)
1385 {
1386  U8BIT *end_ptr;
1387  U8BIT *desc_ptr;
1388  U8BIT desc_num;
1389  U8BIT desc_len;
1390  U8BIT *current_location_info;
1391  U8BIT current_location_len;
1392  S_STB_CI_OPERATOR_TUNE_STATUS tune_status;
1393  SI_DELIVERY_SYS_DESC_TYPE del_type;
1394  SI_DELIVERY_SYS_DESC *desc;
1395  BOOLEAN send_status;
1396  S_CIP_TUNE_DEL_SYS_DESC tune_del_sys;
1397  U32BIT frequency;
1398 
1399  FUNCTION_START(PerformOperatorTune);
1400 
1401  if (op_state->op_current_location != NULL)
1402  {
1403  STB_FreeMemory(op_state->op_current_location);
1404  op_state->op_current_location = NULL;
1405  op_state->op_current_loc_len = 0;
1406  }
1407 
1408  desc_ptr = op_state->op_desc_loop;
1409  end_ptr = desc_ptr + op_state->op_desc_loop_len;
1410 
1411  /* Find the start of the next descriptor to be used */
1412  for (desc_num = 0; (desc_num < op_state->op_desc_num) && (desc_ptr < end_ptr); )
1413  {
1414  desc_len = *(desc_ptr + 1);
1415  desc_ptr += (desc_len + 2);
1416  /* s2_satellite_delivery_descriptor should always be present together a
1417  satellite_delivery_descriptor and have to be dealt with it */
1418  if (*desc_ptr != 0x79)
1419  {
1420  desc_num++;
1421  }
1422  }
1423 
1424  if (desc_ptr < end_ptr)
1425  {
1426  send_status = FALSE;
1427 
1428  /* Iterate through the descriptors */
1429  while (desc_ptr < end_ptr)
1430  {
1431  desc_len = *(desc_ptr + 1);
1432 
1433  if (*desc_ptr == 0x43)
1434  {
1435  /* A satellite_delivery_descriptor may be followed by an s2_satellite_delivery_descriptor,
1436  DVBCore ignores the latter (for now), but the reply to the CICAM must include both */
1437  if ((desc_ptr + desc_len + 2 < end_ptr) && (*(desc_ptr + desc_len + 2) == 0x79))
1438  {
1439  desc_len += *(desc_ptr + desc_len + 3) + 2;
1440  }
1441  }
1442 
1443  /* Save this descriptor for passing back to the CI+ stack */
1444  if ((current_location_info = (U8BIT *)STB_GetMemory(desc_len + 2)) != NULL)
1445  {
1446  memcpy(current_location_info, desc_ptr, desc_len + 2);
1447  current_location_len = desc_len + 2;
1448 
1449  /* Find or add a transport for this delivery descriptor */
1450 
1451  /* Find any descriptors, immediately following the current one,
1452  * that would result in tuning to the same TS */
1453  desc_ptr += (desc_len + 2);
1454 
1455  if (desc_ptr == end_ptr)
1456  {
1457  /* This is the last descriptor, the descriptor_number in the reply must be 0xFF */
1458  op_state->op_desc_num = 0xFF;
1459  }
1460  else
1461  {
1462  /* This is not the last descriptor, the descriptor_number in the reply must be the
1463  next unprocessed descriptor number */
1464  op_state->op_desc_num++;
1465  }
1466 
1467  /* Check whether the descriptor to be used for tuning can be used and is valid */
1468  desc = NULL;
1469  if (STB_SIParseDelSysDesc(current_location_info, &del_type, &desc))
1470  {
1471  /* Check that the delivery type is supported */
1472  switch (del_type)
1473  {
1474  case SI_DEL_SYS_DESC_TYPE_TERR:
1475  if (desc->terr.is_t2)
1476  {
1477  if ((op_state->host_delivery_types & CIP_DELIVERY_TYPE_DVBT2) == 0)
1478  {
1479  /* DVB-T2 isn't supported */
1480  tune_status.status = STB_CI_OPERATOR_TUNE_NOT_SUPPORTED;
1481  send_status = TRUE;
1482  }
1483  else
1484  {
1485  if ((desc->terr.u.t2.num_cells > 0) &&
1486  (desc->terr.u.t2.cell[0].num_freqs > 0))
1487  {
1488  frequency = desc->terr.u.t2.cell[0].freq_hz[0] / 1000; // Convert to kHz
1489  }
1490  else
1491  {
1492  frequency = 0;
1493  }
1494  }
1495  }
1496  else
1497  {
1498  if ((op_state->host_delivery_types & CIP_DELIVERY_TYPE_DVBT) == 0)
1499  {
1500  /* DVB-T isn't supported */
1501  tune_status.status = STB_CI_OPERATOR_TUNE_NOT_SUPPORTED;
1502  send_status = TRUE;
1503  }
1504  else
1505  {
1506  frequency = desc->terr.u.t1.freq_hz / 1000; // Convert to kHz
1507  }
1508  }
1509  break;
1510 
1511  case SI_DEL_SYS_DESC_TYPE_CABLE:
1512  if ((op_state->host_delivery_types & CIP_DELIVERY_TYPE_DVBC) == 0)
1513  {
1514  /* DVB-C isn't supported */
1515  tune_status.status = STB_CI_OPERATOR_TUNE_NOT_SUPPORTED;
1516  send_status = TRUE;
1517  }
1518  else
1519  {
1520  frequency = desc->cable.freq_hz / 1000; // Convert to kHz
1521  }
1522  break;
1523 
1524  case SI_DEL_SYS_DESC_TYPE_SAT:
1525  if ((op_state->host_delivery_types & CIP_DELIVERY_TYPE_DVBS) == 0)
1526  {
1527  /* DVB-S isn't supported */
1528  tune_status.status = STB_CI_OPERATOR_TUNE_NOT_SUPPORTED;
1529  send_status = TRUE;
1530  }
1531  else
1532  {
1533  /* freq_hz seems to contain MHz */
1534  frequency = desc->sat.freq_hz * 1000; // Convert to kHz
1535  }
1536  break;
1537  }
1538  if (!send_status)
1539  {
1540  /* Signal type is supported, now check that the frequency is valid */
1541  send_status = !ValidateFrequency(del_type, frequency);
1542  if (send_status)
1543  {
1544  tune_status.status = STB_CI_OPERATOR_TUNE_INVALID;
1545  }
1546  }
1547 
1548  /* Status will be sent if an error has been detected */
1549  if (send_status)
1550  {
1551  STB_SIReleaseDelSysDesc(desc, del_type);
1552  break;
1553  }
1554 
1555  /* Try to tune to the TS defined by the current location descriptor.
1556  * It's the responsibility of the callback function to free the delivery descriptor */
1557  op_state->tune_started = TRUE;
1558 
1559  op_state->op_current_location = current_location_info;
1560  op_state->op_current_loc_len = current_location_len;
1561 
1562  memset(&tune_del_sys, 0, sizeof(tune_del_sys));
1563  tune_del_sys.type = del_type;
1564  tune_del_sys.desc = desc;
1565  ACI_TuneToDelSysDesc(op_state->module, &tune_del_sys, CIP_NORMAL_TUNE);
1566  break;
1567  }
1568  else
1569  {
1570  /* Delivery descriptor is invalid */
1571  tune_status.status = STB_CI_OPERATOR_TUNE_INVALID;
1572  send_status = TRUE;
1573  break;
1574  }
1575  }
1576  }
1577 
1578  if (send_status)
1579  {
1580  tune_status.descriptor_number = op_state->op_desc_num;
1581  tune_status.signal_strength = 0;
1582  tune_status.signal_quality = 0;
1583  tune_status.desc_loop = current_location_info;
1584  tune_status.desc_loop_len = current_location_len;
1585 
1586  STB_CISendOperatorTuneStatus(op_state->module, &tune_status);
1587 
1588  /* Now free the descriptor data sent to the CI+ stack */
1589  STB_FreeMemory(current_location_info);
1590  }
1591  }
1592  else
1593  {
1594  /* No more descriptors to tune to. The tuning operation has failed */
1595  tune_status.descriptor_number = 0xff;
1596  tune_status.signal_strength = 0;
1597  tune_status.signal_quality = 0;
1598  tune_status.status = STB_CI_OPERATOR_TUNE_NO_SIGNAL;
1599  tune_status.desc_loop_len = 0;
1600  tune_status.desc_loop = NULL;
1601 
1602  STB_CISendOperatorTuneStatus(op_state->module, &tune_status);
1603 
1604  /* Free any saved data */
1605  if (op_state->op_desc_loop != NULL)
1606  {
1607  STB_FreeMemory(op_state->op_desc_loop);
1608  op_state->op_desc_loop = NULL;
1609  op_state->op_desc_loop_len = 0;
1610  }
1611  }
1612 
1613  FUNCTION_FINISH(PerformOperatorTune);
1614 }
1615 
1616 static U32BIT ConvertLangCode(U8BIT *data)
1617 {
1618  U32BIT lcode;
1619  U8BIT code_char;
1620  U16BIT i;
1621 
1622  FUNCTION_START(ConvertLangCode);
1623 
1624  lcode = 0;
1625  for (i = 0; i < 3; i++)
1626  {
1627  code_char = *data;
1628  data++;
1629  if ((code_char >= 'A') && (code_char <= 'Z'))
1630  {
1631  code_char += 0x20; // convert to lower case
1632  }
1633  lcode = (lcode << 8) | code_char;
1634  }
1635 
1636  FUNCTION_FINISH(ConvertLangCode);
1637 
1638  return(lcode);
1639 }
1640 
1649 static U8BIT GetCharacterCodeTable(S_STB_CI_OPERATOR_INFO *op_info)
1650 {
1651  U8BIT table;
1652 
1653  FUNCTION_START(GetCharacterCodeTable);
1654 
1655  /* Default */
1656  table = 0;
1657 
1658  if ((op_info->character_code_table >= 1) && (op_info->character_code_table <= 11))
1659  {
1660  // one of the Latin tables specified in the DVB SI specification from ISO 8859.
1661  // 1 => 8859-5, 2 => 8859-6, 3 => 8859-7, 4 => 8859-8, 5 => 8859-9
1662  // 6 => 8859-10, 7 => 8859-11, 8 => 8859-12, 9 => 8859-13, 10 => 8859-14, 11 => 8859-15
1663  table = op_info->character_code_table + 4;
1664  }
1665  else if (op_info->character_code_table == 0x10)
1666  {
1667  // next 2 bytes indicate the table from ISO 8859
1668  table = (op_info->second_byte_value << 8) | (op_info->third_byte_value);
1669  }
1670 
1671  FUNCTION_FINISH(GetCharacterCodeTable);
1672 
1673  return table;
1674 }
1675 
1685 static void CopyLinkageDesc(SI_LINKAGE_DESC_ENTRY *source_desc_entry,
1686  SI_LINKAGE_DESC_ENTRY **destination_list_head, SI_LINKAGE_DESC_ENTRY **destination_last_entry,
1687  U16BIT *destination_num_linkage_desc)
1688 {
1689  SI_LINKAGE_DESC_ENTRY *desc_ptr;
1690 
1691  FUNCTION_START(CopyLinkageDesc);
1692 
1693  desc_ptr = (SI_LINKAGE_DESC_ENTRY *)STB_GetMemory(sizeof(SI_LINKAGE_DESC_ENTRY) + source_desc_entry->data_length);
1694  if (desc_ptr != NULL)
1695  {
1696  desc_ptr->next = NULL;
1697  desc_ptr->tran_id = source_desc_entry->tran_id;
1698  desc_ptr->orig_net_id = source_desc_entry->orig_net_id;
1699  desc_ptr->serv_id = source_desc_entry->serv_id;
1700  desc_ptr->link_type = source_desc_entry->link_type;
1701  desc_ptr->data_length = source_desc_entry->data_length;
1702 
1703  if (source_desc_entry->data_length != 0)
1704  {
1705  memcpy(&(desc_ptr->data), &(source_desc_entry->data), source_desc_entry->data_length);
1706  }
1707 
1708  // now add descriptor to linked list
1709  if (*destination_last_entry == NULL)
1710  {
1711  // first entry in the list
1712  *destination_list_head = desc_ptr;
1713  }
1714  else
1715  {
1716  // not the first entry
1717  (*destination_last_entry)->next = desc_ptr;
1718  }
1719  *destination_last_entry = desc_ptr;
1720  (*destination_num_linkage_desc)++;
1721 
1722  DBG_OP("Linkage desc: tid=0x%04x, onid=0x%04x, sid=0x%04x, type=%d, dlen=%d",
1723  desc_ptr->tran_id, desc_ptr->orig_net_id, desc_ptr->serv_id,
1724  desc_ptr->link_type, desc_ptr->data_length)
1725  }
1726 
1727  FUNCTION_FINISH(CopyLinkageDesc);
1728 }
1729 
1734 static void DeleteLinkageDescriptorArray(SI_LINKAGE_DESC_ENTRY *list_ptr)
1735 {
1736  SI_LINKAGE_DESC_ENTRY *desc_ptr, *tmp_ptr;
1737 
1738  FUNCTION_START(DeleteLinkageDescriptorArray);
1739 
1740  desc_ptr = list_ptr;
1741  while (desc_ptr != NULL)
1742  {
1743  tmp_ptr = desc_ptr->next;
1744  STB_FreeMemory(desc_ptr);
1745  desc_ptr = tmp_ptr;
1746  }
1747 
1748  FUNCTION_FINISH(DeleteLinkageDescriptorArray);
1749 }
1750 
1755 static ADB_SERVICE_REC *GetServiceFromLcn(U16BIT lcn)
1756 {
1757  ADB_SERVICE_REC *s_ptr;
1758 
1759  FUNCTION_START(GetServiceFromLcn);
1760  s_ptr = DBDEF_GetNextServiceRec(NULL);
1761  while (s_ptr != NULL)
1762  {
1763  if (s_ptr->allocated_lcn == lcn)
1764  {
1765  break;
1766  }
1767  s_ptr = DBDEF_GetNextServiceRec(s_ptr);
1768  }
1769  FUNCTION_FINISH(GetServiceFromLcn);
1770 
1771  return s_ptr;
1772 }
1773 
1780 static U8BIT GetFreeLcns(U16BIT start_lcn, U16BIT *free_lcns)
1781 {
1782  ADB_SERVICE_REC *s_ptr;
1783  U16BIT num_services, nx, lcn;
1784  U16BIT *existing_lcns;
1785  U8BIT num_found;
1786 
1787  FUNCTION_START(GetFreeLcns);
1788  if (start_lcn == 0)
1789  {
1790  start_lcn = 1;
1791  }
1792  num_found = 0;
1793  num_services = DBDEF_GetNumServices();
1794  if (num_services != 0 && free_lcns != NULL)
1795  {
1796  existing_lcns = STB_AppGetMemory(num_services * sizeof(U16BIT));
1797  if (existing_lcns != NULL)
1798  {
1799  s_ptr = DBDEF_GetNextServiceRec(NULL);
1800  for (nx = 0; nx != num_services && s_ptr != NULL; nx++)
1801  {
1802  existing_lcns[nx] = s_ptr->allocated_lcn;
1803  s_ptr = DBDEF_GetNextServiceRec(s_ptr);
1804  }
1805  lcn = start_lcn;
1806  while (--lcn != 0)
1807  {
1808  for (nx = 0; nx != num_services; nx++)
1809  {
1810  if (existing_lcns[nx] == lcn)
1811  {
1812  break;
1813  }
1814  }
1815  if (nx == num_services)
1816  {
1817  /* lcn is not used */
1818  free_lcns[num_found] = lcn;
1819  num_found++;
1820  break;
1821  }
1822  }
1823  lcn = start_lcn;
1824  while (++lcn <= 9999)
1825  {
1826  for (nx = 0; nx != num_services; nx++)
1827  {
1828  if (existing_lcns[nx] == lcn)
1829  {
1830  break;
1831  }
1832  }
1833  if (nx == num_services)
1834  {
1835  /* this lcn is not used */
1836  free_lcns[num_found] = lcn;
1837  num_found++;
1838  if (num_found == CIP_NUM_FREE_LCNS)
1839  {
1840  break;
1841  }
1842  }
1843  }
1844  STB_AppFreeMemory(existing_lcns);
1845  }
1846  }
1847  FUNCTION_FINISH(GetFreeLcns);
1848  return num_found;
1849 }
1850 
1858 static ADB_EVENT_REC *CreateVirtualEventRec(SI_STRING_DESC *name_str, U8BIT *event_info, U8BIT event_info_len)
1859 {
1860  ADB_EVENT_REC *e_ptr;
1861  ADB_EVENT_DESC *event_desc;
1862  U8BIT *data;
1863  U32BIT lang;
1864  U8BIT dlen;
1865 
1866  e_ptr = STB_AppGetMemory(sizeof(ADB_EVENT_REC));
1867  if (e_ptr != NULL)
1868  {
1869  memset(e_ptr, 0, sizeof(ADB_EVENT_REC));
1870 
1871  dlen = 5 + event_info_len;
1872  if (name_str != NULL)
1873  {
1874  dlen += name_str->nbytes;
1875  }
1876  event_desc = (ADB_EVENT_DESC *)STB_AppGetMemory(sizeof(ADB_EVENT_DESC) + dlen + 2);
1877  if (event_desc != NULL)
1878  {
1879  /* set lang to UND */
1881  data = (U8BIT *)(event_desc + 1);
1882  event_desc->desc_data = data;
1883  data[0] = SHORT_EVENT_DTAG;
1884  data[1] = dlen;
1885  data[2] = (lang >> 16) & 0xFF;
1886  data[3] = (lang >> 8) & 0xFF;
1887  data[4] = lang & 0xFF;
1888  data += 5;
1889  if (name_str != NULL)
1890  {
1891  /* fill 'event name' with name of Virtual Channel */
1892  dlen = name_str->nbytes;
1893  *data = dlen;
1894  data++;
1895  memcpy(data, name_str->str_ptr, dlen);
1896  data += dlen;
1897  }
1898  else
1899  {
1900  *data = 0;
1901  data++;
1902  }
1903  /* add event description with the event information that
1904  * "may be used to populate the EPG information field". See TS 103 205, section 15.3.1 */
1905  dlen = event_info_len;
1906  data++;
1907  memcpy(data, event_info, dlen);
1908  e_ptr->desc_list_head = event_desc;
1909  e_ptr->desc_list_tail = event_desc;
1910  /* start and end times are not specified: so set start to now with duration of 24 hours */
1911  e_ptr->start = STB_GCNowDHMSLocal();
1912  e_ptr->duration = DHMS_CREATE(0, 23, 59, 59);
1913  }
1914  else
1915  {
1916  STB_AppFreeMemory(e_ptr);
1917  e_ptr = NULL;
1918  }
1919  }
1920  return e_ptr;
1921 }
1922 
1931 static S_STB_CI_OPERATOR_NIT_MANAGEMENT_SERVICE_ITEM_DATA *
1932 AddVirtualChannel(ADB_NETWORK_REC *network, SI_CIPLUS_VIRTUAL_CHANNEL *v_chan)
1933 {
1934  ADB_SERVICE_REC *s_ptr;
1935  ADB_TRANSPORT_REC* t_ptr;
1936  S_STB_CI_OPERATOR_NIT_MANAGEMENT_SERVICE_ITEM_DATA *s_item;
1937 
1938  FUNCTION_START(AddVirtualChannel);
1939  if (!STB_CIIsMmiEngineRegistered(v_chan->app_domain_id))
1940  {
1941  s_item = STB_AppGetMemory(sizeof(S_STB_CI_OPERATOR_NIT_MANAGEMENT_SERVICE_ITEM_DATA));
1942  if (s_item != NULL)
1943  {
1944  s_item->channel_issue_type = STB_CI_OPERATOR_NIT_DOMAIN_NOT_SUPPORTED;
1945  s_item->logical_channel_number = v_chan->lcn;
1946  if (v_chan->name_str != NULL)
1947  {
1948  s_item->length_service_name = v_chan->name_str->nbytes;
1949  s_item->service_name = v_chan->name_str->str_ptr;
1950  }
1951  else
1952  {
1953  s_item->length_service_name = 0;
1954  s_item->service_name = NULL;
1955  }
1956  s_item->number_free_lcn = 0;
1957  s_item->free_lcn = NULL;
1958  }
1959  }
1960  else
1961  {
1962  s_ptr = GetServiceFromLcn(v_chan->lcn);
1963  if (s_ptr != NULL)
1964  {
1965  /* LCN Collision ! */
1966  s_item = STB_AppGetMemory(sizeof(S_STB_CI_OPERATOR_NIT_MANAGEMENT_SERVICE_ITEM_DATA));
1967  if (s_item != NULL)
1968  {
1969  s_item->channel_issue_type = STB_CI_OPERATOR_NIT_LCN_COLLISION;
1970  s_item->logical_channel_number = v_chan->lcn;
1971  if (v_chan->name_str != NULL)
1972  {
1973  s_item->length_service_name = v_chan->name_str->nbytes;
1974  s_item->service_name = v_chan->name_str->str_ptr;
1975  }
1976  else
1977  {
1978  s_item->length_service_name = 0;
1979  s_item->service_name = NULL;
1980  }
1981  s_item->free_lcn = (U16BIT *)STB_AppGetMemory(CIP_NUM_FREE_LCNS * sizeof(U16BIT));
1982  s_item->number_free_lcn = GetFreeLcns(v_chan->lcn, s_item->free_lcn);
1983  }
1984  }
1985  else
1986  {
1987  s_item = NULL; /* set to NULL, because Virtual channel is supported and LCN is okay */
1988 
1989  /* create 'virtual' transport rec to link virtual channel to the network rec */
1990  t_ptr = DBDEF_AddVirtualTransportRec(network);
1991  if (t_ptr != NULL)
1992  {
1993  if ((s_ptr = DBDEF_AddServiceRec(0xFFFF, t_ptr)) != NULL)
1994  {
1995  s_ptr->new_service = TRUE;
1996  s_ptr->serv_lcn = v_chan->lcn;
1997  s_ptr->allocated_lcn = v_chan->lcn;
1998  DBDEF_SetServiceType(s_ptr, ADB_SERVICE_TYPE_VIRTUAL);
1999  if (v_chan->name_str != NULL)
2000  {
2001  DBDEF_SetServiceName(s_ptr, v_chan->name_str->str_ptr);
2002  DBDEF_SetServiceShortName(s_ptr, v_chan->name_str->str_ptr);
2003  }
2004  if (v_chan->provider_str != NULL)
2005  {
2006  DBDEF_SetServiceProviderName(s_ptr, v_chan->provider_str->str_ptr);
2007  }
2008  if (v_chan->event_info_len != 0)
2009  {
2010  s_ptr->now_event = CreateVirtualEventRec(v_chan->name_str, v_chan->event_info, v_chan->event_info_len);
2011  }
2012  }
2013  else
2014  {
2015  DBG_OP("failed to create Virtual channel");
2016  DBDEF_DeleteTransportRec(t_ptr);
2017  }
2018  }
2019  else
2020  {
2021  DBG_OP("failed to create Virtual transport");
2022  }
2023  }
2024  }
2025  FUNCTION_FINISH(AddVirtualChannel);
2026  return s_item;
2027 }
2028 
2029 
2035 static void ProcessNit(U32BIT module, S_CIP_OPERATOR_NIT *nit)
2036 {
2037  ADB_NETWORK_REC *n_ptr;
2038  ADB_TRANSPORT_REC *t_ptr;
2039  ADB_TRANSPORT_REC *next_t_ptr;
2040  ADB_SERVICE_REC *s_ptr;
2041  ADB_SERVICE_REC *next_s_ptr;
2042  BOOLEAN changed;
2043  SI_NIT_TRANSPORT_ENTRY *nit_entry;
2044  SI_CIPLUS_SERVICE *serv_entry;
2045  SI_STRING_DESC *str_desc;
2046  U8BIT *tmp_str;
2047  U16BIT profile_name_bytes;
2048  ADB_FAVLIST_REC *fav_list = NULL;
2049  SI_LINKAGE_DESC_ENTRY *linkage_desc_ptr;
2050  S_STB_CI_OPERATOR_NIT_MANAGEMENT_SERVICE_ITEM_DATA *serv_items;
2051  U8BIT serv_item_count;
2052 
2053  FUNCTION_START(ProcessNit);
2054 
2056 
2057  /* Save the current profile type so it can be restored at the end */
2058  DBDEF_PushCIPlusProfile(nit->cicam_onet_id, nit->cicam_identifier);
2059 
2060  /* Check whether there's already a network for this CICAM */
2061  if ((n_ptr = DBDEF_FindNetworkForCIPlusProfile(nit->cicam_onet_id, nit->cicam_identifier)) == NULL)
2062  {
2063  /* Add a new network for this CAM and set its profile info */
2064  n_ptr = DBDEF_AddNetworkRec(nit->table->net_id, NULL);
2065  DBG_OP("(%lu): Added network %p", module, n_ptr)
2066 
2067  n_ptr->profile_type = ADB_PROFILE_TYPE_CIPLUS;
2068  DBA_SetFieldValue(n_ptr->dba_rec, DBA_FIELD_PROFILE_TYPE, (U32BIT)n_ptr->profile_type);
2069 
2070  n_ptr->cicam_onet_id = nit->cicam_onet_id;
2071  DBA_SetFieldValue(n_ptr->dba_rec, DBA_FIELD_ORIG_NET_ID, n_ptr->cicam_onet_id);
2072 
2073  n_ptr->cicam_identifier = nit->cicam_identifier;
2074  DBA_SetFieldValue(n_ptr->dba_rec, DBA_FIELD_PROFILE_CAM_ID, n_ptr->cicam_identifier);
2075  }
2076 
2077  /* Now process the NIT if there's a network record */
2078  if (n_ptr != NULL)
2079  {
2080  if (n_ptr->profile_name != NULL)
2081  {
2082  profile_name_bytes = n_ptr->profile_name->nbytes;
2083  }
2084  else
2085  {
2086  profile_name_bytes = 0;
2087  }
2088  if ((profile_name_bytes != nit->profile_name_length + 2) ||
2089  (memcmp(n_ptr->profile_name->str_ptr, nit->profile_name, nit->profile_name_length) != 0))
2090  {
2091  if (n_ptr->profile_name != NULL)
2092  {
2093  DBDEF_ReleaseString(n_ptr->profile_name);
2094  }
2095 
2096  /* Profile string isn't null terminated, so null terminate it before saving it. If
2097  profile_name_length=0 the resulting string will be empty */
2098  if ((tmp_str = (U8BIT *)STB_AppGetMemory(nit->profile_name_length + 2)) != NULL)
2099  {
2100  memset(tmp_str, 0, nit->profile_name_length + 2);
2101  if (nit->profile_name_length > 0)
2102  {
2103  memcpy(tmp_str, nit->profile_name, nit->profile_name_length);
2104  }
2105 
2106  n_ptr->profile_name = DBDEF_MakeString(nit->lang_code, tmp_str, nit->profile_name_length + 2);
2107 
2108  STB_AppFreeMemory(tmp_str);
2109  }
2110  }
2111 
2112  if (n_ptr->fav_list_id != 0)
2113  {
2114  fav_list = DBDEF_FindFavouriteList(n_ptr->fav_list_id);
2115  if (fav_list != NULL)
2116  {
2118  }
2119  }
2120 
2121  if (fav_list == NULL)
2122  {
2123  fav_list = DBDEF_AddFavouriteList(0, n_ptr->profile_name->str_ptr, n_ptr->cicam_identifier, -1);
2124  if (fav_list != NULL)
2125  {
2126  n_ptr->fav_list_id = fav_list->list_id;
2127  DBA_SetFieldValue(n_ptr->dba_rec, DBA_FIELD_FAVLIST_ID, n_ptr->fav_list_id);
2128  }
2129  }
2130 
2131  n_ptr->module_present = TRUE;
2132  n_ptr->module = module;
2133 
2134  DBG_OP(" NIT v%u", nit->table->version)
2135 
2136  /* Save version in network record */
2137  n_ptr->nit_version = nit->table->version;
2138  DBA_SetFieldValue(n_ptr->dba_rec, DBA_FIELD_VERSION, n_ptr->nit_version);
2139  n_ptr->nit_version_changed = FALSE;
2140 
2141  /* Update the network name */
2142  changed = TRUE;
2143  if ((n_ptr->name_str != NULL) && (nit->table->name_str != NULL))
2144  {
2145  str_desc = nit->table->name_str;
2146  if (str_desc->nbytes == n_ptr->name_str->nbytes)
2147  {
2148  if (memcmp(n_ptr->name_str->str_ptr, str_desc->str_ptr, n_ptr->name_str->nbytes) == 0)
2149  {
2150  changed = FALSE;
2151  }
2152  }
2153  }
2154 
2155  if (changed)
2156  {
2157  /* Release old name */
2158  if (n_ptr->name_str != NULL)
2159  {
2160  STB_AppFreeMemory(n_ptr->name_str);
2161  n_ptr->name_str = NULL;
2162  }
2163 
2164  /* Add new name */
2165  if (nit->table->name_str != NULL)
2166  {
2167  str_desc = nit->table->name_str;
2168  n_ptr->name_str = DBDEF_MakeString(nit->lang_code, str_desc->str_ptr, str_desc->nbytes);
2169 
2170  DBG_OP(" Network name \"%s\"", str_desc->str_ptr)
2171  }
2172  }
2173 
2174  serv_item_count = 0;
2175  if (nit->table->ciplus_virtual_channel != NULL)
2176  {
2177  serv_items = AddVirtualChannel(n_ptr, nit->table->ciplus_virtual_channel);
2178  if (serv_items != NULL)
2179  {
2180  serv_item_count++;
2181  }
2182  }
2183  else
2184  {
2185  serv_items = NULL;
2186  }
2187 
2188  /* Mark any existing transports in this network as unavailable so they can be deleted
2189  * if they're not found while parsing the transport list */
2190  t_ptr = DBDEF_GetNextTransportRec(NULL);
2191  while (t_ptr != NULL)
2192  {
2193  if (t_ptr->network == n_ptr)
2194  {
2195  t_ptr->available = FALSE;
2196  }
2197  t_ptr = DBDEF_GetNextTransportRec(t_ptr);
2198  }
2199 
2200  /* Process each transport */
2201  nit_entry = nit->table->transport_list;
2202  while (nit_entry != NULL)
2203  {
2204  t_ptr = DBDEF_FindTransportRecByIds(NULL, nit->table->net_id, nit_entry->orig_net_id, nit_entry->tran_id);
2205  if (t_ptr != NULL)
2206  {
2207  if ((t_ptr->network == NULL) || (t_ptr->network->profile_type == ADB_PROFILE_TYPE_BROADCAST))
2208  {
2209  /* Do not re-use transport records from the broadcast prfile for a CI+ profile */
2210  t_ptr = NULL;
2211  }
2212  }
2213 
2214  if ( t_ptr != NULL)
2215  {
2216  DBA_SetRecordParent(t_ptr->dba_rec, n_ptr->dba_rec);
2217  DBA_SaveRecord(t_ptr->dba_rec);
2218  }
2219  else
2220  {
2221  /* A delivery descriptor is required to add the transport */
2222  if (nit_entry->del_sys_desc != NULL)
2223  {
2224  /* Add the new transport */
2225  switch (nit_entry->del_sys_desc_type)
2226  {
2227  case SI_DEL_SYS_DESC_TYPE_TERR:
2228  {
2229  if (nit_entry->del_sys_desc->terr.is_t2)
2230  {
2231  if ((nit_entry->del_sys_desc->terr.u.t2.num_cells > 0) &&
2232  (nit_entry->del_sys_desc->terr.u.t2.cell[0].num_freqs > 0))
2233  {
2234  t_ptr = DBDEF_AddTerrestrialTransportRec( nit_entry->del_sys_desc->terr.u.t2.cell[0].freq_hz[0],
2235  nit_entry->del_sys_desc->terr.u.t2.plp_id, n_ptr);
2236 
2237  DBG_OP("Add DVB-T2 transport %p, freq %lu Hz", t_ptr, nit_entry->del_sys_desc->terr.u.t2.cell[0].freq_hz[0])
2238  }
2239  }
2240  else
2241  {
2242  t_ptr = DBDEF_AddTerrestrialTransportRec(nit_entry->del_sys_desc->terr.u.t1.freq_hz, 0, n_ptr);
2243 
2244  DBG_OP("Add DVB-T transport %p, freq %lu Hz", t_ptr,nit_entry->del_sys_desc->terr.u.t1.freq_hz)
2245  }
2246  break;
2247  }
2248 
2249  case SI_DEL_SYS_DESC_TYPE_CABLE:
2250  {
2251  t_ptr = DBDEF_AddCableTransportRec(nit_entry->del_sys_desc->cable.freq_hz,
2252  nit_entry->del_sys_desc->cable.symbol_rate, n_ptr);
2253  DBG_OP("Add DVB-C transport %p, freq %lu Hz, symbol rate %u Kbits", t_ptr,
2254  nit_entry->del_sys_desc->cable.freq_hz,
2255  nit_entry->del_sys_desc->cable.symbol_rate)
2256  break;
2257  }
2258 
2259  case SI_DEL_SYS_DESC_TYPE_SAT:
2260  {
2261  t_ptr = DBDEF_AddSatTransportRec(nit_entry->del_sys_desc->sat.freq_hz,
2262  nit_entry->del_sys_desc->sat.sym_rate,
2263  nit_entry->del_sys_desc->sat.polarity,
2264  nit_entry->del_sys_desc->sat.dvb_s2,
2265  nit_entry->del_sys_desc->sat.modulation, n_ptr);
2266  DBG_OP("Add DVB-%s transport %p, %lu Hz, symrate %u, polarity %u, modulation %u",
2267  (nit_entry->del_sys_desc->sat.dvb_s2 ? "S2" : "S"),
2268  t_ptr, nit_entry->del_sys_desc->sat.freq_hz,
2269  nit_entry->del_sys_desc->sat.sym_rate,
2270  nit_entry->del_sys_desc->sat.polarity,
2271  nit_entry->del_sys_desc->sat.modulation)
2272  break;
2273  }
2274  }
2275 
2276  if (t_ptr != NULL)
2277  {
2278  DBDEF_SetTransportOrigNetworkId(t_ptr, nit_entry->orig_net_id);
2279  DBDEF_SetTransportTransportId(t_ptr, nit_entry->tran_id);
2280  }
2281  }
2282  }
2283 
2284  if (t_ptr != NULL)
2285  {
2286  t_ptr->available = TRUE;
2287 
2288  DBG_OP("Transport ids: %u/%u", t_ptr->orig_net_id, t_ptr->tran_id)
2289 
2290  /* Mark any services on this transport as unavailable
2291  * so they can be deleted later if not found */
2292  s_ptr = DBDEF_GetNextServiceOnTransport(NULL, t_ptr);
2293  while (s_ptr != NULL)
2294  {
2295  s_ptr->unavailable = TRUE;
2296  s_ptr = DBDEF_GetNextServiceOnTransport(s_ptr, t_ptr);
2297  }
2298 
2299  serv_entry = nit_entry->ciplus_service_list;
2300  while (serv_entry != NULL)
2301  {
2302  s_ptr = DBDEF_FindServiceRecByIds(NULL, nit->table->net_id,
2303  nit_entry->orig_net_id, nit_entry->tran_id, serv_entry->id);
2304  if (s_ptr != NULL)
2305  {
2306  if ((s_ptr->transport->network->profile_type == ADB_PROFILE_TYPE_BROADCAST) ||
2307  (s_ptr->allocated_lcn != serv_entry->lcn))
2308  {
2309  /* Do not re-use service records from the broadcast profile for a CI+ profile.
2310  Also, CI+ services can have the same SID, so if the LCN is different, it's
2311  a different service */
2312  s_ptr = NULL;
2313  }
2314  }
2315 
2316  if (s_ptr == NULL)
2317  {
2318  next_s_ptr = GetServiceFromLcn(serv_entry->lcn);
2319  if (next_s_ptr != NULL)
2320  {
2321  /* LCN Collision ! */
2322  serv_items = STB_AppResizeMemory(serv_items,
2323  (serv_item_count+1) * sizeof(S_STB_CI_OPERATOR_NIT_MANAGEMENT_SERVICE_ITEM_DATA));
2324  if (serv_items != NULL)
2325  {
2326  serv_items[serv_item_count].channel_issue_type = STB_CI_OPERATOR_NIT_LCN_COLLISION;
2327  serv_items[serv_item_count].logical_channel_number = serv_entry->lcn;
2328  if (serv_entry->name_str != NULL)
2329  {
2330  serv_items[serv_item_count].length_service_name = serv_entry->name_str->nbytes;
2331  serv_items[serv_item_count].service_name = serv_entry->name_str->str_ptr;
2332  }
2333  else
2334  {
2335  serv_items[serv_item_count].length_service_name = 0;
2336  serv_items[serv_item_count].service_name = NULL;
2337  }
2338  serv_items[serv_item_count].free_lcn = (U16BIT *)STB_AppGetMemory(CIP_NUM_FREE_LCNS * sizeof(U16BIT));
2339  serv_items[serv_item_count].number_free_lcn = GetFreeLcns(serv_entry->lcn, serv_items[serv_item_count].free_lcn);
2340  serv_item_count++;
2341  }
2342  }
2343  else
2344  {
2345  /* Add the new service */
2346  if ((s_ptr = DBDEF_AddServiceRec(serv_entry->id, t_ptr)) != NULL)
2347  {
2348  s_ptr->new_service = TRUE;
2349  }
2350  }
2351  }
2352  else
2353  {
2354  s_ptr->new_service = FALSE;
2355  }
2356 
2357  if (s_ptr != NULL)
2358  {
2359  s_ptr->found = TRUE;
2360 
2361  /* Update the service type */
2362  if (s_ptr->new_service || (s_ptr->serv_type != serv_entry->type))
2363  {
2364  s_ptr->serv_type = serv_entry->type;
2365  }
2366  if (s_ptr->new_service || (s_ptr->serv_lcn != serv_entry->lcn))
2367  {
2368  s_ptr->serv_lcn = serv_entry->lcn;
2369  s_ptr->allocated_lcn = serv_entry->lcn;
2370  }
2371  s_ptr->hidden = !serv_entry->visible;
2372  DBA_SetFieldValue(s_ptr->dba_rec, DBA_FIELD_SERV_HIDDEN, s_ptr->hidden);
2373 
2374  s_ptr->selectable = serv_entry->selectable;
2375  DBA_SetFieldValue(s_ptr->dba_rec, DBA_FIELD_SERV_SELECTABLE, s_ptr->selectable);
2376 
2377  /* Update the service's name */
2378  changed = TRUE;
2379  if ((s_ptr->name_str != NULL) && (serv_entry->name_str != NULL))
2380  {
2381  str_desc = serv_entry->name_str;
2382  if (str_desc->nbytes == s_ptr->name_str->nbytes)
2383  {
2384  if (memcmp(s_ptr->name_str->str_ptr, str_desc->str_ptr, str_desc->nbytes) == 0)
2385  {
2386  changed = FALSE;
2387  }
2388  }
2389  }
2390 
2391  if (changed)
2392  {
2393  /* Free the old name */
2394  if (s_ptr->name_str != NULL)
2395  {
2396  DBDEF_ReleaseString(s_ptr->name_str);
2397  s_ptr->name_str = NULL;
2398  }
2399  /* Set the new name */
2400  if (serv_entry->name_str != NULL)
2401  {
2402  str_desc = serv_entry->name_str;
2403  s_ptr->name_str = DBDEF_MakeString(nit->lang_code, str_desc->str_ptr, str_desc->nbytes);
2404  }
2405  }
2406 
2407  /* Update the provider */
2408  if (s_ptr->provider_str != NULL)
2409  {
2410  DBDEF_ReleaseString(s_ptr->provider_str);
2411  s_ptr->provider_str = NULL;
2412  }
2413 
2414  if (serv_entry->provider_str != NULL)
2415  {
2416  str_desc = serv_entry->provider_str;
2417  s_ptr->provider_str = DBDEF_MakeString(nit->lang_code, str_desc->str_ptr, str_desc->nbytes);
2418  }
2419 
2420  s_ptr->unavailable = FALSE;
2421 #ifdef CI_DEBUG
2422  if (s_ptr->new_service)
2423  {
2424  DBG_OP("Added service %p, \"%s\", LCN=%u", s_ptr, s_ptr->name_str->str_ptr,s_ptr->serv_lcn)
2425  }
2426  else
2427  {
2428  DBG_OP("Updated service %p, \"%s\", LCN=%u", s_ptr, s_ptr->name_str->str_ptr,s_ptr->serv_lcn)
2429  }
2430 #endif
2431  }
2432 
2433  serv_entry = serv_entry->next;
2434  }
2435 
2436  /* Now delete any services that are no longer present */
2437  s_ptr = DBDEF_GetNextServiceOnTransport(NULL, t_ptr);
2438  while (s_ptr != NULL)
2439  {
2440  next_s_ptr = DBDEF_GetNextServiceOnTransport(s_ptr, t_ptr);
2441 
2442  if (s_ptr->unavailable)
2443  {
2444  /* Send an event to inform the app that this service is being deleted */
2445  DBG_OP("Delete unavailable service %p, nm ptr %p, LCN=%u", s_ptr, s_ptr->name_str, s_ptr->serv_lcn)
2446  if (s_ptr->name_str != NULL)
2447  {
2448  DBG_OP(" name \"%s\"", s_ptr->name_str->str_ptr)
2449  }
2450 
2451  STB_ERSendEvent(FALSE, FALSE, EV_CLASS_APPLICATION, EV_SERVICE_DELETED,
2452  &s_ptr, sizeof(s_ptr));
2453 
2454  DBDEF_DeleteServiceRec(s_ptr);
2455  }
2456 
2457  s_ptr = next_s_ptr;
2458  }
2459  }
2460 
2461  nit_entry = nit_entry->next;
2462  }
2463 
2464  /* Delete the linkage array for repopulation */
2465  DeleteLinkageDescriptorArray(n_ptr->linkage_desc_list);
2466  n_ptr->last_linkage_entry = NULL;
2467  n_ptr->num_linkage_entries = 0;
2468  n_ptr->linkage_desc_list = NULL;
2469 
2470  /* Copy all network linkage descripters */
2471  linkage_desc_ptr = nit->table->linkage_desc_list;
2472  while (linkage_desc_ptr != NULL)
2473  {
2474  CopyLinkageDesc(linkage_desc_ptr,
2475  &n_ptr->linkage_desc_list,
2476  &n_ptr->last_linkage_entry,
2477  &n_ptr->num_linkage_entries);
2478 
2479  linkage_desc_ptr = linkage_desc_ptr->next;
2480  }
2481 
2482  /* Check the transports for any that are no longer available */
2483  t_ptr = DBDEF_GetNextTransportRec(NULL);
2484  while (t_ptr != NULL)
2485  {
2486  next_t_ptr = DBDEF_GetNextTransportRec(t_ptr);
2487 
2488  if (!((ADB_TRANSPORT_REC *)t_ptr)->available)
2489  {
2490  DBG_OP("Delete unavailable transport %p", t_ptr)
2492  }
2493 
2494  t_ptr = next_t_ptr;
2495  }
2496 
2497  if (fav_list != NULL)
2498  {
2499  t_ptr = NULL;
2500  while ((t_ptr = DBDEF_GetNextTransportRec(t_ptr)) != NULL)
2501  {
2502  if (t_ptr->network == n_ptr)
2503  {
2504  s_ptr = NULL;
2505  while ((s_ptr = DBDEF_GetNextServiceOnTransport(s_ptr, t_ptr)) != NULL)
2506  {
2507  DBDEF_AddServiceToFavouriteList(fav_list, s_ptr, -1);
2508  }
2509  }
2510  }
2511 
2512  DBA_LockDatabase();
2513  DBA_SaveDatabase();
2515  }
2516  if (serv_items != NULL)
2517  {
2518  /* There was an error allocating service - report to CAM */
2519  STB_CISendOperatorNITManagement(module, STB_CI_OPERATOR_NIT_ERROR_NIT_ERROR, serv_item_count, serv_items);
2520  while (serv_item_count != 0)
2521  {
2522  serv_item_count--;
2523  if (serv_items[serv_item_count].free_lcn != NULL)
2524  {
2525  STB_AppFreeMemory(serv_items[serv_item_count].free_lcn);
2526  }
2527  }
2528  STB_AppFreeMemory(serv_items);
2529  }
2530  else
2531  {
2532  STB_CISendOperatorNITManagement(module, STB_CI_OPERATOR_NIT_ERROR_NO_ISSUE, 0, NULL);
2533  }
2534  }
2535 
2536  DBDEF_PopProfile();
2538  /* Free the table */
2539  STB_SIReleaseNitTable(nit->table);
2540  FUNCTION_FINISH(ProcessNit);
2541 }
2542 
2543 
2549 static void RequestHostInfo(S_CIP_HOST_INFO *host_info)
2550 {
2551  U8BIT i, num_tuners;
2552  E_STB_TUNE_SYSTEM_TYPE system;
2553 
2554  FUNCTION_START(RequestHostInfo);
2555 
2556  host_info->standby = ASTE_InStandby();
2557 
2558  /* Setup the supported service types */
2559  host_info->num_service_types = 8;
2560  host_info->service_types = CIP_SERVICE_TYPE_TV | CIP_SERVICE_TYPE_RADIO |
2561  CIP_SERVICE_TYPE_TELETEXT | CIP_SERVICE_TYPE_AVC_RADIO | CIP_SERVICE_TYPE_DATA |
2562  CIP_SERVICE_TYPE_HD_TV | CIP_SERVICE_TYPE_AVC_SD_TV | CIP_SERVICE_TYPE_AVC_HD_TV;
2563 
2564  /* Setup the supported delivery types */
2565  host_info->delivery_types = 0;
2566 
2567  num_tuners = STB_HWGetTunerPaths();
2568  for (i = 0; i < num_tuners; i++)
2569  {
2570  system = STB_TuneGetSupportedSystemType(i);
2571  switch (system)
2572  {
2573  case TUNE_SYSTEM_TYPE_DVBT2:
2574  host_info->delivery_types |= CIP_DELIVERY_TYPE_DVBT2;
2575  /* Intentionally falling through to the next case */
2576  case TUNE_SYSTEM_TYPE_DVBT:
2577  host_info->delivery_types |= CIP_DELIVERY_TYPE_DVBT;
2578  break;
2579  case TUNE_SYSTEM_TYPE_DVBS2:
2580  host_info->delivery_types |= CIP_DELIVERY_TYPE_DVBS2;
2581  /* Intentionally falling through to the next case */
2582  case TUNE_SYSTEM_TYPE_DVBS:
2583  host_info->delivery_types |= CIP_DELIVERY_TYPE_DVBS;
2584  break;
2585  case TUNE_SYSTEM_TYPE_DVBC:
2586  host_info->delivery_types |= CIP_DELIVERY_TYPE_DVBC;
2587  break;
2588  default:
2589  break;
2590  }
2591  }
2592 
2593  /* Setup the supported application capabilities */
2594  host_info->app_types = 0;
2595 #ifdef INTEGRATE_MHEG5
2596  host_info->app_types |= CIP_APP_TYPE_MHEG;
2597 #endif
2598 #ifdef HBBTV_BUILD
2599  host_info->app_types |= CIP_APP_TYPE_HBBTV;
2600 #endif
2601 
2602  FUNCTION_FINISH(RequestHostInfo);
2603 }
2604 
2613 static BOOLEAN RequestOperatorSearch(U32BIT module, S_CIP_OPERATOR_SEARCH *op_search)
2614 {
2615  BOOLEAN retval;
2616  U16BIT date;
2617  U8BIT hours, mins, secs;
2618  void *profile;
2619 
2620  FUNCTION_START(RequestOperatorSearch);
2621  retval = FALSE;
2622  STB_GCGetGMTDateTime(&date, &hours, &mins, &secs);
2623  if ((op_search->refresh_request == CIP_OPERATOR_SEARCH_SCHEDULED) &&
2624  STB_GCIsFutureDateTime(op_search->refresh_date, op_search->refresh_hour, op_search->refresh_min, 0))
2625  {
2626  /* Set the operator search date/time for the module */
2627  ACI_ScheduleOperatorSearch(op_search->cicam_id, op_search->refresh_date, op_search->refresh_hour,
2628  op_search->refresh_min);
2629 
2630  /* If there is a profile associated to this module, update it with the search request */
2631  if ((profile = ADB_FindProfileForModule(module)) != NULL)
2632  {
2633  ADB_SetProfileSearchRequired(profile, TRUE, op_search->refresh_date,
2634  op_search->refresh_hour, op_search->refresh_min);
2635  }
2636  }
2637  else
2638  {
2639  switch (ACI_GetOperatorSearchMode())
2640  {
2641  case CIP_START_OPERATOR_SEARCH_NO:
2642  {
2643  /* Search can't be started, so inform the app that a search is required */
2644  ACI_OperatorSearchRequired(module, TRUE);
2645  break;
2646  }
2647 
2648  case CIP_START_OPERATOR_SEARCH_YES:
2649  {
2650  /* Search can be started */
2651  retval = TRUE;
2652  break;
2653  }
2654 
2655  case CIP_START_OPERATOR_SEARCH_ASK:
2656  {
2657  /* Set flag to indicate a search is required */
2658  ACI_OperatorSearchRequired(module, TRUE);
2659 
2660  if (op_search->refresh_request == CIP_OPERATOR_SEARCH_IMMEDIATE)
2661  {
2662  /* This is an urgent request, so ask the user immediately */
2663  STB_ERSendEvent(FALSE, FALSE, EV_CLASS_CI, EV_TYPE_CI_REQUEST_OPERATOR_SEARCH,
2664  &module, sizeof(module));
2665  }
2666  break;
2667  }
2668  }
2669  }
2670 
2671  FUNCTION_FINISH(RequestOperatorSearch);
2672  return(retval);
2673 }
2674 
2675 /****************************************************************************
2676 ** End of file
2677 *****************************************************************************/
Application level CI control functions.
U32BIT ACFG_GetUndefinedLanguageBehaviour(void)
Gets the language code set by ACFG_SetUndefinedLanguageBehaviour, or &#39;und&#39; if that function has not b...
Definition: ap_cfg.c:2061
CI plus support functions.
U8BIT STB_TuneGetDataIntegrity(U8BIT path)
Returns the current data integrity.
void * STB_GetMemory(U32BIT bytes)
Attempts to allocate memory from the heap.
Definition: stbheap.c:221
U32DHMS STB_GCNowDHMSLocal(void)
Reads the current Local date code and time.
Definition: stbgc.c:2296
U8BIT STB_HWGetTunerPaths(void)
Returns the number of front end (Tuner) paths on the platform.
BOOLEAN DBA_SaveDatabase(void)
Saves any changes made to the working database to non-volatile storage. If saving to a file...
Definition: dba_nvm.c:667
SI_NIT_TABLE * STB_SIParseNitTable(SI_TABLE_RECORD *table_rec)
Parses the Nit table supplied in TABLE_RECORD format to create a NIT_TABLE structure. Returns a pointer to the table. Application must call STB_SIReleaseNitTable to free the data.
Definition: stbsitab.c:9155
ADB_FAVSERV_REC * DBDEF_AddServiceToFavouriteList(ADB_FAVLIST_REC *fav_list, ADB_SERVICE_REC *serv_ptr, S16BIT index)
Adds a new service to the given favourite list at the given position.
Definition: ap_dbdef.c:9404
Application database control.
BOOLEAN ACI_PathOwnedByModule(U8BIT path, U32BIT module)
Checks whether path is owned by CI module.
Definition: ap_ci.c:2324
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
void * STB_AppGetMemory(U32BIT bytes)
Attempts to allocate memory from the application heap.
Definition: stbheap.c:651
U32BIT STB_TuneGetMinTunerFreqKHz(U8BIT path)
Returns the minimum tuner frequency in KHz.
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
void DBDEF_SetTransportTransportId(ADB_TRANSPORT_REC *t_ptr, U16BIT tran_id)
Sets the transport ID of the given transport.
Definition: ap_dbdef.c:5368
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
BOOLEAN ACI_RequestOperatorStatus(U32BIT module)
Called by the host to request changing to an operator profile and request the operator status to be s...
Definition: ap_ciop.c:227
void DBDEF_PopProfile(void)
Restores a previously pushed profile.
Definition: ap_dbdef.c:10253
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
BOOLEAN ACI_OperatorExit(void)
Request the current operator module to exit operator profile.
Definition: ap_ciop.c:286
ADB_FAVLIST_REC * DBDEF_AddFavouriteList(U8BIT list_id, U8BIT *name, U32BIT user_data, S16BIT index)
Creates a new favourite list and adds it to the list of favourite lists. Creation of the new list wil...
Definition: ap_dbdef.c:9061
void ACI_OpNotifyOperatorStatus(U32BIT module, S_STB_CI_OPERATOR_STATUS *status)
This function is called by the CI+ stack to deliver the operator status to the host. This should be called if the CICAM supports the Operator Profile. This provides the module to be used for other Operator Profile related calls.
Definition: ap_ciop.c:391
void DBDEF_ReleaseString(ADB_STRING *string)
Releases an ADB_STRING.
Definition: ap_dbdef.c:3983
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 cicam_id
CICAM ID used when refres_request = CIP_OPERATOR_SEARCH_SCHEDULED to associate a timer to the request...
Definition: ap_ciop.c:128
void ACI_OpNotifyOperatorNit(U32BIT module, U16BIT nit_loop_length, U8BIT *nit_sections)
This function is called by the CI+ stack to deliver the operator NIT to the host. The CICAM delivers ...
Definition: ap_ciop.c:808
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
Definition: stbsitab.h:560
ADB_NETWORK_REC * DBDEF_AddNetworkRec(U16BIT net_id, ADB_SATELLITE_REC *satellite)
Adds a new network record to the database with the given network ID.
Definition: ap_dbdef.c:4644
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
void STB_OSMutexUnlock(void *mutex)
Unlock a mutex (a.k.a. &#39;leave&#39;, &#39;signal&#39; or &#39;release&#39;)
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 DBDEF_DeleteServiceRec(ADB_SERVICE_REC *s_ptr)
Deletes specified service record.
Definition: ap_dbdef.c:1754
ADB_FAVLIST_REC * DBDEF_FindFavouriteList(U8BIT list_id)
Return the favourite list with the given list id.
Definition: ap_dbdef.c:9237
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_AppResizeMemory(void *ptr, U32BIT new_num_bytes)
Re-allocates a given memory area to the new size, ensuring data contained within the original memory ...
Definition: stbheap.c:891
void ACI_OpNotifyOperatorInfo(U32BIT module, U8BIT info_version, S_STB_CI_OPERATOR_INFO *info)
This function is called by the CI+ stack to deliver the operator information to the host...
Definition: ap_ciop.c:520
BOOLEAN ACI_FindOperatorProfileModule(U32BIT cicam_id, U32BIT *module)
Returns the Operator Profile module associated with a CICAM ID.
Definition: ap_ciop.c:355
ADB_STRING * DBDEF_MakeString(U32BIT lang_code, U8BIT *str_ptr, U16BIT nbytes)
Creates an ADB_STRING, copying the given data into it. If the string passed in is NULL or the number ...
Definition: ap_dbdef.c:3890
U8BIT STB_DPGetNumPaths(void)
Returns the maximum number of decode paths.
Definition: stbdpc.c:532
U16BIT DBDEF_GetNumServices(void)
Returns the total number of services.
Definition: ap_dbdef.c:5506
U8BIT STB_TuneGetSignalStrength(U8BIT path)
Returns the current signal strength.
ADB_TRANSPORT_REC * DBDEF_GetNextTransportRec(ADB_TRANSPORT_REC *t_ptr)
Returns the transport following the one given. If the argument is NULL then the first transport will ...
Definition: ap_dbdef.c:4842
void STB_FreeMemory(void *addr)
Releases previously allocated heap memory.
Definition: stbheap.c:336
BOOLEAN STB_SIParseDelSysDesc(U8BIT *data, SI_DELIVERY_SYS_DESC_TYPE *type, SI_DELIVERY_SYS_DESC **desc)
Parses and allocates a system delivery descriptor which should be freed by calling STB_SIReleaseDelSy...
Definition: stbsitab.c:11071
void DBDEF_ReleaseAccess(void)
Releases access to the app&#39;s database.
Definition: ap_dbdef.c:245
void DBDEF_SetTransportOrigNetworkId(ADB_TRANSPORT_REC *t_ptr, U16BIT orig_net_id)
Sets the original network ID of the given transport.
Definition: ap_dbdef.c:5387
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;).
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
Database access defines, structures and public functions.
void STB_GCGetGMTDateTime(U16BIT *code, U8BIT *hour, U8BIT *min, U8BIT *secs)
Reads the current GMT date code and time.
Definition: stbgc.c:1372
ADB_SERVICE_REC * DBDEF_GetNextServiceRec(ADB_SERVICE_REC *s_ptr)
Returns the service after the one given. If NULL is passed then the first service in the list is retu...
Definition: ap_dbdef.c:5535
Application level CI - internal functions.
U32BIT STB_TuneGetMaxTunerFreqKHz(U8BIT path)
Returns the maximum tuner frequency in KHz.
U8BIT STB_DPGetPathTuner(U8BIT path)
Returns the tuner ID acquired by the given decode path.
Definition: stbdpc.c:1605
Header file - Function prototypes for Event Reporting.
void ACI_OpNotifyOperatorSearchStatus(U32BIT module, S_STB_CI_OPERATOR_STATUS *status)
This function is called by the CI+ stack to deliver the operator search status to the host...
Definition: ap_ciop.c:734
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
Header for STB unicode string handling routines.
void DBDEF_RequestAccess(void)
Requests access to the app&#39;s database.
Definition: ap_dbdef.c:235
BOOLEAN DBDEF_SetServiceProviderName(ADB_SERVICE_REC *s_ptr, U8BIT *name)
Set or change the name of a service&#39;s provider.
Definition: ap_dbdef.c:5910
BOOLEAN STB_GCIsFutureDateTime(U16BIT code, U8BIT hour, U8BIT min, U8BIT secs)
Tests given date and time against current GMT date and time.
Definition: stbgc.c:1411
void DBDEF_DeleteTransportRec(ADB_TRANSPORT_REC *t_ptr)
Deletes the given transport from the service database, deleting any service records that it&#39;s the par...
Definition: ap_dbdef.c:5431
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
ADB_SERVICE_REC * DBDEF_GetNextServiceOnTransport(ADB_SERVICE_REC *s_ptr, ADB_TRANSPORT_REC *t_ptr)
Find the next service following the given service that&#39;s on the given transport.
Definition: ap_dbdef.c:6083
void DBDEF_DeleteAllServicesFromFavouriteList(ADB_FAVLIST_REC *fav_list)
Delete the all services from the given favourite list.
Definition: ap_dbdef.c:9673
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
void STB_AppFreeMemory(void *addr)
Releases previously allocated application heap memory.
Definition: stbheap.c:781
void ACI_OpNotifyOperatorTune(U32BIT module, U16BIT desc_loop_len, U8BIT *desc_loop)
This function is called by the CI+ stack to request that the host performs the tune request as descri...
Definition: ap_ciop.c:688
BOOLEAN ACI_StartOperatorSearch(U32BIT module)
Called by the app to start an operator profile search that has been requested.
Definition: ap_ciop.c:323
void ACFG_SetUndefinedLanguageBehaviour(U32BIT lang_code)
Sets the language code to be used when the SI descriptors contain &#39;und&#39;, &#39;qaa&#39; or don&#39;t contain any l...
Definition: ap_cfg.c:2041
BOOLEAN ACI_OpAskRelease(U32BIT module)
Ask the opertaor module to restore replaced PIDs.
Definition: ap_ciop.c:906
BOOLEAN DBDEF_SetServiceShortName(ADB_SERVICE_REC *s_ptr, U8BIT *name)
Set or change the short name of a service.
Definition: ap_dbdef.c:5850
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
BOOLEAN ASTE_InStandby(void)
Definition: ap_state.c:117
Header file - Function prototypes for heap memory.
void * STB_OSCreateMutex(void)
Create a mutex.
Application header file.
ADB_TRANSPORT_REC * DBDEF_FindTransportRecByIds(ADB_TRANSPORT_REC *transp, U32BIT net_id, U32BIT onet_id, U32BIT tran_id)
Find a transport record matching the given set of IDs, starting from the given transport.
Definition: ap_dbdef.c:5314
E_STB_TUNE_SYSTEM_TYPE STB_TuneGetSupportedSystemType(U8BIT path)
Returns the system type supported by the path. This function differs from STB_TuneGetSystemType which...
void DBA_LockDatabase(void)
Locks the database to prevent access from other threads or processes.
Definition: dba_nvm.c:866
void DBA_UnlockDatabase(void)
Unlocks the database to allow other threads or processes to access it.
Definition: dba_nvm.c:876
void STB_SetDefaultAsciiTable(U8BIT table)
Sets default ascii table to be used, if not overridden by the table index at the start of a string...
Definition: stbuni.c:2157
void DBA_SetRecordParent(void *record, void *parent)
Set of change the parent of the given record.
Definition: dba_nvm.c:1080
void ACI_OperatorSearchRequired(U32BIT module, BOOLEAN required)
Sets whether an operator profile search needs to be run.
Definition: ap_ci.c:1056
Application database access functions.
void STB_SIReleaseNitTable(SI_NIT_TABLE *nit_table)
Frees the memory used by the nit table.
Definition: stbsitab.c:11299
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
Application level CI Operator Profile functions.