source: svn/trunk/newcon3bcm2_21bu/dta/src/app/nanotv/chan_mgr.c

Last change on this file was 2, checked in by phkim, 11 years ago

1.phkim

  1. revision copy newcon3sk r27
  • Property svn:executable set to *
File size: 163.1 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2003-2006, Broadcom Corporation
3 *     All Rights Reserved
4 *     Confidential Property of Broadcom Corporation
5 *
6 *  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7 *  AGREEMENT  BETWEEN THE USER AND BROADCOM.  YOU HAVE NO RIGHT TO USE OR
8 *  EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9 *
10 * $brcm_Workfile:  $
11 * $brcm_Revision:  $
12 * $brcm_Date: $
13 *
14 * Module Description:
15 *
16 * Revision History:
17 *
18 * $brcm_Log:  $
19 *
20 ***************************************************************************/
21
22#include "chan_mgr.h"
23#include "bstd.h"
24#include "bavc.h"
25#include "ts_psi.h"
26#include "ts_pat.h"
27#include "ts_pmt.h"
28#include "ts_scte_18.h"
29#include "bapp.h"
30#include "psip_ett.h"
31#include "bsettop_smessage.h"
32#include "image_recv.h"
33#include "ca_parser.h"
34#include "bos_task_priorities.h"
35#if defined(ENABLE_UMESSAGE)
36#include "umessage.h"
37#include "cmode.h"
38#endif
39#include "bapp_util.h"
40#include "ch_map.h"
41#ifdef  FOR_DOLBY_CERTIFICATION
42        #include "bchp_hifidac_ctrl0.h"
43        #include "projinc.h"
44#endif
45
46#ifdef  HAS_VBI
47        #include "pes_scte_127.h"
48#endif
49
50#include "ram_header.h"
51
52BDBG_MODULE(chan_mgr);          /* Register software module with debug interface */
53
54
55/* PR32033 fix, for ETT 10.5- 10.10, need more buffer and timeout */
56
57#define CHM_MIN(x,y)        ((x < y) ? x : y)
58
59#ifdef BCM_DEBUG
60static const char *s_chm_cmd_name[] = { "eCHM_CANCEL","eCHM_TUNE","eCHM_INFO","eCHM_STOP","eCHM_CHECK_SIGNAL","eCHM_HUNT","eCHM_HUNTING","eCHM_PENDING_INIT","eCHM_DOWNLOAD","eCHM_SAP", "eCHM_DSUB"};
61#endif
62
63#define CURR_CH                 0
64#define NEXT_CH                 1
65#define PREV_CH                 2
66
67#define CHM_INT_STK_SIZE        1024    /* in words */
68
69#define CHM_CHECK_SIGNAL_FREQ   1000
70#define CHM_CHECK_CHMAP_FREQ    5000
71#define CHM_CHECK_PROG_FREQ             1000
72
73#define PAT_BUF_LEN         (1024 + 188)
74#define CAT_BUF_LEN         (1024 + 188)
75#define PMT_BUF_LEN         (1024 + 188)
76#define STT_BUF_LEN         (256 + 188)
77#define NIT_BUF_LEN         (4400 + 188)
78#define NTT_BUF_LEN         (4400 + 188)
79#define SVCT_BUF_LEN            (4400 + 188)
80#define EAS_BUF_LEN             (1024 + 188)
81#define EMM_BUF_LEN             (1024 + 188)
82#define CVT_BUF_LEN                     (1024 + 188)
83#ifdef CONFIG_DVB
84#define SDT_BUF_LEN         (4400 + 188)
85#define EIT_BUF_LEN         (4400 + 188)
86#define TDT_BUF_LEN         (1024 + 188)
87#endif
88#define CHM_IDLE_TIMEOUT        30
89
90#define CAT_TIMEOUT         3000
91#define PAT_TIMEOUT         800
92#define PMT_TIMEOUT         800
93#define STT_TIMEOUT         1200
94#define EAS_TIMEOUT         1200
95
96/* These timeouts are for testing only and need to be adjusted to match actual system cycle times (in ms) */
97#define NIT_TIMEOUT         20000
98#define NTT_TIMEOUT         20000
99#define SVCT_TIMEOUT        35000
100#define HUNT_TIMEOUT            35000
101#define CHM_UPDATING_DELAY      4000
102
103#ifdef CONFIG_DVB
104/* need adjustment */
105#define SDT_TIMEOUT         20000
106#endif
107
108#define CHM_DEF_VCT_ID          CONFIG_DEF_VCT_ID
109#define CHM_DEF_NETWORK_PID CONFIG_NETWORK_PID
110
111#define CHM_MUTEX_TIMEOUT   10
112#define MAX_TIME_SLOTS      4
113#define MGT_CYCLE_TIMEOUT   1           /* in seconds */
114
115#define SCTE_18_ALERT_PRIORITY          0       /* all priority */
116
117/* frequency vector is encoded in 0.25MHz increments */
118#define CHM_VECTOR_MULTIPLIER (25 * 10000)
119
120#define CHM_MIN(x,y)        ((x < y) ? x : y)
121
122#ifndef toupper
123#define toupper(x) (x&0xDF)
124#endif
125
126typedef struct iso_lang_map_t
127{
128        char            iso_lang_code[3];
129        bapp_lang_t     lang;
130}iso_lang_map_t;
131
132typedef enum chm_err_t
133{
134        eCHM_ERR_OK         = 0,
135        eCHM_ERR_FAILED     = -1,
136        eCHM_ERR_TIMEOUT    = -2,
137        eCHM_ERR_CANCELED   = -3,
138        eCHM_ERR_NO_PAT     = -4
139}chm_err_t;
140
141const static iso_lang_map_t s_iso_lang_map[] =
142{
143        { { 'e','n','g'},eLANG_ENGLISH},
144        { { 'f','r','a'},eLANG_FRENCH},
145        { { 'f','r','e'},eLANG_FRENCH},
146        { { 'e','s','l'},eLANG_SPANISH},
147        { { 's','p','a'},eLANG_SPANISH},
148};
149const static int s_iso_lang_map_num = sizeof(s_iso_lang_map)/sizeof(iso_lang_map_t);
150
151
152/* These files are in flash_install_<platform>.c and are assumed to be RAM only and
153 * are therefore not access through dispatch table.
154 */
155extern void flash_install(uint32_t base, uint32_t offset, uint8_t * data, size_t len);
156extern void chip_reset(void);
157
158#define MAX_MAJOR_CH        p_chm->num_freq
159
160static int chm_post_app_event(chm_mgr_t *p_chm,         /* Channel manager reference */
161                                                          chm_event_t *p_event  /* Event to post to app queue */
162                                                         );
163static int chm_stop_decode(chm_mgr_t *p_chm);
164static int chm_tune_freq(chm_mgr_t *p_chm,unsigned int freq_hz,unsigned int freq_idx);
165static int chm_rotate_audio(chm_mgr_t *p_chm);
166static int chm_cvt_start(chm_mgr_t *p_chm, unsigned short network_pid);
167static void chm_cvt_stop(chm_mgr_t *p_chm);
168static int chm_stt_start(chm_mgr_t *p_chm, unsigned short network_pid);
169static void chm_stt_stop(chm_mgr_t *p_chm);
170static int chm_emm_start(chm_mgr_t *p_chm, unsigned short emm_pid);
171static void chm_emm_stop(chm_mgr_t *p_chm);
172static void chm_cache_pids(chm_mgr_t *p_chm);
173static int chm_cat_start(chm_mgr_t *p_chm);
174static void chm_cat_stop(chm_mgr_t *p_chm);
175
176#ifdef CONFIG_DVB
177static void chm_dvb_nit_cb(nit_t *nit, void *data);
178static void chm_dvb_sdt_cb(sdt_t *sdt, void *data);
179static void chm_dvb_nit_stop(chm_mgr_t *p_chm);
180static int chm_dvb_nit_start(chm_mgr_t *p_chm, bband_t band);
181static void chm_dvb_sdt_stop(chm_mgr_t *p_chm);
182static int chm_dvb_sdt_start(chm_mgr_t *p_chm, bband_t band);
183static void chm_dvb_tdt_stop(chm_mgr_t *p_chm);
184static int chm_dvb_tdt_start(chm_mgr_t *p_chm, bband_t band);
185static void chm_dvb_eit_stop(chm_mgr_t *p_chm);
186static int chm_dvb_eit_start(chm_mgr_t *p_chm, bband_t band);
187#endif
188
189#ifdef  HAS_VBI
190static int chm_scte127_start(chm_mgr_t *p_chm, uint16_t scte127_pid);
191#endif
192
193#ifdef CONFIG_DVB_SUBTITLE
194static void chm_subtitle_stop(chm_mgr_t *p_chm);
195static int chm_subtitle_start(chm_mgr_t *p_chm, uint16_t dsub_pid);
196static int chm_rotate_dsub(chm_mgr_t *p_chm);
197#endif
198
199bresult chm_write_software(struct image_t * image);
200
201static bool chm_check_sc(chm_mgr_t *p_chm, bband_t band, unsigned short pid);
202static void chm_stop_stream(chm_mgr_t *p_chm, chm_stream_t *p_stream);
203
204//#define DBG_DUMP
205#ifdef DBG_DUMP
206static void DBG_HEXDUMP(unsigned char* ptr, unsigned long len)
207{
208        unsigned long i;
209        for (i=0; i<len; i++ )
210        {
211                if ( i % 16 == 0 )
212                        printf ("\n");
213                printf ("0x%02x, ", ptr[i]);
214        }
215        printf("\n\n");
216}
217#else
218        #define DBG_HEXDUMP(ptr, len)
219#endif
220
221/*
222Summary:
223   Get section crc.
224*/
225static inline unsigned int chm_section_crc(unsigned char *buf,size_t length)
226{
227        unsigned int crc32;
228        memcpy(&crc32, &(buf[length-4]),4);
229        return crc32;
230}
231
232/*
233Summary:
234        Get the current UTC time, local offset and dst flag.
235        Returns non-zero when it is not possible to determine local time.
236        Currently this function uses XDS local offset over one obtained from the TSIDs
237       
238*/
239int chm_get_time_info(chm_mgr_t *p_chm, 
240                                          unsigned int *utc_secs,                       /* Current UTC time in seconds */
241                                          int *local_offset,                            /* Local time offset from UTC time in seconds */
242                                          bool *dst                                                     /* Daylight savings flag */
243                                         )
244{
245#if 0
246        int result;
247
248        if ((result = chm_get_utctime(p_chm,utc_secs)) != 0)
249                return result;
250
251        /* Use XDS local time over time obtained from a TSID */
252        if (g_xds_time_offset != 0)
253        {
254                p_chm->local_offset = 3600 * g_xds_time_offset;
255                p_chm->local_time_source = eTS_XDS;
256                p_chm->local_dst_obs = g_xds_dst;
257        }
258
259        if (p_chm->local_time_source == eTS_NONE)
260                return eCHM_ERR_FAILED;
261
262        *local_offset = p_chm->local_offset;
263        *dst = ((p_chm->stt.daylight_savings.DS_status != 0) && p_chm->local_dst_obs) ? true : false;
264
265        BDBG_MSG(("STT system_time = %u\n",p_chm->stt.system_time));
266        BDBG_MSG(("STT GPS_UTC_offset = %u\n",p_chm->stt.GPS_UTC_offset));
267        BDBG_MSG(("STT DS_status = %d\n",p_chm->stt.daylight_savings.DS_status));
268        BDBG_ERR(("Timesource %d, local_offset = %d, dst\n",p_chm->local_time_source,p_chm->local_offset,p_chm->local_dst_obs));
269
270        if (*dst)
271        {
272                *utc_secs += 3600;
273        }
274        return 0;
275#else
276#ifdef CONFIG_DVB
277        *utc_secs = dvb_get_cur_time();
278        *local_offset = 0; /* TODO:: */
279        *dst = false; /* TODO */
280
281        if (*utc_secs) 
282                return eCHM_ERR_OK;
283        else
284#endif
285        return eCHM_ERR_FAILED;
286#endif
287}
288
289/*
290Summary:
291        Get the current utc time in seconds.
292        Return non-zero on failure.
293*/
294
295static void chm_send_status(chm_mgr_t *p_chm,unsigned int freq, bool locked)
296{
297        bapp_t *p_app = (bapp_t*)p_chm->p_app;
298        btuner_status status;
299        chm_signal_event_t *p_sig = &(p_chm->signal_evt);
300        memset(&(p_chm->signal_evt),0,sizeof(chm_signal_event_t));
301        p_sig->type = eCHM_EVT_SIGNAL;
302        /* check power level only if we are in tuner status screen */
303        if ((p_app->screen_id == eSCREEN_ANTENNA) || (p_app->screen_id == eSCREEN_TUNER_STATUS) ||
304                (p_app->screen_id == eSCREEN_BANNER) || (p_app->screen_id == eSCREEN_BANNER_SMALL)) {
305                status.get_power = true;
306        } else {
307                status.get_power = false;
308        }
309        if (!locked)
310        {
311                p_sig->freq_hz = freq;
312        } else if (btuner_get_status(p_chm->tuner,&status) == b_ok)
313        {
314                /* Send message to app */
315                p_sig->freq_hz = status.freq;
316                p_sig->SNR = status.snr;
317                //p_sig->qam_b_mode = status.mode;
318                p_sig->power = status.power;
319                p_sig->lock = status.lock;
320               
321        }
322        chm_post_app_event(p_chm,(chm_event_t*)&(p_chm->signal_evt));
323}
324
325/*
326Summary:
327        Check for a valid language code for the current language settings.
328        Returns the bapp_lang_t number or < 0 if not a valid language.
329*/
330
331static int chm_valid_lang(chm_mgr_t *p_chm,                     /* Channel manager reference */
332                                                  char *p_code    /* Three byte iso 639-2 language code */
333                                                 )
334{
335        bapp_lang_t lang = iso_639_to_lang(p_code);
336
337        BDBG_MSG(("ISO 639-2 language not found %c%c%c\n",p_code[0],p_code[1],p_code[2]));
338        return (lang == eLANG_MAX) ? eCHM_ERR_FAILED : (int)lang;
339}
340
341/*
342Summary:
343        SCTE-65 Parser Callback.
344*/
345void chm_mms_cb(NIT_MMS_RECORD *p_MMS, void *data)
346{
347        chm_mgr_t *p_chm = (chm_mgr_t *)data;
348        mms_t mms;
349
350        if (p_MMS->transmission_system != ITU_T_ANNEX_B_TX_SYS)
351        {
352                BDBG_MSG(("%s Invalid Transmission System %d\n",__FUNCTION__,p_MMS->transmission_system));
353                //return;//Allow all the transmission_system type
354        }
355
356        BDBG_MSG(("%s(%d,%d,%d,%d)\n",__FUNCTION__,p_MMS->idx,p_MMS->modulation_format,p_MMS->inner_coding_mode,p_MMS->symbol_rate));
357        memset(&mms,0,sizeof(mms_t));
358        mms.idx = p_MMS->idx;
359        mms.code_rate = p_MMS->inner_coding_mode;
360        mms.modulation = p_MMS->modulation_format;
361        p_chm->mms_flag = true;
362
363        switch (p_MMS->modulation_format)
364        {
365        case MOD_QAM64: mms.modulation = eQAM_64; break;
366        case MOD_QAM256: mms.modulation = eQAM_256; break;
367        case MOD_QAM1024: mms.modulation = eQAM_256; break;
368        default: mms.modulation = eQAM_Scan; break;
369        }
370
371        mms.symbol_rate = p_MMS->symbol_rate;
372        ch_map_add_mms(&(p_chm->ch_map),&mms);
373
374}
375
376/*
377Summary:
378        SCTE-65 Parser Callback.
379*/
380void chm_cds_cb(unsigned int freq_khz, int idx, void *data)
381{
382        chm_mgr_t *p_chm = (chm_mgr_t *)data;
383        freq_t freq;
384
385        BDBG_MSG(("%s(%d,%d)\n",__FUNCTION__,freq_khz,idx));
386        memset(&freq,0,sizeof(freq_t));
387        freq.idx = idx;
388        freq.freq_khz = freq_khz;
389        ch_map_add_freq(&(p_chm->ch_map),&freq);
390
391}
392/*
393Summary:
394        SCTE-65 Parser Callback.
395*/
396void chm_sns_cb(SI_NTT_SNS_t *sns, void *data)
397{
398        chm_mgr_t *p_chm = (chm_mgr_t *)data;
399        st_t    st;
400        unsigned char code[3];
401        int len;
402        bapp_lang_t     lang = eLANG_ENGLISH; 
403
404
405        code[0] = (unsigned char)((sns->iso639 >> 16) & 0xFF);
406        code[1] = (unsigned char)((sns->iso639 >> 8) & 0xFF);
407        code[2] = (unsigned char)((sns->iso639 >> 0) & 0xFF);
408        lang = (bapp_lang_t)chm_valid_lang(p_chm,(char*)code);
409
410        if ((int)lang < 0)
411        {
412                BDBG_MSG(("INVALID ISO639 Language Code = %c%c%c\n",code[0],code[1],code[2]));
413        } else
414        {
415                BDBG_MSG(("bapp_lang_t = %d(%c%c%c)\n",lang,code[0],code[1],code[2]));
416        }
417        memset(&st,0,sizeof(st_t));
418
419        st.source_id = sns->source_id;
420
421        if (sns->mtt[0] != 0)
422        {
423                BDBG_WRN(("Only latin character set supported 0x%02x\n",sns->mtt[0]));
424                return;
425        }
426
427        len = sns->mtt[1];
428        if (len >= MAX_VCH_LEN)
429        {
430                len = MAX_VCH_LEN - 1;
431        }
432
433        BDBG_MSG(("name_length = %d\n",len));
434        memcpy(st.name,&sns->mtt[2],len);
435        st.name[len] = 0; /* null terminate string */
436        BDBG_MSG(("name = %s\n",st.name));
437        ch_map_add_st(&(p_chm->ch_map),&st);
438}
439/*
440Summary:
441        SCTE-65 Parser Callback.
442*/
443void chm_vcm_cb(SI_SVCT_VCM_CHANNEL *channel, void *data)
444{
445        chm_mgr_t *p_chm = (chm_mgr_t *)data;
446        vch_t vch;
447        bapp_t *p_app = (bapp_t*)p_chm->p_app;
448
449        memset(&vch,0,sizeof(vch));
450
451
452        if (channel->ChanPropUnion.mpeg_prop.prog_num == 0x0000)
453        {
454                BDBG_WRN(("%s analog program or invalid program number\n",__FUNCTION__));
455                return;
456        }
457
458        if (channel->vct_id != p_app->settings.VCT_ID)
459        {
460                BDBG_WRN(("%s SVCT VCT_ID != current VCT_ID (0x%04x != 0x%04x)\n",__FUNCTION__,channel->vct_id,p_app->settings.VCT_ID));
461                if (p_app->settings.VCT_ID != 0xFFFF)
462                {
463                        DBG_HEXDUMP(p_chm->svct_buf,16);
464                        return;
465                }
466        }
467
468        if (channel->channel_type != NORMAL_CHAN)
469        {
470                BDBG_MSG(("%s hidden - %d\n",__FUNCTION__,channel->channel_type));
471        }
472
473        vch.ch_num = channel->channum1;
474        vch.freq_idx = channel->CDS_reference;
475        vch.mms_idx = channel->ChanPropUnion.mpeg_prop.MMS_reference;
476        vch.program_num = channel->ChanPropUnion.mpeg_prop.prog_num;
477        vch.source_id = channel->source_ID;
478        vch.vchflags = channel->channel_type;
479        ch_map_add_vch(&(p_chm->ch_map),&vch);
480}
481
482/*
483Summary:
484        Check for cancel, returns true if a cancel occured.
485*/
486#ifdef BCM_DEBUG
487static int chm_check_cancel_ex(chm_mgr_t *p_chm ,const char* func, int line)
488        #define chm_check_cancel(chm)   chm_check_cancel_ex(chm,__FUNCTION__,__LINE__)
489#else
490static int chm_check_cancel(chm_mgr_t *p_chm )
491#endif
492{
493        chm_cmd_event_t *p_cmd;
494
495        if (p_chm->cmd == eCHM_CANCEL)
496                return 1;
497
498        p_cmd = (chm_cmd_event_t*)bos_pend_event(p_chm->queue,0);
499
500        if (!p_cmd)
501                return 0;
502
503        if (p_cmd->cmd_id == eCHM_CANCEL)
504        {
505                p_chm->cmd = eCHM_CANCEL;
506                BDBG_WRN(("Command canceled(%s:%d)...\n",func,line));
507
508                /* Send message to app */
509                p_chm->chm_evt.type = eCHM_EVT_CANCEL;
510                p_chm->chm_evt.id = 0;
511                chm_post_app_event(p_chm,&p_chm->chm_evt);
512        } else
513        {
514                if (p_cmd->cmd_id == eCHM_SAP)
515                {
516                        chm_rotate_audio(p_chm);
517                } 
518#ifdef CONFIG_DVB_SUBTITLE
519                else if (p_cmd->cmd_id == eCHM_DSUB)
520                {
521                        chm_rotate_dsub(p_chm);
522                }
523#endif
524                else
525                {
526                        BDBG_WRN(("Throwing away command %d(%s:%d)...\n", p_chm->cmd ,func,line));
527                }
528        }
529
530        return(p_chm->cmd == eCHM_CANCEL) ? 1 : 0;
531} 
532
533
534static void * chm_smessage_callback(void *context, size_t data_size)
535{
536        chm_mgr_t *p_chm = (chm_mgr_t *)context;
537        /* ignore return value */
538        bos_post_event(p_chm->gen_queue, (b_event_t*)data_size);
539        return NULL;
540}
541
542static int chm_getmessage(chm_mgr_t *p_chm,     /* Channel manager reference */
543                                                  void *buf, /* buffer to copy section into */
544                                                  unsigned int *len, /* [in] max size of buffer, [out] section size copied into buffer */
545                                                  unsigned int timeout /* timeout in milliseconds */
546                                                 )
547{
548        bresult bres;
549        size_t msg_size;
550        int result = eCHM_ERR_FAILED;
551        smessage_stream_params_t params;
552
553        smessage_stream_params_init(&params, p_chm->smsg);
554        params.band = p_chm->msg_params.band;
555        params.pid = p_chm->msg_params.pid;
556        params.filter = p_chm->msg_params.filter;
557        params.buffer = buf;
558        params.buffer_size = *len;
559        params.crc_disabled = p_chm->msg_params.crc_disabled;
560        params.data_ready_callback = chm_smessage_callback;
561        params.overflow = NULL;
562        params.callback_context = (void *)p_chm;
563        params.priv = (void *)4;
564        BDBG_MSG(("pid %x fil %x tim %u len %u", params.pid, params.filter.coef[0], timeout, *len));
565        bres = smessage_start(&params, p_chm->smsg);
566        if (b_ok != bres)
567        {
568                BDBG_ERR(("%s:%d",__FILE__, __LINE__));
569                goto ExitFunc;
570        }
571        msg_size = (size_t) bos_pend_event(p_chm->gen_queue, timeout);
572        if (0 == msg_size)
573        {
574                result = eCHM_ERR_TIMEOUT;
575        } else
576        {
577                *len = msg_size;
578                result = eCHM_ERR_OK;
579        }
580        bres = smessage_stop(p_chm->smsg);
581        if (b_ok != bres)
582        {
583                BDBG_ERR(("%s:%d",__FILE__, __LINE__));
584                result = eCHM_ERR_FAILED;
585                goto ExitFunc;
586        }
587
588        ExitFunc:
589        return result;
590}
591
592/*
593Summary:
594        Add a chanell to the channel map.
595Description:
596        Add the channel to the channel map in sorted order.
597*/
598static unsigned short s_channel_num = 100;
599static void chm_add_channel(chm_mgr_t *p_chm,           /* Channel manager reference */
600                                                        vch_t *p_vch
601                                                   )
602{
603        freq_t freq;
604        st_t  st;
605        mms_t  mms;
606        btuner_status status;
607
608        freq.idx = (unsigned char)p_vch->freq_idx;
609        freq.freq_khz = p_chm->freq_table[p_vch->freq_idx];
610        ch_map_add_freq(&(p_chm->ch_map),&freq);
611
612        memset(&mms,0,sizeof(mms));
613        mms.idx = (unsigned char)p_vch->freq_idx;
614        status.get_power = false;
615        if (btuner_get_status(p_chm->tuner,&status) == b_ok)
616                mms.modulation = status.mode;
617        else
618                mms.modulation = eQAM_Scan;
619
620        ch_map_add_mms(&(p_chm->ch_map),&mms);
621
622        p_vch->ch_num = (unsigned short)s_channel_num++;
623        p_vch->source_id = (unsigned short)p_vch->ch_num;
624        p_vch->mms_idx = (unsigned char)mms.idx;
625        ch_map_add_vch(&(p_chm->ch_map),p_vch);
626
627        st.source_id = p_vch->source_id;
628        snprintf(st.name,MAX_VCH_LEN,"Ch - %d.%d",p_vch->freq_idx + 2,p_vch->program_num);
629        ch_map_add_st(&(p_chm->ch_map),&st);
630
631}
632
633
634/*
635Summary:
636   Stop monitoring..
637*/
638void chm_nit_stop(chm_mgr_t *p_chm)
639{
640        if (NULL != p_chm->nit_msg)
641        {
642                if (b_ok != smessage_stop(p_chm->nit_msg))
643                {
644                        BDBG_ERR(("%s:%d",__FILE__, __LINE__));
645                        return;
646                }
647                smessage_close(p_chm->nit_msg);
648                p_chm->nit_msg = NULL;
649        }
650}
651
652/*
653Summary:
654   Stop monitoring..
655*/
656void chm_ntt_stop(chm_mgr_t *p_chm)
657{
658        if (NULL != p_chm->ntt_msg)
659        {
660                if (b_ok != smessage_stop(p_chm->ntt_msg))
661                {
662                        BDBG_ERR(("%s:%d",__FILE__, __LINE__));
663                        return;
664                }
665                smessage_close(p_chm->ntt_msg);
666                p_chm->ntt_msg = NULL;
667        }
668}
669
670
671/*
672Summary:
673   Stop monitoring..
674*/
675void chm_svct_stop(chm_mgr_t *p_chm)
676{
677        if (NULL != p_chm->svct_msg)
678        {
679                if (b_ok != smessage_stop(p_chm->svct_msg))
680                {
681                        BDBG_ERR(("%s:%d",__FILE__, __LINE__));
682                        return;
683                }
684                smessage_close(p_chm->svct_msg);
685                p_chm->svct_msg = NULL;
686        }
687}
688
689#ifdef  HAS_VBI
690/*
691Summary:
692   Stop SCTE 127 monitoring..
693*/
694static void chm_scte127_stop(chm_mgr_t *p_chm)
695{
696        if (NULL != p_chm->scte127_msg)
697        {
698                if (b_ok != smessage_stop(p_chm->scte127_msg))
699                {
700                        BDBG_ERR(("%s:%d",__FILE__, __LINE__));
701                        return;
702                }
703                smessage_close(p_chm->scte127_msg);
704                p_chm->scte127_msg = NULL;
705        }
706}
707#endif
708/*
709Summary:
710   Stop EAS monitoring..
711*/
712static void chm_eas_stop(chm_mgr_t *p_chm)
713{
714        if (NULL != p_chm->eas_msg)
715        {
716                if (b_ok != smessage_stop(p_chm->eas_msg))
717                {
718                        BDBG_ERR(("%s:%d",__FILE__, __LINE__));
719                        return;
720                }
721                smessage_close(p_chm->eas_msg);
722                p_chm->eas_msg = NULL;
723                p_chm->eas_timer_started = false;
724        }
725}
726
727/*
728Summary:
729   Stop CVT monitoring..
730*/
731static void chm_cvt_stop(chm_mgr_t *p_chm)
732{
733        if (NULL != p_chm->cvt_msg)
734        {
735                if (b_ok != smessage_stop(p_chm->cvt_msg))
736                {
737                        BDBG_ERR(("%s:%d",__FILE__, __LINE__));
738                        return;
739                }
740                smessage_close(p_chm->cvt_msg);
741                p_chm->cvt_msg = NULL;
742        }
743}
744/******************************************************************************
745* INPUTS:      context
746* OUTPUTS:     none.
747* RETURNS:     none
748* FUNCTION:    message_callback
749* DESCRIPTION: Callback function normally called when a complete message has
750*              been received and passed the filter criteria.
751******************************************************************************/
752
753void * chm_smessage_nit_callback(void * context, size_t size)
754{
755        chm_mgr_t * p_chm = (chm_mgr_t*)context;
756        SI_RET_CODE rc;
757        unsigned int crc32;
758        ch_map_t * p_ch_map = bapp_cur_ch_map(p_chm->p_app);
759
760        crc32 = chm_section_crc(p_chm->nit_buf,size);
761
762        p_chm->mms_flag = false;
763        if ((rc = SI_NIT_parse(p_chm->nit_buf)) != SI_SUCCESS)
764        {
765                BDBG_WRN(("NIT parse error %d\n",rc));
766        } else
767        {
768                if (p_chm->mms_flag)
769                        p_chm->mms_cnt++;
770                else
771                        p_chm->cds_cnt++;
772        }
773
774        if ((p_chm->ch_map.freq_map.num_freq > 0) && SI_NIT_CDS_Complete() && 
775                ch_map_cmp_freq(&(p_chm->ch_map.freq_map),&(p_ch_map->freq_map)))
776        {
777                p_chm->cds_changed = true;
778                BDBG_WRN(("Updated NIT-CDS\n"));
779        }
780
781        if ((p_chm->ch_map.mms_map.num_mms > 0) && SI_NIT_MMS_Complete() && 
782                ch_map_cmp_mms(&(p_chm->ch_map.mms_map),&(p_ch_map->mms_map)))
783        {
784                p_chm->mms_changed = true;
785                BDBG_WRN(("Updated NIT-MMS\n"));
786        }
787//      DBG_HEXDUMP(p_chm->nit_buf,size);
788
789        return(void*)(p_chm->nit_buf);
790}
791
792/******************************************************************************
793* INPUTS:      context
794* OUTPUTS:     none.
795* RETURNS:     none
796* FUNCTION:    message_callback
797* DESCRIPTION: Callback function normally called when a complete message has
798*              been received and passed the filter criteria.
799******************************************************************************/
800
801void * chm_smessage_ntt_callback(void * context, size_t size)
802{
803        chm_mgr_t * p_chm = (chm_mgr_t*)context;
804        SI_RET_CODE rc;
805        ch_map_t * p_ch_map = bapp_cur_ch_map(p_chm->p_app);
806
807
808        BDBG_WRN(("#### NTT Event ####\n"));
809
810        if ((rc = SI_NTT_parse(p_chm->ntt_buf)) != SI_SUCCESS)
811        {
812                BDBG_WRN(("NTT parse error %d\n",rc));
813        } else
814        {
815                p_chm->sns_cnt++;
816                if ((p_chm->ch_map.st_map.num_st > 0) && SI_NTT_SNS_Complete() &&
817                        ch_map_cmp_st(&(p_chm->ch_map.st_map),&(p_ch_map->st_map)))
818                {
819                        p_chm->sns_changed = true;
820                        BDBG_WRN(("Updated NTT\n"));
821                }
822        }
823
824        return(void*)p_chm->ntt_buf;
825}
826
827/******************************************************************************
828* INPUTS:      context
829* OUTPUTS:     none.
830* RETURNS:     none
831* FUNCTION:    message_callback
832* DESCRIPTION: Callback function normally called when a complete message has
833*              been received and passed the filter criteria.
834******************************************************************************/
835
836void * chm_smessage_svct_callback(void * context, size_t size)
837{
838        chm_mgr_t * p_chm = (chm_mgr_t*)context;
839        SI_RET_CODE rc;
840        unsigned int crc32;
841        ch_map_t * p_ch_map = bapp_cur_ch_map(p_chm->p_app);
842
843        crc32 = chm_section_crc(p_chm->svct_buf,size);
844
845        BDBG_WRN(("#### SVCT Event ####\n"));
846
847        if ((rc = SI_SVCT_parse(p_chm->svct_buf)) != SI_SUCCESS)
848        {
849                BDBG_WRN(("SVCT parse error %d\n",rc));
850        } else
851        {
852                p_chm->vcm_cnt++;
853                if ((p_chm->ch_map.vch_map.num_vch > 0) && SI_SVCT_Complete() &&
854                        ch_map_cmp_vch(&(p_chm->ch_map.vch_map),&(p_ch_map->vch_map)))
855                {
856                        p_chm->vcm_changed = true;
857                        BDBG_WRN(("Updated SVCT\n"));
858                }
859        }
860
861        return(void*)p_chm->svct_buf;
862}
863
864
865/*
866Summary:
867   Start nit monitoring..
868*/
869int chm_nit_start(chm_mgr_t *p_chm, unsigned short network_pid)
870{
871        int cerr = eCHM_ERR_OK;
872        smessage_stream_params_t params;
873
874        chm_nit_stop(p_chm);
875
876        p_chm->cds_changed = false;
877        p_chm->mms_changed = false;
878        p_chm->nit_msg = smessage_open(smessage_format_psi);
879        if (NULL == p_chm->nit_msg)
880        {
881                BDBG_ERR(("%s:%d",__FILE__, __LINE__));
882                cerr = eCHM_ERR_FAILED;
883                goto ExitFunc;
884        }
885        smessage_stream_params_init(&params, p_chm->nit_msg);
886        params.band = p_chm->band;
887        params.pid = (uint16_t)network_pid;
888        params.filter.coef[0] = 0xc2;   /* Table ID for NIT */
889        params.filter.mask[0] = 0x00;
890        params.filter.excl[0] = 0xff;
891        /* All PSIP tables have protocol_version which must be = 0 */
892        params.filter.coef[3] = 0x00;   /* protocol_version */
893        params.filter.mask[3] = 0x00;
894        params.filter.excl[3] = 0xff;
895
896        params.buffer = p_chm->nit_buf;
897        params.buffer_size = NIT_BUF_LEN;
898        /* processing is done in callback */
899        params.data_ready_callback = chm_smessage_nit_callback;
900        params.overflow = NULL;
901        params.callback_context = (void *)p_chm;
902        /* Always reset the starting version numbers to work around
903           cases where headend sends new map but does not change version */
904        SI_NIT_Init (&p_chm->cds_cb,&p_chm->mms_cb,0xFF,0xFF);
905        if (b_ok != smessage_start(&params, p_chm->nit_msg))
906        {
907                BDBG_ERR(("%s:%d",__FILE__, __LINE__));
908                cerr = eCHM_ERR_FAILED;
909        }
910        ExitFunc:
911        return cerr;
912}
913/*
914Summary:
915   Start ntt monitoring..
916*/
917int chm_ntt_start(chm_mgr_t *p_chm, unsigned short network_pid)
918{
919        int cerr = eCHM_ERR_OK;
920        smessage_stream_params_t params;
921
922        chm_ntt_stop(p_chm);
923
924        p_chm->sns_changed = false;
925        p_chm->ntt_msg = smessage_open(smessage_format_psi);
926        BDBG_MSG(("%s:%d ntt_msg = 0x%08x\n",__FUNCTION__,__LINE__,p_chm->ntt_msg));
927        if (NULL == p_chm->ntt_msg)
928        {
929                BDBG_ERR(("%s:%d",__FILE__, __LINE__));
930                cerr = eCHM_ERR_FAILED;
931                goto ExitFunc;
932        }
933        smessage_stream_params_init(&params, p_chm->ntt_msg);
934        params.band = p_chm->band;
935        params.pid = (uint16_t)network_pid;
936        params.filter.coef[0] = 0xc3;   /* Table ID for NTT */
937        params.filter.mask[0] = 0x00;
938        params.filter.excl[0] = 0xff;
939        /* All PSIP tables have protocol_version which must be = 0 */
940        params.filter.coef[3] = 0x00;   /* protocol_version */
941        params.filter.mask[3] = 0x00;
942        params.filter.excl[3] = 0xff;
943
944        params.buffer = p_chm->ntt_buf;
945        params.buffer_size = NTT_BUF_LEN;
946        /* processing is done in callback */
947        params.data_ready_callback = chm_smessage_ntt_callback;
948        params.overflow = NULL;
949        /* Always reset the starting version numbers to work around
950           cases where headend sends new map but does not change version */
951        params.callback_context = (void *)p_chm;
952        SI_NTT_Init (&p_chm->sns_cb,0xFF);
953        if (b_ok != smessage_start(&params, p_chm->ntt_msg))
954        {
955                BDBG_ERR(("%s:%d",__FILE__, __LINE__));
956                cerr = eCHM_ERR_FAILED;
957        }
958        ExitFunc:
959        return cerr;
960}
961/*
962Summary:
963   Start svct monitoring..
964*/
965int chm_svct_start(chm_mgr_t *p_chm, unsigned short network_pid)
966{
967        int cerr = eCHM_ERR_OK;
968        smessage_stream_params_t params;
969        bapp_t *p_app = (bapp_t*)p_chm->p_app;
970
971        chm_svct_stop(p_chm);
972
973        p_chm->vcm_changed = false;
974        p_chm->svct_msg = smessage_open(smessage_format_psi);
975        BDBG_MSG(("%s:%d svct_msg = 0x%08x\n",__FUNCTION__,__LINE__,p_chm->svct_msg));
976        if (NULL == p_chm->svct_msg)
977        {
978                BDBG_ERR(("%s:%d",__FILE__, __LINE__));
979                cerr = eCHM_ERR_FAILED;
980                goto ExitFunc;
981        }
982        smessage_stream_params_init(&params, p_chm->svct_msg);
983        params.band = p_chm->band;
984        params.pid = (uint16_t)network_pid;
985        params.filter.coef[0] = 0xc4;   /* Table ID for SVCT */
986        params.filter.mask[0] = 0x00;
987        params.filter.excl[0] = 0xff;
988        /* All PSIP tables have protocol_version which must be = 0 */
989        params.filter.coef[3] = 0x00;   /* protocol_version */
990        params.filter.mask[3] = 0x00;
991        params.filter.excl[3] = 0xff;
992
993        params.filter.coef[4] = 0x00;   /* protocol_version */
994        params.filter.mask[4] = 0xf0;
995        params.filter.excl[4] = 0xff;
996
997        if (p_app->settings.VCT_ID != 0xFFFF)
998        {
999                /* little endian!!!! */
1000                params.filter.coef[5] = (unsigned char)((p_app->settings.VCT_ID >> 8) & 0xFF);   
1001                params.filter.mask[5] = 0x00;
1002                params.filter.excl[5] = 0xff;
1003                params.filter.coef[6] = (unsigned char)(p_app->settings.VCT_ID & 0xFF); 
1004                params.filter.mask[6] = 0x00;
1005                params.filter.excl[6] = 0xff;
1006        }
1007
1008        params.buffer = p_chm->svct_buf;
1009        params.buffer_size = SVCT_BUF_LEN;
1010        /* processing is done in callback */
1011        params.data_ready_callback = chm_smessage_svct_callback;
1012        params.overflow = NULL;
1013        params.callback_context = (void *)p_chm;
1014        /* Always reset the starting version numbers to work around
1015           cases where headend sends new map but does not change version */
1016        SI_SVCT_Init (&p_chm->vcm_cb,0xFF);
1017        if (b_ok != smessage_start(&params, p_chm->svct_msg))
1018        {
1019                BDBG_ERR(("%s:%d",__FILE__, __LINE__));
1020                cerr = eCHM_ERR_FAILED;
1021        }
1022        ExitFunc:
1023        return cerr;
1024}
1025
1026/*
1027Summary:
1028        Get the program info for the program.
1029Description:
1030        Get the PMT for the program.
1031        Returns non-zero on failure.
1032*/
1033
1034static int chm_get_program_pid(chm_mgr_t *p_chm,                /* Channel manager reference */
1035                                                           bband_t band, 
1036                                                           unsigned short prog_number,
1037                                                           unsigned short *PID
1038                                                          )
1039{
1040        unsigned int section_size, pmt_section_size;
1041        TS_PMT_stream pmt;
1042        TS_PAT_program pat;
1043        int result = eCHM_ERR_FAILED;
1044        int idx,p_idx;
1045
1046        *PID = 0xFFFF;
1047
1048        smessage_stream_params_init(&p_chm->msg_params, NULL);
1049        p_chm->msg_params.band = band;
1050        p_chm->msg_params.pid = (unsigned short)0;      /* PAT */
1051        section_size = PAT_BUF_LEN;
1052
1053        if ((result = chm_getmessage(p_chm,p_chm->pat_buf,&section_size, PAT_TIMEOUT)) != 0)
1054        {
1055                BDBG_WRN(("Error getting PAT 0x%04x = %d\n",prog_number, result));
1056                return result;
1057        }
1058
1059        if (TS_PAT_validate(p_chm->pat_buf, section_size) != true)
1060        {
1061                BDBG_WRN(("TS_PAT_validate failed 0x%04x\n",prog_number));
1062                return eCHM_ERR_FAILED;
1063        }
1064
1065
1066        if (TS_PAT_getNumPrograms(p_chm->pat_buf) == 0)
1067        {
1068                BDBG_WRN(("TS_PAT_getNumPrograms = 0\n"));
1069                return eCHM_ERR_FAILED;
1070        }
1071
1072        BDBG_WRN(("TS_PAT_getNumPrograms %d\n",TS_PAT_getNumPrograms(p_chm->pat_buf)));
1073
1074        for (idx = 0; idx < TS_PAT_getNumPrograms(p_chm->pat_buf); idx++)
1075        {
1076                if (TS_PAT_getProgram( p_chm->pat_buf, section_size, idx, &pat ) != b_ok)
1077                {
1078                        BDBG_WRN(("TS_PAT_validate failed 0x%04x\n",prog_number));
1079                        return eCHM_ERR_FAILED;
1080                }
1081                BDBG_WRN(("TS_PAT_getProgram(%d,0x%04x)\n", pat.program_number,pat.PID));
1082
1083                if (pat.program_number != prog_number)
1084                        continue;
1085
1086                smessage_stream_params_init(&p_chm->msg_params, NULL);
1087                p_chm->msg_params.band = band;
1088                p_chm->msg_params.pid = (unsigned short)pat.PID;        /* PMT */
1089                p_chm->msg_params.filter.coef[0] = 0x2;
1090                p_chm->msg_params.filter.mask[0] = 0x00;
1091                p_chm->msg_params.filter.excl[0] = 0xff;
1092                pmt_section_size = PMT_BUF_LEN;
1093                if ((result = chm_getmessage(p_chm,p_chm->pmt_buf,&pmt_section_size, PMT_TIMEOUT)) != 0)
1094                {
1095                        BDBG_ERR(("Error getting PAT 0x%04x\n",prog_number));
1096                        return result;
1097                }
1098                //p_chm->pmt_crc = chm_section_crc(p_chm->pmt_buf,pmt_section_size);
1099
1100                for (p_idx = 0; p_idx < TS_PMT_getNumStreams(p_chm->pmt_buf,pmt_section_size); p_idx++)
1101                {
1102
1103                        if (TS_PMT_getStream( p_chm->pmt_buf, pmt_section_size, p_idx, &pmt ) != b_ok)
1104                        {
1105                                BDBG_WRN(("Failure processing PMT %d\n",p_idx));
1106                                return eCHM_ERR_FAILED;
1107                        }
1108
1109                        if (pmt.stream_type == 0x0B) /* DSMCC */
1110                        {
1111                                BDBG_WRN(("DSMCC PID[%d] = 0x%04x\n",p_idx,pmt.elementary_PID ));
1112                                *PID = pmt.elementary_PID;
1113                                return eCHM_ERR_OK;
1114                        } else
1115                        {
1116                                /* We only support the above 3 types of stream */ 
1117                                BDBG_MSG(("Unsupported stream type[0x%02x]\n", pmt.stream_type ));
1118                        }
1119                }
1120        }
1121        return result;
1122}
1123
1124/*
1125Summary:
1126        Get the program info for the program.
1127Description:
1128        Get the PMT for the program.
1129        Returns non-zero on failure.
1130*/
1131
1132static int chm_get_program(chm_mgr_t *p_chm,            /* Channel manager reference */
1133                                                   vch_t *p_vch)
1134{
1135        unsigned int section_size, pmt_section_size;
1136        TS_PMT_stream pmt;
1137        TS_PAT_program pat;
1138        TS_PSI_descriptor psi_desc;
1139        int result = 0;
1140        int idx,p_idx,desc_idx,num_prog;
1141        bapp_t *p_app = (bapp_t*)p_chm->p_app;
1142        unsigned int prog_ticks;
1143        bsettop_av_stream_type_t *stream_type;
1144#ifdef CONFIG_DVB_SUBTITLE
1145        unsigned char dsub_lang[MAX_DSUB_PIDS][3];
1146        unsigned short dsub_page[MAX_DSUB_PIDS];
1147        unsigned char dsub_cnt, i;
1148#endif
1149
1150        BDBG_MSG(("%s:%d\n",__FUNCTION__,__LINE__));
1151
1152        prog_ticks = bos_getticks();
1153
1154        smessage_stream_params_init(&p_chm->msg_params, NULL);
1155        p_chm->msg_params.band = p_chm->band;
1156        p_chm->msg_params.pid = (unsigned short)0;      /* PAT */
1157        section_size = PAT_BUF_LEN;
1158
1159        if ((result = chm_getmessage(p_chm,p_chm->pat_buf,&section_size, PAT_TIMEOUT)) != 0)
1160        {
1161                BDBG_WRN(("%s(%d): Error getting PAT 0x%04x = %d\n",__FUNCTION__,__LINE__,p_chm->vch.program_num, result));
1162                return result;
1163        }
1164        p_chm->pat_crc = chm_section_crc(p_chm->pat_buf,section_size);
1165        p_chm->pat_cnt++;
1166        if (TS_PAT_validate(p_chm->pat_buf, section_size) != true)
1167        {
1168                BDBG_WRN(("TS_PAT_validate failed 0x%04x\n",p_chm->vch.program_num));
1169                return eCHM_ERR_FAILED;
1170        }
1171
1172        num_prog = TS_PAT_getNumPrograms(p_chm->pat_buf);
1173        if (num_prog == 0)
1174        {
1175                BDBG_WRN(("TS_PAT_getNumPrograms = 0\n"));
1176                return eCHM_ERR_FAILED;
1177        }
1178
1179        BDBG_MSG(("TS_PAT_getNumPrograms %d\n",num_prog));
1180
1181        for (idx = 0; idx < num_prog; idx++)
1182        {
1183                if (TS_PAT_getProgram( p_chm->pat_buf, section_size, idx, &pat ) != b_ok)
1184                {
1185                        BDBG_WRN(("TS_PAT_validate failed 0x%04x\n",idx));
1186                        return eCHM_ERR_FAILED;
1187                }
1188
1189                BDBG_MSG(("TS_PAT_getProgram(%d,0x%04x)\n", pat.program_number,pat.PID));
1190
1191                /* Check for new network PID */
1192                if (pat.program_number == 0)
1193                {
1194                        if (pat.PID != p_app->settings.network_PID)
1195                        {
1196                                p_chm->network_pid = pat.PID;
1197                        }
1198                }
1199
1200                if (p_chm->vch.program_num != pat.program_number)
1201                        continue;
1202
1203                p_vch->num_audio = 0;
1204                p_vch->cur_audio = 0;
1205                p_vch->pcr_pid = 0;
1206                p_vch->video_pid = 0;
1207                p_vch->scte127_pid = 0;
1208                p_vch->audio_pid[0] = 0;
1209#ifdef CONFIG_DVB_SUBTITLE
1210                p_vch->num_dsub = 0;
1211                p_vch->cur_dsub = 0;
1212#endif
1213
1214                smessage_stream_params_init(&p_chm->msg_params, NULL);
1215                p_chm->msg_params.band = p_chm->band;
1216                p_chm->msg_params.pid = (unsigned short)pat.PID;        /* PMT */
1217                p_chm->msg_params.filter.coef[0] = 0x2;
1218                p_chm->msg_params.filter.mask[0] = 0x00;
1219                p_chm->msg_params.filter.excl[0] = 0xff;
1220                pmt_section_size = PMT_BUF_LEN;
1221                if ((result = chm_getmessage(p_chm,p_chm->pmt_buf,&pmt_section_size, PMT_TIMEOUT)) != 0)
1222                {
1223                        BDBG_ERR(("%s(%d): Error getting PAT 0x%04x = %d\n",__FUNCTION__,__LINE__,p_chm->vch.program_num, result));
1224                        return result;
1225                }
1226                p_chm->pmt_crc = chm_section_crc(p_chm->pmt_buf,pmt_section_size);
1227
1228                p_chm->pmt_cnt++;
1229
1230                p_vch->pcr_pid = TS_PMT_getPcrPid(p_chm->pmt_buf,pmt_section_size);
1231
1232                /* Get CA pid */
1233                desc_idx = 0;
1234                p_vch->ca_pid = 0;
1235                while ((psi_desc = TS_PMT_getDescriptor(p_chm->pmt_buf, pmt_section_size,desc_idx++)) != NULL)
1236                {
1237                        static ca_descriptor ca_desc;
1238                        if (desc_idx > 0xFF)
1239                        {
1240                                BDBG_ERR(("PMT Desc limit exceeded %d\n",desc_idx));
1241                                break;
1242                        }
1243                        if (chm_check_cancel(p_chm))
1244                        {
1245                                return eCHM_ERR_CANCELED;
1246                        }
1247
1248                        if (psi_desc[0] != 9)
1249                                continue;
1250
1251                        if (ca_parser(psi_desc, pmt_section_size, &ca_desc) == 0)
1252                                continue;
1253
1254                        if (ca_desc.CA_system_ID == p_app->settings.CA_System_ID)
1255                        {
1256                                p_vch->ca_pid = ca_desc.CA_PID;
1257                                BDBG_WRN(("CA PID = 0x%04x\n",p_vch->ca_pid));
1258                                p_app->settings.SCP_operating_mode = 0;
1259                                if (ca_desc.CA_system_ID == 0x0E11)
1260                                {
1261                                        /* Send message to app */
1262                                        if ((ca_desc.priv_data[0] == 0x5) && (ca_desc.priv_data[1] == 0x1))
1263                                                p_app->settings.SCP_operating_mode = ca_desc.priv_data[2];
1264                                }
1265                                break;
1266                        }
1267                        else
1268                        {
1269                                p_chm->system_id_errors++;
1270                        }
1271
1272                }
1273
1274                for (p_idx = 0; p_idx < TS_PMT_getNumStreams(p_chm->pmt_buf,pmt_section_size); p_idx++)
1275                {
1276                        TS_PSI_descriptor psi_desc,lang_desc;
1277                        int strm_idx;
1278
1279                        if (TS_PMT_getStream( p_chm->pmt_buf, pmt_section_size, p_idx, &pmt ) != b_ok)
1280                        {
1281                                BDBG_WRN(("Failure processing PMT %d\n",p_idx));
1282                                return eCHM_ERR_FAILED;
1283                        }
1284
1285                        strm_idx = 0;
1286                        lang_desc = NULL;
1287                        /* default is not supported */
1288                        //p_vch->scte127_pid = 0;
1289#ifdef CONFIG_DVB_SUBTITLE
1290                        dsub_cnt = 0;
1291#endif
1292                        while ((psi_desc = TS_PMT_getStreamDescriptor(p_chm->pmt_buf,pmt_section_size, p_idx,strm_idx)) != NULL)
1293                        {
1294#ifdef CONFIG_DVB_SUBTITLE
1295                                if (psi_desc[0] == TS_PSI_DT_DVB_Subtitling)
1296                                {
1297                                        if ((psi_desc[5]<0x10) || (psi_desc[5]>0x23))
1298                                                continue; /* not DVB subtitle */
1299                                        /* could multiple subtitle program in same pid */
1300                                        dsub_lang[dsub_cnt][0] = toupper(psi_desc[2]);
1301                                        dsub_lang[dsub_cnt][1] = toupper(psi_desc[3]);
1302                                        dsub_lang[dsub_cnt][2] = toupper(psi_desc[4]);
1303                                        dsub_page[dsub_cnt] = psi_desc[6]<<8|psi_desc[7];
1304                                        dsub_cnt++;
1305                                }
1306#endif
1307                                if (psi_desc[0] == TS_PSI_DT_ISO_639_Language) /* 0x0A ISO-639 Language descriptor */
1308                                {
1309                                        BDBG_MSG(("ISO-639 DESC\n" ));
1310                                        lang_desc = psi_desc;
1311                                        /* if get VBI desc alrady */
1312                                        if (p_vch->scte127_pid)
1313                                                break;
1314                                }
1315                                if (0 == p_vch->scte127_pid)
1316                                {
1317                                        if (TS_PSI_DT_DVB_VBI_Data == psi_desc[0])
1318                                        {
1319                                                BDBG_MSG(("SCTE 127 supported, pid=0x%04x", pmt.elementary_PID));
1320                                                p_vch->scte127_pid = pmt.elementary_PID;
1321                                                /* if get lang desc alrady */
1322                                                if (lang_desc)
1323                                                        break;
1324                                        }
1325                                }
1326                                strm_idx++;
1327                                if (strm_idx > 0xFF)
1328                                {
1329                                        BDBG_ERR(("PMT Stream Desc limit exceeded %d\n",strm_idx));
1330                                        break;
1331                                }
1332                                if (chm_check_cancel(p_chm))
1333                                {
1334                                        return eCHM_ERR_CANCELED;
1335                                }
1336                        }
1337
1338                        if ((stream_type = bdecode_supported_video(pmt.stream_type)) != NULL)
1339                        {
1340                                BDBG_MSG(("Video PID[%d] = 0x%04x\n",p_idx,pmt.elementary_PID ));
1341                                if (!p_vch->video_pid)
1342                                {
1343                                        p_vch->video_pid = pmt.elementary_PID;
1344                                        p_vch->video_type = stream_type->codec_id;
1345                                }
1346                        }
1347                        else if ((stream_type = bdecode_supported_audio(pmt.stream_type)) != NULL)
1348                        {
1349                                BDBG_MSG(("Audio PID[%d] = 0x%04x\n",p_vch->num_audio,pmt.elementary_PID ));
1350                                if (!p_vch->audio_pid[p_vch->num_audio])
1351                                {
1352                                p_vch->audio_pid[p_vch->num_audio] = pmt.elementary_PID;
1353                                        p_vch->audio_type[p_vch->num_audio] = stream_type->codec_id;
1354                                if (lang_desc)
1355                                {
1356                                        p_vch->audio_lang[p_vch->num_audio][0] = toupper(lang_desc[2]);
1357                                        p_vch->audio_lang[p_vch->num_audio][1] = toupper(lang_desc[3]);
1358                                        p_vch->audio_lang[p_vch->num_audio][2] = toupper(lang_desc[4]);
1359                                }
1360                                p_vch->num_audio++;
1361                                }
1362                        }
1363#ifdef CONFIG_DVB_SUBTITLE
1364                        else if (pmt.stream_type == PES_PRIVATE_STREAM_TYPE) 
1365                        {
1366                                dsub_cnt = (dsub_cnt>MAX_DSUB_PIDS)?MAX_DSUB_PIDS:dsub_cnt;
1367                                for (i=0; i<dsub_cnt; i++) {
1368                                        if (p_vch->num_dsub >= MAX_DSUB_PIDS) break;
1369                                        p_vch->dsub_pid[p_vch->num_dsub] = pmt.elementary_PID;
1370                                        p_vch->dsub_lang[p_vch->num_dsub][0] = dsub_lang[i][0];
1371                                        p_vch->dsub_lang[p_vch->num_dsub][1] = dsub_lang[i][1];
1372                                        p_vch->dsub_lang[p_vch->num_dsub][2] = dsub_lang[i][2];
1373                                        p_vch->dsub_page[p_vch->num_dsub] = dsub_page[i];
1374                                        BDBG_MSG(("DSUB PID [%d] = 0x%04x lang:%c%c%c, page:%d", p_vch->num_dsub, pmt.elementary_PID,
1375                                                dsub_lang[i][0], dsub_lang[i][1], dsub_lang[i][2], dsub_page[i]));     
1376                                        p_vch->num_dsub++;
1377                                }
1378                        }
1379#endif
1380                        else
1381                        {
1382                                BDBG_MSG(("Unsupported stream type[0x%02x]\n", pmt.stream_type));
1383                        }
1384                }
1385        }
1386
1387        prog_ticks = bos_getticks() - prog_ticks;
1388        p_chm->status_evt.type = eCHM_EVT_STATUS;
1389        p_chm->status_evt.id = eCHM_STATUS_SI_MS;
1390        p_chm->status_evt.ticks = TICKS_TO_MS(prog_ticks);
1391        chm_post_app_event(p_chm,&p_chm->status_evt);
1392
1393
1394        return result;
1395}
1396/*
1397Summary:
1398        Scan for channels using PSI.
1399Description:
1400        Scan for channels using PSI.
1401        Returns number of channels added.
1402*/
1403
1404static int chm_scan_psi(chm_mgr_t *p_chm,               /* Channel manager reference */
1405                                                bband_t band, int freq_idx)
1406{
1407        unsigned int section_size, pmt_section_size;
1408        TS_PMT_stream pmt;
1409        TS_PAT_program pat;
1410        int result = 0;
1411        int idx,p_idx,tresult, desc_idx;
1412        vch_t vch;
1413        TS_PSI_descriptor psi_desc;
1414        unsigned short ca_pid = 0;
1415#ifdef CONFIG_DVB_SUBTITLE
1416        unsigned char dsub_lang[MAX_DSUB_PIDS][3];
1417        unsigned short dsub_page[MAX_DSUB_PIDS];
1418        unsigned char dsub_cnt, i;
1419#endif
1420
1421        memset(&vch,0,sizeof(vch));
1422
1423        /* Get the PAT */
1424        smessage_stream_params_init(&p_chm->msg_params, NULL);
1425        p_chm->msg_params.band = band;
1426        p_chm->msg_params.pid = (unsigned short)0;      /* PAT */
1427        section_size = PAT_BUF_LEN;
1428
1429        if ((result = chm_getmessage(p_chm,p_chm->pat_buf,&section_size, PAT_TIMEOUT * 10)) != 0)
1430        {
1431                BDBG_WRN(("%s Timeout getting PAT\n",__FUNCTION__));
1432                return result;
1433        }
1434        p_chm->pat_crc = chm_section_crc(p_chm->pat_buf,section_size);
1435
1436        if (TS_PAT_validate(p_chm->pat_buf, section_size) != true)
1437        {
1438                BDBG_WRN(("TS_PAT_validate failed\n"));
1439                return eCHM_ERR_FAILED;
1440        }
1441        BDBG_WRN(("%s:%d section_size = %d\n",__FUNCTION__,__LINE__,section_size));
1442
1443        BDBG_WRN(("Programs %d\n",TS_PAT_getNumPrograms(p_chm->pat_buf)));
1444
1445        if (TS_PAT_getNumPrograms(p_chm->pat_buf) == 0)
1446        {
1447                BDBG_WRN(("%s TS_PAT_getNumPrograms = 0,section_size = %d\n",__FUNCTION__,section_size));
1448                DBG_HEXDUMP(p_chm->pat_buf,section_size);
1449                return eCHM_ERR_FAILED;
1450        }
1451
1452        for (idx = 0; idx < TS_PAT_getNumPrograms(p_chm->pat_buf); idx++)
1453        {
1454                if (chm_check_cancel(p_chm))
1455                {
1456                        return eCHM_ERR_CANCELED;
1457                }
1458
1459                memset(&vch,0,sizeof(vch));
1460                section_size = PAT_BUF_LEN;
1461                if (TS_PAT_getProgram( p_chm->pat_buf, section_size, idx, &pat ) != b_ok)
1462                {
1463                        BDBG_WRN(("TS_PAT_validate failed 0x%04x\n",pat.PID));
1464                        return eCHM_ERR_FAILED;
1465                }
1466                //p_chm->pat_crc = chm_section_crc(p_chm->pat_buf,section_size);
1467
1468                smessage_stream_params_init(&p_chm->msg_params, NULL);
1469                p_chm->msg_params.band = band;
1470                p_chm->msg_params.pid = (unsigned short)pat.PID;        /* PMT */
1471                p_chm->msg_params.filter.coef[0] = 0x2;
1472                p_chm->msg_params.filter.mask[0] = 0x00;
1473                p_chm->msg_params.filter.excl[0] = 0xff;
1474                pmt_section_size = PMT_BUF_LEN;
1475                if ((tresult = chm_getmessage(p_chm,p_chm->pmt_buf,&pmt_section_size, PMT_TIMEOUT)) != 0)
1476                {
1477                        BDBG_WRN(("Failed getting PMT 0x%04x\n",pat.PID));
1478                        continue;
1479                }
1480                p_chm->pmt_crc = chm_section_crc(p_chm->pmt_buf,pmt_section_size);
1481
1482                vch.freq_idx = freq_idx;
1483                vch.pcr_pid = TS_PMT_getPcrPid(p_chm->pmt_buf,pmt_section_size);
1484                ca_pid = 0;
1485                vch.program_num = pat.program_number;
1486                /* Get CA pid for cable */
1487                desc_idx = 0;
1488#ifdef CONFIG_DVB_SUBTITLE
1489                vch.num_dsub = 0;
1490                vch.cur_dsub = 0;
1491                int strm_idx;
1492#endif
1493                while ((psi_desc = TS_PMT_getDescriptor(p_chm->pmt_buf, pmt_section_size,desc_idx++)) != NULL)
1494                {
1495                        if (desc_idx > 0xFF)
1496                        {
1497                                BDBG_ERR(("PMT Desc limit exceeded %d\n",desc_idx));
1498                                break;
1499                        }
1500                        if (chm_check_cancel(p_chm))
1501                        {
1502                                return eCHM_ERR_CANCELED;
1503                        }
1504                        if (psi_desc[0] == 9)
1505                        {
1506                                ca_pid = (((unsigned short)(psi_desc[4] & 0x1F)) << 8) | (unsigned short)psi_desc[5];
1507                                BDBG_MSG(("CA PID = 0x%04x\n",ca_pid));
1508                                break;
1509                        }
1510                }
1511                if (ca_pid != 0x0000)
1512                {
1513                        BDBG_MSG(("Program has CA PID 0x%02x check for scrambling control bit.\n",ca_pid));
1514                        vch.ca_pid = ca_pid;
1515                }
1516
1517                BDBG_MSG(("Streams = %d\n",TS_PMT_getNumStreams(p_chm->pmt_buf,pmt_section_size)));
1518                for (p_idx = 0; p_idx < TS_PMT_getNumStreams(p_chm->pmt_buf,pmt_section_size); p_idx++)
1519                {
1520                        bsettop_av_stream_type_t *stream_type;
1521
1522                        if (TS_PMT_getStream( p_chm->pmt_buf, pmt_section_size, p_idx, &pmt ) != b_ok)
1523                        {
1524                                BDBG_WRN(("Failure processing PMT %d\n",p_idx));
1525                                return eCHM_ERR_FAILED;
1526                        }
1527#ifdef CONFIG_DVB_SUBTITLE
1528                        dsub_cnt = 0;
1529                        strm_idx = 0;
1530                        while ((psi_desc = TS_PMT_getStreamDescriptor(p_chm->pmt_buf,pmt_section_size, p_idx,strm_idx)) != NULL)
1531                        {
1532                                if (psi_desc[0] == TS_PSI_DT_DVB_Subtitling)
1533                                {
1534                                        if ((psi_desc[5]<0x10) || (psi_desc[5]>0x23)) 
1535                                                continue; /* not DVB subtitle */
1536                                        dsub_lang[dsub_cnt][0] = toupper(psi_desc[2]);
1537                                        dsub_lang[dsub_cnt][1] = toupper(psi_desc[3]);
1538                                        dsub_lang[dsub_cnt][2] = toupper(psi_desc[4]);
1539                                        dsub_page[dsub_cnt] = psi_desc[6]<<8|psi_desc[7];
1540                                        dsub_cnt++;
1541                                }
1542                                strm_idx++;
1543                                if (strm_idx > 0xFF)
1544                                {
1545                                        BDBG_ERR(("PMT Stream Desc limit exceeded %d\n",strm_idx));
1546                                        break;
1547                                }
1548                                if (chm_check_cancel(p_chm))
1549                                {
1550                                        return eCHM_ERR_CANCELED;
1551                                }
1552                        }
1553#endif
1554
1555                        if ((stream_type = bdecode_supported_video(pmt.stream_type)) != NULL)
1556                        {
1557                                BDBG_MSG(("Video PID[%d] = 0x%04x\n",p_idx,pmt.elementary_PID ));
1558                                if (!vch.video_pid)
1559                                {
1560                                        vch.video_pid = pmt.elementary_PID;
1561                                        vch.video_type = stream_type->codec_id;
1562                                }
1563                        }
1564                        else if ((stream_type = bdecode_supported_audio(pmt.stream_type)) != NULL)
1565                        {
1566                                BDBG_MSG(("Audio PID[%d] = 0x%04x\n",vch.num_audio,pmt.elementary_PID ));
1567                                if (!vch.audio_pid[vch.num_audio])
1568                                {
1569                                        vch.audio_pid[vch.num_audio] = pmt.elementary_PID;
1570                                        vch.audio_type[vch.num_audio] = stream_type->codec_id;
1571                                        vch.num_audio++;
1572                                }
1573                        }
1574#ifdef CONFIG_DVB_SUBTITLE
1575                        else if (pmt.stream_type == PES_PRIVATE_STREAM_TYPE) 
1576                        {
1577                                dsub_cnt = (dsub_cnt > MAX_DSUB_PIDS)?MAX_DSUB_PIDS:dsub_cnt;
1578                                for (i=0; i<dsub_cnt; i++) {
1579                                        if (vch.num_dsub>=MAX_DSUB_PIDS) break;
1580                                        BDBG_WRN(("%s: private PID[%d] = 0x%04x page:%d [%c%c%c]", 
1581                                                __FUNCTION__, vch.num_dsub, pmt.elementary_PID,
1582                                                dsub_page[i], dsub_lang[i][0], dsub_lang[i][1], dsub_lang[i][2]));
1583                                        vch.dsub_pid[vch.num_dsub] = pmt.elementary_PID;
1584                                        vch.dsub_lang[vch.num_dsub][0] = dsub_lang[i][0];
1585                                        vch.dsub_lang[vch.num_dsub][1] = dsub_lang[i][1];
1586                                        vch.dsub_lang[vch.num_dsub][2] = dsub_lang[i][2];
1587                                        vch.dsub_page[vch.num_dsub] = dsub_page[i];
1588                                        vch.num_dsub++;
1589                                }
1590                        }
1591#endif
1592                }
1593
1594                if ((vch.video_pid) || (vch.audio_pid[0]))
1595                {
1596                        bool clear = true;;
1597                        unsigned short pid;
1598                        if (vch.video_pid)
1599                                pid = (unsigned short)vch.video_pid;
1600                        else
1601                                pid     = (unsigned short)vch.audio_pid[0];
1602                        /* correct pid in case video pid carries too few frames */
1603                        if(vch.pcr_pid == vch.audio_pid[0])
1604                                pid = (unsigned short)vch.audio_pid[0];
1605
1606                        if (vch.ca_pid != 0x0000)
1607                        clear = chm_check_sc(p_chm, band, pid);
1608                        else
1609                                clear = 1;
1610
1611                        if (clear)
1612                        {
1613                                bapp_t *p_app = (bapp_t *)p_chm->p_app;
1614
1615                                p_chm->chm_pat_evt.type = eCHM_EVT_STATUS;
1616                                p_chm->chm_pat_evt.id = eCHM_STATUS_PAT;
1617                                p_chm->chm_pat_evt.ticks = 0;
1618                                chm_post_app_event(p_chm,&p_chm->chm_pat_evt);
1619                                chm_add_channel(p_chm,&vch);
1620                               
1621                                /* in the chm_scan_psi, it will post STATUS_PAT. but sometimes the event is missed.. don't know why.. */ 
1622                                if (p_app->screen_id == eSCREEN_CH_SCAN_PROGRESS) {
1623                                        bos_sleep(100);
1624                                }
1625                               
1626                                result += 1;
1627                        }
1628                }
1629        }
1630
1631        return result;
1632}
1633/*
1634Summary:
1635        Generic tuner cancel callback.
1636*/
1637void chm_tune_cancel_callback(void *context)
1638{
1639        chm_mgr_t *p_chm    =    (   chm_mgr_t    *)context;
1640
1641        if (chm_check_cancel(p_chm))
1642        {
1643                BDBG_WRN(("### CANCEL TUNE ###\n"));
1644                p_chm->tuner_params.cancel = true;
1645        }
1646}
1647
1648/*
1649Summary:
1650        Stop the STT. return non-zero on failure
1651*/
1652static void chm_stt_stop(chm_mgr_t *p_chm)
1653{
1654        if (NULL != p_chm->stt_msg)
1655        {
1656                BDBG_WRN(("%s\n",__FUNCTION__));
1657                if (b_ok != smessage_stop(p_chm->stt_msg))
1658                {
1659                        BDBG_ERR(("%s:%d",__FUNCTION__, __LINE__));
1660                        return;
1661                }
1662                smessage_close(p_chm->stt_msg);
1663                p_chm->stt_msg = NULL;
1664        }
1665}
1666
1667/*
1668Summary:
1669        Scan for channels to create a channel map.
1670Description:
1671        Scan for all available channels.
1672*/
1673
1674static void chm_stream_close(chm_mgr_t *p_chm           /* Channel manager reference */
1675                                                        )
1676{
1677}
1678/*
1679Summary:
1680        Callback function normally called when a complete message has
1681        been received and passed the filter criteria.
1682 */
1683bool found_system = false;
1684static void * chm_smessage_cat_callback(void * context, size_t section_size)
1685{
1686        chm_mgr_t * p_chm = (chm_mgr_t*)context;
1687        unsigned int len = section_size;
1688        unsigned char *ptr;
1689        ca_descriptor ca_desc;
1690        found_system = false;
1691        p_chm->cat_cnt++;
1692
1693        if ((ptr = cat_parser(p_chm->cat_buf, &len)) != NULL)
1694        {
1695                while ((len > 9) && ptr)
1696                {          /* 6 + 4 for CRC */
1697                        if (ca_parser(ptr, len, &ca_desc) != 0)
1698                        {
1699                                ptr += ca_desc.priv_length + 6;
1700                                len -= (ca_desc.priv_length + 6);
1701                                BDBG_MSG(("%s CA_System_ID = 0x%04x, EMM_PID = 0x%04x.\n",__FUNCTION__,
1702                                                  ca_desc.CA_system_ID,ca_desc.CA_PID));
1703                                if ((ca_desc.CA_system_ID == 0x4749) || (ca_desc.CA_system_ID == 0x0E11))
1704                                {
1705                                        /* Send message to app */
1706                                        chm_ca_event_t *p_ca_evt = (chm_ca_event_t*)&p_chm->ca_evt;
1707                                        p_ca_evt->type = eCHM_EVT_CA;
1708                                        p_ca_evt->CA_System_ID = ca_desc.CA_system_ID;
1709                                        p_ca_evt->EMM_Provider_ID = 0;
1710                                        p_ca_evt->SCP_operating_mode = 0;
1711                                        if (ca_desc.CA_system_ID == 0x4749)
1712                                                p_ca_evt->EMM_Provider_ID = (unsigned short)ca_desc.priv_data[0] | ((unsigned short)ca_desc.priv_data[1] << 8);
1713                                        else if ((ca_desc.CA_system_ID == 0x0E11) && (ca_desc.priv_data[0] == 0x5) && (ca_desc.priv_data[1] == 0x1))
1714                                                p_ca_evt->SCP_operating_mode = ca_desc.priv_data[2];
1715
1716                                        p_ca_evt->EMM_PID = ca_desc.CA_PID;
1717                                        p_ca_evt->freq_khz = p_chm->last_freq_hz;
1718                                        chm_post_app_event(p_chm,(chm_event_t*)p_ca_evt);
1719                    found_system = true;
1720                                } else
1721                                {
1722                                        p_chm->system_id_errors++;
1723                                        BDBG_MSG(("INVALID CA SYSTEM 0x%04x\n",ca_desc.CA_system_ID));
1724                                }
1725                        } else
1726                        {
1727                                BDBG_MSG(("%s ca_parse failed.\n",__FUNCTION__));
1728                                break;
1729                        }
1730                }
1731        } else
1732        {
1733                BDBG_MSG(("%s Timeout getting CAT\n",__FUNCTION__));
1734        }
1735        return p_chm->cat_buf;
1736}
1737/*
1738Summary:
1739Start CAT monitoring..
1740 */
1741static int chm_cat_start(chm_mgr_t *p_chm)
1742{
1743        int cerr = eCHM_ERR_OK;
1744        smessage_stream_params_t params;
1745
1746        chm_cat_stop(p_chm);
1747
1748        p_chm->cat_msg = smessage_open(smessage_format_psi);
1749        if (NULL == p_chm->cat_msg)
1750        {
1751                BDBG_ERR(("%s:%d",__FILE__, __LINE__));
1752                cerr = eCHM_ERR_FAILED;
1753                goto ExitFunc;
1754        }
1755        smessage_stream_params_init(&params, p_chm->cat_msg);
1756        params.band = p_chm->band;
1757        params.pid = 1;
1758        params.buffer = p_chm->cat_buf;
1759        params.buffer_size = CAT_BUF_LEN;
1760        params.data_ready_callback = chm_smessage_cat_callback;
1761        params.overflow = NULL;
1762        params.callback_context = (void *)p_chm;
1763
1764        if (b_ok != smessage_start(&params, p_chm->cat_msg))
1765        {
1766                BDBG_ERR(("%s:%d",__FILE__, __LINE__));
1767                cerr = eCHM_ERR_FAILED;
1768        }
1769
1770        ExitFunc:
1771        return cerr;
1772}
1773
1774/*
1775Summary:
1776   Stop CAT monitoring..
1777*/
1778static void chm_cat_stop(chm_mgr_t *p_chm)
1779{
1780        if (NULL != p_chm->cat_msg)
1781        {
1782                if (b_ok != smessage_stop(p_chm->cat_msg))
1783                {
1784                        BDBG_ERR(("%s:%d",__FILE__, __LINE__));
1785                        return;
1786                }
1787                smessage_close(p_chm->cat_msg);
1788                p_chm->cat_msg = NULL;
1789        }
1790}
1791
1792/*
1793Summary:
1794        Scan for the CAT/CA descriptor.
1795Description:
1796        Scan for the CAT/CA descriptor.
1797        Returns non-zero on error.
1798 */
1799
1800static int chm_scan_cat(chm_mgr_t *p_chm,               /* Channel manager reference */
1801                                                bband_t band,
1802                                                unsigned int freq_khz)
1803{
1804        unsigned int section_size;
1805        int result = eCHM_ERR_FAILED;
1806
1807        /* Get the VCT */
1808        smessage_stream_params_init(&p_chm->msg_params, NULL);
1809        p_chm->msg_params.band = band;
1810        p_chm->msg_params.pid = (unsigned short)1;      /* CAT */
1811        section_size = CAT_BUF_LEN;
1812
1813        if ((result = chm_getmessage(p_chm,p_chm->cat_buf,&section_size, CAT_TIMEOUT)) != 0)
1814        {
1815                BDBG_WRN(("%s Timeout getting CAT\n",__FUNCTION__));
1816                return result;
1817        }
1818
1819        chm_smessage_cat_callback(p_chm,section_size);
1820        result = (found_system) ? eCHM_ERR_OK : eCHM_ERR_FAILED;
1821
1822        return result;
1823}
1824
1825#if 0
1826
1827/*
1828Summary:
1829        Scan for the CAT/CA descriptor.
1830Description:
1831        Scan for the CAT/CA descriptor.
1832        Returns non-zero on error.
1833*/
1834
1835static int chm_scan_cat(chm_mgr_t *p_chm,               /* Channel manager reference */
1836                                                bband_t band,
1837                                                unsigned int freq_khz)
1838{
1839        unsigned int section_size,len;
1840        unsigned char *ptr;
1841        static ca_descriptor ca_desc;
1842        int result = eCHM_ERR_FAILED;
1843        bapp_t *p_app = (bapp_t*)p_chm->p_app;
1844
1845        /* Get the VCT */
1846        smessage_stream_params_init(&p_chm->msg_params, NULL);
1847        p_chm->msg_params.band = band;
1848        p_chm->msg_params.pid = (unsigned short)1;      /* CAT */
1849        section_size = CAT_BUF_LEN;
1850
1851        if ((result = chm_getmessage(p_chm,p_chm->cat_buf,&section_size, CAT_TIMEOUT)) != 0)
1852        {
1853                BDBG_WRN(("%s Timeout getting CAT\n",__FUNCTION__));
1854                return result;
1855        }
1856
1857        p_chm->cat_cnt++;
1858        if ((ptr = cat_parser(p_chm->cat_buf, &len)) != NULL)
1859        {
1860                while ((len > 9) && ptr)
1861                {          /* 6 + 4 for CRC */
1862                        if (ca_parser(ptr, len, &ca_desc))
1863                        {
1864                                ptr += ca_desc.priv_length + 6;
1865                                len -= (ca_desc.priv_length + 6);
1866
1867                                BDBG_WRN(("%s CA_System_ID = 0x%04x, EMM_PID = 0x%04x.\n",__FUNCTION__,
1868                                                  ca_desc.CA_system_ID,ca_desc.CA_PID));
1869
1870                                if (freq_khz == 0)
1871                                {
1872                                        if (ca_desc.CA_system_ID != p_app->settings.CA_System_ID)
1873                                        {
1874                                                p_chm->system_id_errors++;
1875                                        }
1876                                }
1877                                else
1878                                {
1879                                        if ((ca_desc.CA_system_ID == 0x4749) || (ca_desc.CA_system_ID == 0x0E11))
1880                                        {
1881                                                /* Send message to app */
1882                                                chm_ca_event_t *p_ca_evt = (chm_ca_event_t*)&p_chm->ca_evt;
1883                                                p_ca_evt->type = eCHM_EVT_CA;
1884                                                p_ca_evt->CA_System_ID = ca_desc.CA_system_ID;
1885                                                p_ca_evt->EMM_Provider_ID = 0;
1886                                                p_ca_evt->SCP_operating_mode = 0;
1887                                                if (ca_desc.CA_system_ID == 0x4749)
1888                                                        p_ca_evt->EMM_Provider_ID = (unsigned short)ca_desc.priv_data[0] | ((unsigned short)ca_desc.priv_data[1] << 8);
1889                                                else if ((ca_desc.CA_system_ID == 0x0E11) && (ca_desc.priv_data[0] == 0x5) && (ca_desc.priv_data[1] == 0x1))
1890                                                        p_ca_evt->SCP_operating_mode = ca_desc.priv_data[2];
1891
1892                                                p_ca_evt->EMM_PID = ca_desc.CA_PID;
1893                                                p_ca_evt->freq_khz = freq_khz;
1894                                                chm_post_app_event(p_chm,(chm_event_t*)p_ca_evt);
1895                                                result = eCHM_ERR_OK;
1896                                        } else
1897                                        {
1898                                                p_chm->system_id_errors++;
1899                                                BDBG_WRN(("INVALID CA SYSTEM 0x%04x\n",ca_desc.CA_system_ID));
1900                                        }
1901                                }
1902
1903                        } else
1904                        {
1905                                BDBG_WRN(("%s ca_parse failed.\n",__FUNCTION__));
1906                                result = eCHM_ERR_FAILED;
1907                                break;
1908                        }
1909                }
1910        } else
1911        {
1912                BDBG_WRN(("%s Timeout getting CAT\n",__FUNCTION__));
1913        }
1914
1915
1916        return result;
1917}
1918#endif
1919/*
1920Summary:
1921        Scan for the network PID.
1922Description:
1923        Scan for the network PID in pat PMT with program id 0.
1924        Returns the network PID.
1925*/
1926
1927static int chm_scan_network(chm_mgr_t *p_chm,           /* Channel manager reference */
1928                                                        bband_t band, 
1929                                                        unsigned short *network_PID)
1930{
1931        unsigned int section_size;
1932        TS_PAT_program pat;
1933        int result = eCHM_ERR_FAILED;
1934        int idx;
1935
1936        *network_PID = CHM_DEF_NETWORK_PID;     /* Default PID value for this network */
1937
1938        /* Get the VCT */
1939        smessage_stream_params_init(&p_chm->msg_params, NULL);
1940        p_chm->msg_params.band = band;
1941        p_chm->msg_params.pid = (unsigned short)0;      /* PAT */
1942        section_size = PAT_BUF_LEN;
1943
1944        if ((result = chm_getmessage(p_chm,p_chm->pat_buf,&section_size, PAT_TIMEOUT)) != 0)
1945        {
1946                BDBG_WRN(("%s Timeout getting PAT\n",__FUNCTION__));
1947                return result;
1948        }
1949        if (TS_PAT_validate(p_chm->pat_buf, section_size) != true)
1950        {
1951                BDBG_WRN(("TS_PAT_validate failed\n"));
1952                return eCHM_ERR_FAILED;
1953        }
1954        p_chm->pat_cnt++;
1955
1956        for (idx = 0; idx < TS_PAT_getNumPrograms(p_chm->pat_buf); idx++)
1957        {
1958                if (chm_check_cancel(p_chm))
1959                {
1960                        return eCHM_ERR_CANCELED;
1961                }
1962
1963                section_size = PAT_BUF_LEN;
1964                if (TS_PAT_getProgram( p_chm->pat_buf, section_size, idx, &pat ) != b_ok)
1965                {
1966                        BDBG_WRN(("TS_PAT_validate failed 0x%04x\n",pat.PID));
1967                        return eCHM_ERR_FAILED;
1968                }
1969                p_chm->pmt_cnt++;
1970
1971                if (pat.program_number == 0 )
1972                {
1973                        *network_PID = pat.PID;
1974                        /* Send message to app */
1975                        p_chm->chm_network_evt.type = eCHM_EVT_NETWORK;
1976                        p_chm->chm_network_evt.id = *network_PID;
1977                        chm_post_app_event(p_chm,&p_chm->chm_network_evt);
1978                }
1979        }
1980
1981        return result;
1982}
1983/*
1984Summary:
1985        Return the hunt mode progress in percent.
1986 */
1987
1988int chm_get_hunt_progress(chm_mgr_t *p_chm)
1989{
1990        int total;
1991
1992        if (p_chm->num_freq == 0)
1993        {
1994                bapp_freq_table_get(p_chm->fe_type,(const unsigned int **)&(p_chm->freq_table),&(p_chm->num_freq));
1995        }
1996
1997        if (p_chm->num_freq == 0)
1998        {
1999                BDBG_WRN(("%s:%d p_chm->num_freq = %d\n",__FUNCTION__,__LINE__,p_chm->num_freq));
2000                return 0;
2001        }
2002        total = p_chm->num_freq;
2003
2004        if (p_chm->cmd == eCHM_HUNTING)
2005        {
2006                if ((p_chm->hunt_cnt + 1) % 2)
2007                        total *= 2;
2008        }
2009               
2010        return (p_chm->select_idx * 100)/total;
2011
2012}
2013
2014
2015/*
2016Summary:
2017        Scan for channels to create a channel map.
2018Description:
2019        Scan for all available channels.
2020*/
2021
2022static void chm_scan(chm_mgr_t *p_chm           /* Channel manager reference */
2023                                        )
2024{
2025        unsigned int freq;
2026        int num;
2027
2028        bapp_freq_table_get(p_chm->fe_type,(const unsigned int **)&(p_chm->freq_table),&(p_chm->num_freq));
2029
2030        for (p_chm->select_idx = 0; p_chm->select_idx <  p_chm->num_freq; p_chm->select_idx++)
2031        {
2032                freq = (unsigned int)(p_chm->freq_table[p_chm->select_idx]);
2033                freq *= 1000; /* convert to Hz */
2034                BDBG_WRN(("Scan[%d] freq = %d\n",p_chm->select_idx,freq));
2035
2036                /* Check to see if scan was canceled */
2037                if (chm_check_cancel(p_chm))
2038                        break;
2039
2040                /* output progress event id will be % done */
2041                p_chm->chm_pat_evt.type = eCHM_EVT_STATUS;
2042                p_chm->chm_pat_evt.id = eCHM_STATUS_NOPAT;
2043                p_chm->chm_pat_evt.ticks = (unsigned int)(((p_chm->select_idx+1)*100)/p_chm->num_freq);
2044                chm_post_app_event(p_chm,&p_chm->chm_pat_evt);
2045                /* Try tuning */
2046
2047                btuner_params_init(&p_chm->tuner_params, p_chm->tuner);
2048                p_chm->tuner_params.cancel_callback = chm_tune_cancel_callback;
2049                p_chm->tuner_params.cancel_callback_context = p_chm;
2050                p_chm->tuner_params.wait_for_lock = true;
2051                p_chm->tuner_params.fecMode = eFEC_ANNEX_B;
2052                p_chm->tuner_params.qamMode = eQAM_Scan;
2053
2054                if (btuner_tune(p_chm->tuner, freq, &p_chm->tuner_params) < 0)
2055                {
2056                        BDBG_WRN(("FREQ[%d] freq = %d not locked, try next freq\n",p_chm->select_idx,freq));
2057                        chm_send_status(p_chm,freq,false);
2058                        continue;
2059                } else
2060                {
2061                        BDBG_WRN(("btuner_tune_xxx[%d] freq = %d, success\n",p_chm->select_idx,freq));
2062                        chm_send_status(p_chm,freq,true);
2063                }
2064
2065                p_chm->band = TUNER_BAND;
2066        if ((num = chm_scan_psi(p_chm,p_chm->band,p_chm->select_idx)) <= 0)
2067                {
2068                        BDBG_WRN(("chm_scan_psi found no channels\n"));
2069                } else
2070                {
2071                        BDBG_MSG(("PSI channels %d \n", num));
2072                }
2073        }
2074}
2075
2076#ifdef CONFIG_DVB
2077static int chm_scan_dvb_sdt(chm_mgr_t *p_chm, bband_t band, int freq_idx)
2078{
2079        unsigned short num_vch, num_st;
2080        unsigned char num_freq;
2081        unsigned int timeout;
2082
2083        bool done = false;
2084        timeout = bos_getticks() + MS_TO_TICKS(HUNT_TIMEOUT);
2085
2086        chm_dvb_nit_start(p_chm, band);
2087        do {
2088                if (chm_check_cancel(p_chm))
2089                        break;
2090                if (dvb_nit_complete())
2091                        done = true;
2092                else
2093                        done = (timeout<bos_getticks());
2094                bos_sleep(1);
2095        } while (!done);
2096
2097        chm_dvb_nit_stop(p_chm);
2098        ch_map_get_counts(&p_chm->ch_map, &num_vch, &num_st, &num_freq);
2099        if (!num_freq) {
2100                BDBG_WRN(("no frequency is delivered..."));
2101                return 0;
2102        }
2103
2104        chm_dvb_sdt_start(p_chm, band);
2105        do {
2106                if (chm_check_cancel(p_chm)) 
2107                        break;
2108                if (dvb_nit_complete() && dvb_sdt_complete(num_freq))
2109                        done = true;
2110                else 
2111                        done = (timeout<bos_getticks());
2112                bos_sleep(1);
2113        } while (!done);
2114
2115        /* TODO:: the case all SDTs for every stream id are not delivered within timeout */
2116        chm_dvb_sdt_stop(p_chm);
2117        ch_map_get_counts(&p_chm->ch_map, &num_vch, &num_st, &num_freq);
2118        BDBG_WRN(("DVB scan completed... %d:", num_vch));
2119
2120        if (num_vch) {
2121                chm_cache_pids(p_chm);
2122        }
2123        return (timeout < bos_getticks())?eCHM_ERR_TIMEOUT:num_vch;     
2124}
2125
2126static void chm_scan_dvb(chm_mgr_t *p_chm)
2127{
2128        unsigned int freq;
2129        int num;
2130        uint16_t network_pid;
2131
2132        bapp_freq_table_get(p_chm->fe_type, (const unsigned int **)&(p_chm->freq_table), &(p_chm->num_freq));
2133        for (p_chm->select_idx = 0; p_chm->select_idx < p_chm->num_freq; p_chm->select_idx++)
2134        {
2135                freq = (unsigned int)(p_chm->freq_table[p_chm->select_idx]);
2136                freq *= 1000;
2137                BDBG_WRN(("Scan[%d] freq = %d", p_chm->select_idx, freq));
2138                if (chm_check_cancel(p_chm))
2139                        break;
2140
2141                btuner_params_init(&p_chm->tuner_params, p_chm->tuner);
2142                p_chm->tuner_params.cancel_callback = chm_tune_cancel_callback;
2143                p_chm->tuner_params.cancel_callback_context = p_chm;
2144                p_chm->tuner_params.wait_for_lock = true;
2145                p_chm->tuner_params.fecMode = eFEC_ANNEX_B;
2146                p_chm->tuner_params.qamMode = eQAM_Scan;
2147       
2148                if (btuner_tune(p_chm->tuner, freq, &p_chm->tuner_params)<0)
2149                {
2150                        BDBG_WRN(("FREQ[%d] freq=%d not locked, try next freq", p_chm->select_idx, freq));
2151                        chm_send_status(p_chm,freq,false);
2152                }
2153                else {
2154                        BDBG_WRN(("btuner_tune [%x] freq = %d, success", p_chm->select_idx, freq));
2155                        chm_send_status(p_chm,freq,true);
2156                }
2157
2158                p_chm->band = TUNER_BAND;
2159                if (chm_scan_network(p_chm, p_chm->band, &network_pid) != eCHM_ERR_OK) 
2160                {
2161                        BDBG_WRN(("chm_scan_network = no network PID found, use default"));
2162                }
2163                if (network_pid != 0x10) {
2164                        BDBG_WRN(("invalid network PID for DVB"));
2165                        continue;
2166                }
2167
2168                p_chm->chm_network_evt.type = eCHM_EVT_NETWORK;
2169                p_chm->chm_network_evt.id = network_pid;
2170                chm_post_app_event(p_chm, &p_chm->chm_network_evt);
2171
2172                if ((num=chm_scan_dvb_sdt(p_chm,p_chm->band,p_chm->select_idx))<=0)
2173                {
2174                        BDBG_WRN(("chm_scan_psi found no channels"));
2175                } else {
2176                        /* TODO:: check multi-frequency which deliver either NIT or SDT */
2177                        BDBG_WRN(("PSI channels %d", num));
2178                }
2179        }
2180}
2181#endif
2182
2183/*
2184Summary:
2185        Scan for channels using SCTE 65.
2186Description:
2187        Scan for channels SCTE 65.
2188        Returns number of channels added.
2189*/
2190static int chm_scan_scte65(chm_mgr_t *p_chm,            /* Channel manager reference */
2191                                                   bband_t band, 
2192                                                   unsigned short network_PID
2193                                                  )
2194{
2195        unsigned short num_vch, num_st;
2196        unsigned char num_freq ;
2197        unsigned int timeout;
2198        bool done = false;
2199        timeout = bos_getticks() + MS_TO_TICKS(HUNT_TIMEOUT);
2200        BDBG_MSG(("%s Network PID = 0x%04x\n",__FUNCTION__,network_PID));
2201
2202        /* scan for SCTE 65 tables */
2203        if (chm_nit_start(p_chm,network_PID) != eCHM_ERR_OK)
2204                return eCHM_ERR_FAILED;
2205        if (p_chm->cmd != eCHM_HUNTING)
2206        {
2207                if (chm_svct_start(p_chm,network_PID) != eCHM_ERR_OK)
2208                        return eCHM_ERR_FAILED;
2209                if (chm_ntt_start(p_chm,network_PID) != eCHM_ERR_OK)
2210                        return eCHM_ERR_FAILED;
2211        }
2212
2213        do
2214        {
2215                /* Check to see if scan was canceled */
2216                if (chm_check_cancel(p_chm))
2217                        break;
2218
2219                ch_map_get_counts(&p_chm->ch_map,&num_vch,&num_st,&num_freq);
2220
2221                /* When in hunt mode only get require CDS then transition into pending init mode */
2222                if (p_chm->cmd == eCHM_HUNTING)
2223                {
2224                        if (SI_NIT_CDS_Complete() && SI_NIT_MMS_Complete())
2225                                done = true;
2226                        else
2227                                done  = (timeout < bos_getticks());
2228                } else
2229                {
2230                        /* In Pending Init mode both CDS and VCH are required to exit. */
2231                        if (p_chm->cds_changed && p_chm->mms_changed && p_chm->vcm_changed && p_chm->sns_changed)
2232                                done = true;
2233                        else
2234                                done  = (timeout < bos_getticks()) && (num_freq > 0) && (num_vch > 0);
2235                }
2236
2237                if (chm_check_cancel(p_chm))
2238                {
2239                        return eCHM_ERR_CANCELED;
2240                }
2241                bos_sleep(CHM_IDLE_TIMEOUT);
2242        }while (!done);
2243
2244        chm_nit_stop(p_chm);
2245        if (p_chm->cmd != eCHM_HUNTING)
2246        {
2247                chm_svct_stop(p_chm);
2248                chm_ntt_stop(p_chm);
2249        }
2250
2251        ch_map_get_counts(&p_chm->ch_map,&num_vch,&num_st,&num_freq);
2252        BDBG_MSG(("%s num_vch = %d,num_st = %d,num_freq = %d \n",__FUNCTION__,num_vch,num_st,num_freq));
2253        return(timeout < bos_getticks()) ? eCHM_ERR_TIMEOUT : num_vch;
2254
2255}
2256
2257/*
2258Summary:
2259process the MMS string and associated tables.
2260Returns non-zero on failure.
2261 */
2262
2263int chm_process_mss(chm_mgr_t *p_chm,                           /* Channel manager reference */
2264                                        PSIP_MSS_string p_mms,                  /* Pointer to MMS */
2265                                        unsigned char* mms_buf,                 /* string buffer */
2266                                        unsigned int mms_len                    /* string buffer length */
2267                                   )
2268{
2269        int str_idx,lsize;
2270        char *p_code;
2271        BERR_Code retcode;
2272        int num_str;
2273        bapp_t *p_app;
2274
2275        if (!p_mms)
2276                return eCHM_ERR_FAILED;
2277
2278        num_str = PSIP_MSS_getNumStrings(p_mms);
2279        p_app = (bapp_t*)p_chm->p_app;
2280        memset(mms_buf,0,mms_len);
2281
2282        for (str_idx = 0; str_idx < num_str; ++str_idx)
2283        {
2284                if ((retcode = PSIP_MSS_getCode(p_mms,str_idx, &p_code)) != BERR_SUCCESS)
2285                {
2286                        BDBG_WRN(("PSIP_MSS_getCode:%d failed %d\n",__LINE__,retcode));
2287                        memset(mms_buf,0,mms_len);
2288                        continue;
2289                }
2290
2291                lsize = mms_len;
2292                if (chm_valid_lang(p_chm,p_code) != (int)p_app->lang)
2293                {
2294#ifdef BDBG_DEBUG_BUILD
2295                        if ((retcode = PSIP_MSS_getString(p_mms,str_idx,&lsize, (char*)mms_buf)) != BERR_SUCCESS)
2296                        {
2297                                BDBG_WRN(("PSIP_MSS_getCode:%d failed %d\n",__LINE__,retcode));
2298                        }
2299
2300                        if (lsize > 0)
2301                        {
2302                                BDBG_MSG(("Lang mismatch %c%c%c %s\n",p_code[0],p_code[1],p_code[2],mms_buf));
2303                        }
2304                        memset(mms_buf,0,mms_len);
2305#endif
2306                        continue;
2307                }
2308
2309
2310                if ((retcode = PSIP_MSS_getString(p_mms,str_idx,&lsize, (char*)mms_buf)) != BERR_SUCCESS)
2311                {
2312                        BDBG_ERR(("MSS invalid %d\n",retcode));
2313                        memset(mms_buf,0,mms_len);
2314                }
2315
2316                BDBG_MSG(("%s:%d idx = %d, %d/%d-%s\n",__FUNCTION__,__LINE__,str_idx,lsize,mms_len,mms_buf));
2317
2318                return 0;
2319        }
2320
2321        /* in case no valid language exists just use first string */
2322        if (num_str > 0)
2323        {
2324                lsize = mms_len;
2325                if ((retcode = PSIP_MSS_getString(p_mms,0,&lsize, (char*)mms_buf)) == BERR_SUCCESS)
2326                {
2327                        BDBG_WRN(("No language match using default\n"));
2328                        return eCHM_ERR_OK;
2329                } else
2330                {
2331                        BDBG_WRN(("PSIP_MSS_getString failed %d\n",retcode));
2332                }
2333
2334        }
2335        BDBG_WRN(("%s:%d no valid string found, num_str = %d\n",__FUNCTION__,__LINE__,num_str));
2336        return eCHM_ERR_FAILED;
2337}
2338
2339/*
2340Summary:
2341Hunt for an SCTE65 Channel on the given frequency.
2342 */
2343
2344static bool chm_hunt_channel(chm_mgr_t *p_chm, 
2345                                                         unsigned int freq_hz, 
2346                                                         unsigned short *network_pid)
2347{
2348        unsigned short num_vch; 
2349        unsigned short num_st;
2350        unsigned char num_freq; 
2351        int num;
2352        bapp_t *p_app = (bapp_t*)p_chm->p_app;
2353        bapp_freq_table_get(p_chm->fe_type,(const unsigned int **)&(p_chm->freq_table),&(p_chm->num_freq));
2354
2355
2356        btuner_params_init(&p_chm->tuner_params, p_chm->tuner);
2357        p_chm->tuner_params.cancel_callback = chm_tune_cancel_callback;
2358        p_chm->tuner_params.cancel_callback_context = p_chm;
2359        p_chm->tuner_params.wait_for_lock = true;
2360        p_chm->tuner_params.fecMode = eFEC_ANNEX_B;
2361        p_chm->tuner_params.qamMode = eQAM_Scan;
2362        if (btuner_tune(p_chm->tuner, freq_hz, &p_chm->tuner_params) < 0)
2363        {
2364                BDBG_WRN(("FREQ[%d] freq = %d not locked, try next freq\n",p_chm->select_idx,freq_hz));
2365                /* Send message to app */
2366                chm_send_status(p_chm,freq_hz,false);
2367                return false;
2368        } else
2369        {
2370                BDBG_WRN(("btuner_tune_[%d] freq = %d, success\n",p_chm->select_idx,freq_hz));
2371                chm_send_status(p_chm,freq_hz,true);
2372        }
2373
2374        p_chm->band = TUNER_BAND;
2375
2376        if (chm_scan_cat(p_chm,p_chm->band,freq_hz) != eCHM_ERR_OK)
2377        {
2378                BDBG_WRN(("chm_scan_cat - No valid EMM PID found\n"));
2379#ifdef CONFIG_REQUIRE_CAT
2380                return false;
2381#endif
2382        }
2383
2384        if (chm_scan_network(p_chm,p_chm->band,network_pid) != eCHM_ERR_OK)
2385        {
2386                BDBG_WRN(("chm_scan_network - No network PID found, use default\n"));
2387        }
2388
2389        p_chm->chm_network_evt.type = eCHM_EVT_NETWORK;
2390        p_chm->chm_network_evt.id = *network_pid;
2391        chm_post_app_event(p_chm,&p_chm->chm_network_evt);
2392
2393        chm_emm_start( p_chm, p_app->settings.EMM_PID );
2394        chm_stt_start(p_chm,*network_pid);
2395
2396        if ((num = chm_scan_scte65(p_chm,p_chm->band,*network_pid)) <= 0)
2397        {
2398                BDBG_WRN(("chm_scan_scte65 no virtual channels\n"));
2399        } else
2400        {
2401                BDBG_MSG(("chm_scan_scte65 found %d \n", num));
2402        }
2403
2404        chm_stt_stop(p_chm);
2405        chm_emm_stop(p_chm);
2406
2407        ch_map_get_counts(&p_chm->ch_map,&num_vch,&num_st,&num_freq);
2408
2409        return(num_freq > 0);
2410}
2411/*
2412Summary:
2413Process pending initialization state.
2414 */
2415
2416static void chm_pending_init(chm_mgr_t *p_chm           /* Channel manager reference */
2417                                                        )
2418{
2419        unsigned short network_pid,vct_id;
2420        bapp_t *p_app = (bapp_t*)p_chm->p_app;
2421        ch_map_t *p_ch_map = bapp_cur_ch_map(p_app);
2422        unsigned int timeout;
2423
2424        if (p_app->settings.activated && (p_app->settings.timeout_cnt > 0) && (p_ch_map->vch_map.num_vch > 0))
2425        {
2426                p_chm->cmd = eCHM_CANCEL;
2427                p_chm->chmap_evt.type = eCHM_EVT_STATUS;
2428                p_chm->chmap_evt.id = eCHM_STATUS_CHMAP;
2429                BDBG_WRN(("%s - Activated and has a map\n",__FUNCTION__));
2430                p_chm->chmap_evt.ticks = 0;
2431                chm_post_app_event(p_chm,&p_chm->chmap_evt);
2432                return;
2433        }
2434
2435        p_chm->chm_pending_evt.type = eCHM_EVT_STATUS;
2436        p_chm->chm_pending_evt.id = eCHM_STATUS_PENDING_INIT;
2437        chm_post_app_event(p_chm,&p_chm->chm_pending_evt);
2438
2439        if (chm_scan_network(p_chm,p_chm->band,&network_pid) != eCHM_ERR_OK)
2440        {
2441                BDBG_WRN(("chm_scan_network - No network PID found, use default\n"));
2442        }
2443
2444        chm_cvt_start(p_chm,network_pid);
2445        chm_stt_start(p_chm,network_pid);
2446
2447        /* scan for VCH if none exists */
2448        vct_id = p_app->settings.VCT_ID;
2449        if (p_chm->ch_map.vch_map.num_vch == 0)
2450        {
2451                if (chm_svct_start(p_chm,network_pid) != eCHM_ERR_OK)
2452                {
2453                        p_chm->cmd = eCHM_CANCEL;
2454                        return;
2455                }
2456                if (chm_ntt_start(p_chm,network_pid) != eCHM_ERR_OK)
2457                {
2458                        p_chm->cmd = eCHM_CANCEL;
2459                        return;
2460                }
2461        }
2462
2463        chm_emm_start(p_chm,p_app->settings.EMM_PID);
2464
2465        timeout = bos_getticks() + MS_TO_TICKS(SVCT_TIMEOUT);
2466
2467        /* For testing ### REMOVE */
2468#if 1
2469#warning "FOR TEST PURPOSES ONLY:  Activate and set default timeout count to 8"
2470        p_app->settings.activated = 1;
2471        p_app->settings.timeout_cnt = 8;
2472#endif
2473        while ((p_chm->ch_map.vch_map.num_vch == 0) || (timeout > bos_getticks()) || !p_app->settings.activated)
2474        {
2475                if (p_chm->cds_changed && p_chm->mms_changed && p_chm->vcm_changed && p_chm->sns_changed)
2476                {
2477                        BDBG_MSG(("%s - Full channel map received\n",__FUNCTION__));
2478
2479                        // if we are not expecting a config message and activated, break out of the while loop.
2480                        if (p_app->settings.activated)
2481                        {
2482                                BDBG_WRN(("Full Channel Map Received and Activated!\n" ));
2483                                bos_sleep(CHM_IDLE_TIMEOUT);
2484                                break;
2485                        }
2486                }
2487
2488                /* Check to see if scan was canceled */
2489                if (chm_check_cancel(p_chm))
2490                {
2491                        /* leave pending state */
2492                        p_chm->cmd = eCHM_CANCEL;
2493                        break;
2494                }
2495
2496                /* Check to see if configuration message was received.  If so restart svct. */
2497                if (vct_id != p_app->settings.VCT_ID)
2498                {
2499                        vct_id = p_app->settings.VCT_ID;
2500                        BDBG_WRN(("configuration message was received while pending, get SVCT with VCTID = 0x%04x!\n",vct_id));
2501                        timeout = bos_getticks() + MS_TO_TICKS(SVCT_TIMEOUT);
2502                        if (chm_svct_start(p_chm,network_pid) != eCHM_ERR_OK)
2503                        {
2504                                p_chm->cmd = eCHM_CANCEL;
2505                                return;
2506                        }
2507                }
2508                bos_sleep(CHM_IDLE_TIMEOUT);
2509        }
2510        if (chm_check_cancel(p_chm))
2511        {
2512                /* leave scan state */
2513                p_chm->cmd = eCHM_CANCEL;
2514                return;
2515        }
2516        chm_cache_pids(p_chm);
2517
2518        p_chm->chmap_evt.ticks = ch_map_cmp(&(p_chm->ch_map),&(p_app->settings.ch_map));
2519        if (p_chm->chmap_evt.ticks)
2520        {
2521                /* copy channel map so application can perform update without risk of modification by channel manager */
2522                p_chm->chmap_evt.type = eCHM_EVT_STATUS;
2523                p_chm->chmap_evt.id = eCHM_STATUS_CHMAP;
2524                BDBG_WRN(("%s - Activated and New Channel Map\n",__FUNCTION__));
2525                chm_post_app_event(p_chm,&p_chm->chmap_evt);
2526                bos_sleep(200);
2527        }
2528        chm_ntt_stop(p_chm);
2529        chm_svct_stop(p_chm);
2530        chm_stt_stop(p_chm);
2531
2532        chm_cvt_stop(p_chm);
2533        chm_emm_stop(p_chm);
2534
2535        if (chm_check_cancel(p_chm))
2536        {
2537                /* leave scan state */
2538                p_chm->cmd = eCHM_CANCEL;
2539                return;
2540        }
2541
2542        /* Force transition into normal mode */
2543        if (!p_chm->chmap_evt.ticks)
2544        {
2545                p_chm->chmap_evt.type = eCHM_EVT_STATUS;
2546                p_chm->chmap_evt.id = eCHM_STATUS_CHMAP;
2547                p_chm->chmap_evt.ticks = 0x0;
2548                BDBG_WRN(("%s - Send empty map event \n",__FUNCTION__));
2549
2550                chm_post_app_event(p_chm,&p_chm->chmap_evt);
2551        }
2552        p_chm->cmd = eCHM_CANCEL;
2553
2554}
2555/*
2556Summary:
2557Hunt for an SCTE65 Channel Map.
2558Description:
2559Scan for all available channels.
2560 */
2561
2562static void chm_hunt(chm_mgr_t *p_chm           /* Channel manager reference */
2563                                        )
2564{
2565        unsigned int freq;
2566        unsigned short network_pid;
2567        bapp_t *p_app = (bapp_t*)p_chm->p_app;
2568
2569        // reset last frequency to force tune first channel change after getting a new map
2570        p_chm->last_freq_hz = 0;
2571
2572        p_chm->chm_hunt_evt.type = eCHM_EVT_STATUS;
2573        p_chm->chm_hunt_evt.id = eCHM_STATUS_HUNT;
2574        chm_post_app_event(p_chm,&p_chm->chm_hunt_evt);
2575
2576        chm_stop_decode(p_chm);
2577        /* stop all streams */
2578        chm_stop_stream(p_chm,&(p_chm->chm_stream[CURR_CH]));
2579        chm_stop_stream(p_chm,&(p_chm->chm_stream[PREV_CH]));
2580        chm_stop_stream(p_chm,&(p_chm->chm_stream[NEXT_CH]));
2581
2582        /* Completely reset and start over */
2583        ch_map_reset(&(p_chm->ch_map));
2584#ifdef CONFIG_DVB
2585        dvb_nit_init(&p_chm->dvb_nit_cb);
2586        dvb_sdt_init(&p_chm->dvb_sdt_cb);
2587        dvb_eit_init();
2588        dvb_tdt_init();
2589#endif
2590        /* Add streamer channel */
2591        if (p_app->settings.psi_scan)
2592        {
2593#ifdef CONFIG_DVB
2594                BDBG_WRN(("%s - PSI Scan Channel Map for DVB\n",__FUNCTION__));
2595                if (p_app->settings.dvb_scan)
2596                        chm_scan_dvb(p_chm);
2597                else
2598                        chm_scan(p_chm);
2599#else
2600                BDBG_WRN(("%s - PSI Scan Channel Map\n",__FUNCTION__));
2601                /* Fallback to simple SI scan */
2602                chm_scan(p_chm);
2603#endif
2604                p_chm->chmap_evt.type = eCHM_EVT_STATUS;
2605                p_chm->chmap_evt.id = eCHM_STATUS_CHMAP;
2606                p_chm->chmap_evt.ticks = 0xF;
2607                /* copy channel map so application can perform update without risk of modification by channel manager */
2608                chm_post_app_event(p_chm,&p_chm->chmap_evt);
2609                BDBG_WRN(("%s - PSI Scan Channel Map\n",__FUNCTION__));
2610                bos_sleep(200);
2611                /* leave scan state */
2612                p_chm->cmd = eCHM_CANCEL;
2613                return;
2614        }
2615
2616        /* Check "turn on QAM" */
2617        if (p_app->settings.turn_on_freq_khz != 0)
2618        {
2619                if (!chm_hunt_channel(p_chm,p_app->settings.turn_on_freq_khz * 1000,&network_pid))
2620                {
2621                        BDBG_WRN(("Turn on QAM tune failed %d KHz.\n",p_app->settings.turn_on_freq_khz));
2622                        p_app->settings.turn_on_freq_khz = 0;
2623                        p_app->settings_dirty |= DIRTY_MISC;
2624                } else
2625                {
2626                        BDBG_WRN(("Turn on QAM tune %d KHz. OK\n",p_app->settings.turn_on_freq_khz));
2627
2628                        /* leave scan state */
2629                        p_chm->cmd = eCHM_PENDING_INIT;
2630                        p_chm->select_idx = p_chm->num_freq;
2631                        return;
2632                }
2633        }
2634
2635        /* check for SCTE-65 data */
2636        for (p_chm->select_idx = 0; p_chm->select_idx <  p_chm->num_freq; p_chm->select_idx++)
2637        {
2638                freq = (unsigned int)p_chm->freq_table[p_chm->select_idx];
2639                freq *= 1000; /* convert to Hz */
2640                BDBG_WRN(("Hunt[%d of %d] freq = %d\n",p_chm->select_idx,p_chm->num_freq,freq));
2641
2642                /* Check to see if scan was canceled */
2643                if (chm_check_cancel(p_chm))
2644                {
2645                        /* leave scan state */
2646                        p_chm->cmd = eCHM_CANCEL;
2647                        return;
2648                }
2649
2650                if (!chm_hunt_channel(p_chm,freq,&network_pid))
2651                {
2652                        BDBG_WRN(("Hunt failed %d Hz.\n",freq));
2653                } else
2654                {
2655                        BDBG_WRN(("Set turn on QAM to %d Hz. OK\n",freq));
2656                        p_app->settings.turn_on_freq_khz = freq/1000;
2657                        p_app->settings_dirty |= DIRTY_MISC;
2658
2659                        /* leave scan state */
2660                        p_chm->cmd = eCHM_PENDING_INIT;
2661                        p_chm->select_idx = p_chm->num_freq;
2662                        break;
2663                }
2664        }
2665        p_chm->hunt_cnt++;
2666}
2667
2668
2669/*
2670Summary:
2671Update the program pids associated with the freq_idx.
2672Assumes that the channel manager channel map semaphore is already acquired.
2673Returns chm error codes.
2674 */
2675
2676static int chm_update_programs(chm_mgr_t *p_chm,                /* Channel manager reference */
2677                                                           int freq_idx                                   /* frequency index */
2678                                                          )
2679{
2680        unsigned int section_size, pmt_section_size;
2681        TS_PMT_stream pmt;
2682        TS_PAT_program pat;
2683        int result = 0;
2684        int idx,p_idx;
2685        vch_t vch;
2686        TS_PSI_descriptor psi_desc,lang_desc;
2687        int strm_idx,vch_idx,desc_idx;
2688        bapp_t *p_app = (bapp_t*)p_chm->p_app;
2689#ifdef CONFIG_DVB_SUBTITLE
2690        unsigned char dsub_lang[MAX_DSUB_PIDS][3];
2691        unsigned short dsub_page[MAX_DSUB_PIDS];
2692        unsigned char dsub_cnt, i;
2693#endif
2694        smessage_stream_params_init(&p_chm->msg_params, NULL);
2695        p_chm->msg_params.band = p_chm->band;
2696        p_chm->msg_params.pid = (unsigned short)0;      /* PAT */
2697        section_size = PAT_BUF_LEN;
2698        memset(&vch,0,sizeof(vch));
2699
2700        if ((result = chm_getmessage(p_chm,p_chm->pat_buf,&section_size, PAT_TIMEOUT)) != 0)
2701        {
2702                BDBG_WRN(("%s(%d): Error getting PAT 0x%04x = %d\n",__FUNCTION__,__LINE__,p_chm->vch.program_num, result));
2703                return eCHM_ERR_NO_PAT;
2704        }
2705
2706        if (TS_PAT_validate(p_chm->pat_buf, section_size) != true)
2707        {
2708                BDBG_WRN(("TS_PAT_validate failed\n"));
2709                return eCHM_ERR_NO_PAT;
2710        }
2711
2712
2713        if (TS_PAT_getNumPrograms(p_chm->pat_buf) == 0)
2714        {
2715                BDBG_WRN(("TS_PAT_getNumPrograms = 0\n"));
2716                return eCHM_ERR_NO_PAT;
2717        }
2718
2719        BDBG_WRN(("TS_PAT_getNumPrograms %d\n",TS_PAT_getNumPrograms(p_chm->pat_buf)));
2720
2721        for (vch_idx = 0; vch_idx < p_chm->ch_map.vch_map.num_vch; vch_idx++)
2722        {
2723                /* Only process entries which match the current frequency index */
2724                if (p_chm->ch_map.vch_map.vch[vch_idx].freq_idx != freq_idx)
2725                        continue;
2726
2727                /* copy current vch */
2728                vch = p_chm->ch_map.vch_map.vch[vch_idx];
2729
2730                /* Process the PAT to find the correct program to update */
2731                for (idx = 0; idx < TS_PAT_getNumPrograms(p_chm->pat_buf); idx++)
2732                {
2733                        if (TS_PAT_getProgram( p_chm->pat_buf, section_size, idx, &pat ) != b_ok)
2734                        {
2735                                BDBG_WRN(("TS_PAT_getProgram(%d,0x%04x)\n", idx,pat.PID));
2736                                return eCHM_ERR_NO_PAT;
2737                        }
2738
2739                        if (pat.program_number != vch.program_num)
2740                        {
2741                                BDBG_MSG(("pat.program_number != prog_number (%d != %d)\n", pat.program_number, vch.program_num));
2742                                continue;
2743                        }
2744
2745                        smessage_stream_params_init(&p_chm->msg_params, NULL);
2746                        p_chm->msg_params.band = p_chm->band;
2747                        p_chm->msg_params.pid = (unsigned short)pat.PID;        /* PMT */
2748                        p_chm->msg_params.filter.coef[0] = 0x2;
2749                        p_chm->msg_params.filter.mask[0] = 0x00;
2750                        p_chm->msg_params.filter.excl[0] = 0xff;
2751                        pmt_section_size = PMT_BUF_LEN;
2752                        if ((result = chm_getmessage(p_chm,p_chm->pmt_buf,&pmt_section_size, PMT_TIMEOUT)) != 0)
2753                        {
2754                                BDBG_ERR(("Error getting PMT 0x%04x, prog %d\n",pat.PID,vch.program_num));
2755                                continue;
2756                        }
2757                        p_chm->pmt_crc = chm_section_crc(p_chm->pmt_buf,pmt_section_size);
2758
2759                        vch.num_audio = 0;
2760                        vch.cur_audio = 0;
2761                        vch.pcr_pid = 0;
2762                        vch.video_pid = 0;
2763                        vch.scte127_pid = 0;
2764#ifdef CONFIG_DVB_SUBTITLE
2765                        vch.num_dsub = 0;
2766                        vch.cur_dsub = 0;
2767#endif
2768                        memset(vch.audio_pid,0,sizeof(unsigned short) * MAX_AUDIO_PIDS);
2769                        memset(vch.audio_type,0,sizeof(unsigned char) * MAX_AUDIO_PIDS);
2770                        memset(vch.audio_lang,'_',sizeof(char) * MAX_AUDIO_PIDS * 3);
2771
2772                        vch.pcr_pid = TS_PMT_getPcrPid(p_chm->pmt_buf,pmt_section_size);
2773
2774                        /* Get CA pid */
2775                        desc_idx = 0;
2776                        vch.ca_pid = 0;
2777                        while ((psi_desc = TS_PMT_getDescriptor(p_chm->pmt_buf, pmt_section_size,desc_idx++)) != NULL)
2778                        {
2779                                ca_descriptor ca_desc;
2780
2781                                if (desc_idx > 0xFF)
2782                                {
2783                                        BDBG_ERR(("PMT Desc limit exceeded %d\n",desc_idx));
2784                                        break;
2785                                }
2786                                if (chm_check_cancel(p_chm))
2787                                {
2788                                        return eCHM_ERR_CANCELED;
2789                                }
2790
2791                                if (psi_desc[0] != 9)
2792                                        continue;
2793
2794                                if (ca_parser(psi_desc, pmt_section_size, &ca_desc) == 0)
2795                                        continue;
2796
2797                                if (ca_desc.CA_system_ID == p_app->settings.CA_System_ID)
2798                                {
2799                                        vch.ca_pid = ca_desc.CA_PID;
2800                                        BDBG_MSG(("CA PID = 0x%04x\n",vch.ca_pid));
2801                                        p_app->settings.SCP_operating_mode = 0;
2802                                        if (ca_desc.CA_system_ID == 0x0E11)
2803                                        {
2804                                                /* Send message to app */
2805                                                if ((ca_desc.priv_data[0] == 0x5) && (ca_desc.priv_data[1] == 0x1))
2806                                                        p_app->settings.SCP_operating_mode = ca_desc.priv_data[2];
2807                                        }
2808                                        break;
2809                                }
2810                                else
2811                                {
2812                                        p_chm->system_id_errors++;
2813                                }
2814                        }
2815
2816                        for (p_idx = 0; p_idx < TS_PMT_getNumStreams(p_chm->pmt_buf,pmt_section_size); p_idx++)
2817                        {
2818                                bsettop_av_stream_type_t *stream_type;
2819
2820                                if (TS_PMT_getStream( p_chm->pmt_buf, pmt_section_size, p_idx, &pmt ) != b_ok)
2821                                {
2822                                        BDBG_WRN(("Failure processing PMT %d\n",p_idx));
2823                                        break;
2824                                }
2825
2826                                strm_idx = 0;
2827                                lang_desc = NULL;
2828#ifdef CONFIG_DVB_SUBTITLE
2829                                dsub_cnt = 0;
2830#endif
2831                                /* default is not supported */
2832                                while ((psi_desc = TS_PMT_getStreamDescriptor(p_chm->pmt_buf,pmt_section_size, p_idx,strm_idx)) != NULL)
2833                                {
2834#ifdef CONFIG_DVB_SUBTITLE
2835                                        if (psi_desc[0] == TS_PSI_DT_DVB_Subtitling)
2836                                        {
2837                                                if ((psi_desc[5]<0x10) || (psi_desc[5]>0x23))
2838                                                        continue; /* not DVB subtitle */ 
2839
2840                                                dsub_lang[dsub_cnt][0] = toupper(psi_desc[2]);
2841                                                dsub_lang[dsub_cnt][1] = toupper(psi_desc[3]);
2842                                                dsub_lang[dsub_cnt][2] = toupper(psi_desc[4]);
2843                                                dsub_page[dsub_cnt] = psi_desc[6]<<8|psi_desc[7];
2844                                                dsub_cnt++;
2845                                        }
2846#endif
2847                                        if (psi_desc[0] == TS_PSI_DT_ISO_639_Language) /* 0x0A ISO-639 Language descriptor */
2848                                        {
2849                                                BDBG_MSG(("ISO-639 DESC\n" ));
2850                                                lang_desc = psi_desc;
2851                                                /* if get VBI desc alrady */
2852                                                if (vch.scte127_pid)
2853                                                        break;
2854                                        }
2855                                        if (0 == vch.scte127_pid)
2856                                        {
2857                                                if (TS_PSI_DT_DVB_VBI_Data == psi_desc[0])
2858                                                {
2859                                                        BDBG_MSG(("SCTE 127 supported, pid=0x%04x", pmt.elementary_PID));
2860                                                        vch.scte127_pid = pmt.elementary_PID;
2861                                                        /* if get lang desc alrady */
2862                                                        if (lang_desc)
2863                                                                break;
2864                                                }
2865                                        }
2866                                        strm_idx++;
2867                                        if (strm_idx > 0xFF)
2868                                        {
2869                                                BDBG_ERR(("PMT Stream Desc limit exceeded %d\n",strm_idx));
2870                                                break;
2871                                        }
2872                                        if (chm_check_cancel(p_chm))
2873                                        {
2874                                                return eCHM_ERR_CANCELED;
2875                                        }
2876                                }
2877
2878                                if ((stream_type = bdecode_supported_video(pmt.stream_type)) != NULL)
2879                                {
2880                                        BDBG_MSG(("Video PID[%d] = 0x%04x\n",p_idx,pmt.elementary_PID ));
2881                                        if (!vch.video_pid)
2882                                        {
2883                                                vch.video_pid = pmt.elementary_PID;
2884                                                vch.video_type = stream_type->codec_id;
2885                                        }
2886                                }
2887                                else if ((stream_type = bdecode_supported_audio(pmt.stream_type)) != NULL)
2888                                {
2889                                        BDBG_MSG(("Audio PID[%d] = 0x%04x\n",vch.num_audio,pmt.elementary_PID ));
2890                                        if (!vch.audio_pid[vch.num_audio])
2891                                        {
2892                                        vch.audio_pid[vch.num_audio] = pmt.elementary_PID;
2893                                                vch.audio_type[vch.num_audio] = stream_type->codec_id;
2894                                        if (lang_desc)
2895                                        {
2896                                                vch.audio_lang[vch.num_audio][0] = toupper(lang_desc[2]);
2897                                                vch.audio_lang[vch.num_audio][1] = toupper(lang_desc[3]);
2898                                                vch.audio_lang[vch.num_audio][2] = toupper(lang_desc[4]);
2899                                        }
2900                                        BDBG_MSG(("Audio PID[%d][%c%c%c] = 0x%04x, type=0x%04x\n",p_idx,vch.audio_lang[vch.num_audio][0],
2901                                                          vch.audio_lang[vch.num_audio][1],vch.audio_lang[vch.num_audio][2],pmt.elementary_PID, pmt.stream_type));
2902                                        vch.num_audio++;
2903                                        }
2904                                }
2905#ifdef CONFIG_DVB_SUBTITLE
2906                                else if (pmt.stream_type == PES_PRIVATE_STREAM_TYPE) 
2907                                {
2908                                        dsub_cnt = (dsub_cnt>MAX_DSUB_PIDS)?MAX_DSUB_PIDS:dsub_cnt;
2909
2910                                        for (i=0; i<dsub_cnt; i++) {
2911                                                if (vch.num_dsub >= MAX_DSUB_PIDS) break;
2912                                                BDBG_WRN(("%s: private PID[%d] = 0x%04x page:%d [%c%c%c]", 
2913                                                        __FUNCTION__, vch.num_dsub, pmt.elementary_PID,
2914                                                        dsub_page[i], dsub_lang[i][0], dsub_lang[i][1], dsub_lang[i][2]));
2915                                                vch.dsub_pid[vch.num_dsub] = pmt.elementary_PID;
2916                                                vch.dsub_lang[vch.num_dsub][0] = dsub_lang[i][0];
2917                                                vch.dsub_lang[vch.num_dsub][1] = dsub_lang[i][1];
2918                                                vch.dsub_lang[vch.num_dsub][2] = dsub_lang[i][2];
2919                                                vch.dsub_page[vch.num_dsub] = dsub_page[i];
2920                                                vch.num_dsub++;
2921                                        }
2922                                }
2923#endif
2924                                else
2925                                {
2926                                        BDBG_MSG(("Unsupported stream type[0x%02x]\n", pmt.stream_type));
2927                                }
2928                        } /* for (p_idx = 0; p_idx < TS_PMT_getNumStreams(p_chm->pmt_buf,pmt_section_size); p_idx++) */
2929                        p_chm->ch_map.vch_map.vch[vch_idx] = vch;
2930                        break;
2931                } /* for (idx = 0; idx < TS_PAT_getNumPrograms(p_chm->pat_buf); idx++) */
2932        } /* for (vch_idx = 0; vch_idx < p_chm->ch_map.vch_map.num_vch; vch_idx++) */
2933
2934        return result;
2935}
2936
2937/*
2938Summary:
2939Hunt for an SCTE65 Channel Map.
2940Description:
2941Scan for all available channels.
2942 */
2943
2944static void chm_cache_pids(chm_mgr_t *p_chm             /* Channel manager reference */
2945                                                  )
2946{
2947        int freq_idx,vch_idx,result;
2948        unsigned int freq;
2949        bool found;
2950        bapp_t *p_app = (bapp_t*)p_chm->p_app;
2951
2952        if (bos_acquire_mutex(&(p_chm->ch_map_mutex),45) != b_ok)
2953        {
2954                BDBG_WRN(("%s:%d failed to acquire channel map mutex\n", __FUNCTION__,__LINE__));
2955                return;
2956        }
2957
2958        for (freq_idx = 0; freq_idx < p_chm->ch_map.freq_map.num_freq; ++freq_idx)
2959        {
2960                found = false;
2961                for (vch_idx = 0; vch_idx < p_chm->ch_map.vch_map.num_vch; vch_idx++)
2962                {
2963                        if (p_chm->ch_map.vch_map.vch[vch_idx].freq_idx == p_chm->ch_map.freq_map.freq[freq_idx].idx)
2964                        {
2965                                found = true;
2966                                break;
2967                        }
2968                }
2969                if (!found)
2970                        continue;
2971
2972
2973                freq = (unsigned int)(p_chm->ch_map.freq_map.freq[freq_idx].freq_khz);
2974                freq *= 1000; /* convert to Hz */
2975                BDBG_WRN(("%s cache[%d] freq = %d\n",__FUNCTION__,freq_idx,freq));
2976
2977                /* Check to see if scan was canceled */
2978                if (chm_check_cancel(p_chm))
2979                        break;
2980
2981                /* Try tuning */
2982                btuner_params_init(&p_chm->tuner_params, p_chm->tuner);
2983                p_chm->tuner_params.cancel_callback = chm_tune_cancel_callback;
2984                p_chm->tuner_params.cancel_callback_context = p_chm;
2985                p_chm->tuner_params.wait_for_lock = true;
2986                p_chm->tuner_params.fecMode = eFEC_ANNEX_B;
2987                p_chm->tuner_params.qamMode = eQAM_Scan;
2988
2989                if (btuner_tune(p_chm->tuner, freq, &p_chm->tuner_params) < 0)
2990                {
2991                        BDBG_WRN(("FREQ[%d] freq = %d not locked, try next freq\n",freq_idx,freq));
2992                        chm_send_status(p_chm,freq,false);
2993                        continue;
2994                } else
2995                {
2996                        BDBG_WRN(("btuner_tune_xxx[%d] freq = %d, success\n",freq_idx,freq));
2997                        chm_send_status(p_chm,freq,true);
2998                }
2999
3000                p_chm->band = TUNER_BAND;
3001
3002                if ((result = chm_update_programs(p_chm,p_chm->ch_map.freq_map.freq[freq_idx].idx)) != eCHM_ERR_OK)
3003                {
3004                        BDBG_WRN(("chm_update_programs failed %d\n",result));
3005                        if (result == eCHM_ERR_TIMEOUT)
3006                                break;
3007                        else
3008                                continue;
3009                }
3010        }
3011
3012        if (p_app->settings.turn_on_freq_khz) {
3013                /* Go back to turn on QAM in case the map has channels that don't exist */
3014                freq = (unsigned int)p_app->settings.turn_on_freq_khz * 1000; /* Freq in HZ !!! */
3015                BDBG_WRN(("%s Go to turn on QAM freq %dKHz\n",__FUNCTION__,freq));
3016
3017                /* Try tuning */
3018                btuner_params_init(&p_chm->tuner_params, p_chm->tuner);
3019                p_chm->tuner_params.cancel_callback = chm_tune_cancel_callback;
3020                p_chm->tuner_params.cancel_callback_context = p_chm;
3021                p_chm->tuner_params.wait_for_lock = true;
3022                p_chm->tuner_params.fecMode = eFEC_ANNEX_B;
3023                p_chm->tuner_params.qamMode = eQAM_Scan;
3024                if (btuner_tune(p_chm->tuner, freq, &p_chm->tuner_params) < 0)
3025                {
3026                        BDBG_WRN(("Turn on freq = %dHz not locked, try next freq\n",freq));
3027                        chm_send_status(p_chm,freq,false);
3028                } else
3029                {
3030                        BDBG_WRN(("Turn on freq = %dHz, success\n",freq));
3031                        chm_send_status(p_chm,freq,true);
3032                }
3033        }
3034        bos_release_mutex(&(p_chm->ch_map_mutex));
3035
3036}
3037
3038/*
3039Summary:
3040Post an event the app queue to provide status.
3041 */
3042
3043static int chm_post_app_event_cb(chm_mgr_t *p_chm,              /* Channel manager reference */
3044                                                                 chm_event_t *p_event    /* Event to post to app queue */
3045                                                                )
3046{
3047        bapp_t *p_app = (bapp_t*)p_chm->p_app;
3048        bos_post_event(p_app->msg_queue,(b_event_t*)p_event);
3049
3050        return 0;
3051}
3052
3053/*
3054Summary:
3055Post an event the app queue to provide status.
3056 */
3057
3058static int chm_post_app_event(chm_mgr_t *p_chm,         /* Channel manager reference */
3059                                                          chm_event_t *p_event    /* Event to post to app queue */
3060                                                         )
3061{
3062        int result = chm_post_app_event_cb(p_chm,p_event);
3063
3064        bos_sleep(10);
3065        return result;
3066}
3067
3068#ifdef  HAS_VBI
3069/******************************************************************************
3070 * INPUTS:      context
3071 * OUTPUTS:     none.
3072 * RETURNS:     none
3073 * FUNCTION:    chm_scte_feed_callback
3074 * DESCRIPTION: feed scte 127 data for encoding
3075 ******************************************************************************/
3076static pscte_127_handle s_pscte_127 = NULL;
3077
3078void chm_scte_feed_callback(int field)
3079{
3080        if (s_pscte_127 && scte_127_has_data(s_pscte_127, field))
3081        {
3082                scte_127_feed_data_buf(s_pscte_127, field);
3083        }
3084}
3085
3086/******************************************************************************
3087 * INPUTS:      context
3088 * OUTPUTS:     none.
3089 * RETURNS:     none
3090 * FUNCTION:    message_callback
3091 * DESCRIPTION: Callback function normally called when a complete message has
3092 *              been received and passed the filter criteria.
3093 ******************************************************************************/
3094void * chm_smessage_scte127_callback(void * context, size_t size)
3095{
3096        chm_mgr_t * p_chm = (chm_mgr_t*)context;
3097        bapp_t *p_app;
3098        uint8_t *ptr, *ptr1;
3099        int len;
3100
3101        p_app = (bapp_t*)p_chm->p_app;
3102        //BDBG_MSG(("#### SCTE127 Event (size=%d)####\n", size));
3103
3104        ptr = ptr1 = p_chm->scte127_buf;
3105        if (size != p_chm->scte127_buf_size)
3106        {
3107                if (size % 188)
3108                {
3109                        BDBG_WRN(("Size not match, make adjustment if not multiple of 188"));
3110                        size = (size / 188) * 188;
3111                }
3112        }
3113        for (; size; size -= 188)
3114        {
3115                ptr = pes_parser(ptr, &len);
3116                if (ptr)
3117                {
3118                        /* should be data unit id byte */
3119                        len = (188 - len);
3120                        scte_127_pes_data_field_parser(p_chm->pscte_127, ptr, len);
3121                } else
3122                {
3123                        /* if not private data */
3124                        if (0xff == len)
3125                                break;
3126
3127                        BDBG_WRN(("Invalid SCTE127 packet"));
3128                }
3129                ptr1 += 188;
3130                ptr = ptr1;
3131        }
3132        return(void*)p_chm->scte127_buf;
3133}
3134#endif
3135
3136/******************************************************************************
3137 * INPUTS:      context
3138 * OUTPUTS:     none.
3139 * RETURNS:     none
3140 * FUNCTION:    message_callback
3141 * DESCRIPTION: Callback function normally called when a complete message has
3142 *              been received and passed the filter criteria.
3143 ******************************************************************************/
3144void * chm_smessage_eas_callback(void * context, size_t size)
3145{
3146        TS_SCTE_18_header header;               /* header structure */
3147        chm_mgr_t * p_chm = (chm_mgr_t*)context;
3148        bapp_t *p_app;
3149        unsigned int timegpssec, event_end_time;
3150        unsigned short source_id,exp_source_id;
3151        b_timeval cur;
3152        bool found_sourceid = false;
3153        size_t ex_size,i;
3154        uint8_t *pOffset;
3155
3156        p_app = (bapp_t*)p_chm->p_app;
3157        BDBG_WRN(("#### EAS Event ####\n"));
3158        p_chm->eas_cnt++;
3159
3160        if (!p_app->power)
3161        {
3162                BDBG_WRN(("####EAS Event: DTA in standby state: ignore. #### \n"));
3163                goto ExitFunc;
3164        }
3165
3166        if (TS_SCTE_18_getSectionHeader(p_chm->eas_buf, size, &header) != 0)
3167        {
3168                BDBG_ERR(("#### TS_SCTE_18_getSectionHeader failed ####\n"));
3169                goto ExitFunc;
3170        }
3171
3172        /* for priority == 0, initialize sequence number only per DTA30-DIG-I01-081210 */
3173        if (0 == header.alert_priority)
3174        {
3175                /* establish a new sequence number */
3176                p_chm->sequence_number = header.sequence_number;
3177                goto ExitFunc;
3178        }
3179
3180        if (p_chm->sequence_number == header.sequence_number)
3181        {
3182                BDBG_ERR(("#### EAS Event %d duplicate ####\n",header.sequence_number));
3183                goto ExitFunc;
3184        }
3185        p_chm->sequence_number = header.sequence_number;
3186
3187        if ((int8_t)header.alert_priority < SCTE_18_ALERT_PRIORITY)
3188        {
3189                BDBG_WRN(("#### EAS Event alert priority %d < %d, ignore.#### \n", header.alert_priority, SCTE_18_ALERT_PRIORITY));
3190                goto ExitFunc;
3191        }
3192
3193        if ((int8_t)header.alert_message_time_remaining < 0 || header.alert_message_time_remaining > 120)
3194        {
3195                BDBG_WRN(("#### EAS Event alert_message_time_remaining %d out of range ####\n",header.alert_message_time_remaining));
3196                goto ExitFunc;
3197        }
3198        if (p_chm->EAS_event_ID == header.EAS_event_ID)
3199        {
3200                /* same EAS message, but only time remaining changed */
3201                GETTIMEOFDAY(&cur);
3202                if (header.alert_message_time_remaining)
3203                        p_app->eas_timeout = cur.tv_sec + header.alert_message_time_remaining;
3204                else
3205                        p_app->eas_timeout = 0;
3206
3207                BDBG_MSG(("#### EAS Event %d already processed ####\n",header.EAS_event_ID));
3208                goto ExitFunc;
3209        }
3210        /* new EAS message is distributed */
3211        p_chm->EAS_event_ID = header.EAS_event_ID;
3212
3213        if (header.event_start_time && header.event_duration)
3214        {
3215                /* 15 mins to 100 hours */
3216                if (header.event_duration < 15 || header.event_duration > 600)
3217                {
3218                        BDBG_WRN(("#### EAS Event event_duration %d out of range ####\n",header.event_duration));
3219                        goto ExitFunc;
3220                }
3221                GETTIMEOFDAY(&cur);
3222                timegpssec = p_app->system_time + cur.tv_sec;
3223                event_end_time = header.event_start_time+(header.event_duration * 60);
3224
3225                if (event_end_time < timegpssec)
3226                {
3227                        BDBG_WRN(("#### EAS Event has expired %d < %d, ignore.#### \n", event_end_time, timegpssec));
3228                        goto ExitFunc;
3229                }
3230        }
3231
3232        /* if exception list existed, check to see if current channel is in exception list */
3233        if (header.exception_count)
3234        {
3235                BDBG_WRN(("#### EAS exception count = %d\n",header.exception_count));
3236                pOffset = TS_SCTE_18_getExpectionOffset((const char *)p_chm->eas_buf, &ex_size);
3237                if (pOffset)
3238                {
3239                        vch_t vch;
3240                        st_t st;
3241                        freq_t freq;
3242                        TS_SCTE_18_exception s;
3243
3244                        if (!ch_map_get_current(bapp_cur_ch_map(p_app),&vch,&st,&freq))
3245                        {
3246                                BDBG_WRN(("#### EAS Current channel map invalid.#### \n"));
3247                                goto ExitFunc;
3248                        }
3249                        for (i = 0; i < header.exception_count; i++)
3250                        {
3251                                if (TS_SCTE_18_getException(pOffset, i, &s))
3252                                {
3253                                        BDBG_WRN(("#### EAS exception (%d,0x%04x,0x%04x)\n",s.in_band_reference,s.major_channel_number,s.minor_channel_number));
3254                                        if (s.in_band_reference && ch_map_find_soure_id(bapp_cur_ch_map(p_app),
3255                                                                                                                                        (unsigned char)s.major_channel_number,
3256                                                                                                                                        (unsigned short)s.minor_channel_number,&exp_source_id))
3257                                        {
3258                                                if (exp_source_id == vch.source_id)
3259                                                {
3260                                                        BDBG_WRN(("#### 0x%04x in exception list, discard\n",exp_source_id));
3261                                                        goto ExitFunc;
3262                                                }
3263                                        } else
3264                                        {
3265                                                //use source ID
3266                                                if (s.OOB_source_ID == vch.source_id)
3267                                                {
3268                                                        BDBG_WRN(("#### OOB 0x%04x in exception list, discard\n",exp_source_id));
3269                                                        goto ExitFunc;
3270                                                }
3271                                        }
3272                                } else
3273                                {
3274                                        BDBG_WRN(("#### EAS TS_SCTE_18_getException %d failed\n",i));
3275                                        goto ExitFunc;
3276                                }
3277                        }
3278                }
3279        }
3280
3281        /* try details OOB source ID first */
3282        if (header.details_OOB_source_ID)
3283        {
3284                BDBG_WRN(("#### EAS Attempt to set details source ID = 0x%04x.#### \n", header.details_OOB_source_ID));
3285                source_id = header.details_OOB_source_ID;
3286                found_sourceid = ch_map_set(bapp_cur_ch_map(p_app),source_id);
3287        }
3288        /* if OOB source ID or not in the VCM */
3289        if (!found_sourceid && (header.details_major_channel_number && header.details_minor_channel_number))
3290        {
3291                BDBG_WRN(("#### EAS Attempt to set major.minor [0x%04x.0x%04x] #### \n", header.details_major_channel_number, header.details_minor_channel_number));
3292                if (!ch_map_find_soure_id(bapp_cur_ch_map(p_app),
3293                                                                  (unsigned char)header.details_major_channel_number,
3294                                                                  (unsigned short)header.details_minor_channel_number,
3295                                                                  &source_id))
3296                {
3297                        /* try audio only */
3298                        if (15 == header.alert_priority && header.audio_OOB_source_ID)
3299                        {
3300                                BDBG_WRN(("#### EAS Attempt to set audio source ID = 0x%04x.#### \n", header.audio_OOB_source_ID));
3301                                source_id = header.audio_OOB_source_ID;
3302                                found_sourceid = ch_map_set(bapp_cur_ch_map(p_app),source_id);
3303                        } else
3304                        {
3305                                BDBG_WRN(("#### EAS no details source ID available\n"));
3306                                goto ExitFunc;
3307                        }
3308                } else
3309                        found_sourceid = true;
3310        }
3311
3312        /* Check for Channel Descriptor */
3313        if (!found_sourceid)
3314        {
3315                /* try channel description */
3316                TS_SCTE_18_in_band_channel_descriptor ib_channel_desc;
3317                pOffset = TS_SCTE_18_getDescriptorOffset((const char *)p_chm->eas_buf, &ex_size);
3318
3319                if (pOffset == NULL)
3320                {
3321                        BDBG_WRN(("#### EAS Channel Descriptor not found #### \n"));
3322                        goto ExitFunc;
3323                }
3324
3325                if (!TS_SCTE_18_getInBandChannelDescriptor(pOffset, &ib_channel_desc,ex_size))
3326                {
3327                        BDBG_WRN(("#### EAS Channel Desc not found #### \n"));
3328                        goto ExitFunc;
3329                }
3330                if (!ch_map_find_soure_id(bapp_cur_ch_map(p_app),
3331                                                                  (unsigned char)ib_channel_desc.exception_RF_channel,
3332                                                                  (unsigned short)ib_channel_desc.exception_program_number,
3333                                                                  &source_id))
3334                {
3335                        BDBG_WRN(("#### EAS sourceID not found for ib channel desc [0x%04x.0x%04x] #### \n", ib_channel_desc.exception_RF_channel, ib_channel_desc.exception_program_number));
3336                        goto ExitFunc;
3337                }
3338        }
3339
3340        if ( ((header.location_code_count) < 1) || ((header.location_code_count) > 31) )
3341        {
3342                BDBG_WRN(("#### EAS location code count invalid %d #### \n",header.location_code_count));
3343                goto ExitFunc;
3344        } else
3345        {
3346                pOffset = TS_SCTE_18_getLocationOffset((const char *)p_chm->eas_buf, &size);
3347                if (pOffset)
3348                {
3349                        TS_SCTE_18_location_code s;
3350                        for (i = 0; i < header.location_code_count; i++)
3351                        {
3352                                if (TS_SCTE_18_getLocationCode(pOffset, i, &s))
3353                                {
3354                                        if ( (((int8_t)s.state_code) < 0) || ((s.state_code) > 99) || 
3355                                                 (((int8_t)s.county_subdivision) < 0) || ((s.county_subdivision) > 9) ||
3356                                                 (((int8_t)s.county_code) < 0) || ((s.county_code) > 999) )
3357                                        {
3358                                                BDBG_WRN(("#### EAS state code %d or subdivision %d country_code %d invalid#### \n",s.state_code, s.county_subdivision, s.county_code));
3359                                                goto ExitFunc;
3360                                        }
3361                                } else
3362                                {
3363                                        goto ExitFunc;
3364                                }
3365                        }
3366                } else
3367                {
3368                        goto ExitFunc;
3369                }
3370        }
3371
3372        if (ch_map_set(bapp_cur_ch_map(p_app),source_id))
3373        {
3374                BDBG_WRN(("#### EAS source ID = 0x%04x found (timeout %d secs).#### \n", source_id,header.alert_message_time_remaining));
3375                p_chm->chm_eas_evt.type = eCHM_EVT_EAS;
3376                p_chm->chm_eas_evt.id = (header.alert_message_time_remaining << 16) | source_id;
3377                p_chm->eas_timer_started = true;
3378                memcpy(p_app->eas_buf, p_chm->eas_buf, size);
3379                p_app->eas_buf_size = size;
3380
3381                chm_post_app_event_cb(p_chm,&p_chm->chm_eas_evt);
3382        } else
3383        {
3384                BDBG_ERR(("#### EAS source ID = 0x%04x not found.#### \n", source_id));
3385        }
3386        ExitFunc:
3387        return(void*)p_chm->eas_buf;
3388}
3389/******************************************************************************
3390* INPUTS:      context
3391* OUTPUTS:     none.
3392* RETURNS:     none
3393* FUNCTION:    message_callback
3394* DESCRIPTION: Callback function normally called when a complete message has
3395*              been received and passed the filter criteria.
3396******************************************************************************/
3397#if defined(ENABLE_UMESSAGE)
3398static struct udta_message umessage;
3399static struct udta_subcommand  usubcommand;
3400static struct udta_network_config unetwork_config;
3401static struct udta_descriptor udescriptor;
3402static struct udta_time_zone_descriptor utime_zone_descriptor;
3403static struct udta_eas_location_descriptor ueas_descriptor;
3404static struct udta_site_announcement_subcommand usite;
3405static struct udta_phone_number_descriptor uphone_descriptor;
3406static struct udta_reset_user_processor_subcommand ureset;
3407static struct udta_key_table_subcommand keyt;
3408static struct udta_eas_filter_control_subcommand efc;
3409static struct udta_content_control ccm;
3410static struct udta_scp_amm amm;
3411static struct udta_scp_acm acm;
3412static struct udta_encrypted_global_key egk;
3413static struct udta_soc_type soc_type;
3414
3415void* chm_smessage_emm_callback(void * context, size_t size)
3416{
3417        chm_mgr_t * p_chm = (chm_mgr_t*)context;
3418        unsigned char hw_address[6];
3419        unsigned char singlecast_address[6];
3420        struct udta_subcommand_count cnt;
3421        struct udta_parser_state pst;
3422        uint16_t parsed_len;
3423        int subcmd_count, idx;
3424        bapp_t *p_app;
3425
3426        p_chm->emm_count++;
3427        BDBG_MSG(("#### %s #### \n", __FUNCTION__));
3428
3429        p_app = (bapp_t*)p_chm->p_app;
3430
3431        if (!get_hw_address(hw_address))
3432                return(void*)(p_chm->emm_buf);
3433
3434        memset(&umessage,0,sizeof(umessage));
3435        udta_parser_start(p_chm->emm_buf, &pst);
3436        udta_parse_message(&pst, &umessage);
3437
3438        if (umessage.address_type == 1)
3439        {
3440                unsigned int utc_time;
3441                singlecast_address[0] = umessage.singlecast_address[4];
3442                singlecast_address[1] = umessage.singlecast_address[3];
3443                singlecast_address[2] = umessage.singlecast_address[2];
3444                singlecast_address[3] = umessage.singlecast_address[1];
3445                singlecast_address[4] = umessage.singlecast_address[0];
3446                if (memcmp(singlecast_address,hw_address,5) == 0)
3447                {
3448                        /* valid singlecast message */
3449                        get_utc_time(p_app,&utc_time);
3450                        p_app->settings.addressable_time = utc_time;
3451                } else
3452                {
3453                        return(void*)(p_chm->emm_buf);
3454                }
3455
3456        } else if (umessage.address_type == 0)
3457        {
3458                BDBG_WRN(("Broadcast message:  %d\n",umessage.message_type));
3459        } else {
3460                goto ExitFunc;
3461        }
3462
3463        BDBG_WRN(("EMM message type 0x%02X\n", umessage.message_type));
3464
3465        switch (umessage.message_type)
3466        {
3467        case UDTA_CONTENT_CONTROL:
3468                p_chm->ccm_cnt++;
3469                udta_parse_content_control(&pst, &ccm);
3470                for (idx = 0; idx < ccm.soc_type_count; ++idx)
3471                {
3472                        udta_parse_soc_type(&pst, &soc_type);
3473                        /* TODO put into soc type structure */
3474                }
3475                /* TODO Send to application for storage */
3476                break;
3477        case UDTA_SCP_AMM:
3478                p_chm->amm_cnt++;
3479                udta_parse_scp_amm(&pst, &amm);
3480                /* TODO Send to application for storage */
3481                break;
3482        case UDTA_SCP_ACM_EVEN:
3483                p_chm->acm_even_cnt++;
3484                udta_parse_scp_acm(&pst, &acm);
3485                cmode_acm_handler(0x80, &acm, 0);
3486                break;
3487        case UDTA_SCP_ACM_ODD:
3488                p_chm->acm_odd_cnt++;
3489                udta_parse_scp_acm(&pst, &acm);
3490                cmode_acm_handler(0x80, &acm, 0);
3491                break;
3492        case UDTA_CONFIGURATION_1:
3493        case UDTA_CONFIGURATION_2:
3494                p_chm->cfg_cnt++;
3495                udta_parse_subcommand_count(&pst, &cnt);
3496                subcmd_count = cnt.subcommand_count;
3497                while (subcmd_count--)
3498                {
3499                        udta_parse_subcommand(&pst,&usubcommand);
3500                        BDBG_WRN(("DCT CONFIG Subcommand %d\n",usubcommand.subcommand_id));
3501
3502                        switch (usubcommand.subcommand_id)
3503                        {
3504                        case UDTA_NETWORK_CONFIG:
3505                                udta_parse_network_config(&pst, &unetwork_config);
3506
3507                                if (p_chm->cmd == eCHM_PENDING_INIT)
3508                                {
3509                                        /* since we are alread in pending init mode there is no need to notify application of VCT_ID change. */
3510                                        if (p_app->settings.VCT_ID != unetwork_config.home_vct_id)
3511                                        {
3512                                                BDBG_WRN(("%s:%d Configuration VCT_ID %d does not match current value %d\n",
3513                                                                  __FUNCTION__,__LINE__,unetwork_config.home_vct_id, p_app->settings.VCT_ID));
3514                                                p_chm->ch_map.vch_map.num_vch = 0;
3515                                                p_app->settings.VCT_ID = unetwork_config.home_vct_id;
3516                                                p_app->settings.activated = false;
3517                                        }
3518                                } else
3519                                {
3520                                        p_chm->vct_id_evt.type = eCHM_EVT_VCT_ID;
3521                                        p_chm->vct_id_evt.id = unetwork_config.home_vct_id;
3522                                        chm_post_app_event(p_chm,&p_chm->vct_id_evt);
3523                                }
3524                                BDBG_WRN(("chm_smessage_emm_callback()- DCT Network Configuration Message Received! VctId: %d \n", unetwork_config.home_vct_id ));
3525
3526                                if (p_chm->cmd == eCHM_PENDING_INIT)
3527                                {
3528                                        /* since we are alread in pending init mode there is no need to notify application of VCT_ID change. */
3529                                        p_app->settings.timeout = unetwork_config.site_timeout;
3530                                        p_app->settings.timeout_cnt = unetwork_config.site_timeout;
3531                                        p_app->settings.location = unetwork_config.site_code;
3532                                        p_app->settings.timeout_policy  = unetwork_config.timeout_policy;
3533                                        p_app->settings.max_location_errors = unetwork_config.max_site_errors;
3534
3535                                        if (p_app->settings.VCT_ID != unetwork_config.home_vct_id)
3536                                        {
3537                                                BDBG_WRN(("%s:%d Configuration VCT_ID %d does not match current value %d\n",
3538                                                                  __FUNCTION__,__LINE__,unetwork_config.home_vct_id,p_app->settings.VCT_ID));
3539                                                p_chm->ch_map.vch_map.num_vch = 0;
3540                                                p_app->settings.VCT_ID = unetwork_config.home_vct_id;
3541                                                p_app->settings.activated = false;
3542                                        }
3543                                }
3544                                p_chm->config_evt.type = eCHM_EVT_CONFIGURATION;
3545                                p_chm->config_evt.location = unetwork_config.site_code;
3546                                p_chm->config_evt.timeout = unetwork_config.site_timeout;
3547                                p_chm->config_evt.timeout_policy = unetwork_config.timeout_policy;
3548                                p_chm->config_evt.max_location_errors = unetwork_config.max_site_errors;
3549
3550                                if (p_chm->config_evt.VCT_ID != unetwork_config.home_vct_id)
3551                                {
3552                                        p_chm->refresh_count++;
3553
3554                                        BDBG_WRN(("Changing VCT-ID from 0x%04X to 0x%04X; count = %d\n",
3555                                                          p_chm->config_evt.VCT_ID, unetwork_config.home_vct_id, p_chm->refresh_count));
3556                                }
3557                                p_chm->config_evt.VCT_ID = unetwork_config.home_vct_id;
3558                                chm_post_app_event(p_chm,(chm_event_t*)&p_chm->config_evt);
3559
3560                                parsed_len = pst.bits.bindex >> 3;
3561                                /* if we have more message body parse descriptors */
3562                                while(parsed_len < umessage.message_length){
3563                                        udta_parse_descriptor(&pst, &udescriptor);
3564                                        switch(udescriptor.descriptor_tag){
3565                                        case UDTA_TIME_ZONE_DESCRIPTOR:
3566                                                udta_parse_timezone_descriptor(&pst, &utime_zone_descriptor);
3567                                                p_chm->tz_evt.type = eCHM_EVT_TIMEZONE;
3568                                                p_chm->tz_evt.dst_delta = utime_zone_descriptor.daylight_savings_delta_time;
3569                                                p_chm->tz_evt.dst_entry = utime_zone_descriptor.daylight_savings_entry_time;
3570                                                p_chm->tz_evt.dst_exit = utime_zone_descriptor.daylight_savings_exit_time;
3571                                                p_chm->tz_evt.utc_offset = utime_zone_descriptor.time_zone_offset;
3572                                                chm_post_app_event(p_chm,(chm_event_t*)&p_chm->tz_evt);
3573
3574                                                break;
3575                                        case UDTA_EAS_LOCATION_DESCRIPTOR:
3576                                                udta_parse_eas_location_descriptor(&pst, &ueas_descriptor);
3577                                                break;
3578                                        default:
3579                                                udta_skip_descriptor(&pst, &udescriptor);
3580                                                break;
3581                                        }
3582                                        parsed_len = pst.bits.bindex >> 3;
3583                                }
3584                                break;
3585                        default:
3586                                udta_skip_subcommand(&pst, &usubcommand);
3587                                break;
3588                        }
3589                }
3590                break;
3591
3592        case UDTA_OPERATIONS_1:
3593        case UDTA_OPERATIONS_2:
3594                p_chm->ops_cnt++;
3595                udta_parse_subcommand_count(&pst, &cnt);
3596                subcmd_count = cnt.subcommand_count;
3597                while (subcmd_count--)
3598                {
3599                        udta_parse_subcommand(&pst, &usubcommand);
3600                        BDBG_WRN(("DCT OPP Subcommand %d\n",usubcommand.subcommand_id));
3601                        switch (usubcommand.subcommand_id)
3602                        {
3603                        case UDTA_INITIALIZE:
3604                                BDBG_WRN(("chm_smessage_emm_callback() DCT_INITIALIZE_SCMD \n" ));
3605
3606                                p_chm->reset_evt.type = eCHM_EVT_RESET;
3607                                p_chm->reset_evt.id = 4;
3608                                chm_post_app_event(p_chm,&p_chm->reset_evt);
3609                                break;
3610                        case UDTA_RESET_USER_PROCESSOR:
3611                                BDBG_WRN(("chm_smessage_emm_callback() DCT_RESET_USER_PROCESSOR_SCMD \n" ));
3612                                udta_parse_reset_user_processor_subcommand(&pst, &ureset);
3613                                p_chm->reset_evt.type = eCHM_EVT_RESET;
3614                                p_chm->reset_evt.id = ureset.reset_command;     /* 0,1,2 */
3615                                chm_post_app_event(p_chm,&p_chm->reset_evt);
3616                                break;
3617                        case UDTA_CONNECT:
3618                                if (!p_app->settings.activated)
3619                                {
3620                                        BDBG_WRN(("CONNECT message received - activating\n"));
3621                                }
3622                                p_chm->activate_evt.type = eCHM_EVT_ACTIVATION;
3623                                p_chm->activate_evt.id = 1;     /* activate */
3624                                chm_post_app_event(p_chm,&p_chm->activate_evt);
3625                                break;
3626                        case UDTA_DISCONNECT:
3627                                p_chm->activate_evt.type = eCHM_EVT_ACTIVATION;
3628                                p_chm->activate_evt.id = 0;     /* deactivate */
3629                                chm_post_app_event(p_chm,&p_chm->activate_evt);
3630                                break;
3631                        case UDTA_SITE_ANNOUNCEMENT:
3632                                udta_parse_site_announcement_subcommand(&pst, &usite);
3633                                p_chm->location_evt.type = eCHM_EVT_LOCATION;
3634                                p_chm->location_evt.id = usite.site_code;
3635                                chm_post_app_event(p_chm,&p_chm->location_evt);
3636
3637                                parsed_len = pst.bits.bindex >> 3;
3638                                while(parsed_len < umessage.message_length){
3639                                        udta_parse_descriptor(&pst, &udescriptor);
3640                                        if(UDTA_PHONE_NUMBER_DESCRIPTOR == udescriptor.descriptor_tag){
3641                                                uphone_descriptor.length = udescriptor.descriptor_lenght;
3642                                                udta_parse_phone_number_descriptor(&pst, &uphone_descriptor);
3643                                                uphone_descriptor.phone_number_string[uphone_descriptor.length] = 0; // ensure string terminator
3644                                                strcpy(p_chm->phone_evt.data,uphone_descriptor.phone_number_string);
3645                                        p_chm->phone_evt.type = eCHM_EVT_PHONENUMBER;
3646                                                chm_post_app_event(p_chm,(chm_event_t*)&p_chm->phone_evt);
3647                                        }else{
3648                                                udta_skip_descriptor(&pst, &udescriptor);
3649                                        }
3650                                        parsed_len = pst.bits.bindex >> 3;
3651                                }
3652                                break;
3653                        case UDTA_KEY_TABLE:
3654                                p_chm->key_table_cnt++;
3655                                udta_parse_key_table_subcommand(&pst, &keyt);
3656                                for (idx = 0; idx < keyt.number_of_global_keys; ++idx)
3657                                {
3658                                        udta_parse_encrypted_global_key(&pst, &egk);
3659                                        /* TODO Put into EGK structure */
3660                                }
3661                                /* TODO Send key table to application for storage.  */
3662                                break;
3663                        case UDTA_EAS_FILTER_CONTROL:
3664                                p_chm->eas_filter_cnt++;
3665                                udta_parse_eas_filter_control_subcommand(&pst, &efc);
3666                                /* TODO Send filter control information to application for storage.  */
3667                                break;
3668                        default:
3669                                udta_skip_subcommand(&pst, &usubcommand);
3670                                break;
3671                        }
3672                }
3673                break;
3674        default:
3675                BDBG_WRN(("#### Unsupported MSP Command 0x%02x #### \n", umessage.message_type));
3676                break;
3677        }
3678
3679ExitFunc:
3680        return(void*)(p_chm->emm_buf);
3681}
3682#else
3683void* chm_smessage_emm_callback(void * context, size_t size)
3684{
3685        chm_mgr_t * p_chm = (chm_mgr_t*)context;
3686
3687        return(void*)(p_chm->emm_buf);
3688}
3689#endif
3690
3691/******************************************************************************
3692 * INPUTS:      context
3693 * OUTPUTS:     none.
3694 * RETURNS:     none
3695 * FUNCTION:    message_callback
3696 * DESCRIPTION: Callback function normally called when a complete message has
3697 *              been received and passed the filter criteria.
3698 ******************************************************************************/
3699
3700void * chm_smessage_stt_callback(void * context, size_t size)
3701{
3702        chm_mgr_t * p_chm;
3703        b_tm utc_time;
3704        b_timeval tv;
3705
3706        p_chm = (chm_mgr_t*)context;
3707
3708        p_chm->time_evt.type = eCHM_EVT_TIME;
3709
3710        if (SI_STT_parse(p_chm->stt_buf) != SI_SUCCESS)
3711        {
3712                BDBG_WRN(("%s SI_STT_parse failed\n",__FUNCTION__));
3713                return(void*)p_chm->stt_buf;
3714        }
3715
3716        p_chm->stt_cnt++;
3717
3718        /* current platform seconds when STT was received */
3719        GETTIMEOFDAY(&tv);
3720
3721        /* Current UTC time according to STT */
3722        p_chm->time_evt.system_time = SI_STT_Get_Sys_Time() - SI_STT_Get_GPS_UTC_Offset();
3723        p_chm->time_evt.system_offset = tv.tv_sec;
3724        p_chm->time_evt.utc_offset = SI_STT_Get_GPS_UTC_Offset();
3725
3726        chm_post_app_event(p_chm,(chm_event_t*)&p_chm->time_evt);
3727
3728        utctime(p_chm->time_evt.system_time,&utc_time);
3729        BDBG_WRN(("STT UTC = %2d/%2d/%4d %2d:%2d:%2d\n",
3730                          utc_time.tm_mon + 1,utc_time.tm_mday,utc_time.tm_year + 1980, 
3731                          utc_time.tm_hour,utc_time.tm_min,utc_time.tm_sec));
3732        return(void*)p_chm->stt_buf;
3733}
3734
3735/*
3736   Destination for cvt parser so the actual data would not be changed while
3737   it is being processed by another thread
3738 */
3739static struct cvt_info_t cvt_info;
3740
3741/******************************************************************************
3742 * INPUTS:      context
3743 * OUTPUTS:     none.
3744 * RETURNS:     none
3745 * FUNCTION:    message_callback
3746 * DESCRIPTION: Callback function normally called when a complete message has
3747 *              been received and passed the filter criteria.
3748 ******************************************************************************/
3749
3750void * chm_smessage_cvt_callback(void * context, size_t size)
3751{
3752        chm_mgr_t * p_chm = (chm_mgr_t*)context;
3753        bapp_t *p_app;
3754        int res,i;
3755        unsigned short vch_num;
3756
3757        p_app = (bapp_t*)p_chm->p_app;
3758
3759        BDBG_ERR(("#### CVT Event ####\n"));
3760
3761        ch_map_get_vch_num(bapp_cur_ch_map(p_app),&vch_num);
3762
3763        if (vch_num == 0)
3764        {
3765                BDBG_WRN(("%s No channels in map.\n",__FUNCTION__));
3766                goto ExitFunc;
3767        }
3768        res = cvt_parse(p_chm->cvt_buf, size, &cvt_info);
3769        if (res != 0)
3770        {
3771                BDBG_WRN(("#### CVT Inavlid.####, res=%d\n", res));
3772                goto ExitFunc;
3773        }
3774
3775        p_chm->cvt_cnt++;
3776
3777        //#define       CVT_DEBUG
3778#ifdef  CVT_DEBUG
3779        BDBG_WRN(("protocol_version                = %d", cvt_info.protocol_version));
3780        BDBG_WRN(("configuration_count_change      = %d", cvt_info.configuration_count_change));
3781        BDBG_WRN(("vendor_id                       = %d (0x%08x)", cvt_info.vendor_id, cvt_info.vendor_id));
3782        BDBG_WRN(("hardware_version_id             = %d (0x%08x)", cvt_info.hardware_version_id, cvt_info.hardware_version_id));
3783        BDBG_WRN(("location_type                   = %d", cvt_info.location_type));
3784        BDBG_WRN(("source_ID                       = %d", cvt_info.source_ID));
3785        BDBG_WRN(("frequency_vector                = %d (0x%04x)", cvt_info.frequency_vector, cvt_info.frequency_vector));
3786        BDBG_WRN(("modulation_type                 = %d", cvt_info.modulation_type));
3787        BDBG_WRN(("program_number                  = %d (0x%04x)", cvt_info.program_number & 0xffff, cvt_info.program_number & 0xffff));
3788        BDBG_WRN(("pid                             = %d (0x%04x)", cvt_info.pid, cvt_info.pid));
3789        BDBG_WRN(("code_file_name_length           = %d", cvt_info.code_file_name_length));
3790        cvt_info.code_file_name[cvt_info.code_file_name_length] = '\0';
3791        BDBG_WRN(("code_file_name                  = %s", cvt_info.code_file_name));
3792#endif
3793        if (cvt_info.vendor_id != p_chm->vendor_id)
3794        {
3795                BDBG_ERR(("#### CVT Vendor ID mismatch (0x%08x != 0x%08x) ####\n",cvt_info.vendor_id, p_chm->vendor_id));
3796                goto ExitFunc;
3797        }
3798
3799        if (cvt_info.hardware_version_id != p_chm->hardware_version_id)
3800        {
3801                BDBG_ERR(("#### CVT Vendor ID mismatch (0x%08x != 0x%08x) ####\n",cvt_info.vendor_id, p_chm->vendor_id));
3802                goto ExitFunc;
3803        }
3804
3805        BDBG_WRN(("#### CVT Got Vendor ID  (0x%08x) ####\n",cvt_info.vendor_id));
3806        if (true == p_chm->cvt_valid)
3807        {
3808                if (cvt_info.configuration_count_change == p_chm->cvt.configuration_count_change)
3809                {
3810                        BDBG_WRN(("configuration_count_change %d:%d", cvt_info.configuration_count_change, p_chm->cvt.configuration_count_change));
3811                        goto ExitFunc;
3812                }
3813
3814                i = 0;
3815                if (cvt_info.code_file_name_length == p_chm->cvt.code_file_name_length)
3816                {
3817                        for (i = 0; i < cvt_info.code_file_name_length; ++i)
3818                        {
3819                                if (cvt_info.code_file_name[i] != p_chm->cvt.code_file_name[i])
3820                                {
3821                                        break;
3822                                }
3823                        }
3824                }
3825                if (i == cvt_info.code_file_name_length)
3826                {
3827                        BDBG_WRN(("CVT file names match"));
3828                        goto ExitFunc;
3829                }
3830        }
3831
3832        if (p_chm->cmd == eCHM_HUNTING)
3833                p_chm->cmd = eCHM_CANCEL;
3834
3835        if (p_chm->num_freq == 0)
3836        {
3837                bapp_freq_table_get(p_chm->fe_type,(const unsigned int **)&(p_chm->freq_table),&(p_chm->num_freq));
3838        }
3839
3840        if (p_chm->num_freq == 0)
3841        {
3842                BDBG_WRN(("%s:%d p_chm->num_freq = %d\n",__FUNCTION__,__LINE__,p_chm->num_freq));
3843                goto ExitFunc;
3844        }
3845       
3846        /* copy structure to channel manager and mark cvt as valid */
3847        memcpy(&(p_chm->cvt), &cvt_info, sizeof(struct cvt_info_t));
3848        p_chm->cvt_valid = true;
3849        p_chm->download_evt.type = eCHM_EVT_DOWNLOAD;
3850        p_chm->download_evt.id = (p_chm->select_idx * (100/p_chm->num_freq))/p_chm->num_freq;
3851        chm_post_app_event_cb(p_chm,&p_chm->download_evt);
3852        ExitFunc:
3853        return(void*)p_chm->cvt_buf;
3854}
3855/*
3856Summary:
3857Get the STT. return non-zero on failure
3858 */
3859
3860static int chm_stt_start(chm_mgr_t *p_chm,              /* Channel manager reference */
3861                                                 unsigned short network_pid)
3862{
3863        int cerr;
3864        smessage_stream_params_t params;
3865
3866        cerr = eCHM_ERR_OK;
3867        BDBG_MSG(("%s:%d (0x%04x)",__FUNCTION__, __LINE__,network_pid));
3868
3869        chm_stt_stop(p_chm);
3870
3871        p_chm->stt_msg = smessage_open(smessage_format_psi);
3872        if (NULL == p_chm->stt_msg)
3873        {
3874                BDBG_ERR(("%s:%d",__FILE__, __LINE__));
3875                cerr = eCHM_ERR_FAILED;
3876                goto ExitFunc;
3877        }
3878        smessage_stream_params_init(&params, p_chm->stt_msg);
3879        params.band = p_chm->band;
3880        params.pid = (uint16_t)network_pid;
3881        params.filter.coef[0] = 0xC5;
3882        params.filter.mask[0] = 0x00;
3883        /* All PSIP tables have protocol_version which must be = 0 */
3884        params.filter.coef[3] = 0x00;   /* protocol_version */
3885        params.filter.mask[3] = 0x00;
3886        params.buffer = p_chm->stt_buf;
3887        params.buffer_size = STT_BUF_LEN;
3888        /* processing is done in callback */
3889        params.data_ready_callback = chm_smessage_stt_callback;
3890        params.overflow = NULL;
3891        params.callback_context = (void *)p_chm;
3892        BDBG_WRN(("%s\n",__FUNCTION__));
3893        if (b_ok != smessage_start(&params, p_chm->stt_msg))
3894        {
3895                BDBG_ERR(("%s:%d",__FILE__, __LINE__));
3896                cerr = eCHM_ERR_FAILED;
3897        }
3898        ExitFunc:
3899        return cerr;
3900}
3901/*
3902Summary:
3903Stop checking for EMM messages. return non-zero on failure
3904 */
3905
3906static void chm_emm_stop(chm_mgr_t *p_chm               /* Channel manager reference */
3907                                                )
3908{
3909        if (NULL != p_chm->emm_msg)
3910        {
3911                if (b_ok != smessage_stop(p_chm->emm_msg))
3912                {
3913                        BDBG_ERR(("%s:%d",__FUNCTION__, __LINE__));
3914                        return;
3915                }
3916                smessage_close(p_chm->emm_msg);
3917                p_chm->emm_msg = NULL;
3918        }
3919}
3920/*
3921Summary:
3922Start checking for EMM messages. return non-zero on failure
3923 */
3924
3925static int chm_emm_start(chm_mgr_t *p_chm,              /* Channel manager reference */
3926                                                 unsigned short emm_pid)
3927{
3928        int cerr;
3929        smessage_stream_params_t params;
3930
3931        cerr = eCHM_ERR_OK;
3932        BDBG_MSG(("%s:%d (0x%04x)",__FUNCTION__, __LINE__,emm_pid));
3933
3934        chm_emm_stop(p_chm);
3935
3936        p_chm->emm_msg = smessage_open(smessage_format_psi);
3937        if (NULL == p_chm->emm_msg)
3938        {
3939                BDBG_ERR(("%s:%d",__FILE__, __LINE__));
3940                cerr = eCHM_ERR_FAILED;
3941                goto ExitFunc;
3942        }
3943        smessage_stream_params_init(&params, p_chm->emm_msg);
3944        params.band = p_chm->band;
3945        params.pid = (uint16_t)emm_pid;
3946        params.filter.coef[0] = 0x80;
3947        params.filter.mask[0] = 0x0f;
3948        /* filter on byte 2 */
3949        params.filter.coef[1] = 0x00;
3950        params.filter.mask[1] = 0x1f;
3951#if 0
3952
3953        /* All PSIP tables have protocol_version which must be = 0 */
3954        params.filter.coef[3] = 0x00;   /* protocol_version */
3955        params.filter.mask[3] = 0x00;
3956#endif
3957        params.buffer = p_chm->emm_buf;
3958        params.buffer_size = EMM_BUF_LEN;
3959        /* processing is done in callback */
3960        params.data_ready_callback = chm_smessage_emm_callback;
3961        params.overflow = NULL;
3962        params.callback_context = (void *)p_chm;
3963        if (b_ok != smessage_start(&params, p_chm->emm_msg))
3964        {
3965                BDBG_ERR(("%s:%d",__FILE__, __LINE__));
3966                cerr = eCHM_ERR_FAILED;
3967        }
3968        ExitFunc:
3969        return cerr;
3970}
3971
3972/*
3973Summary:
3974Tune to the current frequency.
3975 */
3976static int chm_tune_freq(chm_mgr_t *p_chm,unsigned int freq_hz,unsigned int freq_idx)
3977{
3978        bapp_t *p_app = (bapp_t*)p_chm->p_app;
3979        mms_t mms;
3980        unsigned int tune_ticks;
3981        BDBG_WRN(("%s: freq_hz=%d, last_freq_hz=%d\n",__FUNCTION__, freq_hz, p_chm->last_freq_hz));
3982
3983        if (p_chm->force_tune)
3984        {
3985                p_chm->last_freq_hz = 0;
3986                p_chm->force_tune = false;
3987        }
3988
3989        if (p_chm->last_freq_hz != freq_hz)
3990        {
3991                btuner_params_init(&p_chm->tuner_params, p_chm->tuner);
3992                p_chm->tuner_params.cancel_callback = chm_tune_cancel_callback;
3993                p_chm->tuner_params.cancel_callback_context = p_chm;
3994                p_chm->tuner_params.wait_for_lock = true;
3995                p_chm->tuner_params.fecMode = eFEC_ANNEX_B;
3996                p_chm->tuner_params.qamMode = eQAM_Scan;
3997
3998                if (ch_map_get_mms(bapp_cur_ch_map(p_app),p_chm->vch.mms_idx,&mms))
3999                {
4000                        /* This is where QAM optimizations go */
4001                        if ((mms.modulation != eQAM_64) && (mms.modulation != eQAM_256))
4002                                p_chm->tuner_params.qamMode = eQAM_Scan;
4003                        else
4004                        p_chm->tuner_params.qamMode = mms.modulation;
4005                } else
4006                        p_chm->tuner_params.qamMode = eQAM_Scan;
4007
4008                BDBG_WRN(("Tune to frequency = %d (0x%02x)\n",freq_hz,p_chm->tuner_params.qamMode));
4009
4010                tune_ticks = bos_getticks();
4011
4012                p_chm->band = btuner_tune(p_chm->tuner, freq_hz, &p_chm->tuner_params);
4013
4014                tune_ticks = bos_getticks() - tune_ticks;
4015                p_chm->status_evt.type = eCHM_EVT_STATUS;
4016                p_chm->status_evt.id = eCHM_STATUS_TUNE_MS;
4017                p_chm->status_evt.ticks = TICKS_TO_MS(tune_ticks);
4018                chm_post_app_event(p_chm,(chm_event_t*)&p_chm->status_evt);
4019
4020                if (p_chm->band < 0)
4021                {
4022                        BDBG_WRN(("Tune failed (freq = %d)\n",freq_hz));
4023                        p_chm->last_freq_hz = 0;
4024                        /* Send message to app */
4025                        chm_send_status(p_chm,freq_hz,false);
4026
4027                        return eCHM_ERR_FAILED;
4028                }
4029                p_chm->last_freq_hz = freq_hz;
4030        } else
4031        {
4032                BDBG_WRN(("Already tuned to frequency = %d\n",freq_hz));
4033        }
4034        p_chm->status_evt.ticks = TICKS_TO_MS((bos_getticks() - tune_ticks));
4035        chm_post_app_event(p_chm,(chm_event_t*)&p_chm->status_evt);
4036
4037        BDBG_ERR(("%s:%d\n",__FUNCTION__, __LINE__));
4038        chm_send_status(p_chm,freq_hz,true);
4039
4040        return eCHM_ERR_OK;
4041}
4042
4043
4044/*
4045Summary:
4046Rotate audio pids.
4047 */
4048
4049static int chm_rotate_audio(chm_mgr_t *p_chm)
4050{
4051#ifdef CONFIG_HAS_AUDIO
4052        bapp_t *p_app = (bapp_t*)p_chm->p_app;
4053        vch_t vch;
4054        st_t st;
4055        freq_t freq;
4056
4057        if (!p_chm->curr_stream || !p_chm->curr_stream->stream)
4058                return eCHM_ERR_FAILED;
4059
4060        if (!ch_map_get_current(bapp_cur_ch_map(p_app),&vch,&st,&freq))
4061        {
4062                BDBG_WRN(("%s Invalid current channel or map.\n",__FUNCTION__));
4063                return 0;
4064        }
4065
4066        BDBG_WRN(("%s from 0x%04x to 0x%04x\n",__FUNCTION__,p_chm->mpeg[CURR_CH].audio[0].pid, vch.audio_pid[vch.cur_audio]));
4067
4068        if (p_app->audio && (p_chm->mpeg[CURR_CH].audio[0].pid != 0))
4069        {
4070                BDBG_WRN(("baudio_decode_stop  0x%04x\n",p_chm->mpeg[CURR_CH].audio[0].pid));
4071                baudio_decode_stop(p_app->audio);
4072        }
4073
4074        p_chm->mpeg[CURR_CH].audio[0].pid = vch.audio_pid[vch.cur_audio];
4075        if (p_app->audio)
4076        {
4077                if (p_chm->mpeg[CURR_CH].audio[0].pid != 0)
4078                {
4079                        BDBG_WRN(("baudio_decode_start  0x%04x\n",p_chm->mpeg[CURR_CH].audio[0].pid));
4080                        bstream_update_mpeg(p_chm->curr_stream->stream,&p_chm->mpeg[CURR_CH]);
4081                        if (baudio_decode_start(p_app->audio, (void *)1, p_chm->curr_stream->stream))
4082                        {
4083                                BDBG_WRN(("baudio_decode_start failed\n"));
4084                                return eCHM_ERR_FAILED;
4085                        }
4086                }
4087        }
4088#endif
4089        return eCHM_ERR_OK;
4090}
4091
4092#ifdef CONFIG_DVB_SUBTITLE
4093static int chm_rotate_dsub(chm_mgr_t *p_chm)
4094{
4095        bapp_t *p_app = (bapp_t *)p_chm->p_app;
4096        vch_t tmp_vch;
4097        st_t tmp_st;
4098        freq_t tmp_freq;
4099
4100        if (p_app->dsub) {
4101                chm_subtitle_stop(p_chm);
4102                ch_map_get_current(bapp_cur_ch_map(p_app), &tmp_vch, &tmp_st, &tmp_freq);
4103                if (tmp_vch.dsub_pid[tmp_vch.cur_dsub]) {
4104                        BDBG_WRN(("subtitle_start %d 0x%x", tmp_vch.cur_dsub, tmp_vch.dsub_pid[tmp_vch.cur_dsub]));
4105                        chm_subtitle_start(p_chm, tmp_vch.dsub_pid[tmp_vch.cur_dsub]);
4106                }
4107        }
4108        return eCHM_ERR_OK;
4109}
4110#endif
4111/*
4112Summary:
4113        Open a stream given an mpeg program structure.
4114 */
4115static int chm_start_stream(chm_mgr_t *p_chm, chm_stream_t *p_stream,bstream_mpeg *p_mpeg)
4116{
4117        BDBG_ASSERT(p_stream);
4118        BDBG_ASSERT(p_mpeg);
4119       
4120        if (p_stream->stream)
4121        {
4122                bstream_close(p_stream->stream);
4123                p_stream->stream = NULL;
4124        }
4125
4126        p_stream->stream = bstream_open(p_chm->band,p_mpeg);
4127        if (p_stream->stream)
4128        {
4129                p_stream->freq_hz = p_chm->last_freq_hz;
4130                p_stream->pid = p_mpeg->video[0].pid;
4131        }
4132        return (p_stream->stream) ? eCHM_ERR_OK : eCHM_ERR_FAILED;
4133}
4134
4135
4136/*
4137Summary:
4138        Close the stream.
4139 */
4140void chm_stop_stream(chm_mgr_t *p_chm, chm_stream_t *p_stream)
4141{
4142        BDBG_ASSERT(p_stream);
4143       
4144        if (p_stream->stream)
4145        {
4146                bstream_close(p_stream->stream);
4147                p_stream->stream = NULL;
4148                p_stream->pid = 0;
4149        }
4150}
4151/*
4152Summary:
4153        Stop unused stream.
4154 */
4155static void chm_stop_unused_streams(chm_mgr_t *p_chm)
4156{
4157        int mpeg_idx,stream_idx;
4158        bool match;
4159       
4160        for (stream_idx = 0; stream_idx < BSETTOP_MAX_STREAMS; ++stream_idx)
4161        {
4162                match = false;
4163                for (mpeg_idx = 0; mpeg_idx < BSETTOP_MAX_STREAMS; ++mpeg_idx)
4164                {
4165                        if (p_chm->mpeg[mpeg_idx].video[0].pid == p_chm->chm_stream[stream_idx].pid)
4166                        {
4167                                match = true;
4168                                continue;
4169                        }
4170                }
4171                if (!match)
4172                {
4173                        chm_stop_stream(p_chm,&(p_chm->chm_stream[stream_idx]));
4174                }
4175
4176        }
4177}
4178/*
4179Summary:
4180        Find the stream with this PID .
4181 */
4182static chm_stream_t *chm_find_stream(chm_mgr_t *p_chm, unsigned short pid)
4183{
4184        int stream_idx;
4185        BDBG_ASSERT(p_chm);
4186       
4187        for (stream_idx = 0; stream_idx < BSETTOP_MAX_STREAMS; ++stream_idx)
4188        {
4189                if (pid == p_chm->chm_stream[stream_idx].pid)
4190                {
4191                        return &(p_chm->chm_stream[stream_idx]);
4192                }
4193        }
4194        return NULL;
4195}
4196/*
4197Summary:
4198        Find an unused stream.
4199 */
4200static chm_stream_t *chm_find_unused_stream(chm_mgr_t *p_chm)
4201{
4202        int stream_idx;
4203        BDBG_ASSERT(p_chm);
4204       
4205        for (stream_idx = 0; stream_idx < BSETTOP_MAX_STREAMS; ++stream_idx)
4206        {
4207                if (p_chm->chm_stream[stream_idx].stream == NULL)
4208                {
4209                        return &(p_chm->chm_stream[stream_idx]);
4210                }
4211        }
4212        return NULL;
4213}
4214
4215/*
4216Summary:
4217Start audio and video decode.
4218Description:
4219Handle tuning to the current channel. Returns non-zero on failure.
4220 */
4221static int chm_start_decode(chm_mgr_t *p_chm, bool force_restart)
4222{
4223        bapp_t *p_app = (bapp_t*)p_chm->p_app;
4224        chm_stream_t *tmp_stream;
4225
4226        if ((p_chm->mpeg[CURR_CH].audio[0].pid == 0x0000) && (p_chm->mpeg[CURR_CH].video[0].pid == 0x0000))
4227        {
4228                BDBG_WRN(("%s (0x%04x,0x%04x,0x%04x,%d) failed \n",
4229                                  __func__,p_chm->mpeg[CURR_CH].video[0].pid,p_chm->mpeg[CURR_CH].pcr_pid,
4230                                  p_chm->mpeg[CURR_CH].audio[0].pid,p_chm->band));
4231                return eCHM_ERR_FAILED;
4232        }
4233
4234        if (p_chm->mpeg[CURR_CH].video[0].pid == 0x0000)
4235        {
4236                bdecode_config cfg;
4237                bdecode_get_config(p_app->decode,&cfg);
4238                cfg.mute = 1;
4239                cfg.channel_change = 0;
4240                bdecode_set_config(p_app->decode,&cfg);
4241        }
4242
4243        /* Stop the current decode (but not the streams) */
4244        chm_stop_decode(p_chm);
4245       
4246        /* Handle audio only decode */
4247        if (p_app->audio && (p_chm->mpeg[CURR_CH].audio[0].pid != 0x0000) && (p_chm->mpeg[CURR_CH].video[0].pid == 0x0000))
4248        {
4249                BDBG_WRN(("%s (0x%04x,0x%04x,0x%04x,%d) audio only decode \n",
4250                                  __func__,p_chm->mpeg[CURR_CH].video[0].pid,p_chm->mpeg[CURR_CH].pcr_pid,
4251                                  p_chm->mpeg[CURR_CH].audio[0].pid,p_chm->band));
4252
4253                chm_stop_stream(p_chm,&(p_chm->chm_stream[CURR_CH]));
4254                chm_stop_stream(p_chm,&(p_chm->chm_stream[PREV_CH]));
4255                chm_stop_stream(p_chm,&(p_chm->chm_stream[NEXT_CH]));
4256
4257                if (chm_start_stream(p_chm,&(p_chm->chm_stream[CURR_CH]),&(p_chm->mpeg[CURR_CH])))
4258                {
4259                        BDBG_WRN(("chm_start_stream failed\n"));
4260                        return eCHM_ERR_FAILED;
4261                }
4262               
4263                p_chm->curr_stream = &(p_chm->chm_stream[CURR_CH]);
4264
4265                if (baudio_decode_start(p_app->audio, (void *)1, p_chm->curr_stream->stream))
4266                {
4267                        BDBG_WRN(("baudio_decode_start failed\n"));
4268                        return eCHM_ERR_FAILED;
4269                }
4270                p_chm->decoding_audio = true;
4271                return eCHM_ERR_OK;
4272        }
4273
4274        /* Check if all streams need to be restarted */
4275        if (force_restart)
4276        {
4277                chm_stop_stream(p_chm,&(p_chm->chm_stream[CURR_CH]));
4278                chm_stop_stream(p_chm,&(p_chm->chm_stream[PREV_CH]));
4279                chm_stop_stream(p_chm,&(p_chm->chm_stream[NEXT_CH]));
4280
4281                if (chm_start_stream(p_chm,&(p_chm->chm_stream[CURR_CH]),&(p_chm->mpeg[CURR_CH])))
4282                {
4283                        BDBG_WRN(("chm_start_stream failed\n"));
4284                        return eCHM_ERR_FAILED;
4285                }
4286               
4287                p_chm->curr_stream = &(p_chm->chm_stream[CURR_CH]);
4288
4289                if (p_chm->mpeg[NEXT_CH].video[0].pid != 0x0000)
4290                {
4291                        if (chm_start_stream(p_chm,&(p_chm->chm_stream[NEXT_CH]),&(p_chm->mpeg[NEXT_CH])))
4292                        {
4293                                BDBG_WRN(("chm_start_stream next failed\n"));
4294                        }
4295                }
4296
4297                if (p_chm->mpeg[PREV_CH].video[0].pid != 0x0000)
4298                {
4299                        if (chm_start_stream(p_chm,&(p_chm->chm_stream[PREV_CH]),&(p_chm->mpeg[PREV_CH])))
4300                        {
4301                                BDBG_WRN(("chm_start_stream prev failed\n"));
4302                        }
4303                }
4304        }
4305        else
4306        {
4307                chm_stop_unused_streams(p_chm);
4308
4309                p_chm->curr_stream = chm_find_stream(p_chm,p_chm->mpeg[CURR_CH].video[0].pid);
4310
4311                if (p_chm->curr_stream == NULL)
4312                {
4313                        if (chm_start_stream(p_chm,&(p_chm->chm_stream[CURR_CH]),&(p_chm->mpeg[CURR_CH])))
4314                        {
4315                                BDBG_WRN(("chm_start_stream current failed\n"));
4316                                return eCHM_ERR_FAILED;
4317                        }
4318                        p_chm->curr_stream = &(p_chm->chm_stream[CURR_CH]);
4319                }
4320
4321                if (p_chm->mpeg[NEXT_CH].video[0].pid != 0x0000)
4322                {
4323                        tmp_stream = chm_find_stream(p_chm,p_chm->mpeg[NEXT_CH].video[0].pid);
4324
4325                        if (tmp_stream == NULL)
4326                        {
4327                                tmp_stream = chm_find_unused_stream(p_chm);
4328
4329                                if (tmp_stream)
4330                                {
4331                                        if (chm_start_stream(p_chm,tmp_stream,&(p_chm->mpeg[NEXT_CH])))
4332                                        {
4333                                                BDBG_WRN(("chm_start_stream next failed\n"));
4334                                        }
4335                                }
4336                        }
4337                }
4338
4339                if (p_chm->mpeg[PREV_CH].video[0].pid != 0x0000)
4340                {
4341                        tmp_stream = chm_find_stream(p_chm,p_chm->mpeg[PREV_CH].video[0].pid);
4342
4343                        if (tmp_stream == NULL)
4344                        {
4345                                tmp_stream = chm_find_unused_stream(p_chm);
4346
4347                                if (tmp_stream)
4348                                {
4349                                        if (chm_start_stream(p_chm,tmp_stream,&(p_chm->mpeg[PREV_CH])))
4350                                        {
4351                                                BDBG_WRN(("chm_start_stream next failed\n"));
4352                                        }
4353                                }
4354                        }
4355                }
4356        }
4357
4358        if (!p_chm->curr_stream)
4359        {
4360                BDBG_WRN(("%s current stream NULL\n",__FUNCTION__));
4361                return eCHM_ERR_FAILED;
4362        }
4363
4364        BDBG_WRN(("%s(0x%04x,0x%04x,0x%04x,%d)\n",
4365                          __func__,p_chm->mpeg[CURR_CH].video[0].pid,p_chm->mpeg[CURR_CH].pcr_pid,
4366                          p_chm->mpeg[CURR_CH].audio[0].pid,p_chm->band));
4367
4368        timing_profile_start(p_app->ptp_first_pts);
4369        timing_profile_start(p_app->ptp_decode);
4370        if (bdecode_start(p_app->decode, p_chm->curr_stream->stream, p_app->window[0]))
4371        {
4372                BDBG_WRN(("bdecode_start failed\n"));
4373                return eCHM_ERR_FAILED;
4374        }
4375        p_chm->decoding_video = true;
4376       
4377        if (p_app->audio && (p_chm->mpeg[CURR_CH].audio[0].pid != 0))
4378        {
4379                if (baudio_decode_start(p_app->audio, (void *)1, p_chm->curr_stream->stream))
4380                {
4381                        BDBG_WRN(("baudio_decode_start failed\n"));
4382                        return eCHM_ERR_FAILED;
4383                }
4384        }
4385        p_chm->decoding_audio = true;
4386        return eCHM_ERR_OK;
4387}
4388/*
4389Summary:
4390Stop audio and video decode.
4391 */
4392static int chm_stop_decode(chm_mgr_t *p_chm)
4393{
4394        bapp_t *p_app = (bapp_t*)p_chm->p_app;
4395
4396        chm_eas_stop(p_chm);
4397        chm_cvt_stop(p_chm);
4398        chm_nit_stop(p_chm);
4399        chm_ntt_stop(p_chm);
4400        chm_svct_stop(p_chm);
4401        chm_emm_stop(p_chm);
4402        chm_cat_stop(p_chm);
4403
4404#ifdef CONFIG_DVB
4405        chm_dvb_nit_stop(p_chm);
4406        chm_dvb_sdt_stop(p_chm);
4407        chm_dvb_tdt_stop(p_chm);
4408        chm_dvb_eit_stop(p_chm);
4409#endif
4410        if (p_app->decode && p_chm->decoding_video)
4411                bdecode_stop(p_app->decode);
4412        if (p_app->audio && p_chm->decoding_audio)
4413                baudio_decode_stop(p_app->audio);
4414        p_chm->decoding_video = false;
4415        p_chm->decoding_audio = false;
4416
4417        return 0;
4418}
4419/*
4420Summary:
4421Tune to the current frequency and enter steady channel processing state..
4422Description:
4423Tune to the current frequency and enter steady channel processing state..
4424 */
4425static int chm_tune_current(chm_mgr_t *p_chm)
4426{
4427        unsigned int freq_hz;
4428//      bapp_t *p_app = (bapp_t*)p_chm->p_app;
4429
4430        if (chm_check_cancel(p_chm))
4431                return eCHM_ERR_CANCELED;
4432
4433        chm_eas_stop(p_chm);
4434        chm_cvt_stop(p_chm);
4435        chm_nit_stop(p_chm);
4436        chm_ntt_stop(p_chm);
4437        chm_svct_stop(p_chm);
4438        chm_emm_stop(p_chm);
4439
4440#ifdef CONFIG_DVB
4441        chm_dvb_nit_stop(p_chm);
4442        chm_dvb_sdt_stop(p_chm);
4443        chm_dvb_tdt_stop(p_chm);
4444        chm_dvb_eit_stop(p_chm);
4445#endif
4446        freq_hz = p_chm->freq.freq_khz * 1000;
4447
4448        if (chm_tune_freq(p_chm,freq_hz,p_chm->freq.idx) != 0)
4449        {
4450                BDBG_WRN(("chm_tune_freq failed, try to retune and reacq"));
4451                /* force to re-tune */
4452                p_chm->force_tune = true;
4453                if (chm_tune_freq(p_chm,freq_hz,p_chm->freq.idx) == 0)
4454                {
4455                        return eCHM_ERR_OK;
4456                }
4457                BDBG_WRN(("chm_tune_freq failed\n"));
4458                return eCHM_ERR_FAILED;
4459        }
4460
4461        return eCHM_ERR_OK;
4462}
4463/*
4464Summary:
4465Tune to the current frequency and get the VCT.
4466Description:
4467Tune to the current frequency and get the VCT. Returns non-zero on failure.
4468 */
4469
4470static int chm_config_mpeg(chm_mgr_t *p_chm, vch_t *p_vch)
4471{
4472        unsigned short ch_num,ch_num2;
4473        vch_t tmp_vch;
4474        st_t tmp_st; 
4475        freq_t tmp_freq;
4476        bapp_t *p_app = (bapp_t*)p_chm->p_app;
4477        memset(&(p_chm->mpeg[CURR_CH]),0,sizeof(bstream_mpeg));
4478        memset(&(p_chm->mpeg[PREV_CH]),0,sizeof(bstream_mpeg));
4479        memset(&(p_chm->mpeg[NEXT_CH]),0,sizeof(bstream_mpeg));
4480
4481        p_chm->mpeg[CURR_CH].pcr_pid = p_vch->pcr_pid;
4482        p_chm->mpeg[CURR_CH].video[0].pid = p_vch->video_pid;
4483        p_chm->mpeg[CURR_CH].video[0].format = p_vch->video_type;
4484        p_chm->mpeg[CURR_CH].audio[0].pid = p_vch->audio_pid[p_vch->cur_audio];
4485        p_chm->mpeg[CURR_CH].audio[0].format = p_vch->audio_type[p_vch->cur_audio];
4486
4487        if (p_chm->mpeg[CURR_CH].audio[0].pid == 0)
4488        {
4489                BDBG_WRN(("### All audio PIDs are 0x0000 ###\n"));
4490        }
4491
4492        ch_num = ch_num2 = p_vch->ch_num;
4493
4494        if (ch_map_set_next(bapp_cur_ch_map(p_app)))
4495        {
4496                if (ch_map_get_current(bapp_cur_ch_map(p_app),&tmp_vch,&tmp_st, &tmp_freq))
4497                {
4498                        if ((tmp_vch.freq_idx == p_vch->freq_idx) && (tmp_vch.ch_num != ch_num)/*&& (tmp_vch.video_type == BAVC_VideoCompressionStd_eMPEG2)*/)
4499                        {
4500                                p_chm->mpeg[NEXT_CH].video[0].pid = tmp_vch.video_pid;
4501                                p_chm->mpeg[NEXT_CH].video[0].format = tmp_vch.video_type;
4502                                p_chm->mpeg[NEXT_CH].audio[0].pid = tmp_vch.audio_pid[tmp_vch.cur_audio];
4503                                p_chm->mpeg[NEXT_CH].pcr_pid = tmp_vch.pcr_pid;
4504                                p_chm->mpeg[NEXT_CH].audio[0].format =  tmp_vch.audio_type[tmp_vch.cur_audio];
4505                                ch_num2 = tmp_vch.ch_num;
4506                        }
4507                }
4508        }
4509 
4510        ch_map_set_ch(bapp_cur_ch_map(p_app),ch_num);
4511        if (ch_map_set_prev(bapp_cur_ch_map(p_app)))
4512        {
4513                if (ch_map_get_current(bapp_cur_ch_map(p_app),&tmp_vch,&tmp_st, &tmp_freq))
4514                {
4515                        if ((tmp_vch.freq_idx == p_vch->freq_idx) && (tmp_vch.ch_num != ch_num) && (tmp_vch.ch_num != ch_num2)/*&& (tmp_vch.video_type == BAVC_VideoCompressionStd_eMPEG2)*/)
4516                        {
4517                                p_chm->mpeg[PREV_CH].video[0].pid = tmp_vch.video_pid;
4518                                p_chm->mpeg[PREV_CH].video[0].format = tmp_vch.video_type;
4519                                p_chm->mpeg[PREV_CH].audio[0].pid = tmp_vch.audio_pid[tmp_vch.cur_audio];
4520                                p_chm->mpeg[PREV_CH].pcr_pid = tmp_vch.pcr_pid;
4521                                p_chm->mpeg[PREV_CH].audio[0].format = tmp_vch.audio_type[tmp_vch.cur_audio];
4522                        }
4523                }
4524        }
4525
4526        ch_map_set_ch(bapp_cur_ch_map(p_app),ch_num);
4527
4528        return 0;
4529}
4530
4531/*
4532Summary:
4533Tune to the current frequency and enter steady channel processing state..
4534Description:
4535Tune to the current frequency and enter steady channel processing state..
4536 */
4537int chm_tune(chm_mgr_t *p_chm)
4538{
4539        int result = eCHM_ERR_FAILED;
4540        bool force_restart = false;
4541
4542        bapp_t *p_app = (bapp_t*)p_chm->p_app;
4543
4544        BDBG_WRN(("%s entry (line %d)\n",__FUNCTION__,__LINE__));
4545
4546        if (chm_check_cancel(p_chm))
4547        {
4548                BDBG_WRN(("%s cancel detected at line %d\n",__FUNCTION__,__LINE__));
4549                return eCHM_ERR_CANCELED;
4550        }
4551
4552        if (!ch_map_get_current(bapp_cur_ch_map(p_app),&p_chm->vch,&p_chm->st,&p_chm->freq))
4553        {
4554                BDBG_WRN(("%s ch_map_get_current failed\n",__FUNCTION__));
4555                p_chm->cmd = eCHM_CANCEL;
4556                return eCHM_ERR_FAILED;
4557        }
4558        p_chm->vch.cur_audio = 0;
4559        force_restart = ((p_chm->freq.freq_khz * 1000) == p_chm->last_freq_hz) ? false : true;
4560
4561        if (force_restart)
4562                chm_stop_decode(p_chm);
4563
4564        timing_profile_start(p_app->ptp_tune);
4565        if ((result = chm_tune_current(p_chm)) != eCHM_ERR_OK)
4566        {
4567                BDBG_WRN(("%s chm_tune_current failed\n",__FUNCTION__));
4568                timing_profile_stop(p_app->ptp_tune);           
4569                return result;
4570        }
4571        timing_profile_stop(p_app->ptp_tune);           
4572
4573#ifdef  HAS_VBI
4574        if (p_chm->pscte_127)
4575        {
4576                scte_127_reset(p_chm->pscte_127);
4577                scte_127_enable(p_chm->pscte_127, false);
4578                chm_scte127_stop(p_chm);
4579        }
4580#endif
4581
4582#ifdef CONFIG_DVB_SUBTITLE
4583        if (p_app->dsub) {
4584                chm_subtitle_stop(p_chm);
4585        }
4586        p_chm->vch.cur_dsub = 0;
4587#endif
4588
4589        if (chm_check_cancel(p_chm))
4590        {
4591                BDBG_WRN(("%s cancel detected at line %d\n",__FUNCTION__,__LINE__));
4592                return eCHM_ERR_CANCELED;
4593        }
4594
4595        timing_profile_start(p_app->ptp_psi);
4596        /* if no pids exist get them */
4597        if ((p_chm->vch.video_pid == 0) && (p_chm->vch.audio_pid[0] == 0) && (p_chm->vch.pcr_pid == 0))
4598        {
4599                BDBG_WRN(("%s no PIDS\n",__FUNCTION__));
4600                if ((result = chm_get_program(p_chm,&p_chm->vch)) != 0)
4601                {
4602                        BDBG_WRN(("chm_get_program failed %d\n",result));
4603
4604                        p_chm->chm_pat_evt.type = eCHM_EVT_STATUS;
4605                        p_chm->chm_pat_evt.id = eCHM_STATUS_NOPAT;
4606                        p_chm->chm_pat_evt.ticks = 0;
4607                        chm_post_app_event(p_chm,&p_chm->chm_pat_evt);
4608                        timing_profile_stop(p_app->ptp_psi);           
4609                        return result;
4610                } else
4611                {
4612                        /* need to update the channel map - Alternate Audio pid selection fix */
4613                        ch_map_copy(&(p_chm->ch_map),bapp_cur_ch_map(p_app),0xF);
4614
4615                        if (bos_acquire_mutex(&(p_chm->ch_map_mutex),45) == b_ok)
4616                        {
4617
4618                                if ((result = chm_update_programs(p_chm,p_chm->freq.idx)) != eCHM_ERR_OK)
4619                                {
4620                                        BDBG_WRN(("chm_update_programs failed %d\n",result));
4621                                }
4622
4623                                bos_release_mutex(&(p_chm->ch_map_mutex));
4624
4625                                p_chm->chm_pat_evt.type = eCHM_EVT_STATUS;
4626                                p_chm->chm_pat_evt.id = eCHM_STATUS_PAT;
4627                                p_chm->chm_pat_evt.ticks = 0;
4628                                chm_post_app_event(p_chm,&p_chm->chm_pat_evt);
4629
4630                                p_chm->chmap_evt.ticks = 0x82;
4631                                p_chm->chmap_evt.type = eCHM_EVT_STATUS;
4632                                p_chm->chmap_evt.id = eCHM_STATUS_CHMAP;
4633                                chm_post_app_event(p_chm, &p_chm->chmap_evt);
4634
4635                                bos_sleep(100);
4636                        } else
4637                        {
4638                                BDBG_WRN(("%s:%d failed to acquire channel map mutex\n", __FUNCTION__,__LINE__));
4639                        }
4640
4641                }
4642        } else
4643        {
4644                p_chm->pmt_crc = p_chm->pat_crc = 0;
4645
4646                p_chm->chm_pat_evt.type = eCHM_EVT_STATUS;
4647                p_chm->chm_pat_evt.id = eCHM_STATUS_NOPAT;
4648                p_chm->chm_pat_evt.ticks = 0;
4649                chm_post_app_event(p_chm,&p_chm->chm_pat_evt);
4650        }
4651        timing_profile_stop(p_app->ptp_psi);           
4652
4653        if (chm_check_cancel(p_chm))
4654        {
4655                BDBG_WRN(("%s cancel detected at line %d\n",__FUNCTION__,__LINE__));
4656                return eCHM_ERR_CANCELED;
4657        }
4658
4659        chm_stream_close(p_chm);
4660
4661        /* Do not start decode if PIDs are all 0.  Doing so can prevent SI filtering from operating correctly. */
4662        if ((p_chm->vch.video_pid != 0) || (p_chm->vch.audio_pid[0] != 0) || (p_chm->vch.pcr_pid != 0))
4663        {
4664                p_app->lang = chm_config_mpeg(p_chm,&p_chm->vch);
4665
4666                if ((result = chm_start_decode(p_chm,force_restart)) != 0)
4667                {
4668                        BDBG_WRN(("chm_start_decode failed\n"));
4669                        return result;
4670                }
4671        }
4672       
4673        if (chm_check_cancel(p_chm))
4674        {
4675                BDBG_WRN(("%s cancel detected at line %d\n",__FUNCTION__,__LINE__));
4676                return eCHM_ERR_CANCELED;
4677        }
4678
4679        if (result == 0)
4680        {
4681                /* start decode success so transition to info acquire state */
4682                p_chm->cmd = eCHM_INFO;
4683        }
4684
4685        return result;
4686}
4687
4688/*
4689Summary:
4690Do a tune for the purpose of checking the signal strength.
4691 */
4692int chm_check_signal(chm_mgr_t *p_chm)
4693{
4694        int result = eCHM_ERR_FAILED;
4695        btuner_status status;
4696        bapp_t *p_app = (bapp_t*)p_chm->p_app;
4697        unsigned int freq_hz;
4698
4699        if (chm_check_cancel(p_chm))
4700                return eCHM_ERR_CANCELED;
4701
4702        if (!ch_map_get_current(bapp_cur_ch_map(p_app),&p_chm->vch,&p_chm->st,&p_chm->freq))
4703        {
4704                BDBG_WRN(("%s ch_map_get_current failed\n",__FUNCTION__));
4705                return eCHM_ERR_FAILED;
4706        }
4707
4708        freq_hz = p_chm->freq.freq_khz * 1000;
4709
4710        if (chm_tune_freq(p_chm,freq_hz,p_chm->freq.idx) != 0)
4711        {
4712                p_chm->signal_evt.type = eCHM_EVT_SIGNAL;
4713                p_chm->signal_evt.power = 0;
4714                p_chm->signal_evt.SNR = 0;
4715                p_chm->signal_evt.freq_hz = freq_hz;
4716                p_chm->signal_evt.lock = 0;
4717                chm_post_app_event(p_chm,(chm_event_t*)&p_chm->signal_evt);
4718                BDBG_WRN(("bapp_tune_current_freq failed\n"));
4719                return result;
4720        }
4721
4722        while (!chm_check_cancel(p_chm))
4723        {
4724                /* check power level only if we are in tuner status screen */
4725                if ((p_app->screen_id == eSCREEN_ANTENNA) || (p_app->screen_id == eSCREEN_TUNER_STATUS) ||
4726                        (p_app->screen_id == eSCREEN_BANNER) || (p_app->screen_id == eSCREEN_BANNER_SMALL)) {
4727                        status.get_power = true;
4728                } else {
4729                        status.get_power = false;
4730                }
4731                if (btuner_get_status(p_chm->tuner,&status) == b_ok)
4732                {
4733                        p_chm->signal_evt.type = eCHM_EVT_SIGNAL;
4734                        p_chm->signal_evt.power = status.power;
4735                        p_chm->signal_evt.SNR = status.snr;
4736                        p_chm->signal_evt.freq_hz = freq_hz;
4737                        //p_chm->signal_evt.qam_b_mode = status.mode;
4738                        p_chm->signal_evt.lock = status.lock;
4739                        chm_post_app_event(p_chm,(chm_event_t*)&p_chm->signal_evt);
4740
4741                }
4742                bos_sleep(50);
4743        }
4744
4745        return result;
4746}
4747
4748#ifdef  HAS_VBI
4749/*
4750Summary:
4751Start SCTE 127 monitoring...
4752 */
4753static int chm_scte127_start(chm_mgr_t *p_chm, uint16_t scte127_pid)
4754{
4755        int cerr = eCHM_ERR_OK;
4756        smessage_stream_params_t params;
4757
4758        BDBG_WRN(("#### SCTE127 0x%x\n", scte127_pid));
4759
4760        if (!p_chm->pscte_127)
4761        {
4762                BDBG_ERR(("%s:%d: SCTE 127 module is not opened",__FILE__, __LINE__));
4763                return eCHM_ERR_FAILED;
4764        }
4765        //chm_scte127_stop(p_chm);
4766
4767        /* clear any pending queue if any */
4768        scte_127_reset(p_chm->pscte_127);
4769        scte_127_enable(p_chm->pscte_127, true);
4770
4771        //p_chm->scte127_msg = smessage_open(bmessage_format_ts);
4772        p_chm->scte127_msg = smessage_open(smessage_format_tsc);
4773        if (NULL == p_chm->scte127_msg)
4774        {
4775                BDBG_ERR(("%s:%d",__FILE__, __LINE__));
4776                cerr = eCHM_ERR_FAILED;
4777                goto ExitFunc;
4778        }
4779        smessage_stream_params_init(&params, p_chm->scte127_msg);
4780        params.band = p_chm->band;
4781        params.pid = scte127_pid;
4782        params.buffer = p_chm->scte127_buf;
4783        params.buffer_size = p_chm->scte127_buf_size;
4784        /* processing is done in callback */
4785        params.data_ready_callback = chm_smessage_scte127_callback;
4786        params.overflow = NULL;
4787        params.callback_context = (void *)p_chm;
4788        params.crc_disabled = true;
4789
4790        if (b_ok != smessage_start(&params, p_chm->scte127_msg))
4791        {
4792                BDBG_ERR(("%s:%d",__FILE__, __LINE__));
4793                cerr = eCHM_ERR_FAILED;
4794        }
4795
4796        ExitFunc:
4797        return cerr;
4798}
4799
4800#endif
4801
4802/*
4803Summary:
4804Start EAS monitoring..
4805 */
4806static int chm_eas_start(chm_mgr_t *p_chm, unsigned short network_pid)
4807{
4808        int cerr = eCHM_ERR_OK;
4809        smessage_stream_params_t params;
4810
4811        chm_eas_stop(p_chm);
4812
4813        p_chm->eas_msg = smessage_open(smessage_format_psi);
4814        if (NULL == p_chm->eas_msg)
4815        {
4816                BDBG_ERR(("%s:%d",__FILE__, __LINE__));
4817                cerr = eCHM_ERR_FAILED;
4818                goto ExitFunc;
4819        }
4820        smessage_stream_params_init(&params, p_chm->eas_msg);
4821        params.band = p_chm->band;
4822        params.pid = 0x1ffb;
4823        params.filter.coef[0] = 0xD8;
4824        params.filter.mask[0] = 0x00;
4825        params.filter.excl[0] = 0xff;
4826        /* All PSIP tables have protocol_version which must be = 0 */
4827        params.filter.coef[8] = 0x00;   /* protocol_version */
4828        params.filter.mask[8] = 0x00;
4829        params.buffer = p_chm->eas_buf;
4830        params.buffer_size = EAS_BUF_LEN;
4831        /* processing is done in callback */
4832        params.data_ready_callback = chm_smessage_eas_callback;
4833        params.overflow = NULL;
4834        params.callback_context = (void *)p_chm;
4835        if (b_ok != smessage_start(&params, p_chm->eas_msg))
4836        {
4837                BDBG_ERR(("%s:%d",__FILE__, __LINE__));
4838                cerr = eCHM_ERR_FAILED;
4839        }
4840        p_chm->eas_timer_started = false;
4841
4842        ExitFunc:
4843        return cerr;
4844}
4845
4846/*
4847Summary:
4848Start CVT monitoring..
4849 */
4850static int chm_cvt_start(chm_mgr_t *p_chm, unsigned short network_pid)
4851{
4852        int cerr = eCHM_ERR_OK;
4853        smessage_stream_params_t params;
4854
4855        BDBG_MSG(("%s:%d (0x%04x)",__FUNCTION__, __LINE__,network_pid));
4856        chm_cvt_stop(p_chm);
4857        p_chm->cvt_msg = smessage_open(smessage_format_psi);
4858        if (NULL == p_chm->cvt_msg)
4859        {
4860                BDBG_ERR(("%s:%d",__FILE__, __LINE__));
4861                cerr = eCHM_ERR_FAILED;
4862                goto ExitFunc;
4863        }
4864        smessage_stream_params_init(&params, p_chm->cvt_msg);
4865        params.band = p_chm->band;
4866        params.pid = (uint16_t)network_pid;
4867        params.filter.coef[0] = 0xD9;
4868        params.filter.mask[0] = 0x00;
4869        params.filter.coef[3] = 0x9f;
4870        params.filter.mask[3] = 0x00;
4871        params.filter.coef[4] = 0x9C;
4872        params.filter.mask[4] = 0x00;
4873        //params.filter.coef[5] = 0x05;
4874        //params.filter.mask[5] = 0x00;
4875        //params.filter.coef[5] = 0x00;
4876        //params.filter.mask[5] = 0x07; /* APDU 0-5, will let cvt_parse to filter out tables other than 2 and 5 */
4877        params.buffer = p_chm->cvt_buf;
4878        params.buffer_size = CVT_BUF_LEN;
4879        /* processing is done in callback */
4880        params.data_ready_callback = chm_smessage_cvt_callback;
4881        params.overflow = NULL;
4882        params.callback_context = (void *)p_chm;
4883        if (b_ok != smessage_start(&params, p_chm->cvt_msg))
4884        {
4885                BDBG_ERR(("%s:%d",__FILE__, __LINE__));
4886                cerr = eCHM_ERR_FAILED;
4887        }
4888        ExitFunc:
4889        return cerr;
4890}
4891
4892/******************************************************************************
4893 * INPUTS:      context
4894 * OUTPUTS:     none.
4895 * RETURNS:     none
4896 * FUNCTION:    message_callback
4897 * DESCRIPTION: Callback function normally called when a complete message has
4898 *              been received and passed the filter criteria.
4899 ******************************************************************************/
4900
4901void chm_download(chm_mgr_t * p_chm)
4902{
4903        bapp_t *p_app;
4904        unsigned int freq_hz;
4905        vch_t vch;
4906        freq_t freq;
4907        st_t    st;
4908        unsigned short ch_num;
4909        unsigned short PID;
4910        struct image_t * image;
4911        size_t retry;
4912        bresult bres;
4913
4914        p_app = (bapp_t*)p_chm->p_app;
4915
4916        /* disable all message processing during download */
4917        chm_eas_stop(p_chm);
4918        chm_stt_stop(p_chm);
4919        chm_cvt_stop(p_chm);
4920        chm_nit_stop(p_chm);
4921        chm_svct_stop(p_chm);
4922        chm_ntt_stop(p_chm);
4923        chm_emm_stop(p_chm);
4924
4925        ch_map_get_current(bapp_cur_ch_map(p_app), &vch,&st,&freq);
4926        ch_num = vch.ch_num;
4927
4928        PID = 0xFFFF;
4929        freq_hz = (unsigned int)-1;
4930
4931        BDBG_ERR(("#### DSMCC DOWNLOAD ####\n"));
4932
4933        switch (p_chm->cvt.location_type)
4934        {
4935        case 0:
4936                if (!ch_map_set(bapp_cur_ch_map(p_app),p_chm->cvt.source_ID))
4937                {
4938                        BDBG_WRN(("#### CVT Failed to locate download source ID = 0x%04x.#### \n", p_chm->cvt.source_ID));
4939                        break;
4940                } else
4941                {
4942                        if (!ch_map_get_current(&(p_app->settings.ch_map), &vch,&st,&freq))
4943                        {
4944                                BDBG_WRN(("#### CVT Could not get frequency for = 0x%04x #### \n", p_chm->cvt.source_ID));
4945                                break;
4946                        }
4947                        freq_hz = freq.freq_khz * 1000;
4948                }
4949                break;
4950
4951        case 1:
4952                freq_hz = p_chm->cvt.frequency_vector * CHM_VECTOR_MULTIPLIER;
4953                PID = p_chm->cvt.pid;
4954                break;
4955        case 2:
4956                freq_hz = p_chm->cvt.frequency_vector * CHM_VECTOR_MULTIPLIER;
4957                vch.program_num = p_chm->cvt.program_number;
4958                break;
4959        }
4960
4961        if (freq_hz == (unsigned int)-1)
4962                goto failed;
4963
4964
4965        BDBG_WRN(("#### CVT Tune %d #### \n", freq.freq_khz * 1000));
4966        if (chm_tune_freq(p_chm,freq_hz,freq.idx) != eCHM_ERR_OK)
4967                goto failed;
4968
4969
4970        if (PID == 0xFFFF)
4971        {
4972                if (chm_get_program_pid(p_chm,p_chm->band, vch.program_num,&PID ) != eCHM_ERR_OK)
4973                {
4974                        BDBG_WRN(("#### CVT Could not find program %d for source_ID 0x%04x, freq = %d\n", vch.program_num,p_chm->cvt.source_ID,freq_hz));
4975                        goto failed;
4976                }
4977        }
4978
4979        if (image_init() != b_ok)
4980        {
4981                BDBG_WRN(("#### CVT Download Init Failed #### \n"));
4982                goto failed;
4983        }
4984
4985        retry = 3;
4986        while (0 != retry)
4987        {
4988                if ( image_receive(p_chm->band,PID,&image, p_chm->cvt.code_file_name_length, &(p_chm->cvt.code_file_name[0])) == b_ok)
4989                {
4990                        break;
4991                }
4992                BDBG_WRN(("#### CVT Download Failed #### \n"));
4993                --retry;
4994        }
4995        if (0 == retry)
4996        {
4997                goto failed;
4998        }
4999        chm_stop_decode(p_chm);
5000        bres = chm_write_software(image);
5001        if (b_ok != bres)
5002        {
5003                goto failed;
5004        }
5005
5006        /* restore channel number to previous video channel */
5007        ch_map_set_ch(bapp_cur_ch_map(p_app),ch_num);
5008
5009        p_app->settings_dirty |= DIRTY_CHANNEL;
5010        bapp_save_settings(p_app);
5011
5012        chip_reset();
5013
5014        failed:
5015        p_chm->cmd = eCHM_TUNE;
5016        ch_map_set_ch(bapp_cur_ch_map(p_app),ch_num);
5017}
5018
5019/*
5020Summary:
5021Steady state loop..
5022 */
5023int chm_start_scte65(chm_mgr_t *p_chm,unsigned short network_pid)
5024{
5025        bapp_t *p_app = (bapp_t*)p_chm->p_app;
5026
5027        chm_emm_start(p_chm,p_app->settings.EMM_PID);
5028
5029        if (!p_app->settings.psi_scan)
5030        {
5031                ch_map_reset(&(p_chm->ch_map));
5032                chm_stt_start(p_chm,network_pid);
5033                chm_cvt_start(p_chm,network_pid);
5034                chm_nit_start(p_chm, network_pid);
5035                chm_svct_start(p_chm, network_pid);
5036                chm_ntt_start(p_chm, network_pid);
5037        }
5038        return eCHM_PROG_IDLE;
5039}
5040
5041#define CHECK_PROGRAM
5042#ifdef CHECK_PROGRAM
5043/*
5044Summary:
5045check the program for changes..
5046 */
5047int chm_check_program(chm_mgr_t *p_chm)
5048{
5049        int result = eCHM_PROG_IDLE;
5050        bapp_t *p_app = (bapp_t*)p_chm->p_app;
5051        vch_t   *vch;
5052        unsigned int pmt_crc,pat_crc;
5053        bool restart = false;
5054
5055        pmt_crc = p_chm->pmt_crc;
5056        pat_crc = p_chm->pat_crc;
5057        /* temporary until we do smart PAT */
5058        vch = &p_chm->vch;
5059        BDBG_MSG(("***** chm_check_program *****\n"));
5060
5061        if ((result = chm_get_program(p_chm,vch)) != 0)
5062        {
5063                BDBG_WRN(("chm_get_program failed %d\n",result));
5064                return eCHM_PROG_IDLE; /* return state expected */
5065        } else
5066        {
5067                if (p_chm->network_pid != p_app->settings.network_PID)
5068                {
5069                        /* Send message to app */
5070                        p_chm->chm_network_evt.type = eCHM_EVT_NETWORK;
5071                        p_chm->chm_network_evt.id = p_chm->network_pid;
5072                        chm_post_app_event(p_chm,&p_chm->chm_network_evt);
5073                        result = eCHM_PROG_SCTE65;
5074                }
5075
5076                /* Check the PIDs match vcm PIDs */
5077                if ((pat_crc != p_chm->pat_crc) || (pmt_crc != p_chm->pmt_crc))
5078                {
5079                        if (vch->pcr_pid != p_chm->vch.pcr_pid)
5080                        {
5081                                BDBG_WRN(("VCM PCR PIDs do not match(0x%04x != 0x%04x)\n",vch->pcr_pid, p_chm->vch.pcr_pid));
5082                                p_chm->vch.pcr_pid = vch->pcr_pid;
5083                                restart = true;
5084                        }
5085                        if (vch->video_pid != p_chm->vch.video_pid)
5086                        {
5087                                BDBG_WRN(("VCM Video PIDs do not match(0x%04x != 0x%04x)\n",vch->video_pid, p_chm->vch.video_pid));
5088                                p_chm->vch.video_pid = vch->video_pid;
5089                                restart = true;
5090                        }
5091                        if ((vch->num_audio < p_chm->vch.cur_audio) || (p_chm->vch.audio_pid[p_chm->vch.cur_audio] != vch->audio_pid[p_chm->vch.cur_audio]))
5092                        {
5093                                /*Fixed error where cur_audio was set to num_audio. */
5094                                if (p_chm->vch.cur_audio >= vch->num_audio)
5095                                        p_chm->vch.cur_audio = 0;
5096                                BDBG_WRN(("VCM Audio PID no longer valid(0x%04x != 0x%04x)\n", vch->audio_pid[p_chm->vch.cur_audio],p_chm->vch.audio_pid[p_chm->vch.cur_audio]));
5097                                memcpy(p_chm->vch.audio_pid,vch->audio_pid,sizeof(unsigned short) * MAX_AUDIO_PIDS);
5098                                memcpy(p_chm->vch.audio_type,vch->audio_type,sizeof(unsigned char) * MAX_AUDIO_PIDS);
5099                                memcpy(p_chm->vch.audio_lang,vch->audio_lang,sizeof(char) * MAX_AUDIO_PIDS * 3);
5100                                restart = true;
5101                        }
5102
5103#ifdef CONFIG_DVB_SUBTITLE
5104                        if ((vch->num_dsub < p_chm->vch.cur_dsub) || (p_chm->vch.dsub_pid[p_chm->vch.cur_dsub] != vch->dsub_pid[p_chm->vch.cur_dsub]))
5105                        {
5106                                if (p_chm->vch.cur_dsub >= vch->num_dsub)
5107                                        p_chm->vch.cur_dsub = 0;
5108                       
5109                                BDBG_WRN(("VCM DSUB PID no longer valid (0x%04x != 0x%04x)", 
5110                                        vch->dsub_pid[p_chm->vch.cur_dsub], p_chm->vch.dsub_pid[p_chm->vch.cur_dsub]));
5111                                BKNI_Memcpy(p_chm->vch.dsub_pid, vch->dsub_pid, sizeof(unsigned short)*MAX_DSUB_PIDS);
5112                                BKNI_Memcpy(p_chm->vch.dsub_lang, vch->dsub_lang, sizeof(unsigned char)*MAX_DSUB_PIDS*3);
5113                                BKNI_Memcpy(p_chm->vch.dsub_page, vch->dsub_page, sizeof(unsigned short)*MAX_DSUB_PIDS);
5114                                restart = true;
5115                        }
5116#endif
5117                        if (restart)
5118                        {
5119                                chm_stop_decode(p_chm);
5120
5121                                p_app->lang = chm_config_mpeg(p_chm,&p_chm->vch);
5122
5123                                if ((result = chm_start_decode(p_chm,true)) != 0)
5124                                {
5125                                        BDBG_WRN(("%s chm_start_decode failed\n",__FUNCTION__));
5126                                }
5127                        }
5128                } else
5129                {
5130                        BDBG_MSG(("####pat_crc or pmt_crc not match####\n"));
5131                }
5132        }
5133        return eCHM_PROG_IDLE;
5134}
5135#endif
5136/*
5137Summary:
5138Steady state loop..
5139 */
5140int chm_info(chm_mgr_t *p_chm)
5141{
5142        bapp_t *p_app = (bapp_t*)p_chm->p_app;
5143        p_chm->network_pid = p_app->settings.network_PID;
5144
5145        while (!chm_check_cancel(p_chm))
5146        {
5147                chm_state_t curstate = p_chm->state;
5148                switch (curstate)
5149                {
5150                case eCHM_PROG_INIT:
5151                        chm_eas_start(p_chm, 0x1FFB);
5152                        p_chm->state = eCHM_PROG_CAT;
5153                        break;
5154                case eCHM_PROG_CAT:
5155                        chm_cat_start(p_chm);
5156                        if (p_chm->network_pid != 0)
5157                                p_chm->state = eCHM_PROG_SCTE65;
5158                        else
5159                                p_chm->state = eCHM_PROG_IDLE;
5160
5161                        break;
5162                case eCHM_PROG_SCTE65:
5163                        p_chm->state = chm_start_scte65(p_chm,p_chm->network_pid);
5164                        break;
5165                case eCHM_PROG_IDLE:
5166                        {
5167                                static unsigned int last_signal_check = 0;
5168//                              static unsigned int last_chmap_check = 0;
5169#ifdef CHECK_PROGRAM
5170                                static unsigned int last_prog_check = 0;
5171
5172                                if (last_prog_check < bos_getticks())
5173                                {
5174                                        p_chm->state = chm_check_program(p_chm);
5175#ifdef  HAS_VBI
5176
5177                                        /* with latest changes, the scte127_pid could be 0 when in eCHM_PROG_INIT state, so check here again */
5178                                        if (p_chm->pscte_127 && p_chm->vch.scte127_pid && !p_chm->scte127_msg)
5179                                        {
5180                                                BDBG_WRN(("Start SCTE 127 packet checking..."));
5181                                                chm_scte127_start(p_chm, p_chm->vch.scte127_pid);
5182                                        }
5183#endif
5184                                        last_prog_check = bos_getticks() + MS_TO_TICKS(CHM_CHECK_PROG_FREQ);
5185                                }
5186#endif
5187#ifdef CONFIG_DVB_SUBTITLE
5188                                if (p_app->dsub && p_chm->vch.dsub_pid[p_chm->vch.cur_dsub] && !p_chm->subtitle_msg)
5189                                {
5190                                        vch_t tmp_vch; st_t tmp_st; freq_t tmp_freq;
5191                                        ch_map_get_current(bapp_cur_ch_map(p_app), &tmp_vch, &tmp_st, &tmp_freq);
5192                                        if (tmp_vch.dsub_pid[tmp_vch.cur_dsub]) {
5193                                                BDBG_WRN(("%s start dvb subtitle %d %x", __FUNCTION__, tmp_vch.cur_dsub, tmp_vch.dsub_pid[tmp_vch.cur_dsub]));
5194                                                chm_subtitle_start(p_chm, tmp_vch.dsub_pid[tmp_vch.cur_dsub]);
5195                                        }
5196                                }
5197#endif
5198#ifdef CONFIG_DVB
5199                                if (!p_chm->dvb_eit_msg)
5200                                        chm_dvb_eit_start(p_chm, p_chm->band);
5201                                if (!p_chm->dvb_tdt_msg)
5202                                        chm_dvb_tdt_start(p_chm, p_chm->band);
5203#endif
5204                                if (last_signal_check < bos_getticks())
5205                                {
5206                                        chm_send_status(p_chm,0,true);
5207                                        last_signal_check = bos_getticks() + MS_TO_TICKS(CHM_CHECK_SIGNAL_FREQ);
5208                                }
5209
5210                                p_chm->chmap_evt.ticks = 0;
5211                                p_chm->chmap_evt.type = eCHM_EVT_STATUS;
5212                                p_chm->chmap_evt.id = eCHM_STATUS_CHMAP;
5213                                /* Compare the NIT - MMS to the current one */
5214                                if (p_chm->mms_changed)
5215                                {
5216                                        if (ch_map_cmp_mms(&(p_chm->ch_map.mms_map),&(p_app->settings.ch_map.mms_map)) != 0)
5217                                                p_chm->chmap_evt.ticks |= 0x8;
5218                                }
5219
5220                                /* Compare the NIT - CDS to the current one */
5221                                if (p_chm->cds_changed)
5222                                {
5223                                        if (ch_map_cmp_freq(&(p_chm->ch_map.freq_map),&(p_app->settings.ch_map.freq_map)) != 0)
5224                                                p_chm->chmap_evt.ticks |= 0x1;
5225                                }
5226
5227                                /* Compare the NTT to the current one */
5228                                if (p_chm->sns_changed)
5229                                {
5230                                        if (ch_map_cmp_st(&(p_chm->ch_map.st_map),&(p_app->settings.ch_map.st_map)) != 0)
5231                                                p_chm->chmap_evt.ticks |= 0x4;
5232                                }
5233
5234                                /* Compare the SVCT to the current one */
5235                                if (p_chm->vcm_changed)
5236                                {
5237                                        if (bos_acquire_mutex(&(p_chm->ch_map_mutex),45) == b_ok)
5238                                        {
5239                                                if (chm_update_programs(p_chm,p_chm->freq.idx) != eCHM_ERR_OK)
5240                                                {
5241                                                        BDBG_WRN(("chm_update_programs failed %s\n",__FUNCTION__));
5242                                                }
5243
5244                                                bos_release_mutex(&(p_chm->ch_map_mutex));
5245                                        } else
5246                                        {
5247                                                BDBG_WRN(("%s:%d failed to acquire channel map mutex\n", __FUNCTION__,__LINE__));
5248                                        }
5249
5250                                        if (ch_map_cmp_vch(&(p_chm->ch_map.vch_map),&(p_app->settings.ch_map.vch_map)) != 0)
5251                                                p_chm->chmap_evt.ticks |= 0x2;
5252                                }
5253
5254                                if (p_chm->chmap_evt.ticks)
5255                                {
5256                                        /* copy channel map so application can perform update without risk of modification by channel manager */
5257                                        chm_post_app_event(p_chm,&p_chm->chmap_evt);
5258                                        p_chm->state = eCHM_PROG_UPDATING;
5259                                        /* p_chm->xxx_changed flags will be reset when filters are restarted */
5260                                }
5261
5262                        }
5263                        break;
5264
5265                        /* Give application time to update channel map before searching for SCTE65 again */
5266                case eCHM_PROG_UPDATING:
5267                        {
5268                                static unsigned int updating_check = 0;
5269
5270                                if (updating_check < bos_getticks())
5271                                {
5272                                        if (updating_check == 0)
5273                                        {
5274                                                updating_check = bos_getticks() + MS_TO_TICKS(CHM_UPDATING_DELAY);
5275                                        } else
5276                                        {
5277                                                updating_check = 0;
5278                                                p_chm->state = eCHM_PROG_SCTE65;
5279                                        }
5280                                }
5281                                break;
5282                        }
5283
5284
5285                }
5286                bos_sleep(CHM_IDLE_TIMEOUT);
5287                if (p_chm->state == curstate)
5288                {
5289                        BDBG_MSG(("p_chm->state is still %d\n",p_chm->state));
5290                } else
5291                {
5292                        BDBG_MSG(("chm state changed from %d to %d\n",curstate,p_chm->state));
5293                }
5294
5295        }
5296
5297        return eCHM_ERR_OK;
5298}
5299
5300/*
5301Summary:
5302Channel Manager Task.
5303 */
5304static void chm_handler(void *data)
5305{
5306        chm_cmd_t orig_cmd;
5307        chm_mgr_t *p_chm = (chm_mgr_t *)data;
5308        chm_cmd_event_t *p_cmd;
5309
5310        while (1)
5311        {
5312                orig_cmd = p_chm->cmd;
5313                switch (p_chm->cmd)
5314                {
5315                case eCHM_CANCEL:
5316                        p_cmd = (chm_cmd_event_t*)bos_pend_event(p_chm->queue,-1);
5317                        if (p_cmd == NULL)
5318                                break;
5319
5320                        p_chm->cmd = (chm_cmd_t)p_cmd->cmd_id;
5321                        break;
5322                case eCHM_SAP:
5323                        p_chm->cmd = eCHM_CANCEL;
5324                        break;
5325               
5326                case eCHM_STOP:
5327                        chm_stop_decode(p_chm);
5328                        p_chm->cmd = eCHM_CANCEL;
5329                        break;
5330
5331                case eCHM_TUNE:
5332                        chm_tune(p_chm); 
5333                        break;
5334                case eCHM_HUNT:
5335                        p_chm->hunt_cnt = 0;
5336                        p_chm->cmd = eCHM_HUNTING;
5337                        break;
5338                case eCHM_HUNTING:
5339                        chm_hunt(p_chm); 
5340                        break;
5341                case eCHM_PENDING_INIT:
5342                        chm_pending_init(p_chm); 
5343                        break;
5344                case eCHM_INFO:
5345                        p_chm->state = eCHM_PROG_INIT;
5346                        chm_info(p_chm);
5347                        break;
5348                case eCHM_CHECK_SIGNAL:
5349                        chm_check_signal(p_chm);
5350                        break;
5351                case eCHM_DOWNLOAD:
5352                        chm_download(p_chm);
5353                        break;
5354                case eCHM_DSUB:
5355#ifdef CONFIG_DVB_SUBTITLE
5356                        p_chm->cmd = eCHM_CANCEL;
5357#endif
5358                        break;
5359                }
5360
5361                if (orig_cmd != p_chm->cmd)
5362                {
5363                        BDBG_WRN(("CHM CMD changed from %s to %s\n", s_chm_cmd_name[orig_cmd],s_chm_cmd_name[p_chm->cmd]));
5364                }
5365
5366                /* Yield a little */
5367                bos_sleep(40);
5368        }
5369}
5370
5371/*
5372Summary:
5373Initialize the channel manager.
5374 */
5375
5376void chm_init(chm_mgr_t *p_chm, void *p_app)
5377{
5378        b_task_params   params;
5379        bresult rc;
5380        memset(p_chm,0,sizeof(chm_mgr_t));
5381        p_chm->p_app = p_app;
5382        p_chm->fe_type = eFREQ_TABLE_NORTH_AMERICA_QAM;
5383
5384        rc = bos_create_queue(&p_chm->queue,p_chm->event,MAX_CHM_EVENT);
5385        BDBG_ASSERT(rc == b_ok);
5386        rc = bos_create_queue(&p_chm->gen_queue,p_chm->gen_event,MAX_MSG_EVENTS);
5387        BDBG_ASSERT(rc == b_ok);
5388        rc = bos_create_mutex(&p_chm->mutex);
5389        BDBG_ASSERT(rc == b_ok);
5390        rc = bos_create_mutex(&p_chm->ch_map_mutex);
5391        BDBG_ASSERT(rc == b_ok);
5392        ch_map_init(&(p_chm->ch_map),&(p_chm->ch_map_mutex));
5393
5394        p_chm->stack = malloc(CHM_INT_STK_SIZE * 4);
5395        BDBG_ASSERT(p_chm->stack);
5396
5397        params.priority = CHM_INT_PRIORITY;
5398        params.stack = p_chm->stack;
5399        params.name = "chan_mgr";
5400        params.stack_size = CHM_INT_STK_SIZE;
5401
5402        p_chm->svct_buf = malloc(SVCT_BUF_LEN);
5403        p_chm->pat_buf = malloc(PAT_BUF_LEN);
5404        p_chm->cat_buf = malloc(CAT_BUF_LEN);
5405        p_chm->pmt_buf = malloc(PMT_BUF_LEN);
5406        p_chm->stt_buf = malloc(STT_BUF_LEN);
5407        p_chm->nit_buf = malloc(NIT_BUF_LEN);
5408        p_chm->ntt_buf = malloc(NTT_BUF_LEN);
5409        p_chm->eas_buf = malloc(EAS_BUF_LEN);
5410        p_chm->cvt_buf = malloc(EAS_BUF_LEN);
5411        p_chm->emm_buf = malloc(EMM_BUF_LEN);
5412
5413#ifdef CONFIG_DVB
5414        p_chm->dvb_nit_buf = malloc(NIT_BUF_LEN);
5415        p_chm->dvb_sdt_buf = malloc(SDT_BUF_LEN);
5416        p_chm->dvb_eit_buf = malloc(EIT_BUF_LEN);
5417        p_chm->dvb_tdt_buf = malloc(TDT_BUF_LEN);
5418       
5419        p_chm->dvb_sdt_cb.data = p_chm;
5420        p_chm->dvb_sdt_cb.cb = chm_dvb_sdt_cb;
5421        p_chm->dvb_nit_cb.data = p_chm;
5422        p_chm->dvb_nit_cb.cb = chm_dvb_nit_cb;
5423
5424        dvb_nit_init(&p_chm->dvb_nit_cb);
5425        dvb_sdt_init(&p_chm->dvb_sdt_cb);
5426        dvb_eit_init();
5427        dvb_tdt_init();
5428#endif
5429        BDBG_ASSERT(p_chm->svct_buf && p_chm->pat_buf && p_chm->pmt_buf && 
5430                                p_chm->stt_buf && p_chm->nit_buf && p_chm->ntt_buf && p_chm->cat_buf);
5431
5432        p_chm->vcm_cb.data = p_chm;
5433        p_chm->vcm_cb.cb = chm_vcm_cb;
5434
5435        p_chm->sns_cb.data = p_chm;
5436        p_chm->sns_cb.cb = chm_sns_cb;
5437
5438        p_chm->cds_cb.data = p_chm;
5439        p_chm->cds_cb.cb = chm_cds_cb;
5440
5441        p_chm->mms_cb.data = p_chm;
5442        p_chm->mms_cb.cb = chm_mms_cb;
5443
5444        SI_SVCT_Init (&p_chm->vcm_cb,0xFF);
5445
5446        SI_NTT_Init (&p_chm->sns_cb,0xFF);
5447
5448        SI_NIT_Init (&p_chm->cds_cb,&p_chm->mms_cb,0xFF,0xFF);
5449
5450        SI_STT_Init ();
5451
5452#ifdef  HAS_VBI
5453        p_chm->pscte_127 = scte_127_init();
5454        BDBG_ASSERT(p_chm->pscte_127);
5455        s_pscte_127 = p_chm->pscte_127;
5456        p_chm->scte127_buf_size = 188 * 1;      /* currently 1 packet */
5457        p_chm->scte127_buf = malloc(p_chm->scte127_buf_size);
5458        BDBG_ASSERT(p_chm->scte127_buf);
5459#endif
5460
5461#ifdef CONFIG_DVB_SUBTITLE
5462        p_chm->subtitle_buf_size = 188*1;
5463        p_chm->subtitle_buf = malloc(p_chm->subtitle_buf_size);
5464#endif
5465
5466        bstream_mpeg_init(&p_chm->mpeg[CURR_CH]);
5467        bstream_mpeg_init(&p_chm->mpeg[NEXT_CH]);
5468        bstream_mpeg_init(&p_chm->mpeg[PREV_CH]);
5469
5470        p_chm->tuner = btuner_open((0));
5471        BAPP_ASSERT(p_chm->tuner);
5472#ifdef BQAM_SCRIPT
5473#if (BCHP_CHIP == 3543)
5474        p_chm->tuner_params.power_tune = true;          /* conduct a power tune in first time */
5475#endif
5476#endif
5477
5478        p_chm->smsg = smessage_open(smessage_format_psi);
5479
5480        BAPP_ASSERT(p_chm->smsg);
5481
5482        p_chm->vendor_id = DEF_VENDOR_ID;
5483        p_chm->hardware_version_id = DEF_HARDWARE_ID;
5484        p_chm->cvt_valid = false;
5485
5486#if defined(ENABLE_UMESSAGE)
5487        cmode_init();
5488#endif
5489
5490        bos_start_task(&p_chm->task,&params,chm_handler,p_chm);
5491
5492#ifdef BCM_DEBUG
5493        BDBG_SetModuleLevel("chan_mgr",BDBG_eWrn);
5494#endif
5495}
5496
5497/*
5498Summary:
5499Function to pass a command to the channel manager.
5500Any results and notification is handled by passing events to the app via
5501the msg_queue.
5502
5503 */
5504void chm_cmd(chm_mgr_t *p_chm,chm_cmd_event_t *p_cmd_evt)
5505{
5506        chm_cmd_t       cmd;
5507
5508        BAPP_ASSERT(p_chm);
5509        BAPP_ASSERT(p_cmd_evt);
5510
5511        cmd = p_cmd_evt->cmd_id;
5512
5513        /* Handle special case to rotate audio */
5514        if ((cmd == eCHM_SAP) && (p_chm->cmd != eCHM_CANCEL))
5515        {
5516                BDBG_WRN(("Command %s, during %s\n",s_chm_cmd_name[cmd], s_chm_cmd_name[p_chm->cmd]));
5517                bos_post_event(p_chm->queue,(b_event_t*)p_cmd_evt);
5518                return;
5519        }
5520#ifdef CONFIG_DVB_SUBTITLE
5521        if ((cmd == eCHM_DSUB) && (p_chm->cmd != eCHM_CANCEL))
5522        {
5523                BDBG_WRN(("Command %s, during %s", s_chm_cmd_name[cmd], s_chm_cmd_name[p_chm->cmd]));
5524                bos_post_event(p_chm->queue,(b_event_t*)p_cmd_evt);
5525                return;
5526        }
5527#endif
5528        if ((cmd != eCHM_CANCEL) && (p_chm->cmd != eCHM_CANCEL))
5529        {
5530                BDBG_WRN(("Canceling previous command %s for %s\n", s_chm_cmd_name[p_chm->cmd],s_chm_cmd_name[cmd]));
5531                p_chm->cancel_cmd.cmd_id = eCHM_CANCEL;
5532                bos_post_event(p_chm->queue,(b_event_t*)&p_chm->cancel_cmd);
5533                bos_sleep(40); /* yield so thread can process event right away */
5534        }
5535
5536        bos_post_event(p_chm->queue,(b_event_t*)p_cmd_evt);
5537        bos_sleep(10); /* yield so thread can process event right away */
5538}
5539
5540bresult chm_write_software(struct image_t * image)
5541{
5542        return image_write(image);
5543}
5544
5545        #define CHM_SC_MASK 0xc0
5546        #define CHM_SC_BUFFER_SIZE (188*10)
5547static unsigned char chm_sc_buffer[CHM_SC_BUFFER_SIZE];
5548
5549static void * chm_sc_callback(void * c, size_t msg_size)
5550{
5551        unsigned int * pdata_ready = (unsigned int *)c;
5552        *pdata_ready = msg_size;
5553        return NULL;
5554}
5555
5556bool chm_check_sc(chm_mgr_t *p_chm, bband_t band, unsigned short pid)
5557{
5558        smessage_stream_t ms;
5559        smessage_stream_params_t params;
5560        bresult bres;
5561        bool result;
5562        unsigned int count;
5563        volatile unsigned int data_ready;
5564        unsigned char * walker;
5565
5566        result = false;
5567        ms = smessage_open(smessage_format_tsc);
5568        if (NULL == ms)
5569        {
5570                BDBG_ERR(("%s : smessage_open failed", __PRETTY_FUNCTION__));
5571                goto ExitFunc;
5572        }
5573        smessage_stream_params_init(&params, ms);
5574        params.band = band;
5575        params.pid = pid;
5576        params.buffer_size = CHM_SC_BUFFER_SIZE;
5577        params.buffer = chm_sc_buffer;
5578        params.data_ready_callback = chm_sc_callback;
5579        params.overflow = chm_sc_callback;
5580        params.callback_context = (void *)&data_ready;
5581        data_ready = 0;
5582        bres = smessage_start(&params, ms);
5583        if (b_ok != bres)
5584        {
5585                smessage_close(ms);
5586                BDBG_ERR(("%s : smessage_start", __PRETTY_FUNCTION__));
5587                goto ExitFunc;
5588        }
5589        /* Updating unsigned int is atomic operation on mips. We can just wait for
5590           callback to update our flag when data is ready */
5591        count = 3;
5592        do
5593        {
5594                bos_sleep(50);
5595                count--;
5596        }while ((0 == data_ready)&&(0 != count));
5597
5598        bres = smessage_stop(ms);
5599        if (b_ok != bres)
5600        {
5601                smessage_close(ms);
5602                BDBG_ERR(("%s : smessage_stop", __PRETTY_FUNCTION__));
5603                goto ExitFunc;
5604        }
5605        smessage_close(ms);
5606        /* Figure out if we got data and if sc flags are set */
5607        if (0 != data_ready)
5608        {
5609                /* We have data. Check few packets for sc bits */
5610                walker = chm_sc_buffer;
5611                for (count = 0; count < 5; count++)
5612                {
5613                        if (0 != (walker[3] & CHM_SC_MASK))
5614                        {
5615                                goto ExitFunc;
5616                        }
5617                        walker += 188;
5618                }
5619                result = true;
5620        }
5621        ExitFunc:
5622        BDBG_ERR(("pid %d %s", pid, (result == true ? "clear" : "encr")));
5623        return result;
5624}
5625
5626#ifdef CONFIG_DVB
5627/*
5628 * Update the source desc entry
5629 * If NIT delivers the channel list about SDT's service id, just add or update st
5630 * Otherwise add vch entry first and then insert SDT entry
5631 */
5632static void chm_dvb_sdt_cb(sdt_t *sdt, void *data)
5633{
5634        chm_mgr_t *p_chm = (chm_mgr_t *)data;
5635        vch_t vch;
5636        st_t st;
5637        int freq_idx;
5638
5639        if (!p_chm->ch_map.freq_map.num_freq) {
5640                BDBG_WRN(("frequency map doesn't exist"));
5641                return;
5642        }
5643
5644        for (freq_idx=0; freq_idx<p_chm->ch_map.freq_map.num_freq; freq_idx++) {
5645                if (p_chm->ch_map.freq_map.freq[freq_idx].freq_khz == sdt->frequency) 
5646                        break;
5647        }
5648
5649        if (freq_idx == p_chm->ch_map.freq_map.num_freq) {
5650                BDBG_WRN(("frequency map is not matched with sdt's frequency"));
5651                return;
5652        }
5653
5654        vch.program_num = sdt->service_id;
5655
5656        /* some stream didn't deliver correct channel list in nit.
5657         * in this case, add vch based on the SDT table */
5658        if (ch_map_is_new_vch(&(p_chm->ch_map), &vch)) {
5659                if (freq_idx == p_chm->ch_map.freq_map.num_freq) {
5660                        BDBG_WRN(("couldn't find frequency entry for SDT entry"));
5661                        return;
5662                }
5663                BKNI_Memset(&vch, 0, sizeof(vch_t));
5664                vch.freq_idx = freq_idx;
5665                vch.ch_num = (unsigned short)s_channel_num++;
5666                vch.source_id = sdt->service_id;
5667                vch.mms_idx = freq_idx; //p_chm->ch_map.mms_map.num_mms-1;
5668                vch.program_num = sdt->service_id;
5669                vch.vchflags = 0;
5670                ch_map_add_vch(&(p_chm->ch_map),&vch);
5671        }
5672       
5673        BKNI_Memset(&st, 0, sizeof(st_t));
5674        st.source_id = sdt->service_id;
5675        if (sdt->service_name[0]) {
5676                if (sdt->service_name[0] < 0x20) 
5677                        BKNI_Memcpy(st.name, &sdt->service_name[1], strlen(sdt->service_name)-1);
5678                else
5679                        BKNI_Memcpy(st.name, sdt->service_name, strlen(sdt->service_name));
5680        }
5681        else {
5682                snprintf(st.name,MAX_VCH_LEN,"Ch - %d.%d",vch.freq_idx + 2,vch.program_num);
5683        }
5684        ch_map_add_update_st(&(p_chm->ch_map),&st);
5685}
5686
5687/*
5688 * NIT delivers
5689 *  - list of frequency where system is supporting
5690 *  - list of services even though service is in other frequency
5691 */
5692static void chm_dvb_nit_cb(nit_t *nit, void *data)
5693{
5694        chm_mgr_t *p_chm = (chm_mgr_t *)data;
5695        freq_t freq;
5696        vch_t vch;
5697        st_t st;
5698        mms_t mms;
5699        int i;
5700       
5701        if (nit && nit->frequency) {
5702                freq.idx = (unsigned char)p_chm->ch_map.freq_map.num_freq;
5703                freq.freq_khz = nit->frequency; 
5704                ch_map_add_freq(&(p_chm->ch_map), &freq);
5705
5706                BKNI_Memset(&mms, 0, sizeof(mms));
5707                mms.idx = freq.idx;
5708                mms.symbol_rate = nit->symbol_rate;
5709                switch(nit->symbol_rate) {
5710                        case eQAM_64: mms.modulation = eQAM_64; break;
5711                        case eQAM_256:
5712                        case eQAM_1024: mms.modulation = eQAM_256; break;
5713                        default:
5714                                mms.modulation = eQAM_Scan; break;
5715                }
5716                mms.code_rate = nit->code_rate;
5717                p_chm->mms_flag = true; 
5718                ch_map_add_mms(&(p_chm->ch_map), &mms);
5719
5720                BDBG_WRN(("[%d] %d KHz (%d)", p_chm->ch_map.freq_map.num_freq-1, freq.freq_khz, nit->program_cnt));
5721                for (i=0; i<nit->program_cnt; i++) {
5722                        BKNI_Memset(&vch, 0, sizeof(vch_t));
5723                        vch.freq_idx = freq.idx;
5724                        vch.ch_num = (unsigned short)s_channel_num++;
5725                        vch.source_id = nit->program_id[i];
5726                        vch.mms_idx = freq.idx;
5727                        vch.program_num = nit->program_id[i];
5728                        vch.vchflags = 0;
5729                        ch_map_add_vch(&(p_chm->ch_map), &vch);
5730
5731                        BKNI_Memset(&st, 0, sizeof(st_t));
5732                        st.source_id = nit->program_id[i];
5733                        snprintf(st.name,MAX_VCH_LEN,"Ch - %d.%d", vch.freq_idx+2, vch.program_num);
5734                        ch_map_add_st(&(p_chm->ch_map), &st);   
5735                }
5736        }
5737       
5738}
5739
5740static void chm_dvb_nit_stop(chm_mgr_t *p_chm)
5741{
5742        if (NULL != p_chm->dvb_nit_msg) {
5743                if (b_ok != smessage_stop(p_chm->dvb_nit_msg))
5744                {
5745                        BDBG_ERR(("%s:%d", __FILE__, __LINE__));
5746                        return;
5747                }
5748                smessage_close(p_chm->dvb_nit_msg);
5749                p_chm->dvb_nit_msg = NULL;
5750        }
5751}
5752
5753static void chm_dvb_sdt_stop(chm_mgr_t *p_chm)
5754{
5755        if (NULL != p_chm->dvb_sdt_msg) {
5756                if (b_ok != smessage_stop(p_chm->dvb_sdt_msg))
5757                {
5758                        BDBG_ERR(("%s:%d", __FILE__, __LINE__));
5759                        return;
5760                }
5761                smessage_close(p_chm->dvb_sdt_msg);
5762                p_chm->dvb_sdt_msg = NULL;
5763        }
5764}
5765
5766static void chm_dvb_eit_stop(chm_mgr_t *p_chm)
5767{
5768        if (NULL != p_chm->dvb_eit_msg) {
5769                if (b_ok != smessage_stop(p_chm->dvb_eit_msg))
5770                {
5771                        BDBG_ERR(("%s:%d", __FILE__, __LINE__));
5772                        return;
5773                }
5774                smessage_close(p_chm->dvb_eit_msg);
5775                p_chm->dvb_eit_msg = NULL;
5776        }
5777}
5778
5779static void chm_dvb_tdt_stop(chm_mgr_t *p_chm)
5780{
5781        if (NULL != p_chm->dvb_tdt_msg) {
5782                if (b_ok != smessage_stop(p_chm->dvb_tdt_msg))
5783                {
5784                        BDBG_ERR(("%s:%d", __FILE__, __LINE__));
5785                        return;
5786                }
5787                smessage_close(p_chm->dvb_tdt_msg);
5788                p_chm->dvb_tdt_msg = NULL;
5789        }
5790}
5791       
5792static void *chm_smessage_dvb_nit_callback(void *context, size_t size)
5793{
5794        chm_mgr_t *p_chm = (chm_mgr_t *)context;
5795        unsigned int nit_section_size = size;
5796        unsigned int crc32;
5797
5798        crc32 = chm_section_crc(p_chm->dvb_nit_buf, size);
5799        BDBG_MSG(("### DVB NIT EVENT ###\n"));
5800       
5801        dvb_nit_parse(p_chm->dvb_nit_buf, &nit_section_size);
5802        return(void*)p_chm->dvb_nit_buf;
5803}
5804
5805static int chm_dvb_nit_start(chm_mgr_t *p_chm, bband_t band)
5806{
5807        int cerr = eCHM_ERR_OK;
5808        smessage_stream_params_t params;
5809
5810        chm_dvb_nit_stop(p_chm);
5811        BDBG_WRN(("dvb_nit_start..."));
5812       
5813        p_chm->dvb_nit_msg = smessage_open(smessage_format_psi);
5814        if (NULL == p_chm->dvb_nit_msg) 
5815        {
5816                BDBG_ERR(("%s:%d", __FILE__, __LINE__));
5817                cerr = eCHM_ERR_FAILED;
5818                goto ExitFunc;
5819        }
5820        smessage_stream_params_init(&params, p_chm->dvb_nit_msg);
5821        params.band = p_chm->band;
5822        params.pid = DVB_PID_NIT;
5823        params.filter.coef[0] = DVB_TID_NIT_OTH;
5824        params.filter.mask[0] = 0x01;
5825        params.filter.excl[0] = 0xff;
5826        params.buffer = p_chm->dvb_nit_buf;
5827        params.buffer_size = NIT_BUF_LEN;
5828        params.data_ready_callback = chm_smessage_dvb_nit_callback;
5829        params.overflow = NULL;
5830        params.callback_context = (void *)p_chm;
5831        if (b_ok != smessage_start(&params, p_chm->dvb_nit_msg))
5832        {
5833                BDBG_ERR(("%s:%d", __FILE__, __LINE__));
5834                cerr = eCHM_ERR_FAILED;
5835        }
5836ExitFunc:
5837        return cerr;
5838}
5839
5840static void *chm_smessage_dvb_sdt_callback(void *context, size_t size)
5841{
5842        chm_mgr_t *p_chm = (chm_mgr_t *)context;
5843        unsigned int sdt_section_size = size;
5844        unsigned int crc32;
5845
5846        crc32 = chm_section_crc(p_chm->dvb_sdt_buf, size);
5847        BDBG_MSG(("### DVB SDT EVENT ###"));
5848        dvb_sdt_parse(p_chm->dvb_sdt_buf, &sdt_section_size);
5849        return(void*)p_chm->dvb_sdt_buf;
5850}
5851
5852static int chm_dvb_sdt_start(chm_mgr_t *p_chm, bband_t band)
5853{
5854        int cerr = eCHM_ERR_OK;
5855        smessage_stream_params_t params;
5856
5857        chm_dvb_sdt_stop(p_chm);
5858        BDBG_WRN(("dvb_sdt_start..."));
5859       
5860        p_chm->dvb_sdt_msg = smessage_open(smessage_format_psi);
5861        if (NULL == p_chm->dvb_sdt_msg)
5862        {
5863                BDBG_ERR(("%s:%d", __FILE__, __LINE__));
5864                cerr = eCHM_ERR_FAILED;
5865                goto ExitFunc;
5866        }
5867
5868        smessage_stream_params_init(&params, p_chm->dvb_sdt_msg);
5869        params.band = band;
5870        params.pid = DVB_PID_SDT;
5871        params.filter.coef[0] = DVB_TID_SDT_OTH;
5872        params.filter.mask[0] = 0x04;
5873        params.filter.excl[0] = 0xff;
5874        params.buffer = p_chm->dvb_sdt_buf;
5875        params.buffer_size = SDT_BUF_LEN;
5876        params.data_ready_callback = chm_smessage_dvb_sdt_callback;
5877        params.overflow = NULL;
5878        params.callback_context = (void *)p_chm;
5879        if (b_ok != smessage_start(&params, p_chm->dvb_sdt_msg))
5880        {
5881                BDBG_ERR(("%s:%d", __FILE__, __LINE__));
5882                cerr = eCHM_ERR_FAILED;
5883        }       
5884ExitFunc:
5885        return cerr;
5886}
5887
5888static void *chm_smessage_dvb_eit_callback(void *context, size_t size)
5889{
5890        chm_mgr_t *p_chm = (chm_mgr_t *)context;
5891        unsigned int eit_section_size = size;
5892        unsigned int crc32;
5893
5894        crc32 = chm_section_crc(p_chm->dvb_eit_buf, size);
5895        dvb_eit_parse(p_chm->dvb_eit_buf, &eit_section_size);
5896        return(void*)p_chm->dvb_eit_buf;
5897}
5898
5899static int chm_dvb_eit_start(chm_mgr_t *p_chm, bband_t band)
5900{
5901        int cerr = eCHM_ERR_OK;
5902        smessage_stream_params_t params;
5903
5904        chm_dvb_eit_stop(p_chm);
5905        BDBG_MSG(("eit_start..."));
5906       
5907        p_chm->dvb_eit_msg = smessage_open(smessage_format_psi);
5908        if (NULL == p_chm->dvb_eit_msg)
5909        {
5910                BDBG_ERR(("%s:%d", __FILE__, __LINE__));
5911                cerr = eCHM_ERR_FAILED;
5912                goto ExitFunc;
5913        }
5914        smessage_stream_params_init(&params, p_chm->dvb_eit_msg);
5915        params.band = band;
5916        params.pid = DVB_PID_EIT;
5917#ifndef SUPPORT_DVB_SCHED_EVENT
5918        params.filter.coef[0] = DVB_TID_EIT_OTH;
5919        params.filter.mask[0] = 0x01;
5920#else
5921        params.filter.coef[0] = 0x5F; // not process EIT_SCHED_OTH
5922        params.filter.mask[0] = 0x1F;
5923#endif
5924        params.filter.excl[0] = 0xFF;
5925        params.buffer = p_chm->dvb_eit_buf;
5926        params.buffer_size = EIT_BUF_LEN;
5927        params.data_ready_callback = chm_smessage_dvb_eit_callback;
5928        params.overflow = NULL;
5929        params.callback_context = (void *)p_chm;
5930        if (b_ok != smessage_start(&params, p_chm->dvb_eit_msg))
5931        {
5932                BDBG_ERR(("%s:%d", __FILE__, __LINE__));
5933                cerr = eCHM_ERR_FAILED;
5934        }
5935ExitFunc:
5936        return cerr;   
5937}
5938
5939static void *chm_smessage_dvb_tdt_callback(void *context, size_t size)
5940{
5941        chm_mgr_t *p_chm = (chm_mgr_t *)context;
5942        unsigned int tdt_section_size = size;
5943        unsigned int crc32;
5944        b_tm cur_time;
5945                       
5946        crc32 = chm_section_crc(p_chm->dvb_tdt_buf, size);
5947        if (dvb_tdt_parse(p_chm->dvb_tdt_buf, &tdt_section_size)) {
5948                crc32 = dvb_get_cur_time();
5949                utctime(crc32, &cur_time);
5950                BDBG_MSG(("############### %d/%02d/%02d %02d:%02d:%02d", 
5951                        cur_time.tm_year+1980, cur_time.tm_mon+1, cur_time.tm_mday,  cur_time.tm_hour, cur_time.tm_min, cur_time.tm_sec));
5952        }
5953        return (void *)p_chm->dvb_tdt_buf;
5954}
5955
5956static int chm_dvb_tdt_start(chm_mgr_t *p_chm, bband_t band)
5957{
5958        int cerr = eCHM_ERR_OK;
5959        smessage_stream_params_t params;
5960       
5961        chm_dvb_tdt_stop(p_chm);
5962        BDBG_MSG(("tdt_start..."));
5963
5964        p_chm->dvb_tdt_msg = smessage_open(smessage_format_psi);
5965        if (NULL == p_chm->dvb_tdt_msg)
5966        {
5967                BDBG_ERR(("%s:%d", __FILE__, __LINE__));
5968                cerr = eCHM_ERR_FAILED;
5969                goto ExitFunc;
5970        }
5971
5972        smessage_stream_params_init(&params, p_chm->dvb_tdt_msg);
5973        params.band = band;
5974        params.pid = DVB_PID_TDT;
5975        params.filter.coef[0] = DVB_TID_TIME_OFFSET; 
5976        params.filter.mask[0] = 0x03;
5977        params.filter.excl[0] = 0xFF;
5978        params.buffer = p_chm->dvb_tdt_buf;
5979        params.buffer_size = TDT_BUF_LEN;
5980        params.data_ready_callback = chm_smessage_dvb_tdt_callback;
5981        params.overflow = NULL;
5982        params.callback_context = (void *)p_chm;
5983        if (b_ok != smessage_start(&params, p_chm->dvb_tdt_msg))
5984        {
5985                BDBG_ERR(("%s:%d", __FILE__, __LINE__));
5986                cerr = eCHM_ERR_FAILED;
5987        }
5988ExitFunc:
5989        return cerr;
5990}
5991
5992#endif
5993
5994#ifdef CONFIG_DVB_SUBTITLE
5995static void chm_subtitle_stop(chm_mgr_t *p_chm)
5996{
5997        BDBG_WRN(("STOP dvb subtitle 0x%x", p_chm->subtitle_msg));
5998        if (NULL != p_chm->subtitle_msg)
5999        {
6000                if (b_ok != smessage_stop(p_chm->subtitle_msg))
6001                {
6002                        BDBG_ERR(("%s:%d", __FILE__, __LINE__));
6003                        return;
6004                }
6005                smessage_close(p_chm->subtitle_msg);
6006                p_chm->subtitle_msg = NULL;
6007        }
6008}
6009
6010void *chm_smessage_subtitle_callback(void *context, size_t size)
6011{
6012        chm_mgr_t *p_chm = (chm_mgr_t *)context;
6013
6014        bapp_dsub_process(p_chm->subtitle_buf, size);
6015        return (void *)p_chm->subtitle_buf;
6016}
6017
6018static int chm_subtitle_start(chm_mgr_t *p_chm, uint16_t dsub_pid)
6019{
6020        int cerr = eCHM_ERR_OK;
6021        smessage_stream_params_t params;
6022
6023        BDBG_WRN(("Start DVB SUBTITLE pid 0x%04x", dsub_pid));
6024       
6025        p_chm->subtitle_msg = smessage_open(smessage_format_tsc);
6026        if (NULL == p_chm->subtitle_msg)
6027        {
6028                BDBG_ERR(("%s:%d", __FILE__, __LINE__));
6029                cerr = eCHM_ERR_FAILED;
6030                goto ExitFunc;
6031        }
6032
6033        smessage_stream_params_init(&params, p_chm->subtitle_msg);
6034        params.band = p_chm->band;
6035        params.pid = dsub_pid;
6036        params.buffer = p_chm->subtitle_buf;
6037        params.buffer_size = p_chm->subtitle_buf_size;
6038
6039        params.data_ready_callback = chm_smessage_subtitle_callback;
6040        params.overflow = NULL;
6041        params.callback_context = (void *)p_chm;
6042        params.crc_disabled = true;
6043
6044        if (b_ok != smessage_start(&params, p_chm->subtitle_msg))
6045        {
6046                BDBG_ERR(("%s:%d", __FILE__, __LINE__));
6047                cerr = eCHM_ERR_FAILED;
6048        }
6049ExitFunc:
6050        return cerr;
6051}               
6052
6053#endif
Note: See TracBrowser for help on using the repository browser.