source: svn/newcon3bcm2_21bu/dst/dmw/src/psi/DMW_PsiEngine.c @ 45

Last change on this file since 45 was 45, checked in by megakiss, 11 years ago
  • Property svn:executable set to *
File size: 76.9 KB
Line 
1/*
2        DMW_PsiEngine.c
3
4        DST TV MW PSI Scan Module
5
6        PSI Scan Core Engine implementation
7
8        Copyright 2006~2009 Digital STREAM Technology, Inc.
9        All Rights Reserved
10
11*/
12
13#include "DMW_Platform.h"
14
15// dlib headers
16#include "DLIB_PSI_Parser.h"
17#include "DLIB_PSIP_Parser.h"
18#include "DLIB_PSI_Monitor.h"
19#include "DLIB_PSIP_Monitor.h"
20
21
22#include "DMW_PsiConfig.h"
23#include "DMW_PsiEngine.h"
24#include "DMW_PsiDatabase.h"
25#include "DMW_PsiUtil.h"
26
27
28DHL_MODULE("psieng", 1);
29
30
31
32#if COMMENT
33____Configs____(){}
34#endif
35
36
37int gPsiIgnoreEtmLocationInfo = 0;
38        // ETM location Á¤º¸°¡ Á¦´ë·Î µÇ¾î ÀÖ´ÂÁö Å×½ºÆ® Çϱâ À§ÇÏ »ç¿ëÇÏ´Â °ª..
39        // Àִµ¥ ¾ø´Ù°í ¼ÓÀÌ´Â °Ç ¾Æ´ÑÁö Å×½ºÆ®..
40        // ÀϹÝÀûÀÎ »óȲ¿¡¼­´Â »ç/¿ë/±Ý/Áö/!!!
41        //
42        // cafrii 060112
43        // ÀϺΠcustomerÀÇ ¿ä±¸¿¡ ÀÇÇØ ÀÌ ¿É¼ÇÀ» »ç¿ëÇÒ ¼ö ÀÖµµ·Ï ÇÔ.
44        // À̸§¿¡¼­ "Test" »èÁ¦
45        //
46        // cafrii 060320 add comment
47        // UpdateEtt ÇÔ¼ö ¾È¿¡¼­´Â ÀÌ º¯¼ö¸¦ Âü°íÇÏ¿© ¹«Á¶°Ç ett monitor ½ÃµµÇÏ°Ô µÈ´Ù.
48        // ±×·¯³ª ettÀÇ ¼ö½Å¿©ºÎ¸¦ üũÇÏ´Â ÇÔ¼ö¿¡¼­´Â ÀÌ º¯¼ö¸¦ °í·ÁÇÏÁö ¾ÊÀ¸¹Ç·Î
49        // ¸ø¹Þ¾ÒÀ½¿¡µµ ºÒ±¸Çϰí ett complete·Î °£ÁֵǾî¹ö¸°´Ù. µû¶ó¼­ retry¸¦ ÇÏÁö ¾Ê´Â´Ù.
50        // Áï first try¿¡ download ¼º°øÇÏÁö ¾ÊÀ¸¸é ±× ÈÄ¿¡´Â retryÁ¶Â÷ ¾ÈµÇ°í °è¼Ó ¾È¹ÞÀ½.
51        // epg_print¿¡¼­´Â ±×³É noneÀ¸·Î Ç¥½ÃµÊ.
52        //
53        // ¸¸¾à ett ¼ö½Å¿©ºÎ üũÇÏ´Â ÇÔ¼ö¿¡±îÁö Àû¿ëÇÏ°Ô µÇ¸é,
54        // etm_noneÀÌ Çϳª¶óµµ Á¸ÀçÇÏ´Â ½ºÆ®¸²¿¡¼­´Â ¿µ¿øÀÌ complete°¡ ¾ÈµÉ ¼ö ÀÖÀ¸¹Ç·Î À§Çè.
55        // ±×·¡¼­ ±×³É À§ÀÇ ´ÜÁ¡¿¡µµ ºÒ±¸Çϰí ÀϺθ¸ Àû¿ëÇϵµ·Ï ÇÑ´Ù.
56
57
58
59#if COMMENT
60____Types____(){}
61#endif
62
63
64#undef IsError
65#undef ErrorString
66
67#define IsError(e) ((e)!=0)
68#define ErrorString(e) p_dhr2str(e)
69
70/* psi engine task¿¡¼­¸¸ »ç¿ëÇÑ´Ù´Â ÀüÁ¦·Î static ¹öÆÛ »ç¿ëÇϵµ·Ï ÇÏÀÚ.
71*/
72static const char *p_dhr2str(DHL_RESULT dhr) 
73{
74        static char buf[10];
75        sprintf(buf, "0x%x", dhr);
76        return buf;
77}
78
79
80
81#if COMMENT
82____EngineModule____(){}
83#endif
84
85// this is singleton object. should be unique.
86
87S_PSIM_CONTEXT *g_psi_engine;
88
89
90#if COMMENT
91____DbgPrint____(){}
92#endif
93
94
95int g_Trace_bPsiEvent = 1;
96int g_Trace_bPsiSttInfo = 1;
97
98
99#if COMMENT
100____Declare____(){}
101#endif
102
103
104
105// forward declaration
106// this is the only psi table event proc.
107PSI_STATIC void _PsiTableEventProc(tDHL_PSI_Event psiEvent, tDHL_PSI_ControlHandle psiCtl, UINT32 userParam);
108
109
110
111
112
113#if COMMENT
114____Private____(){}
115#endif
116
117
118PSI_STATIC void SendUserCallback(S_PSIM_PORT *tsport, E_PSIM_EVENT event, UINT32 param)
119{
120        S_PSIM_USER_INPUT *input = (S_PSIM_USER_INPUT *) &tsport->input;
121
122        if (input->userproc)
123                (*(input->userproc))(tsport->tsd, event, param);
124}
125
126#if 0
127PSI_STATIC void SendEventChannelStarted(S_PSIM_PORT *tsport, int id)
128{
129        S_PSIM_CH_START_CB_PARAM ccb;
130        S_PSIM_CHINFO *chInfo;
131
132        return; //test..
133
134        chInfo = PSIDB_GetPsiChInfo(id);
135       
136        if (1) //if (chInfo->channel_start_notified == 0)
137        {
138                memset(&ccb, 0, sizeof(ccb));
139               
140                ccb.id = chInfo->id;
141                ccb.tsd = chInfo->tsd;
142                ccb.mgt = chInfo->mgt;
143                ccb.vct = chInfo->vct;
144                ccb.n_subchannel = chInfo->n_subchannel;
145
146                SendUserCallback(tsport, ePSIM_EVENT_BasePsipReceived, 0);
147                SendUserCallback(tsport, ePSIM_EVENT_ChannelStarted, (UINT32) &ccb);
148                //chInfo->channel_start_notified = 1;
149        }
150}
151
152PSI_STATIC void SendEventSubchannelStarted(S_PSIM_PORT *tsport, int id, int source_id)
153{
154        S_PSIM_SUBCH_START_CB_PARAM sccb;
155        S_PSIM_SUBCHINFO *subchInfo;
156
157        subchInfo = PSIDB_GetPsiSubChInfo(id, source_id);
158       
159        if (subchInfo->subchannel_start_notified == 0) {
160                memset(&sccb, 0, sizeof(sccb));
161               
162                sccb.index = subchInfo->index;
163                sccb.source_id = subchInfo->source_id;
164                sccb.flags = tsport->input.flags;
165
166        #if 0 // Á¤È®ÇÏ°Ô °°Áö ¾ÊÀº °æ¿ì buffer overflow µîÀÇ ¹®Á¦ ¹ß»ý..
167                //memcpy(&sccb.vct_info, &subchInfo->vct_info, sizeof(sccb.vct_info));
168        #else
169                memcpy(sccb.vct_info.short_name, subchInfo->vct_info.short_name, sizeof(sccb.vct_info.short_name));
170                sccb.vct_info.major_channel_number = subchInfo->vct_info.major_channel_number;
171                sccb.vct_info.minor_channel_number = subchInfo->vct_info.minor_channel_number;
172                sccb.vct_info.program_number = subchInfo->vct_info.program_number;
173        #endif
174               
175                SendUserCallback(tsport, ePSIM_EVENT_SubChannelStarted, (UINT32) &sccb);
176                subchInfo->subchannel_start_notified = 1;
177        }
178}
179
180PSI_STATIC void SendEventEitsCompleted(S_PSIM_PORT *tsport, S_PSIM_SUBCHINFO *subchInfo)
181{
182        S_PSIM_COMPLETE_CB_PARAM cmcb;
183
184        if (subchInfo->eit_complete_notified == 0) {
185                cmcb.id = subchInfo->parent->id;
186                cmcb.index = subchInfo->index;
187                cmcb.source_id = subchInfo->source_id;
188               
189                SendUserCallback(tsport, ePSIM_EVENT_EitsCompleted, (UINT32) &cmcb);
190                subchInfo->eit_complete_notified = 1;
191        }
192}
193
194PSI_STATIC void SendEventSubchannelCompleted(S_PSIM_PORT *tsport, S_PSIM_SUBCHINFO *subchInfo)
195{
196        S_PSIM_COMPLETE_CB_PARAM cmcb;
197
198        if (subchInfo->subchannel_complete_notified == 0) {
199                cmcb.id = subchInfo->parent->id;
200                cmcb.index = subchInfo->index;
201                cmcb.source_id = subchInfo->source_id;
202               
203                SendUserCallback(tsport, ePSIM_EVENT_SubChannelCompleted, (UINT32) &cmcb);
204                subchInfo->subchannel_complete_notified = 1;
205        }
206}
207
208PSI_STATIC void SendEventChannelCompleted(S_PSIM_PORT *tsport, S_PSIM_CHINFO *chInfo)
209{
210        S_PSIM_COMPLETE_CB_PARAM cmcb;
211       
212        if (chInfo->channel_complete_notified == 0) {
213                cmcb.id = chInfo->id;
214                cmcb.index = 0;
215                cmcb.source_id = 0;
216               
217                SendUserCallback(tsport, ePSIM_EVENT_ChannelCompleted, (UINT32) &cmcb);
218                chInfo->channel_complete_notified = 1;
219        }
220}
221
222#endif
223
224
225#if COMMENT
226____Start_Stop____(){}
227#endif
228
229
230void StopMonitorPAT(S_PSIM_PORT *tsport)
231{
232        if (tsport->patPsiCtl) {
233                dprint(3, "cancel prev pat monitor\n");
234                DHL_PSI_StopMonitor(tsport->patPsiCtl);
235                tsport->patPsiCtl = (tDHL_PSI_ControlHandle)0;
236                tsport->n_active_monitors--;
237        }
238}
239
240void StopMonitorPMTs(S_PSIM_PORT *tsport)
241{
242        int i;
243        if (tsport->num_programs) {
244                dprint(3, "cancel all %d pmt ctls..\n", tsport->num_programs);
245                for (i=0; i<tsport->num_programs; i++) {
246                        if (tsport->pmtPsiCtlArray[i]) {
247                                DHL_PSI_StopMonitor(tsport->pmtPsiCtlArray[i]);
248                                tsport->pmtPsiCtlArray[i] = (tDHL_PSI_ControlHandle)0;
249                                tsport->n_active_monitors--;
250                        }
251                }
252        }
253        if (tsport->pmtPsiCtlArray)
254                DHL_OS_Free((void **)&tsport->pmtPsiCtlArray);
255        tsport->num_programs = 0;
256}
257
258void StopMonitorMgt(S_PSIM_PORT *tsport)
259{
260        if (tsport->mgtPsiCtl) {
261                dprint(3, "cancel prev mgt monitor\n");
262                DHL_PSI_StopMonitor(tsport->mgtPsiCtl);
263                tsport->mgtPsiCtl = (tDHL_PSI_ControlHandle)0;
264                tsport->n_active_monitors--;
265        }
266}
267void StopMonitorTvct(S_PSIM_PORT *tsport)
268{
269        if (tsport->tvctPsiCtl) {
270                dprint(3, "cancel prev tvct monitor\n");
271                DHL_PSI_StopMonitor(tsport->tvctPsiCtl);
272                tsport->tvctPsiCtl = (tDHL_PSI_ControlHandle)0;
273                tsport->n_active_monitors--;
274        }
275}
276void StopMonitorCvct(S_PSIM_PORT *tsport)
277{
278        if (tsport->cvctPsiCtl) {
279                dprint(3, "cancel prev cvct monitor\n");
280                DHL_PSI_StopMonitor(tsport->cvctPsiCtl);
281                tsport->cvctPsiCtl = (tDHL_PSI_ControlHandle)0;
282                tsport->n_active_monitors--;
283        }
284}
285
286void StopMonitorStt(S_PSIM_PORT *tsport)
287{
288        if (tsport->sttPsiCtl) {
289                dprint(3, "cancel prev stt monitor\n");
290                DHL_PSI_StopMonitor(tsport->sttPsiCtl);
291                tsport->sttPsiCtl = (tDHL_PSI_ControlHandle)0;
292                tsport->n_active_monitors--;
293        }
294}
295
296void StopMonitorRrt(S_PSIM_PORT *tsport)
297{
298        if (tsport->rrtPsiCtl) {
299                dprint(3, "cancel prev rrt monitor\n");
300                DHL_PSI_StopMonitor(tsport->rrtPsiCtl);
301                tsport->rrtPsiCtl = (tDHL_PSI_ControlHandle)0;
302                tsport->n_active_monitors--;
303        }
304}
305
306void StopMonitorEit(S_PSIM_PORT *tsport, int iEit)
307{
308        if (iEit < 0 || iEit >= 128) return;
309       
310        if (tsport->eitPsiCtl[iEit]) {
311                dprint(3, "cancel prev eit[%d] monitor\n", iEit);
312                DHL_PSI_StopMonitor(tsport->eitPsiCtl[iEit]);
313                tsport->eitPsiCtl[iEit] = (tDHL_PSI_ControlHandle)0;
314                tsport->n_active_monitors--;
315        }
316}
317
318void StopMonitorEtt(S_PSIM_PORT *tsport, int iEit)
319{
320        if (iEit < 0 || iEit > 128) return;
321
322        if (iEit == 128) {
323                if (tsport->ettvPsiCtl) {
324                        dprint(3, "cancel prev ett-v monitor\n");
325                        DHL_PSI_StopMonitor(tsport->ettvPsiCtl);
326                        tsport->ettvPsiCtl = (tDHL_PSI_ControlHandle)0;
327                        tsport->n_active_monitors--;
328                }
329        }
330        else {
331                if (tsport->ettPsiCtl[iEit]) {
332                        dprint(3, "cancel prev ett[%d] monitor\n", iEit);
333                        DHL_PSI_StopMonitor(tsport->ettPsiCtl[iEit]);
334                        tsport->ettPsiCtl[iEit] = (tDHL_PSI_ControlHandle)0;
335                        tsport->n_active_monitors--;
336                }
337        }
338}
339
340void StopMonitorAllEtts(S_PSIM_PORT *tsport)
341{
342        int iEit;
343        if (tsport->ettvPsiCtl) {
344                dprint(3, "cancel prev ett-v monitor\n");
345                DHL_PSI_StopMonitor(tsport->ettvPsiCtl);
346                tsport->ettvPsiCtl = (tDHL_PSI_ControlHandle)0;
347                tsport->n_active_monitors--;
348        }
349        for (iEit=0; iEit<128; iEit++) {
350                if (tsport->ettPsiCtl[iEit]) {
351                        dprint(3, "cancel prev ett[%d] monitor\n", iEit);
352                        DHL_PSI_StopMonitor(tsport->ettPsiCtl[iEit]);
353                        tsport->ettPsiCtl[iEit] = (tDHL_PSI_ControlHandle)0;
354                        tsport->n_active_monitors--;
355                }
356        }
357}
358
359
360/*
361        PAT monitor ½ÃÀÛ.
362*/
363STATUS StartMonitorPAT(S_PSIM_PORT *tsport)
364{
365        DHL_RESULT err;
366        STATUS status = statusOK;
367       
368        if (tsport->patPsiCtl)
369                StopMonitorPAT(tsport);
370       
371        dprint(3, "monitor pat..\n");
372        err = MonitorPAT(
373                        tsport->tsd, // tDHL_TSD *tsd,
374                        TRUE, // BOOLEAN current_next_indicator, // get current pat only
375                        FALSE, // BOOLEAN eager, // get complete table
376                        ePSIUPDATE_VERCHANGE, // tDHL_PSI_Update updateMode,
377                        _PsiTableEventProc, // tDHL_PSI_EventProc eventProc,
378                        (UINT32)tsport, // UINT32 userParam,
379                        &tsport->patPsiCtl //  tDHL_PSI_ControlHandle *returnPSICtl
380                        );
381
382        if (err) {
383                dprint(0, "!! monitor pat err %d\n", err);
384                status = statusError;
385        }
386        else {
387                tsport->n_active_monitors++;
388        }
389
390        return status;
391}
392
393
394/*
395        PMT ¸ð´ÏÅ͸¦ ½ÃÀÛÇÑ´Ù.
396       
397        pat¸¦ ¹Þ¾Æ¼­ »õ·Î pmt ¸ð´ÏÅÍ ½ÃÀÛÇÏ´Â °æ¿ì:
398                »ç¿ëÀÚ ¸ðµå¿¡ µû¶ó¼­ Àüü, ÀϺΠpmt ½ÃÀÛ.
399                        autoscan ¸ðµå: Àüü pmtµéÀ» oneshotÀ¸·Î.
400                        ÀÏ¹Ý ¸ðµå: ÁöÁ¤ÇÑ ÇϳªÀÇ pmt¸¸ ¿¬¼ÓÀ¸·Î..
401
402        pmt ¸ð´ÏÅ͸¦ resource ºÎÁ·À¸·Î ´Ù ½ÃÀÛÇÏÁö ¸øÇߴµ¥ ´Ù¸¥ tableÀÌ Á¾·áµÈ °æ¿ì
403                ¾ÆÁ÷ ½ÃÀÛÇÏÁö ¾ÊÀº pmt¸¸ ½ÃÀÛ.
404
405*/
406STATUS StartMonitorPMTs(S_PSIM_PORT *tsport, int preferred_program_number)
407{
408        int i;
409        int pmt_pid, program_number;
410        MPEG_PAT *pat;
411        MPEG_PMT **pmts;
412        DHL_RESULT err;
413        STATUS status = statusOK;
414        tDHL_PSI_Update updateMode;
415        BOOL bScanMode = (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) ? TRUE : FALSE;
416
417        if (bScanMode) {
418                // for autoscan mode, we need pmts of all program.
419                // but only one copy of pmt is enough.
420                preferred_program_number = -1;
421                updateMode = ePSIUPDATE_ONESHOT;
422                dprint(2, "%s: autoscan mode\n", __FUNCTION__); 
423        }
424        else {
425                // for normal mode, only one program pmt needs to be monitored.
426                updateMode = ePSIUPDATE_VERCHANGE;
427                dprint(2, "%s: program_number %d\n", __FUNCTION__, preferred_program_number);   
428        }
429
430        pat = PSIDB_GetPAT(tsport->input.rf);
431        pmts = PSIDB_GetPMTs(tsport->input.rf);
432       
433        if (pat == NULL || pmts == NULL) {
434                dprint(0, "!! %s: pat %x or pmts %x not ready\n", __FUNCTION__, pat, pmts);
435                return statusInvalidState;
436        }
437       
438        // PSI db¿Í ts port Á¤º¸°¡ ¼­·Î ÀÏÄ¡ÇÏÁö ¾ÊÀ» ¼ö ÀÕÀ¸¹Ç·Î üũ.
439        //
440        if (pat->numPrograms != tsport->num_programs) 
441        {
442                // pmt monitors Á¤º¸°¡ ºÒÀÏÄ¡. ¸ÕÀú reset..
443
444                // ¸Ç óÀ½¿¡ pat°¡ ¼ö½ÅµÇ´Â °æ¿ì¿¡´Â ´ç¿¬È÷ tsport num_programÀº 0ÀÏÅ×´Ï,
445                // ±×·± °æ¿ì´Â µð¹ö±× ¸Þ½ÃÁö Á¦¿Ü..
446                if (tsport->num_programs) {
447                        dprint(0, "!! pat and pmt monitor inconsistent. pat %d, tsport %d, reset pmt monitors first..\n",
448                                        pat->numPrograms, tsport->num_programs);
449                }
450
451                // µ¿ÀÛ ÁßÀÎ pmt monitor¸¦ ¸ðµÎ Á¤Áö.
452                StopMonitorPMTs(tsport);
453
454                tsport->pmtPsiCtlArray = DHL_OS_Malloc(pat->numPrograms * sizeof(tDHL_PSI_ControlHandle));
455                if (!tsport->pmtPsiCtlArray) {
456                        tsport->num_programs = 0; // <- ¹Ýµå½Ã ÇÊ¿ä.
457                        status = statusOutOfMemory;
458                        goto label_end;
459                }
460                tsport->num_programs = pat->numPrograms;
461        }
462
463        // PMTÀÇ °æ¿ì´Â Ưº°ÇÏ°Ô monitor ÃÖ´ë °¹¼ö¿¡ ÁÖÀÇÇØ¾ß ÇÔ.
464        if (tsport->n_active_monitors >= tsport->max_monitors) {
465                dprint(1, "!! cur monitor %d exceed limit %d\n", tsport->n_active_monitors, tsport->max_monitors);
466                status = statusOutOfResource;
467                goto label_end;
468        }
469
470        for (i=0; i<pat->numPrograms; i++)
471        {
472                program_number = pat->programs[i].program_number;
473                if (preferred_program_number >= 0) { // ƯÁ¤ program number ¸¸ ¼ö½ÅÇÏ´Â ¸ðµå..
474                        if (program_number != preferred_program_number)
475                                continue;
476                }
477                pmt_pid = pat->programs[i].program_map_PID;
478
479                // normal mode ÀÎ °æ¿ì¶ó¸é ÀÌ¹Ì pmt°¡ ÀÖ´õ¶óµµ monitor °¡µ¿À» ÇØ¾ß ÇÑ´Ù.
480                if (bScanMode && pmts[i]) // this pmt already exist.
481                        continue;
482               
483                if (tsport->pmtPsiCtlArray[i]) // this pmt is already started.
484                        continue;
485               
486                dprint(3, "new pmt monitor (pid %x, #%d), total monitors %d\n", 
487                        pmt_pid, program_number, tsport->n_active_monitors);
488               
489                err = MonitorPMT(
490                                tsport->tsd, // tDHL_TSD tsd,
491                                pmt_pid,
492                                program_number,
493                                TRUE, // BOOLEAN current_next_indicator, // get current pat only
494                                updateMode, // tDHL_PSI_Update updateMode,
495                                _PsiTableEventProc, // tDHL_PSI_EventProc eventProc,
496                                (UINT32)tsport, // UINT32 userParam,
497                                &tsport->pmtPsiCtlArray[i] //  tDHL_PSI_ControlHandle *returnPSICtl
498                                );
499               
500                if (err) {
501                        dprint(0, "!! %s: monitor pmt err %d\n", __FUNCTION__, err);
502                }
503                else {
504                        tsport->n_active_monitors++;
505                }
506
507                if (preferred_program_number > 0) { // one program monitor..
508                        break;
509                }
510
511                // PMTÀÇ °æ¿ì´Â Ưº°ÇÏ°Ô monitor ÃÖ´ë °¹¼ö¿¡ ÁÖÀÇÇØ¾ß ÇÔ.
512                if (tsport->n_active_monitors >= tsport->max_monitors) {
513                        dprint(1, "!!!! total monitor reached limit %d\n", tsport->n_active_monitors);
514                        status = statusOK;
515                        goto label_end;
516                }
517        }
518       
519label_end:
520        return status;
521       
522}
523
524STATUS StartMonitorMgt(S_PSIM_PORT *tsport)
525{
526        DHL_RESULT err;
527        STATUS status = statusOK;
528        tDHL_PSI_Update updateMode = ePSIUPDATE_VERCHANGE;
529       
530        if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN)
531                updateMode = ePSIUPDATE_ONESHOT; // only one instance is enough.
532       
533        if (tsport->mgtPsiCtl)
534                StopMonitorMgt(tsport);
535       
536        dprint(3, "monitor mgt..\n");
537        err = MonitorMgt(
538                        tsport->tsd, // tDHL_TSD *tsd,
539                        updateMode, // tDHL_PSI_Update updateMode,
540                        _PsiTableEventProc, // tDHL_PSI_EventProc eventProc,
541                        (UINT32)tsport, // UINT32 userParam,
542                        &tsport->mgtPsiCtl //  tDHL_PSI_ControlHandle *returnPSICtl
543                        );
544
545        if (err) {
546                dprint(0, "!! monitor mgt err %d\n", err);
547                status = statusError;
548        }
549        else {
550                tsport->n_active_monitors++;
551        }
552        return status;
553}
554
555STATUS StartMonitorTvct(S_PSIM_PORT *tsport)
556{
557        DHL_RESULT err;
558        STATUS status = statusOK;
559        tDHL_PSI_Update updateMode = ePSIUPDATE_VERCHANGE;
560       
561        if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN)
562                updateMode = ePSIUPDATE_ONESHOT; // only one instance is enough.
563
564        if (tsport->tvctPsiCtl)
565                StopMonitorTvct(tsport);
566       
567        dprint(3, "monitor tvct..\n");
568        err = MonitorTvct(
569                        tsport->tsd, // tDHL_TSD *tsd,
570                        ePSIMODE_TABLE, // tDHL_PSI_Mode psiMode,
571                        updateMode, // tDHL_PSI_Update updateMode,
572                        _PsiTableEventProc, // tDHL_PSI_EventProc eventProc,
573                        (UINT32)tsport, // UINT32 userParam,
574                        &tsport->tvctPsiCtl //  tDHL_PSI_ControlHandle *returnPSICtl
575                        );
576
577        if (err) {
578                dprint(0, "!! monitor tvct err %d\n", err);
579                status = statusError;
580        }
581        else {
582                tsport->n_active_monitors++;
583        }
584        return status;
585}
586
587STATUS StartMonitorCvct(S_PSIM_PORT *tsport)
588{
589        DHL_RESULT err;
590        STATUS status = statusOK;
591        tDHL_PSI_Update updateMode = ePSIUPDATE_VERCHANGE;
592       
593        if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN)
594                updateMode = ePSIUPDATE_ONESHOT; // only one instance is enough.
595
596        if (tsport->cvctPsiCtl)
597                StopMonitorCvct(tsport);
598
599        dprint(3, "monitor cvct..\n");
600        err = MonitorCvct(
601                        tsport->tsd, // tDHL_TSD *tsd,
602                        ePSIMODE_TABLE, // tDHL_PSI_Mode psiMode,
603                        updateMode, // tDHL_PSI_Update updateMode,
604                        _PsiTableEventProc, // tDHL_PSI_EventProc eventProc,
605                        (UINT32)tsport, // UINT32 userParam,
606                        &tsport->cvctPsiCtl //  tDHL_PSI_ControlHandle *returnPSICtl
607                        );
608
609        if (err) {
610                dprint(0, "!! monitor cvct err %d\n", err);
611                status = statusError;
612        }
613        else {
614                tsport->n_active_monitors++;
615        }
616        return status;
617}
618
619STATUS StartMonitorStt(S_PSIM_PORT *tsport)
620{
621        DHL_RESULT err;
622        STATUS status = statusOK;
623        tDHL_PSI_Update updateMode = ePSIUPDATE_CONTINEOUS;
624       
625        if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN)
626                updateMode = ePSIUPDATE_ONESHOT; // only one instance is enough.
627
628        if (tsport->sttPsiCtl)
629                StopMonitorStt(tsport);
630
631        dprint(3, "monitor stt..\n");
632        err = MonitorStt(
633                        tsport->tsd, // tDHL_TSD *tsd,
634                        updateMode, // tDHL_PSI_Update updateMode,
635                        _PsiTableEventProc, // tDHL_PSI_EventProc eventProc,
636                        (UINT32)tsport, // UINT32 userParam,
637                        &tsport->sttPsiCtl //  tDHL_PSI_ControlHandle *returnPSICtl
638                        );
639
640        if (err) {
641                dprint(0, "!! monitor stt err %d\n", err);
642                status = statusError;
643        }
644        else {
645                tsport->n_active_monitors++;
646        }
647        return status;
648}
649
650STATUS StartMonitorRrt(S_PSIM_PORT *tsport)
651{
652        DHL_RESULT err;
653        STATUS status = statusOK;
654        tDHL_PSI_Update updateMode = ePSIUPDATE_CONTINEOUS;
655       
656        if (tsport->rrtPsiCtl)
657                StopMonitorRrt(tsport);
658
659        dprint(3, "monitor rrt..\n");
660        err = MonitorRrt(
661                        tsport->tsd, // tDHL_TSD *tsd,
662                        0, // UINT8 region, // it is not used
663                        updateMode, // tDHL_PSI_Update updateMode,
664                        _PsiTableEventProc, // tDHL_PSI_EventProc eventProc,
665                        (UINT32)tsport, // UINT32 userParam,
666                        &tsport->rrtPsiCtl //  tDHL_PSI_ControlHandle *returnPSICtl
667                        );
668
669        if (err) {
670                dprint(0, "!! monitor rrt err %d\n", err);
671                status = statusError;
672        }
673        else {
674                tsport->n_active_monitors++;
675        }
676        return status;
677}
678
679
680/*
681        eit monitor¸¦ ½ÃÀÛÇÑ´Ù.
682
683*/
684STATUS StartMonitorEits(S_PSIM_PORT *tsport)
685{
686        int iEit, source_id;
687        DHL_RESULT err;
688        STATUS status = statusOK;
689        tDHL_PSI_Update updateMode;
690        int maxIndex;
691
692        S_PSIM_SUBCHINFO *subchInfo = NULL;
693        S_PSIM_MGT_DIGEST *smgt;
694
695        if (tsport->n_active_monitors >= tsport->max_monitors) {
696                dprint(0, "!! cur monitor %d exceed limit %d\n", tsport->n_active_monitors, tsport->max_monitors);
697                return statusOutOfResource;
698        }
699
700        if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) {
701                subchInfo = NULL;  // ƯÁ¤ subch ¿¡ ´ëÇØ µ¿ÀÛÇÏ´Â °ÍÀÌ ¾Æ´Ï´Ù.
702        }
703        else {
704                subchInfo = PSIDB_GetPsiSubChInfo(tsport->input.rf, tsport->source_id);
705                if (!subchInfo) {
706                        dprint(0, "!! rf %d, sid %d not ready for eit scan..\n", tsport->input.rf, tsport->source_id);
707                        return statusInvalidState;
708                }
709        }
710       
711        smgt = PSIDB_GetMgtDigest(tsport->input.rf);
712        if (!smgt) {
713                dprint(0, "!! rf %d has no smgt\n", tsport->input.rf);
714                return statusInvalidState;
715        }
716       
717        // ¾î¶² subchannel eit¸¦ ½ÃÀÛÇÒ °ÍÀÎÁö, ¾î¶² update mode·Î ÁøÇàÇÒ °ÍÀÎÁö °áÁ¤ÇÑ´Ù.
718       
719        // filter-eit °¡ 1:1 À̶ó¸é oneShotÀÌ Àû´çÇϰí,
720        // ÇϳªÀÇ filter·Î ´Ù¼öÀÇ eit¸¦ ¹ÞÀ»·Á°í ÇÑ´Ù¸é Continueous·Î ÁøÇà.
721       
722        if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) {
723                updateMode = ePSIUPDATE_CONTINEOUS;
724                source_id = 0;  // this means that all source_id table should be received..
725                maxIndex = 0;    // eit-0 ¸¸ ¹Þ´Â´Ù.
726                dprint(2, "start eit with autoscan mode..\n");
727        }
728        else {
729                // todo.. ±âÁ¸ ÄÚµå´Â version change. ¹¹°¡ ³ªÀº°¡??
730                updateMode = ePSIUPDATE_ONESHOT;
731                //updateMode = ePSIUPDATE_VERCHANGE;
732                source_id = tsport->source_id;         
733                maxIndex = min(127, gPsiMaxEitEttIndexToReceive);
734                dprint(2, "start eits, normal mode, sid %d, [0~%d]\n", source_id, maxIndex);
735        }
736
737        //-------------------------------------
738        // start/restart eit scan
739       
740        for (iEit=0; iEit<=maxIndex; iEit++)
741        {
742                if (tsport->eitPsiCtl[iEit]) continue; // it is already started.
743
744                // normal mode ¿¡¼­´Â ÀÌ¹Ì ÇØ´ç eit°¡ ¼ö½ÅµÇ¾ú´ÂÁöµµ üũÇÒ ¼ö ÀÖ´Ù.
745                if (subchInfo && subchInfo->eits[iEit]) continue;
746
747                if (smgt->eit_pids[iEit] == 0) // eit[i] does not exist.
748                        continue;
749
750                dprint(3, "monitor eit[%d] (pid %x, source_id %d), cur monitor %d\n", 
751                                iEit, smgt->eit_pids[iEit], source_id, tsport->n_active_monitors);
752               
753                err = MonitorEit(
754                                tsport->tsd, // tDHL_TSD tsd,
755                                smgt->eit_pids[iEit], // UINT16 PID,
756                                source_id, // UINT16 source_id,
757                                ePSIMODE_TABLE, // tDHL_PSI_Mode psiMode,
758                                updateMode, // tDHL_PSI_Update updateMode,
759                                _PsiTableEventProc, // tDHL_PSI_EventProc eventProc,
760                                (UINT32)tsport, // UINT32 userParam,
761                                &tsport->eitPsiCtl[iEit] //  tDHL_PSI_ControlHandle *returnPSICtl
762                                );
763
764                if (err) {
765                        dprint(0, "!! monitor eit[%d] err %d\n", iEit, err);
766                        status = statusError;
767                        goto label_end;
768                }
769                else {
770                        tsport->n_active_monitors++;
771                }       
772
773                if (tsport->n_active_monitors >= tsport->max_monitors) {
774                        dprint(2, "!!!! total monitor reached limit %d\n", tsport->n_active_monitors);
775                        status = statusOK;
776                        goto label_end;
777                }                       
778
779        }
780
781label_end:
782        return status;
783
784}
785
786
787
788/*
789        ett ¸ð´ÏÅ͸¦ ½ÃÀÛÇÑ´Ù.
790
791        tsport->source_id ¿¡¼­ ÁöÁ¤µÈ ¼­ºêä³ÎÀÇ ett¸¸À» scanÇÑ´Ù.
792        subch ptr, smgt µîÀº ÀÌ¹Ì Áغñ µÇ¾î ÀÖ¾î¾ß ÇÑ´Ù.
793
794        autoscan ¸ðµåÀÎ °æ¿ì¿¡´Â »ç¿ëµÇÁö ¾Ê´Â´Ù.
795
796        channel-ett ¸¦ ¸ÕÀú monitor Çϰí, ±× ´ÙÀ½ ÀÏ¹Ý ett monitor ÇÑ´Ù.
797        ÀÌ¹Ì ¹Þ¾ÆÁ® ÀÖ´Â °æ¿ì, ÀÌ¹Ì start µÈ °æ¿ì µîÀº skip ÇϹǷÎ,
798        ett completed ¾Æ´Ñ °æ¿ì¶ó¸é ¾ðÁ¦µçÁö ¿©·¯¹ø È£ÃâÇØµµ »ó°ü ¾ø´Ù.
799*/
800STATUS StartMonitorEtts(S_PSIM_PORT *tsport)
801{
802        int k, t, iEtt, iEvent; // loop variables
803        int n_etm;
804        UINT32 etmid;
805
806        DHL_RESULT err;
807        STATUS status = statusOK;
808        tDHL_PSI_Update updateMode;
809        int maxIndex;
810
811        S_PSIM_SUBCHINFO *subchInfo;
812        S_PSIM_MGT_DIGEST *smgt;
813
814        if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) {
815                dprint(0, "!! ett tried in autoscan mode\n");
816                return statusOK;
817        }
818
819        if (tsport->n_active_monitors >= tsport->max_monitors) {
820                dprint(0, "!! cur monitor %d exceed limit %d\n", tsport->n_active_monitors, tsport->max_monitors);
821                return statusOutOfResource;
822        }
823
824        subchInfo = PSIDB_GetPsiSubChInfo(tsport->input.rf, tsport->source_id);
825        if (!subchInfo) {
826                dprint(0, "!! rf %d, sid %d not ready for ett scan..\n", tsport->input.rf, tsport->source_id);
827                return statusInvalidState;
828        }
829
830        smgt = PSIDB_GetMgtDigest(tsport->input.rf);
831        if (!smgt) {
832                dprint(0, "!! rf %d has no smgt\n", tsport->input.rf);
833                return statusInvalidState;
834        }
835       
836        // ¾î¶² subchannel eit¸¦ ½ÃÀÛÇÒ °ÍÀÎÁö, ¾î¶² update mode·Î ÁøÇàÇÒ °ÍÀÎÁö °áÁ¤ÇÑ´Ù.
837
838        updateMode = ePSIUPDATE_CONTINEOUS;
839        maxIndex = min(127, gPsiMaxEitEttIndexToReceive);
840        dprint(2, "start ett monitoring, sid %d, [0~%d]\n", tsport->source_id, maxIndex);
841
842        //-------------------------------------
843        // start/restart ett scan
844
845        // ****** channel-ett **********
846        do 
847        {
848                if (tsport->ettvPsiCtl) continue;  // already started.
849
850                if (subchInfo->channel_ett) continue; // already received.
851
852                if (!PSIDB_IsSubChEttVRequired(tsport->input.rf, tsport->source_id)) continue; // no ettv exist
853
854                dprint(3, "monitor ett-v (pid %x, source_id %d), cur monitor %d\n", 
855                                smgt->channel_ett_pid, tsport->source_id, tsport->n_active_monitors);
856
857                etmid = PSIUTIL_MakeChannelETMID(subchInfo->source_id) | 0xffff;
858                etmid = 0; // we use all pass mode. just ett_pid is the only key.
859                err = MonitorEtt(
860                                tsport->tsd, // tDHL_TSD *tsd,
861                                smgt->channel_ett_pid, // UINT16 PID,
862                                etmid, // UINT32  etm_id,
863                                updateMode, // tDHL_PSI_Update updateMode,
864                                _PsiTableEventProc, // tDHL_PSI_EventProc eventProc,
865                                (UINT32)tsport, // UINT32 userParam,
866                                &tsport->ettvPsiCtl //  tDHL_PSI_ControlHandle *returnPSICtl
867                                );
868
869                if (err) {
870                        dprint(0, "!! monitor ett-v err %d\n", err);
871                        status = statusError;
872                        goto label_end;
873                }
874                else {
875                        tsport->n_active_monitors++;
876                }       
877
878                if (tsport->n_active_monitors >= tsport->max_monitors) {
879                        dprint(2, "!!!! total monitor reached limit %d\n", tsport->n_active_monitors);
880                        status = statusOK;
881                        goto label_end;
882                }                       
883        } while (0);
884       
885        // ****** normal etts **********
886        for (iEtt=0; iEtt<=maxIndex; iEtt++)
887        {
888                if (tsport->ettPsiCtl[iEtt])
889                        continue;  // already started.
890
891                // eit°¡ ¾ø´Ù¸é ett ¼ö½ÅÀº ºÒ°¡´ÉÇÔ..
892                if (!subchInfo->eits[iEtt] || !subchInfo->eits[iEtt]->event)
893                        continue;  // eit is not received. ett monitor impossible.
894
895                if (smgt->ett_pids[iEtt] == 0) // MGT¿¡ ÀÌ ETT-i Á¤º¸°¡ ¾øÀ¸¸é °Ç³Ê¶Ú´Ù.
896                        continue;
897
898                // ------ °ü·ÃµÈ Eit ºÐ¼®..
899                // ÀÌ EITÀÇ eventµé Áß¿¡¼­ ¸î°³°¡ ETMÀ» °¡Áö°í ÀÖ´ÂÁö ¼ÀÇÑ´Ù.
900                //
901                for (iEvent=0, n_etm=0; iEvent<subchInfo->eits[iEtt]->numEvents; iEvent++) {
902                        if (gPsiIgnoreEtmLocationInfo ||                          // ignore ¿É¼ÇÀÌ¸é ¹«Á¶°Ç ¹Þ´Â´Ù.
903                                subchInfo->eits[iEtt]->event[iEvent].ETM_location != ETM_none)
904                                n_etm++;  // ÀÌ EIT¿¡ °ü·ÃµÈ ETT °¹¼ö..
905                }
906                if (n_etm == 0) {  // ÀÌ EITÀÇ À̺¥Æ®µé¿¡´Â ETT°¡ Çϳªµµ ¾ø´Ù°í ÇÑ´Ù. ´Ù¿î·Îµå ¹ÞÀ» Çʿ䰡 ¾ø´Ù.
907                        dprint(3, "        no etts of this eit / total %d events\n", subchInfo->eits[iEtt]->numEvents);
908                        continue;  // go to next EIT..
909                        // ´ÙÀ½ ´Ü°è·Î °¡±â Àü¿¡ ÇöÀç ettµéÀÇ ÀÚ°Ý °Ë»çµµ ÇØ¾ß ÇÏÁö ¾Ê³ª????
910                }
911                else {
912                        dprint(3, "    %d etm's are expected in this eit / total %d events\n", 
913                                        n_etm, subchInfo->eits[iEtt]->numEvents);
914                }
915
916                // ÀÌ EIT¿¡ ÃÑ n_etm(>0)°³ÀÇ ETT°¡ °É·Á ÀÖÀ» °ÍÀ¸·Î ÃßÁ¤µÈ´Ù..
917
918                // ------ Ett¿ë ¸Þ¸ð¸® ÇÒ´ç..
919                // ett¿ë ¸Þ¸ð¸®°¡ ¾øÀ¸¸é »õ·Î ÇÒ´çÇÑ´Ù.. Æ÷ÀÎÅͰ¡ ÀÖ´õ¶óµµ Å©±â°¡ º¯°æµÇ¾ú´ÂÁö üũ.
920
921                // eit event ³»¿¡ ett¸¦ ÀúÀåÇÏ´Â ¹æ¹ýÀº ¾î¶²°¡??
922
923               
924                if (subchInfo->n_ett[iEtt] != subchInfo->eits[iEtt]->numEvents) { // internal error!!
925                        dprint(0, "!! eit[%d] num event %d != n_ett %d\n", 
926                                iEtt, subchInfo->eits[iEtt]->numEvents, subchInfo->n_ett[iEtt]);
927                        PSIDB_FreeEtts(subchInfo, iEtt);                       
928                }
929               
930                if (subchInfo->etts[iEtt] == NULL)
931                {
932                        int n_event = subchInfo->eits[iEtt]->numEvents;
933                       
934                        PSIDB_LockDB(TRUE); //---------------
935
936                        subchInfo->etts[iEtt] = DHL_OS_Malloc(n_event * sizeof(ettSectionPtr_t));
937                        if (subchInfo->etts[iEtt]) {
938                                dprint(3, "        ++ alloc etts memory %x (max %d)\n", 
939                                                subchInfo->etts[iEtt], n_event);
940                                subchInfo->n_ett[iEtt] = n_event; // ÀÌ Eit¿¡ ¿¬°áµÈ ETT-i ÀÇ °¹¼ö..
941                        }
942                        else {
943                                dprint(0, "!! out of memory for %d ett ptr\n", n_event);
944                                subchInfo->n_ett[iEtt] = 0;
945                        }
946                        PSIDB_LockDB(FALSE); //----------------
947
948                        if (!subchInfo->etts[iEtt])
949                                break; // ¸Þ¸ð¸® ºÎÁ·? ´õ ÀÌ»ó ÁøÇàÇÒ Çʿ䰡 ¾ø´Ù.
950                       
951                }
952                else
953                        dprint(3, "        ** reuse etts memory %x (max %d:%d)\n", subchInfo->etts[iEtt], 
954                                                subchInfo->eits[iEtt]->numEvents, subchInfo->n_ett[iEtt]);
955
956                for (iEvent=0; iEvent<subchInfo->eits[iEtt]->numEvents; iEvent++) // ÀÌ EIT³»ÀÇ ¸ðµç À̺¥Æ®¿¡ ´ëÇØ¼­ ETT¸¦ ¼ö½ÅÇÑ´Ù..
957                {
958                        BOOL bSkipThisEtt;
959                       
960                        // MGT¿¡ ETMÀÌ ¾ø´Ù°í µÇ¾î ÀÖÀ¸¸é ¹ÞÀ¸¸é ¾ÈµÈ´Ù.
961                        if (gPsiIgnoreEtmLocationInfo == FALSE && 
962                                subchInfo->eits[iEtt]->event[iEvent].ETM_location == ETM_none) {
963                                //dprint(3, "    [%d] no ETM\n", iEvent);
964                                continue;
965                        }
966
967                        etmid = PSIUTIL_MakeEventETMID(subchInfo->source_id, subchInfo->eits[iEtt]->event[iEvent].event_id);
968
969                        // ÀÌ¹Ì ÀÌ event¿¡ ÇØ´çÇÏ´Â ETT¸¦ ¹Þ¾Ò´Ù¸é ¹ÞÀ» Çʿ䰡 ¾ø´Ù..  ETM_id¸¦ ÀÌ¿ëÇÏ¿© ±× ¿©ºÎ¸¦ È®ÀÎÇÑ´Ù.
970                        // ±×·±µ¥ event[i] ¿¡ ÇØ´çÇÏ´Â ett°¡ ÀÖ´ÂÁö ¾ø´ÂÁö ã±â°¡ Á» º¹ÀâÇÏ´Ù..
971                        // ²À ÀÌ Eit PID¿¡¸¸ ¾Æ´Ï¶ó ±× ÀÌÀü EitµéÀÇ PID¿¡µµ Á¸ÀçÇÒ °æ¿ì°¡ Àֱ⠶§¹®..
972                        // 3-hour °æ°è¿¡ °ÉÃÄ ÀÖ´Â eventÀÇ °æ¿ì ¾ÕÂÊ eventÀÇ PID¿¡ ett°¡ ÀÖÀ» ¼ö ÀÖ´Ù.
973                        //
974                        bSkipThisEtt = FALSE; 
975                       
976                        if (subchInfo->etts[iEtt] && 
977                                subchInfo->n_ett[iEtt] &&
978                                subchInfo->etts[iEtt][iEvent] &&
979                                subchInfo->etts[iEtt][iEvent]->ETM_id == etmid) {
980                                // ÀÌ Ett°¡ ÀÌ¹Ì ¼ö½ÅµÇ¾î ÀÖ´Ù¸é, ¹ÞÀ» ÇÊ¿ä ¾ø´Ù.
981                                dprint(3, "    [%d] already exist (etmid 0x%x pid %d)\n", iEvent, etmid, smgt->ett_pids[iEtt]);
982                                bSkipThisEtt = TRUE;
983                        }
984                       
985                        for (k=iEtt; !bSkipThisEtt && k>=0; k--) {  // ÇöÀç Etts[iEtt]ºÎÅÍ  Etts[0] ±îÁö ¾ÕÀ¸·Î µÇµ¹¾Æ°¡¸é¼­,
986                                if (subchInfo->etts[k] == NULL) continue;
987                                // °¢ Ett sectionÀ» °Ë»çÇØ¼­ ÇöÀç ¹ÞÀ¸·Á°í ÇÏ´Â etmidÀÇ ett°¡ ¹Þ¾ÆÁ® ÀÖ´ÂÁö °Ë»çÇÑ´Ù.
988                                for (t=0; t<subchInfo->n_ett[k]; t++) {
989                                        if (subchInfo->etts[k][t] && subchInfo->etts[k][t]->ETM_id == etmid) {
990                                                // °°Àº etmid¸¦ °¡Áø Ett°¡ ÀÌ¹Ì ¼ö½ÅµÇ¾î ÀÖ´Ù¸é, ¹ÞÀ» ÇÊ¿ä ¾ø´Ù.
991                                                dprint(2, "    [%d] same etmid 0x%x (ett[%d][%d] pid %d) exist\n", 
992                                                                                iEvent, etmid, k, t, smgt->ett_pids[k]);
993                                                bSkipThisEtt = TRUE;
994                                                break;
995                                        }
996                                }
997                                if (bSkipThisEtt) break;
998                        }
999                        if (bSkipThisEtt) continue;
1000                       
1001                        dprint(3, "    [%d] ett pid 0x%x, etmid 0x%x\n", iEvent, smgt->ett_pids[iEtt], etmid);
1002
1003                #if 0                   
1004                        // °³°³ÀÇ ett¸¦ ¼ö½ÅÇÏ´Â ¸ðµå..
1005                        // ´Ü ÀÌ·¸°Ô ÇÏ·Á¸é ettPsiCtl ÀúÀå °ø°£µµ ÇÊ¿äÇÑ ¸¸Å­ ÇÒ´ç ¹Þ¾Æ¾ß ÇÑ´Ù.
1006
1007                        dprint(3, "monitor ett[%d] (pid %x, source_id %d, etmid 0x%x), cur monitor %d\n",
1008                                        iEtt, smgt->ett_pids[iEtt], source_id, etmid, tsport->n_active_monitors);
1009               
1010                        err = MonitorEtt(tsport->tsd, smgt->ett_pids[iEtt], etmid, updateMode,
1011                                        _PsiTableEventProc, // tDHL_PSI_EventProc eventProc,
1012                                        (UINT32)tsport, // UINT32 userParam,
1013                                        &tsport->ettPsiCtl[iEtt][iEvent] //  tDHL_PSI_ControlHandle *returnPSICtl
1014                                        );
1015                #endif
1016
1017                }
1018               
1019                dprint(3, "monitor ett[%d] (pid %x, source_id %d), cur monitor %d\n", 
1020                                iEtt, smgt->ett_pids[iEtt], tsport->source_id, tsport->n_active_monitors);
1021
1022                etmid = PSIUTIL_MakeChannelETMID(subchInfo->source_id) | 0xffff;
1023                etmid = 0; // we use all pass mode. just ett_pid is the only key.
1024                err = MonitorEtt(
1025                                tsport->tsd, // tDHL_TSD *tsd,
1026                                smgt->ett_pids[iEtt], // UINT16 PID,
1027                                etmid, // UINT32  etm_id,
1028                                updateMode, // tDHL_PSI_Update updateMode,
1029                                _PsiTableEventProc, // tDHL_PSI_EventProc eventProc,
1030                                (UINT32)tsport, // UINT32 userParam,
1031                                &tsport->ettPsiCtl[iEtt] //  tDHL_PSI_ControlHandle *returnPSICtl
1032                                );
1033               
1034                if (err) {
1035                        dprint(0, "!! monitor ett[%d] err %d\n", iEtt, err);
1036                        status = statusError;
1037                        goto label_end;
1038                }
1039                else {
1040                        tsport->n_active_monitors++;
1041                }       
1042
1043                if (tsport->n_active_monitors >= tsport->max_monitors) {
1044                        dprint(2, "!!!! total monitor reached limit %d\n", tsport->n_active_monitors);
1045                        status = statusOK;
1046                        goto label_end;
1047                }                       
1048
1049        }
1050
1051label_end:
1052        return status;
1053
1054}
1055
1056
1057
1058
1059#if COMMENT
1060____Subchannel____(){}
1061#endif
1062
1063
1064
1065
1066/*
1067        SubChannel scan ½ÃÀÛ.
1068        TV ½Ãû ¸ðµå, ·¹ÄÚµù ¸ðµå, Autoscan ¸ðµå ´Ù ÇØ´çµÊ.
1069
1070        ¾î¶² subchannelÀ» ½ÃÀÛÇÒ °ÍÀÎÁö´Â µ¿ÀÛ ¸ðµå¿Í @tsport->source_id ¿¡ µû¸¥´Ù.
1071*/
1072STATUS StartSubChannelScan(S_PSIM_PORT *tsport)
1073{
1074        STATUS status = statusOK;
1075        int i;
1076
1077        if (tsport->n_active_monitors >= tsport->max_monitors) {
1078                dprint(0, "!! cur monitor %d exceed limit %d\n", tsport->n_active_monitors, tsport->max_monitors);
1079                return statusOutOfResource;
1080        }
1081
1082        if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) 
1083        {
1084                // autoscan Àü¿ë eit complete check ÇÔ¼ö°¡ ¾øÀ¸´Ï,
1085                // Á÷Á¢ db search ÇÏ¿© ÆÇ´ÜÇϵµ·Ï ÇÏÀÚ.
1086
1087                S_PSIM_CHINFO *chInfo;
1088                BOOL bEitsCompleted = TRUE;
1089               
1090                chInfo = PSIDB_GetPsiChInfo(tsport->input.rf);
1091                if (!chInfo) {
1092                        dprint(0, "!! rf %d not ready for subch scan..\n", tsport->input.rf);
1093                        goto label_end;
1094                }
1095                // ¸ðµç eit-0 °¡ ´Ù ¼ö½Å µÈ °ÍÀÎÁö üũ. Çϳª¶óµµ ºüÁ® ÀÖ´Ù¸é restart..
1096                for (i=0; i<chInfo->n_subchannel; i++) {               
1097                        if (chInfo->subchannel[i].eits[0] == NULL) {
1098                                bEitsCompleted = FALSE;
1099                                break;
1100                        }
1101                }
1102                if (!bEitsCompleted)
1103                        StartMonitorEits(tsport);
1104                else
1105                        dprint(2, "ch %d eits already completed (autoscan mode)\n", tsport->input.rf);
1106        }
1107        else 
1108        {
1109                // ÀÏ´Ü eit -> ett ¼ø¼­´ë·Î ÁøÇàÇÏÀÚ.
1110               
1111                if (!PSIDB_IsSubChEitsCompleted(tsport->input.rf, tsport->source_id))
1112                        StartMonitorEits(tsport);
1113                       
1114                else if (!PSIDB_IsSubChAllEttsCompleted(tsport->input.rf, tsport->source_id))
1115                        StartMonitorEtts(tsport);
1116
1117                else
1118                        dprint(2, "subch (rf %d, sid %d) already completed\n", tsport->input.rf, tsport->source_id);
1119        }
1120
1121label_end:
1122        return status;
1123}
1124
1125
1126
1127#if COMMENT
1128____EventMonitor____(){}
1129#endif
1130
1131
1132#define IS_VALID_SOURCE_ID(sid) ((sid)>=0 && (UINT32)(sid)<=0xFFFF)
1133
1134#define EVENT_ID_INIT  -2   // last event id °ªÀÇ ÃʱⰪ.
1135#define EVENT_ID_EMPTY -1   // ÇöÀç ½Ã°£¿¡ ÇØ´çÇÏ´Â event °¡ ¾ø´Â °æ¿ìÀÇ id.
1136
1137#define IS_VALID_EVENT_ID(evid) ((evid)>=0)
1138
1139
1140//-----------------------------------
1141//  CheckIfProgramEventChanged
1142//
1143//  ÇöÀçÀÇ STT¸¦ ÃßÁ¤Çϰí,
1144// 
1145//  ÀÌ Ã¤³ÎÀÇ ÀúÀåµÇ¾îÁø ¸¶Áö¸· descriptor Á¤º¸·ÎºÎÅÍ
1146//  descriptor ³»¿ëÀÌ º¯°æµÈ »çÇ×ÀÌ ÀÖ´ÂÁö °Ë»çÇÑ´Ù.
1147//
1148//
1149PSI_STATIC void CheckIfProgramEventChanged(S_PSIM_PORT *tsport)
1150{
1151        int channel_id = tsport->input.rf;
1152        int source_id = tsport->input.source_id;
1153
1154        S_PSIM_CHINFO *chInfo;
1155        S_PSIM_SUBCHINFO *subchInfo;
1156
1157        int i;
1158        int iEit, iEvent;
1159        int stt_offset;
1160
1161        UINT32 system_time;
1162        eitPtr_t eit;
1163        eitEventPtr_t event;
1164
1165        if (!PSITASK_IsPsiTask()) {
1166                dprint(0, "!! %s: called in wrong task\n", __FUNCTION__);
1167                return;
1168        }
1169
1170        // psi task¿¡¼­ Àб⠿뵵·Î¸¸ »ç¿ëÇÒ °æ¿ì lock Àº ÇÊ¿ä ¾ø´Ù.
1171       
1172        //Dmc_EpgLockCoreDB(TRUE);
1173
1174        chInfo = PSIDB_GetPsiChInfo(channel_id);
1175       
1176        if (chInfo == NULL) {
1177                dprint(0, "!! stt from non-exist channel %d\n", channel_id);
1178                goto label_exit;
1179        }
1180       
1181        if (chInfo->stt_valid == 0) {
1182                if (g_Trace_bPsiSttInfo)
1183                        dprint(1, "[STT] stt not available yet\n");
1184                goto label_exit;
1185        }
1186
1187        // ÇöÀçÀÇ program event¸¦ ã¾Æ³»´Âµ¥ »ç¿ëµÉ ±âÁØ GPS ½Ã°£..
1188        //
1189        // STT¸¦ ¼ö½ÅÇÑÁö ¿À·¡ µÈ °æ¿ì¶ó¸é º¸Á¤ °ªÀÌ ÇÊ¿äÇÒ ¼öµµ ÀÖ´Ù.
1190        //
1191        stt_offset = (DHL_OS_GetMsCount() - chInfo->tick_stt_get) / 1000;
1192        system_time = chInfo->flat_stt.system_time + stt_offset;
1193       
1194        if (g_Trace_bPsiSttInfo)
1195        if (stt_offset)
1196                dprint(1, "[STT] stt offset %d applied\n", stt_offset);
1197
1198        //----------------------
1199        // now, use stt data... search subch info
1200       
1201        subchInfo = NULL;
1202        // cafrii 070801 delete check, source_id °¡ 0ÀÎ ½ºÆ®¸²µéÀÌ ÀÖÀ½.
1203        //if (source_id)
1204        {
1205                if (g_Trace_bPsiSttInfo)
1206                        dprint(3, "[STT] source id %d, n_subch %d, subch 0x%x\n", 
1207                                source_id, chInfo->n_subchannel, chInfo->subchannel);
1208               
1209                for (i=0; i<chInfo->n_subchannel; i++) {
1210                        if (chInfo->subchannel[i].source_id == source_id) {
1211                                subchInfo = &chInfo->subchannel[i];
1212                                break;
1213                        }
1214                }
1215        }
1216        if (!subchInfo) {
1217                if (g_Trace_bPsiSttInfo)
1218                        dprint(3, "[STT] !! subchInfo source_id %d not found..\n", source_id);
1219                goto label_exit;
1220        }
1221       
1222        // Spec ´ë·Î¶ó¸é ¹Ýµå½Ã Eit-0 ¿¡ ÀÖ¾î¾ß ÇÒ °ÍÀÌÁö¸¸, Local timeÀ¸·Î 3-hour
1223        // boundary¿¡ Á¤È®ÇÏ°Ô Eit change°¡ ¹ß»ýÇÏÁö ¾Ê´Â´Ù¸é ¾à°£ÀÇ ¿ÀÂ÷°¡ ÀÖÀ» ¼öµµ ÀÖ´Ù.
1224        // µû¶ó¼­ Eit-0 °ú Eit-1 µÎ°³¸¦ Á¶»çÇÑ´Ù.
1225        //
1226        for (iEit=0; iEit<=1; iEit++) 
1227        {
1228                eit = subchInfo->eits[iEit];
1229                if (eit == NULL) continue;
1230
1231                if (eit->source_id != source_id) {
1232                        dprint(0, "[STT] !! eit[%d] source id %d mismatch to subch source id %d\n", 
1233                                                                iEit, eit->source_id, source_id);
1234                        continue;
1235                }
1236               
1237                if (eit->event == NULL || eit->numEvents <= 0)
1238                        continue;
1239
1240                for (iEvent=0; iEvent<eit->numEvents; iEvent++) 
1241                {
1242                        // eitEvent_t
1243                        event = &eit->event[iEvent];
1244                       
1245                        // system_time ÀÌ ÀÌ eventÀÇ ±¸°£ ³»¿¡ µé¾î ÀÖ´ÂÁö È®ÀÎ..
1246                        //
1247                        if (system_time < event->start_time || 
1248                                system_time > event->start_time + event->length_in_seconds-1)
1249                                continue;
1250
1251                        // now, this event is current!!!
1252                       
1253                        if (g_Trace_bPsiSttInfo)
1254                        dprint(3, "[STT] event found: evid 0x%x,  %d min %d sec long\n",
1255                                        event->event_id,
1256                                        event->length_in_seconds/60, event->length_in_seconds%60);
1257                       
1258                        //
1259                        // °¡Àå ¸¶Áö¸·À¸·Î ±â¾ïÇϰí ÀÖ¾ú´ø event id ¶û ´Þ¶óÁö¸é
1260                        // program ÀÌ º¯°æµÈ °ÍÀ¸·Î ÆÇ´ÜÇÑ´Ù.
1261                        //
1262                        if (event->event_id != tsport->last_event_id) {
1263                                goto label_notify;
1264                        }
1265
1266                        // todo..
1267                        // event id °¡ °°´õ¶óµµ ½ÇÁ¦ ³»¿ëÀÌ ¿ÏÀüÈ÷ µ¿ÀÏÇÑÁö Ã¼Å©ÇØº¸ÀÚ.
1268                        // ±×·²·Á¸é last event »çº»À» Åë°·Î º¸ÀüÇØ¾ß ÇÑ´Ù.
1269                        //
1270                        // ÀÏ´Ü Áö±ÝÀº ±âÁ¸ event¿Í µ¿ÀÏÇϹǷΠó¸®ÇÏÁö ¾Ê°í ¹«½ÃÇÑ´Ù.
1271                        goto label_exit;
1272
1273                } // for iEvent
1274               
1275        } // for iEit
1276
1277        // ¾Æ¹« event µµ ¹ß°ßÀÌ ¾ÈµÈ °æ¿ì..
1278        dprint(2, "[STT] no event found. last evid 0x%x\n", tsport->last_event_id);
1279       
1280        if (tsport->last_event_id != EVENT_ID_EMPTY) 
1281        {
1282                // °¡Àå ¸¶Áö¸· eventÀÇ °æ¿ì valid ÇÑ °ÍÀ̾ú´Âµ¥,
1283                // ÀÌÁ¦ valid ÇÑ event°¡ »ç¶óÁ³À¸´Ï ¿ª½Ã notify ÇØ Áà¾ß ÇÑ´Ù.
1284                // No Rating Á¤º¸ µîÀ» ó¸®Çϱâ À§ÇØ.
1285               
1286                event = NULL;
1287                goto label_notify;
1288        }
1289       
1290        goto label_exit;
1291
1292label_notify:
1293
1294        if (1)
1295        {
1296                S_PSIM_PROGRAM_CHANGED_CB_PARAM param;
1297                int new_event_id = event ? event->event_id : EVENT_ID_EMPTY;
1298               
1299                dprint(1, "******** program event changed 0x%x -> 0x%x\n", 
1300                                        tsport->last_event_id, new_event_id);
1301               
1302                tsport->last_event_id = new_event_id;
1303
1304                //
1305                //  º¯°æµÈ »õ event Á¤º¸ÀÇ °ÅÀÇ ´ëºÎºÐÀ» callbackÀ¸·Î ¾Ë·ÁÁØ´Ù.
1306                //
1307                memset(&param, 0, sizeof(param));
1308               
1309                param.channel_id = channel_id;
1310                param.source_id = source_id;
1311                param.eit_index = event ? iEit : -1;   // eit-0 ¿¡¼­ ¿Ô´ÂÁö, eit-1 ¿¡¼­ ¹ß°ßµÇ¾ú´ÂÁö..
1312                param.event_id = new_event_id;
1313               
1314                param.system_time = system_time;
1315
1316                if (event) 
1317                {
1318                        param.start_time        = event->start_time;
1319                        param.length_in_seconds = event->length_in_seconds;
1320                        param.descriptor_length = event->descriptor_length;
1321                       
1322                        // ÇÊ¿äÇϸé client°¡ ¾Ë¾Æ¼­ º¹Á¦¸¦ ÇÏ¸é µÈ´Ù.
1323                        // ±×³É ¿øº» Æ÷ÀÎÅ͸¦ ³Ñ°ÜÁÖÀÚ.
1324                        param.descriptors = event->descriptors;
1325                }
1326                       
1327                //Dmc_EpgSendUserEvent2(epgEventNotifyProgramChange,
1328                //                      (UINT32) new_event_id, (UINT32) &param);
1329
1330                SendUserCallback(tsport, ePSIM_EVENT_ProgramChanged, (UINT32)&param);   
1331               
1332        }
1333
1334label_exit:
1335        //Dmc_EpgLockCoreDB(FALSE);
1336        ;
1337}
1338
1339
1340
1341
1342#if COMMENT
1343____Private____(){}
1344#endif
1345
1346/*
1347        ¼ö½ÅµÈ PAT¸¦ ó¸®ÇÑ´Ù.
1348*/
1349PSI_STATIC STATUS ProcessPAT(S_PSIM_PORT *tsport, tDHL_PSI_DataArray *desc)
1350{
1351        int i;
1352        DHL_RESULT err;
1353        STATUS status = statusOK;
1354
1355        MPEG_PAT *pat, *prev_pat;
1356
1357        dprint(4, "%s:\n", __FUNCTION__);
1358       
1359        err = ParsePAT(desc, &pat);
1360        // desc will be freed at caller.
1361       
1362        if (IsError(err)) {
1363                dprint(0, "%s: ParsePAT returned %s\n", __FUNCTION__, ErrorString(err));
1364                return statusInvalidPSI;
1365        }
1366
1367        // PAT sanity check
1368        if (!pat || pat->numPrograms == 0 || !pat->programs) {
1369                dprint(0, "!! wrong pat\n");
1370                PSIUTIL_FreeTable(&pat);
1371                return statusInvalidPSI;
1372        }
1373
1374        if (tsport->patPsiCtl != desc->handle) {
1375                dprint(0, "!! inconsistent! patPsiCtl %x != desc psictl %x\n", tsport->patPsiCtl, desc->handle);
1376                status = statusInvalidState;
1377                goto label_end;
1378        }
1379
1380        //--------------------------------------------------------------------
1381        // now, table becoms vailid. if not updated to DB, free it carefully.
1382
1383        if (dprintable(3))
1384                PrintPAT(pat);
1385
1386        // ±âÁ¸ pat¿Í ºñ±³ÇÏ¿© º¯°æ »çÇ×ÀÌ ¾øÀ¸¸é skip. --> no!!
1387        //
1388        // º¯°æ »çÇ×ÀÌ ÀÖ´õ¶óµµ pmt_pid, program_number ¿¡ º¯°æ »çÇ×ÀÌ ¾øÀ¸¸é¼­ pmt°¡ ½ÃÀÛ ÁßÀ̸é
1389        // ÇØ´ç pmt monitor´Â ±×´ë·Î À¯Áö.
1390        // --> pmt monitor¸¦ restart ÇØµµ º° ¹®Á¦ ¾ÈµÇ¹Ç·Î Ç×»ó restartÇϵµ·Ï ÇÏÀÚ.
1391
1392        prev_pat = PSIDB_GetPAT(tsport->input.rf);
1393
1394        // something is changed in pat.
1395        //  reset the pmt monitor that is changed (either pid or program_number)
1396       
1397        // pmtPsiCtl array Å©±â(numPrograms)°¡ º¯°æ µÇ¾ú´ÂÁö üũ, Àû¿ë.
1398        // ÁÖÀÇ:
1399        //   prev_pat->numPrograms ¿Í ºñ±³ÇÏÁö ¾Ê°í, tsport->num_programs ¿Í ºñ±³ÇÔ.
1400        //   ¿Ö³Ä¸é ¿¹¿Ü »óȲ µîÀ¸·Î ÀÎÇÏ¿© tsport->num_programs´Â 0 ÀÏ ¼ö ÀÖÀ½.
1401        //
1402        if (prev_pat == NULL || pat->numPrograms != tsport->num_programs)
1403        {
1404                if (!prev_pat) {
1405                        dprint(3, "new pat, %d program\n", pat->numPrograms);
1406                }
1407                else {
1408                        dprint(3, "tsport num programs changed, %d -> %d\n", tsport->num_programs, pat->numPrograms);                   
1409                }
1410                // ±âÁ¸ µ¿ÀÛ ÁßÀÎ pmt monitor¸¦ ¸ðµÎ Á¤Áö.
1411                StopMonitorPMTs(tsport);
1412               
1413                dprint(3, "alloc %d pmt ctl arrays..\n", pat->numPrograms);
1414                tsport->pmtPsiCtlArray = DHL_OS_Malloc(pat->numPrograms * sizeof(tDHL_PSI_ControlHandle));
1415                if (!tsport->pmtPsiCtlArray) {
1416                        // pat ¿Í pmt monitor °£ÀÇ °ü°è°¡ ¾î±ß³µÀ¸¹Ç·Î ¹®Á¦°¡ ¹ß»ýÇÒ ¼ö ÀÖÀ½!!
1417                        tsport->num_programs = 0; // <- ¹Ýµå½Ã ÇÊ¿ä.
1418                        // ÀÌ¿ÕÀ̸é pat ±îÁö ´Ù »èÁ¦Çϸé Àϰü¼ºÀÌ Àִµ¥, DBÀÇ pat¸¸ »èÁ¦ÇÒ ¹æ¹ýÀº ¾øÀ½.
1419                        status = statusOutOfMemory;
1420                        goto label_end;
1421                }
1422                tsport->num_programs = pat->numPrograms;
1423
1424        }
1425        else // program °¹¼ö º¯°æÀÌ ¾ø´Â °æ¿ì.
1426        {
1427                // ASSERT (prev_pat->numPrograms == tsport->num_programs);
1428               
1429                // pmt psictlÀÇ pid, pnÀÌ pat ¿Í ÀÏÄ¡ÇÏ´ÂÁö üũ.
1430                // ÀÏÄ¡ÇÏÁö ¾ÊÀº monitor´Â cancel.
1431                for (i=0; i<pat->numPrograms; i++)
1432                {
1433                        if (tsport->pmtPsiCtlArray[i] == (tDHL_PSI_ControlHandle)0) continue;
1434                       
1435                        if (prev_pat->programs[i].program_map_PID != pat->programs[i].program_map_PID ||
1436                                prev_pat->programs[i].program_number != pat->programs[i].program_number)
1437                        {
1438                                dprint(3, "pid/pn diff! cancel pmt[%d] monitor..\n", i);
1439                                DHL_PSI_StopMonitor(tsport->pmtPsiCtlArray[i]);
1440                                tsport->n_active_monitors--;
1441                                tsport->pmtPsiCtlArray[i] = (tDHL_PSI_ControlHandle)0;
1442                        }
1443                }
1444        }
1445
1446        // pat°¡ ±âÁ¸ pat¿Í ´Ù¸¥ °æ¿ì¿¡¸¸ update Çϰí notify ÇÑ´Ù.
1447        if (!PSIUTIL_IsEquivalentPat(prev_pat, pat))
1448        {
1449                // PAT¸¦ DB¿¡ update ÇÑ´Ù.
1450                status = PSIDB_UpdatePAT(tsport->input.rf, pat);
1451
1452                if (status) {
1453                        // ¹«½¼ ÀÌÀ¯¿¡¼­ÀÎÁö pat update ½ÇÆÐ. (´ëºÎºÐ ¸Þ¸ð¸® ¿¡·¯)
1454                        StopMonitorPMTs(tsport);
1455                        goto label_end;
1456                }
1457               
1458                SendUserCallback(tsport, ePSIM_EVENT_PatReceived, (UINT32)pat);
1459        }
1460       
1461        // PMT¸¦ monitor ½ÃÀÛÇÑ´Ù.
1462        // input flag¿¡ µû¶ó µ¿ÀÛÀÌ ´Þ¶óÁü.
1463
1464        if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) 
1465        {
1466                StopMonitorPAT(tsport);
1467
1468                if (PSIDB_IsPmtsCompleted(tsport->input.rf)) {
1469                        SendUserCallback(tsport, ePSIM_EVENT_AllPmtsReceived, 0);
1470                        // pmt monitor ¸ðµÎ close..
1471                        StopMonitorPMTs(tsport);
1472                }
1473                else {
1474                        // ´Ù¸¥ monitor ½ÃÀÛ..
1475                        StartMonitorPMTs(tsport, -1); // no preference. get all pmts..
1476                }
1477        }
1478        else {
1479                StartMonitorPMTs(tsport, tsport->input.program_number);
1480        }
1481        pat = NULL; // not to be freed later
1482
1483label_end:
1484
1485        if (pat) {
1486                dprint(3, "  free unused pat %x..\n", pat);
1487                PSIUTIL_FreeTable(&pat);
1488        }
1489       
1490        return status;
1491       
1492}
1493
1494PSI_STATIC STATUS ProcessPMT(S_PSIM_PORT *tsport, tDHL_PSI_DataArray *desc)
1495{
1496        DHL_RESULT err;
1497        STATUS status = statusOK;
1498
1499        MPEG_PMT *pmt;
1500        MPEG_PAT *pat;
1501       
1502        int i, index;
1503        BOOL bPsiCtlConsistent = FALSE;
1504        //BOOL bPmtComplete;
1505       
1506        err = ParsePMT(desc, &pmt);
1507        if (IsError(err)) {
1508                dprint(0, "%s: ParsePMT returned %s\n", __FUNCTION__, ErrorString(err));
1509                return statusInvalidPSI;
1510        }
1511
1512        // PMT sanity check.
1513        // todo:  pmt of numStreams zero.. 
1514        // pmt ÀÌÈÄ·ÎÀÇ ¿¬°áµÈ ÀÛ¾÷Àº ¾øÀ¸´Ï, Á» ÀÌ»óÇÑ pmt¶óµµ ÀÏ´Ü ¼ö½ÅÀº ÇØ µÑ±î?
1515        //     ¾Æ´Ï¸é ÇâÈÄ ÀÛ¾÷µéÀ» ÆíÇÏ°Ô Çϱâ À§Çؼ­ ±×³É ¸ø¹ÞÀº °ÍÀ¸·Î??
1516        // ±×³É ¹ö¸°´Ù¸é..
1517        //   pros: ÀÌ»óÇÑ pmt¸¦ ¹Ì¸® filter out ÇØ ¹ö¸®¸é ÇâÈÄ check ÀÛ¾÷ÀÌ ¾ø¾îµµ µÇ´Ï ÆíÇÔ.
1518        //   cons: pmt ¼ö½Å ¿Ï·á°¡ ¾ÈµÇ´Ï±î autoscan µî¿¡¼­ timeout ¹ß»ý½Ã±îÁö ´À·ÁÁü..
1519        //
1520        // --> ¼Óµµº¸´Ù´Â ¾ÈÁ¤¼º.. ±×³É ¹ö¸®ÀÚ.
1521        //
1522        if (!pmt || pmt->numStreams == 0 || !pmt->streams) {
1523                dprint(0, "!! wrong pmt\n");
1524                PSIUTIL_FreeTable(&pmt);
1525                return statusInvalidPSI;
1526        }
1527
1528        for (i=0; tsport->pmtPsiCtlArray && i<tsport->num_programs; i++) {
1529                if (tsport->pmtPsiCtlArray[i] == desc->handle) {
1530                        bPsiCtlConsistent = TRUE;
1531                        break;
1532                }
1533        }
1534        if (!bPsiCtlConsistent) {
1535                dprint(0, "!! inconsistent! any pmtPsiCtls[] != desc psictl %x\n", desc->handle);
1536                status = statusInvalidState;
1537                goto label_end;
1538        }
1539
1540        //--------------------------------------------------------------------
1541        // now, table becoms vailid. if not updated to DB, free it carefully.
1542
1543        // determine index using origianl psictl pointer
1544        index = -1;
1545        for (i=0; i<tsport->num_programs; i++) {
1546                if (tsport->pmtPsiCtlArray[i] == desc->handle) {
1547                        index = i;
1548                        break;
1549                }
1550        }
1551        if (index < 0) {
1552                dprint(0, "!! cannot find psictl origin\n");
1553                // ¿¹¿Ü ó¸®: ±×³É ÇöÀç pmt ¹«½Ã. Àç½Ãµµ ¾ÈÇÔ.
1554                status = statusInvalidPSI;
1555                goto label_end;
1556        }
1557
1558        // pat ³»¿ë°ú ÀÏÄ¡ ¿©ºÎ üũ. (program number ..)
1559       
1560        pat = PSIDB_GetPAT(tsport->input.rf);
1561        if (pat == NULL) {
1562                dprint(0, "!! pmt without pat?\n");
1563                // ¿¹¿Ü ó¸®: ±×³É ÇöÀç pmt ¹«½Ã. Àç½Ãµµ ¾ÈÇÔ.
1564                status = statusInvalidPSI;
1565                goto label_end;
1566        }
1567       
1568        if (pat->numPrograms != tsport->num_programs) {
1569                dprint(0, "!! pat not consistent to pmt monitors\n");
1570                PSIUTIL_FreeTable(&pmt);
1571
1572                // ¿¹¿Ü ó¸®: pmt monitorµéÀº ¸ðµÎ reset ½ÃÄÑ ³õ´Â´Ù.
1573                StopMonitorPMTs(tsport);
1574                status = statusInvalidPSI;
1575                goto label_end;
1576        }
1577
1578        if (dprintable(3))
1579                PrintPMT(pmt);
1580
1581        // update..
1582        status = PSIDB_UpdatePMT(tsport->input.rf, pmt);
1583        // now, don't use pmt any more!
1584
1585        if (status) {
1586                // ¹«½¼ ÀÌÀ¯¿¡¼­ÀÎÁö pmt update ½ÇÆÐ. (´ëºÎºÐ ¸Þ¸ð¸® ¿¡·¯)
1587                goto label_end;
1588        }
1589
1590        // autoscan ¸ðµå¶ó¸é ÇöÀç ¼ö½ÅÇÑ pmt´Â stop Çϰí Ãß°¡ pmt ¼ö½ÅÀÌ ÇÊ¿äÇϸé Á¶Ä¡ÇÔ.
1591        if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN)
1592        {
1593                // ¹æ±Ý ¼ö½ÅÇÑ pmtÀÇ monitor´Â Á¾·á
1594                DHL_PSI_StopMonitor(tsport->pmtPsiCtlArray[index]);
1595                tsport->pmtPsiCtlArray[index] = (tDHL_PSI_ControlHandle)0;
1596                tsport->n_active_monitors--;
1597
1598                if (PSIDB_IsPmtsCompleted(tsport->input.rf)) {
1599                        SendUserCallback(tsport, ePSIM_EVENT_AllPmtsReceived, 0);
1600                        // ÀÌ¹Ì pat monitor´Â Á¤ÁöµÇ¾î ÀÖÀ» °ÍÀÌÁö¸¸ ´Ù½Ã Çѹø üũ..
1601                        StopMonitorPAT(tsport);
1602                        // pmt monitor ¸ðµÎ close..
1603                        StopMonitorPMTs(tsport);
1604                }
1605                else {
1606                        // ´Ù¸¥ monitor ½ÃÀÛ..
1607                        StartMonitorPMTs(tsport, -1);
1608                }
1609        }
1610        else
1611        {
1612        #if 1
1613                // pmt pointer ±×´ë·Î access °¡´ÉÇϹǷΠÁ» ´õ °£´ÜÇØÁü.
1614                SendUserCallback(tsport, ePSIM_EVENT_PmtReceived, (UINT32)pmt);
1615        #else
1616                for (i=0; pmtList && i<pat->numPrograms; i++) {
1617                        if (tsport->input.program_number == pmtList[i]->program_number) {
1618                                SendUserCallback(tsport, ePSIM_EVENT_PmtReceived, (UINT32)pmtList[i]);
1619                                break;
1620                        }
1621                }
1622        #endif
1623        }
1624        pmt = NULL; // not to be freed later
1625
1626label_end:
1627
1628        if (pmt) {
1629                dprint(3, "  free unused pmt %x..\n", pmt);
1630                PSIUTIL_FreeTable(&pmt);
1631        }
1632        return status;
1633
1634}
1635
1636
1637PSI_STATIC STATUS ProcessMgt(S_PSIM_PORT *tsport, tDHL_PSI_DataArray *desc)
1638{
1639        DHL_RESULT err;
1640        STATUS status = statusOK;
1641        BOOL bMgtChanged = FALSE;
1642       
1643        mgtSectionPtr_t mgt, prev_mgt;
1644       
1645        err = ParseMgtSection(desc->sectPtr[0], &mgt);
1646        // desc will be freed at caller.
1647       
1648        if (IsError(err)) {
1649                dprint(0, "%s: ParseMgt returned %s\n", __FUNCTION__, ErrorString(err));
1650                return statusInvalidPSI;
1651        }
1652
1653        // sanity check
1654        if (!mgt || mgt->tables_defined==0 || !mgt->table) {
1655                dprint(0, "!! invalid mgt\n");
1656                PSIUTIL_FreeTable(&mgt);
1657                return statusInvalidPSI;
1658        }
1659
1660        if (tsport->mgtPsiCtl != desc->handle) {
1661                dprint(0, "!! inconsistent! mgtPsiCtl %x != desc psictl %x\n", tsport->mgtPsiCtl, desc->handle);
1662                status = statusInvalidState;
1663                goto label_end;
1664        }
1665
1666        //--------------------------------------------------------------------
1667        // now, table becoms vailid. if not updated to DB, free it carefully.
1668
1669        if (dprintable(4))
1670                PrintMgtSection(mgt);
1671
1672        //-----------------------------------
1673        // ±âÁ¸ table°ú ºñ±³ÇÏ¿© º¯°æ »çÇ×ÀÌ ¿©ºÎ üũ
1674
1675        prev_mgt = PSIDB_GetMgt(tsport->input.rf);
1676
1677        if (prev_mgt == NULL) {
1678                dprint(2, "  mgt newly comes.. new mgt ver %d\n", mgt->version_number);
1679                bMgtChanged = TRUE;
1680        }
1681        else if (PSIUTIL_IsEquivalentMgt(prev_mgt, mgt) == FALSE) {
1682                dprint(2, "  mgt changed.. ver %d --> %d\n", prev_mgt->version_number, mgt->version_number);
1683                bMgtChanged = TRUE;
1684        }
1685        else {
1686                dprint(2, "  mgt version unchagned %d\n", mgt->version_number);
1687
1688                // mgt versionÀÌ º¯°æµÇÁö ¾Ê¾Ò´Ù°í ÇØµµ ¿©·¯°¡Áö ÀÌÀ¯·Î (filter ºÎÁ·) ½ÃÀÛÇÏÁö ¸øÇÑ
1689                // sectionµéÀÌ ÀÖÀ» ¼ö ÀÖÀ¸¹Ç·Î ¿©±â¼­ Áß´ÜÇÏÁö ¾Ê°í °è¼Ó ÁøÇàÇÑ´Ù.
1690        }
1691
1692        //-----------------------------------
1693        if (bMgtChanged) 
1694        {
1695                // DB¿¡ update ÇÑ´Ù. À̶§ ³»ºÎ¿¡¼­ ¸¹Àº ºÎ°¡ ÀÛ¾÷ÀÌ °°ÀÌ ÁøÇà µÈ´Ù.
1696                // ex: º¯°æ µÇ´Â ¸ðµç Å×À̺í Á¤¸®, mgt digest »ý¼º
1697                //
1698                status = PSIDB_UpdateMgt(tsport->input.rf, mgt);
1699                if (status) {
1700                        // ¹«½¼ ÀÌÀ¯¿¡¼­ÀÎÁö mgt update ½ÇÆÐ..
1701                        goto label_end;
1702                }
1703                //SendUserCallback(tsport, ePSIM_EVENT_MgtReceived, (UINT32)mgt);
1704        }
1705
1706        if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) {
1707                // autoscan ¸ðµå¿¡¼­´Â ÇϳªÀÇ instance¸¸ ¼ö½ÅÇÏ¸é µÇ¹Ç·Î ¹Ù·Î ÁßÁö.
1708                StopMonitorMgt(tsport);
1709        }
1710
1711        // mgt¿Í vct°¡ ¸ðµÎ ¹Þ¾ÆÁ® ÀÖ´Ù¸é eit/ett ¼ö½ÅÀ» ½ÃÀÛÇÒ ¼ö ÀÖ´Ù.
1712        if (!PSIDB_IsSubChScanReadyToStart(tsport->input.rf)) {
1713                // not ready.
1714                dprint(2, "  subch scan not ready.. mgt %x, vct %x\n", 
1715                        PSIDB_GetMgt(tsport->input.rf), PSIDB_GetVct(tsport->input.rf));
1716        }
1717        else { 
1718                //test..SendEventChannelStarted(tsport, tsport->input.rf);
1719               
1720                StartSubChannelScan(tsport);
1721        }
1722       
1723        mgt = NULL; // not to be freed later
1724       
1725label_end:
1726
1727        if (mgt) {
1728                dprint(3, "  free unused mgt %x..\n", mgt);
1729                PSIUTIL_FreeTable(&mgt);
1730        }
1731        return status;
1732       
1733}
1734
1735PSI_STATIC STATUS ProcessVct(S_PSIM_PORT *tsport, tDHL_PSI_DataArray *desc)
1736{
1737        DHL_RESULT err;
1738        STATUS status = statusOK;
1739        xvctPtr_t vct, prev_vct;
1740        BOOL bVctChanged = FALSE;
1741
1742        dprint(2, "process vct..\n");
1743       
1744        err = ParseVct(desc->sectPtr, &vct);
1745        // desc will be freed at caller.
1746       
1747        if (IsError(err)) {
1748                dprint(0, "%s: ParseVct returned %s\n", __FUNCTION__, ErrorString(err));
1749                return statusInvalidPSI;
1750        }
1751
1752        // sanity check
1753        if (!vct || vct->numChannels==0 || !vct->channel) {
1754                dprint(0, "!! invalid vct\n");
1755                PSIUTIL_FreeTable(&vct);
1756                return statusInvalidPSI;
1757        }
1758
1759        //--------------------------------------------------------------------
1760        // now, table becoms vailid. if not updated to DB, free it carefully.
1761
1762        //-----------------------------------
1763        // vct °íÀ¯ÀÇ Ã³¸® ·çƾµé.. µÎ°³ÀÇ vct Áß¿¡¼­ ÇϳªÀÇ monitor¸¸ »ì·Á³õ´Â´Ù.
1764       
1765        if (vct->is_cvct) // cvct
1766        {
1767                if (tsport->cvctPsiCtl == (tDHL_PSI_ControlHandle)0) {
1768                        // already cancelled. this is delayed processing.
1769                        dprint(2, "already cancelled cvct mon\n");
1770                        goto label_end;
1771                }
1772                if (tsport->cvctPsiCtl != desc->handle) {
1773                        dprint(0, "!! inconsistent! cvctpsictl %x != desc psictl %x\n", tsport->cvctPsiCtl, desc->handle);
1774                        status = statusInvalidState;
1775                        goto label_end;
1776                }
1777                // ´çÀå tvct´Â ÁßÁö½ÃŲ´Ù. ¿ÀÁ÷ ÇϳªÀÇ vct¸¸ °¡´ÉÇϵµ·Ï...
1778                StopMonitorTvct(tsport);
1779        }
1780        else // tvct
1781        {
1782                if (tsport->tvctPsiCtl == (tDHL_PSI_ControlHandle)0) {
1783                        // already cancelled. this is delayed processing.
1784                        dprint(2, "already cancelled tvct mon\n");
1785                        goto label_end;
1786                }
1787                if (tsport->tvctPsiCtl != desc->handle) {
1788                        dprint(0, "!! inconsistent! tvctpsictl %x != desc psictl %x\n", tsport->tvctPsiCtl, desc->handle);
1789                        status = statusInvalidState;
1790                        goto label_end;
1791                }
1792                // ´çÀå cvct´Â ÁßÁö½ÃŲ´Ù. ¿ÀÁ÷ ÇϳªÀÇ vct¸¸ °¡´ÉÇϵµ·Ï...
1793                StopMonitorCvct(tsport);
1794        }
1795
1796        //-----------------------------------
1797        // ±âÁ¸ table°ú ºñ±³ÇÏ¿© º¯°æ »çÇ×ÀÌ ¿©ºÎ üũ
1798
1799        prev_vct = PSIDB_GetVct(tsport->input.rf);
1800
1801        if (prev_vct == NULL) {
1802                dprint(2, "  vct newly comes.. new vct ver %d\n", vct->version_number);
1803                bVctChanged = TRUE;
1804        }
1805        else if (PSIUTIL_IsEquivalentVct(prev_vct, vct) == FALSE) {
1806                dprint(2, "  vct changed.. ver %d --> %d\n", prev_vct->version_number, vct->version_number);
1807                bVctChanged = TRUE;
1808        }
1809        else {
1810                dprint(2, "  vct version unchagned %d\n", prev_vct->version_number);
1811       
1812                // vct°¡ º¯°æµÇÁö ¾Ê¾Ò´Ù°í ÇØµµ ¿©·¯°¡Áö ÀÌÀ¯·Î (filter ºÎÁ·) ½ÃÀÛÇÏÁö ¸øÇÑ
1813                // sectionµéÀÌ ÀÖÀ» ¼ö ÀÖÀ¸¹Ç·Î ¿©±â¼­ Áß´ÜÇÏÁö ¾Ê°í °è¼Ó ÁøÇàÇÑ´Ù.
1814        }
1815
1816        //-----------------------------------
1817        if (bVctChanged) 
1818        {
1819                // DB¿¡ update ÇÑ´Ù. À̶§ ³»ºÎ¿¡¼­ ¸¹Àº ºÎ°¡ ÀÛ¾÷ÀÌ °°ÀÌ ÁøÇà µÈ´Ù.
1820                // ex: subchannel struct re-init..
1821                //
1822                status = PSIDB_UpdateVct(tsport->input.rf, vct);
1823
1824                if (status) {
1825                        // something wrong! vct not updated to DB..
1826                        goto label_end;
1827                }
1828                SendUserCallback(tsport, ePSIM_EVENT_VctReceived, (UINT32)vct);
1829        }
1830        else {
1831                // todo
1832                //   Equivalent ÇÏÁö´Â ¾ÊÁö¸¸, »ç¼ÒÇÑ ¾ÆÁÖ ÀÛÀº Â÷À̵éÀÌ ÀÖÀ» ¼ö ÀÖÁö ¾Ê´Â°¡?
1833                //   Áï DB¿¡´Â update¸¦ ÇÏ´Â °ÍÀÌ ÁÁÁö ¾Ê³ª?
1834                //
1835                //   -->
1836                //    Equivalence üũ ·çƾÀÇ Á¤È®µµ¿¡ µû¶ó ¿µÇâÀÌ ´Þ¶óÁü.
1837                //    ¶Ç ¸¸¾à vct continuous ¸ðµå·Î ¹Þ°í ÀÖ´Ù¸é °è¼Ó DB¾ÈÀÇ vct°¡ replace µÉ ¿°·Á ÀÖÀ½.
1838                //    µû¶ó¼­ ÀÏ´ÜÀº update ÇÏÁö ¾Êµµ·Ï ÇÏÀÚ.
1839
1840                // db update ¿©ºÎ¸¦ ¶°³ª¼­ event callbackÀº ºÒ·¯ÁÖµµ·Ï ÇÏÀÚ.
1841                SendUserCallback(tsport, ePSIM_EVENT_VctReceived, (UINT32)vct);
1842        }
1843       
1844        if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) {
1845                // ¾î¶² °ÍÀÌ °¡µ¿ÁßÀÎÁö ¾Ë±â ±ÍÂúÀ¸´Ï±î tvct, cvct µÑ ´Ù ÁßÁö.
1846                StopMonitorTvct(tsport);
1847                StopMonitorCvct(tsport);
1848        }
1849
1850        // mgt¿Í vct°¡ ¸ðµÎ ¹Þ¾ÆÁ® ÀÖ´Ù¸é eit/ett ¼ö½ÅÀ» ½ÃÀÛÇÒ ¼ö ÀÖ´Ù.
1851        if (!PSIDB_IsSubChScanReadyToStart(tsport->input.rf)) {
1852                // not ready.
1853                dprint(2, "  subch scan not ready.. mgt %x, vct %x\n", 
1854                        PSIDB_GetMgt(tsport->input.rf), PSIDB_GetVct(tsport->input.rf));
1855        }
1856        else {
1857                //test..SendEventChannelStarted(tsport, tsport->input.rf);
1858
1859                StartSubChannelScan(tsport);
1860        }
1861       
1862        vct = NULL; // not to be freed later
1863       
1864label_end:
1865
1866        if (vct) {
1867                // DB¿¡ update µÇÁö ¾ÊÀº vct´Â ¾ø¾ÖÁà¾ß ¸Þ¸ð¸® ´©¼ö°¡ ¾øÀ½..
1868                dprint(3, "  free unused vct %x..\n", vct);
1869                PSIUTIL_FreeTable(&vct);
1870        }
1871       
1872        return status;
1873}
1874
1875
1876
1877//  STT°¡ ¼ö½ÅµÉ ¶§¸¶´Ù ÀÌ ÇÔ¼ö°¡ ºÒ¸°´Ù..
1878//
1879//  ÀÌ ÇÔ¼ö¿¡¼­ STT 󸮸¦ Çϰí Program event º¯°æ üũµµ ÇÑ´Ù.
1880//  Áï program event º¯°æ üũ´Â STT°¡ ¼ö½Å µÉ °æ¿ì¿¡¸¸ ¼öÇàÇÏ°Ô µÈ´Ù.
1881//
1882//  ¸¸¾à STT ÁֱⰡ ±æ°Å³ª, ½ÅÈ£ »óŰ¡ ¾ÊÁÁÀ½ µîÀÇ ÀÌÀ¯·Î STT update°¡ ´Ê¾îÁú °æ¿ì
1883//  program event º¯°æ üũµµ ´Ê¾îÁú ¼ö ÀÖ´Ù.
1884//
1885//  µû¶ó¼­ User´Â º°µµ·Î ÁÖ±âÀûÀ¸·Î program event º¯°æ üũ¸¦ ºÒ·¯ÁÙ Çʿ䰡 ÀÖ´Ù.
1886//
1887PSI_STATIC STATUS ProcessStt(S_PSIM_PORT *tsport, tDHL_PSI_DataArray *desc)
1888{
1889        DHL_RESULT err;
1890        STATUS status = statusOK;
1891        UINT32 tick = DHL_OS_GetMsCount();
1892
1893        sttSection_t prev_stt_0;
1894        sttSectionPtr_t stt, prev_stt = &prev_stt_0;
1895       
1896        err = ParseSttSection(desc->sectPtr[0], &stt);
1897        // desc will be freed at caller.
1898       
1899        if (IsError(err)) {
1900                dprint(0, "%s: ParseStt returned %s\n", __FUNCTION__, ErrorString(err));
1901                return statusInvalidPSI;
1902        }
1903
1904        // sanity check
1905        if (!stt) {
1906                PSIUTIL_FreeTable(&stt);
1907                return statusInvalidPSI;
1908        }
1909
1910        if (tsport->sttPsiCtl != desc->handle) {
1911                dprint(0, "!! inconsistent! sttPsiCtl %x != desc psictl %x\n", tsport->sttPsiCtl, desc->handle);
1912                status = statusInvalidState;
1913                goto label_end;
1914        }
1915
1916        //--------------------------------------------------------------------
1917        // now, table becoms vailid. if not updated to DB, free it carefully.
1918       
1919        // Ȥ½Ã ÇöÀçÀÇ SttPsiCtl ÀÌ ÀÌ¹Ì Ãë¼Ò µÇ¾î ÀÖÀ» ¼öµµ Àֱ⠶§¹®¿¡
1920        // ÇöÀç contextÀÇ ³»¿ëÀ» È®ÀÎÇØ º¸´Â °Íµµ ÁÁ´Ù.
1921        //
1922        if (tsport->sttPsiCtl == (tDHL_PSI_ControlHandle)0) {
1923                dprint(0, "!! %s: stt from null psi ctl\n", __FUNCTION__);
1924                //return statusInvalidState;
1925                return statusOK;
1926        }
1927
1928
1929        if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) 
1930        {
1931                StopMonitorStt(tsport);
1932                //goto label_end;  // stt notify ÇØÁÖ±â À§Çؼ­ ±×³É skipÀº ¾ÈÇÔ.
1933
1934                // autoscan ¸ðµå¶óµµ stt notify µîÀº ÇÊ¿äÇÒ ¼ö ÀÖÀ¸¹Ç·Î
1935                // ¾Æ·¡ ÀÛ¾÷Àº µ¿ÀÏÇÏ°Ô ¼öÇàÇØ ÁÖµµ·Ï ÇÑ´Ù.
1936                // ´Ü program change notify´Â ÇÒ ÇÊ¿ä ¾ø´Ù.
1937        }
1938
1939
1940        // stt ³»¿¡´Â system time »Ó¸¸ ¾Æ´Ï¶ó GPS_UTC offset ¹× daylight saving Á¤º¸µµ ÀÖ´Ù.
1941        // ÀÌ ¸ðµç ³»¿ëÀÌ µ¿ÀÏÇÑ °æ¿ì¿¡¸¸ equivalent¶ó°í ÇÒ ¼ö ÀÖÀ½.
1942       
1943        prev_stt = PSIDB_GetStt(tsport->input.rf);
1944
1945        if (PSIUTIL_IsEquivalentStt(prev_stt, stt))
1946        {
1947                // µ¿ÀÏÇÑ ½Ã°£À¸·Î stt°¡ ¼ö½ÅµÇ¾úÀ½. ó¸®ÇÒ ÇÊ¿ä ¾ø´Ù.
1948                // sarnoff stream: rpbp, fast base pid stream ´ëÀÀ.
1949                //  stt°¡ ÃÊ´ç 10ȸ¾¿ Àü¼ÛµÊ.
1950        }
1951        else
1952        {
1953                // ±âÁ¸ stt¿¡ ºñÇØ ¹º°¡ ´Ù¸¥ stt°¡ ¼ö½ÅµÈ °æ¿ìÀÌ´Ù.
1954                // »ç½Ç ´ëºÎºÐÀÇ °æ¿ì ÀÌ ¹üÁÖ¿¡ ¼ÓÇÑ´Ù.
1955
1956                if (dprintable(4))
1957                        PrintSttSection(stt);
1958
1959                // update¸¦ Çϱâ Àü¿¡ backupÀ» ÇØ µÎ¾î¾ß ÇÔ. ±×·¸Áö ¾ÊÀ¸¸é
1960                // PSIDB_UpdateStt Çϸ鼭 »õ·Î¿î stt·Î overwrite µÇ¾î ¹ö¸°´Ù.
1961                //
1962                if (prev_stt) {
1963                        prev_stt_0 = *prev_stt;
1964                        prev_stt = &prev_stt_0;
1965                }
1966               
1967                status = PSIDB_UpdateStt(tsport->input.rf, stt, tick);
1968                if (status) {
1969                        goto label_end;
1970                }
1971
1972                // DBÀÇ stt´Â flat_stt ¶ó°í Á» ´Ù¸¥ ÇüÅÂÀ̹ǷΠ¼ö½Å ¹ÞÀº stt´Â ¹ö¸®°í
1973                // DBÀÇ stt Á¤º¸¸¦ Âü°íÇÏÀÚ.
1974                PSIUTIL_FreeTable(&stt);
1975                stt = PSIDB_GetStt(tsport->input.rf);
1976
1977                if (g_Trace_bPsiSttInfo) {
1978                        char cur_time[100] = {0, };             
1979                #if DMW_EPG_TABLE_DUMP_DEBUG   
1980                        Dmc_SetGpsTimeSync(stt);
1981                        GpsTimeString(stt->system_time, cur_time);
1982                #endif
1983                        dprint(2, "[STT] (rf %d, sid %d) %s gps 0x%x\n",
1984                                        tsport->input.rf, tsport->input.source_id, cur_time, stt->system_time);
1985                }
1986
1987                // STT Smart Notification
1988                //
1989                //   if 'system time JUMP' is detected, notify to user.
1990                //   probably stream is changed, tuner setting (rf) is changed,
1991                //     or signal is re-aquired in weak signal environment.
1992                //   user had better re-sync system time to this new STT value..
1993                //     
1994
1995                // »õ stt°¡ ¼ö½ÅµÇ¾ú´Ù°í ÇØ¼­ ¸Å¹ø notify¸¦ ÇÏÁö´Â ¾Ê´Â´Ù.
1996                // ´ÙÀ½ µÎ°¡Áö Á¶°Ç¿¡ ÇØ´ç µÉ °æ¿ì¿¡¸¸ notify ÇÑ´Ù.
1997                //
1998                // 1. ÀÌ RF¿¡¼­ psi scanÀ» ½ÃÀÛ ÇÑ ÈÄ Ã³À½ ¼ö½ÅµÈ stt
1999                // 2. stt threshold¸¦ ³Ñ¾î¼± skipÀÌ ¹ß°ßµÈ °æ¿ì..
2000                //
2001                if (prev_stt == NULL)
2002                {
2003                        // EpgScanÀÌ ½ÃÀÛµÇ°í ³ª¼­ óÀ½ ¹ÞÀº stt¶ó¸é event¸¦ º¸³»ÁØ´Ù.
2004                        //
2005                        dprint(1, "first STT received after psi start..\n");
2006                       
2007                        SendUserCallback(tsport, ePSIM_EVENT_SttReceived, (UINT32)stt);
2008                }
2009                else if (abs((SINT32)(stt->system_time - prev_stt->system_time)) > STT_JUMP_THRESHOLD)
2010                {
2011                        //int age = (DHL_OS_GetMsCount() - tick_stt_get) / 1000;
2012                       
2013                        dprint(1, "STT Jump (%d sec) detected..\n", stt->system_time - prev_stt->system_time);
2014                       
2015                        // jump´Â À½ÀÇ °ªÀÌ µÉ ¼öµµ ÀÖ´Ù. stream ÀÌ ¹Ýº¹Çؼ­ Àç»ýµÇ´Â °æ¿ì..
2016                        //
2017                        // age¸¦ °è»êÇØ¼­ ³Ñ°ÜÁÖ´Â ÀÌÀ¯´Â ÀÌ stt ó¸® task°¡ priority°¡ ³·¾Æ¼­
2018                        // ½ÇÁ¦·Î stt¸¦ ¹ÞÀº ½Ã°£°ú ÀÌ stt¸¦ ó¸®ÇÏ´Â ½Ã°£¿¡ Â÷À̰¡ ÀÖÀ» ¼ö Àֱ⠶§¹®.
2019                        // ´ëºÎºÐ ¾ÆÁÖ ÀÛÀº °ªÀ̰ųª 0ÀÇ °ªÀ» °®À» °ÍÀÌ´Ù.
2020                       
2021                        SendUserCallback(tsport, ePSIM_EVENT_SttReceived, (UINT32)stt);
2022                }
2023
2024                // Program Event º¯°æ »çÇ× Ã¼Å©.
2025                // autoscan ¸ðµåÀÎ °æ¿ì¿¡´Â ºÒÇÊ¿ä.
2026                //
2027                if (PSI_FLAGS_MODE(tsport->input.flags) != PSI_FLAGS_AUTOSCAN /* && IS_VALID_SOURCE_ID(tsport->source_id) */) 
2028                {
2029                        CheckIfProgramEventChanged(tsport);
2030                }
2031               
2032        }
2033        stt = NULL; // not to be freed later
2034       
2035label_end:
2036
2037        if (stt) {
2038                dprint(3, "  free unused stt %x..\n", stt);
2039                PSIUTIL_FreeTable(&stt);
2040        }
2041        return status;
2042}
2043
2044PSI_STATIC STATUS ProcessRrt(S_PSIM_PORT *tsport, tDHL_PSI_DataArray *desc)
2045{
2046        STATUS status = statusOK;
2047       
2048        return status;
2049}
2050
2051/*
2052        ¾î¶² eit[k] ÀÎÁö È®ÀÎÇϱâ À§Çؼ­´Â ÀÌ Å×À̺íÀ» ¼ö½ÅÇÑ psiCtlÀ» ¾Ë¾Æ¾ß ÇÑ´Ù.
2053       
2054*/
2055PSI_STATIC STATUS ProcessEit(S_PSIM_PORT *tsport, tDHL_PSI_DataArray *desc)
2056{
2057        int index, i;
2058        STATUS status = statusOK;
2059        DHL_RESULT err;
2060        eitPtr_t eit;
2061        //BOOL bFilterReleased = FALSE;
2062        BOOL bPsiCtlConsistent = FALSE;
2063       
2064        err = ParseEit(desc->sectPtr, &eit);
2065        // desc will be freed at caller.
2066       
2067        if (IsError(err)) {
2068                dprint(0, "%s: ParseEit returned %s\n", __FUNCTION__, ErrorString(err));
2069                return statusInvalidPSI;
2070        }
2071
2072        // Eit table sanity check
2073        if (eit->numEvents && !eit->event) {
2074                PSIUTIL_FreeTable(&eit);
2075                return statusInvalidPSI;
2076        }
2077
2078        for (i=0; i<128; i++) {
2079                if (tsport->eitPsiCtl[i] == desc->handle) {
2080                        bPsiCtlConsistent = TRUE;
2081                        break;
2082                }
2083        }
2084        if (!bPsiCtlConsistent) {
2085                dprint(0, "!! inconsistent! any eitPsiCtls[] != desc psictl %x\n", desc->handle);
2086                status = statusInvalidState;
2087                goto label_end;
2088        }
2089
2090        //--------------------------------------------------------------------
2091        // now, table becoms vailid. if not updated to DB, free it carefully.
2092
2093        // decide which eit it is..
2094        index = -1;
2095        for (i=0; i<128; i++) {
2096                if (desc->handle == tsport->eitPsiCtl[i]) {
2097                        index = i;
2098                        break;
2099                }
2100        }
2101        if (index < 0) {
2102                dprint(0, "!! orphan eit?\n");
2103                status = statusInvalidPSI;
2104                goto label_end;
2105        }
2106
2107        dprint(2, "eit[%d] received. sid %d\n", index, eit->source_id);
2108        if (dprintable(3)) {
2109                //PrintEit(eit);
2110        }
2111       
2112        // Eit¸¦ DB¿¡ update ÇÑ´Ù.
2113        PSIDB_UpdateEit(tsport->input.rf, eit, index);
2114
2115#if 0
2116        // this is just for informational declare.
2117        if (PSIDB_IsSubChEitsCompleted(tsport->input.rf, eit->source_id)) {
2118                dprint(2, "\n#### source_id %d subch eit completed\n", eit->source_id);
2119        }
2120#endif
2121
2122        // schedule next job..
2123        // Ȥ½Ã filter °¹¼ö Á¦ÇÑ ¶§¹®¿¡ ¹ÞÁö ¸øÇÑ ´Ù¸¥ table µé schedule.
2124        //
2125        if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) 
2126        {
2127                if (PSIDB_IsAllSubChEitsCompleted(tsport->input.rf, index)) 
2128                {
2129                        dprint(2, "all subch's eit[%d] completed. stop monitor..\n", index);
2130                        StopMonitorEit(tsport, index);
2131                        //bFilterReleased = TRUE;
2132
2133                        // monitor remaining pmts..
2134                        StartMonitorPMTs(tsport, -1); // no preference. get all pmts..
2135                }
2136        }
2137        else {
2138                // 1:1 À̹ǷÎ, ¼ö½ÅÇÏ¸é ¹Ù·Î ÁßÁöÇÔ.
2139                StopMonitorEit(tsport, index);
2140                //bFilterReleased = TRUE;
2141               
2142                // monitor remaining eits..
2143                StartSubChannelScan(tsport);
2144        }
2145        eit = NULL; // not to be freed later
2146
2147label_end:
2148
2149        if (eit) {
2150                dprint(3, "  free unused eit %x..\n", eit);
2151                PSIUTIL_FreeTable(&eit);
2152        }
2153        return status;
2154}
2155
2156
2157PSI_STATIC STATUS ProcessEtt(S_PSIM_PORT *tsport, tDHL_PSI_DataArray *desc)
2158{
2159        int index, i;
2160        STATUS status = statusOK;
2161        DHL_RESULT err;
2162        ettSectionPtr_t ett;
2163        BOOL bPsiCtlConsistent = FALSE;
2164
2165        int ett_source_id, ett_event_id;
2166        S_PSIM_SUBCHINFO *subchInfo;
2167       
2168        err = ParseEttSection(desc->sectPtr[0], &ett);
2169        // desc will be freed at caller.
2170       
2171        if (IsError(err)) {
2172                dprint(0, "%s: ParseEtt returned %s\n", __FUNCTION__, ErrorString(err));
2173                return statusInvalidPSI;
2174        }
2175
2176        // Ett table sanity check
2177        if (!ett || ett->ETM_id == 0 || !ett->extended_text_message_length) {
2178                dprint(0, "!! invalid ett\n");
2179                PSIUTIL_FreeTable(&ett);
2180                return statusInvalidPSI;
2181        }
2182
2183        for (i=0; i<128; i++) {
2184                if (tsport->ettPsiCtl[i] == desc->handle) {
2185                        bPsiCtlConsistent = TRUE;
2186                        break;
2187                }
2188        }
2189        if (tsport->ettvPsiCtl == desc->handle)
2190                bPsiCtlConsistent = TRUE;
2191       
2192        if (!bPsiCtlConsistent) {
2193                dprint(0, "!! inconsistent! any ettPsiCtls[] != desc psictl %x\n", desc->handle);
2194                status = statusInvalidState;
2195                goto label_end;
2196        }
2197       
2198        //--------------------------------------------------------------------
2199        // now, table becoms vailid. if not updated to DB, free it carefully.
2200
2201        // context consistency..
2202
2203        if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) {
2204                dprint(0, "!! ett received in autoscan mode?\n");
2205                PSIUTIL_FreeTable(&ett);
2206                return statusInvalidState;
2207        }
2208
2209#if 0
2210        // decide which ett it is..
2211        index = -1;
2212        if (desc->psiCtl == tsport->ettvPsiCtl) {
2213                index = 128;
2214        }
2215        for (i=0; i<128; i++) {
2216                if (desc->psiCtl == tsport->ettPsiCtl[i]) {
2217                        index = i;
2218                        break;
2219                }
2220        }
2221
2222        if (index < 0) {
2223                dprint(0, "!! orphan ett?\n");
2224                return statusInvalidPSI;
2225        }
2226       
2227#else
2228       
2229        // ettÀÇ °æ¿ì ettPsiCtl°úÀÇ ºñ±³·Î iEtt¸¦ ¾Ë¾Æ³»´Â °ÍÀº ¾ÈÀüÇÏÁö ¾Ê´Ù.
2230        // Á÷Á¢ ett ³»ÀÇ etmid °ªÀ» ÀÌ¿ëÇÏ¿© eitsÀÇ event_id ¿Í ºñ±³ÇÏ¿© ã¾Æ¾ß ÇÑ´Ù.
2231
2232        ett_source_id = PSIUTIL_GetSourceIDFromETMID(ett->ETM_id);
2233        ett_event_id = PSIUTIL_GetEventIDFromETMID(ett->ETM_id);
2234
2235        if (tsport->source_id != ett_source_id) {
2236                dprint(0, "!! ett sid %d not matched to port sid %d\n", 
2237                                ett_source_id, tsport->source_id);
2238                PSIUTIL_FreeTable(&ett);
2239                return statusInvalidState;
2240        }
2241
2242        subchInfo = PSIDB_GetPsiSubChInfo(tsport->input.rf, tsport->source_id);
2243        if (!subchInfo) {
2244                PSIUTIL_FreeTable(&ett);
2245                return statusInvalidState;
2246        }
2247       
2248        // ¾î¶² ettÀÎÁö ã´Â´Ù.
2249        index = -1;
2250        if ((ett->ETM_id & 0xffff) == 0) // channel-ett
2251                index = 128;
2252
2253        for (i=0; index<0 && i<128; i++) {
2254                int k;
2255                if (!subchInfo->eits[i]) continue;
2256                for (k=0; k<subchInfo->eits[i]->numEvents; k++) {
2257                        if (subchInfo->eits[i]->event[k].event_id == ett_event_id) {
2258                                index = i;
2259                                break;
2260                        }
2261                }
2262        }
2263        if (index < 0) {
2264                dprint(0, "!! orphan ett? etm 0x%x, no such event_id 0x%x..\n", ett->ETM_id, ett_event_id);
2265                PSIUTIL_FreeTable(&ett);
2266                return statusInvalidPSI;
2267        }
2268       
2269#endif
2270
2271        // todo
2272        // ÀÌ¹Ì ¼ö½ÅÇÑ ett ÀÎÁö °Ë»ç..
2273       
2274
2275        dprint(2, "ett[%d] received. etmid 0x%x\n", index, ett->ETM_id);
2276        if (dprintable(3)) {
2277                //PrintEttSection(ett);
2278        }
2279       
2280        // Eit¸¦ DB¿¡ update ÇÑ´Ù.
2281        PSIDB_UpdateEtt(tsport->input.rf, ett, index);
2282
2283        // ÇØ´ç pidÀÇ ettµéÀÌ ³¡³µ´Ù¸é ÇØ´ç ett psictlÀ» ÁßÁö.
2284        if (PSIDB_IsSubChEttSlotCompleted(tsport->input.rf, tsport->source_id, index)) {
2285                dprint(2, "  ett[%d] slot all received.\n", index);
2286                StopMonitorEtt(tsport, index);
2287        }
2288
2289        // todo
2290        // ÀÌ ¹æ¹ýÀº °áÄÚ È¿À²ÀûÀÌÁö ¸øÇÏ´Ù. ´õ ÁÁÀº ¹æ¹ý Âþ¾Æº¼°Í!
2291        if (PSIDB_IsSubChAllEttsCompleted(tsport->input.rf, tsport->source_id)) {
2292                dprint(2, "  all etts received\n");
2293                StopMonitorAllEtts(tsport);
2294        }
2295        ett = NULL; // not to be freed later
2296       
2297label_end:
2298
2299        if (ett) {
2300                dprint(3, "  free unused ett %x..\n", ett);
2301                PSIUTIL_FreeTable(&ett);
2302        }
2303        return status;
2304}
2305
2306PSI_STATIC void StopAllPsiMonitors(S_PSIM_PORT *tsport)
2307{
2308        //int err;
2309        int i;
2310
2311        dprint(2, "%s:\n", __FUNCTION__);
2312
2313        // PAT
2314        if (tsport->patPsiCtl) {
2315                dprint(3, "\t cancel pat monitor\n");
2316                DHL_PSI_StopMonitor(tsport->patPsiCtl);
2317                tsport->n_active_monitors--;
2318                tsport->patPsiCtl = (tDHL_PSI_ControlHandle)0;
2319        }
2320       
2321        // PMTs
2322        for (i=0; i<tsport->num_programs; i++) {
2323                if (tsport->pmtPsiCtlArray[i]) {
2324                        dprint(3, "\t cancel pmt[%d] monitor\n", i);
2325                        DHL_PSI_StopMonitor(tsport->pmtPsiCtlArray[i]);
2326                        tsport->n_active_monitors--;
2327                        tsport->pmtPsiCtlArray[i] = (tDHL_PSI_ControlHandle)0;
2328                }
2329        }
2330        tsport->num_programs = 0;
2331        DHL_OS_Free((void **)&tsport->pmtPsiCtlArray);
2332
2333        // MGT
2334        if (tsport->mgtPsiCtl) {
2335                dprint(3, "\t cancel mgt monitor\n");
2336                DHL_PSI_StopMonitor(tsport->mgtPsiCtl);
2337                tsport->mgtPsiCtl = (tDHL_PSI_ControlHandle)0;
2338                tsport->n_active_monitors--;
2339        }
2340        // TVCT
2341        if (tsport->tvctPsiCtl) {
2342                dprint(3, "\t cancel tvct monitor\n");
2343                DHL_PSI_StopMonitor(tsport->tvctPsiCtl);
2344                tsport->tvctPsiCtl = (tDHL_PSI_ControlHandle)0;
2345                tsport->n_active_monitors--;
2346        }
2347        // CVCT
2348        if (tsport->cvctPsiCtl) {
2349                dprint(3, "\t cancel cvct monitor\n");
2350                DHL_PSI_StopMonitor(tsport->cvctPsiCtl);
2351                tsport->cvctPsiCtl = (tDHL_PSI_ControlHandle)0;
2352                tsport->n_active_monitors--;
2353        }
2354        // STT
2355        if (tsport->sttPsiCtl) {
2356                dprint(3, "\t cancel stt monitor\n");
2357                DHL_PSI_StopMonitor(tsport->sttPsiCtl);
2358                tsport->sttPsiCtl = (tDHL_PSI_ControlHandle)0;
2359                tsport->n_active_monitors--;
2360        }
2361        // RRT
2362        if (tsport->rrtPsiCtl) {
2363                dprint(3, "\t cancel rrt monitor\n");
2364                DHL_PSI_StopMonitor(tsport->rrtPsiCtl);
2365                tsport->rrtPsiCtl = (tDHL_PSI_ControlHandle)0;
2366                tsport->n_active_monitors--;
2367        }
2368        // EAS
2369        if (tsport->easPsiCtl) {
2370                dprint(3, "\t cancel eas monitor\n");
2371                DHL_PSI_StopMonitor(tsport->easPsiCtl);
2372                tsport->easPsiCtl = (tDHL_PSI_ControlHandle)0;
2373                tsport->n_active_monitors--;
2374        }
2375        // EIT
2376        for (i=0; i<128; i++) {
2377                if (tsport->eitPsiCtl[i]) {
2378                        dprint(3, "\t cancel eit[%d] monitor\n", i);
2379                        DHL_PSI_StopMonitor(tsport->eitPsiCtl[i]);
2380                        tsport->eitPsiCtl[i] = (tDHL_PSI_ControlHandle)0;
2381                        tsport->n_active_monitors--;
2382                }
2383        }
2384        // ETT
2385        for (i=0; i<128; i++) {
2386                if (tsport->ettPsiCtl[i]) {
2387                        dprint(3, "\t cancel ett[%d] monitor\n", i);
2388                        DHL_PSI_StopMonitor(tsport->ettPsiCtl[i]);
2389                        tsport->ettPsiCtl[i] = (tDHL_PSI_ControlHandle)0;
2390                        tsport->n_active_monitors--;
2391                }
2392        }
2393        // Channel-ETT
2394        if (tsport->ettvPsiCtl) {
2395                dprint(3, "\t cancel ett-v monitor\n", i);
2396                DHL_PSI_StopMonitor(tsport->ettvPsiCtl);
2397                tsport->ettvPsiCtl = (tDHL_PSI_ControlHandle)0;
2398                tsport->n_active_monitors--;
2399        }
2400       
2401        if (tsport->n_active_monitors != 0) {
2402                dprint(0, "!! orphan active monitors %d\n", tsport->n_active_monitors);
2403                tsport->n_active_monitors = 0;
2404        }
2405}
2406
2407
2408
2409/*
2410        ¸ðµç tableÀ» ¹Þ´Â event callback
2411
2412        ¹«Á¶°Ç parsing ÇÑ ÈÄ¿¡ task·Î Å×ÀÌºí Æ÷ÀÎÅ͸¦ Àü´ÞÇÑ´Ù.
2413*/
2414PSI_STATIC void _PsiTableEventProc(tDHL_PSI_Event psiEvent, tDHL_PSI_ControlHandle psiCtl, UINT32 userParam)
2415{
2416        STATUS status;
2417        DHL_RESULT err;
2418        tDHL_PSI_DataArray *desc;
2419
2420        S_PSIM_PORT *tsport = (S_PSIM_PORT *) userParam;
2421
2422        if (psiEvent != ePSIEVENT_DATARECEIVED) {
2423                if (g_Trace_bPsiEvent) {
2424                        // ½ÅÈ£°¡ ÁÁÁö ¾ÊÀº °æ¿ì¿¡ lostpacket À̺¥Æ®´Â ¾ÆÁÖ ºó¹øÇÏ°Ô ¹ß»ý °¡´ÉÇϹǷΠÁ¦¿Ü.
2425                        if (psiEvent != ePSIEVENT_LOSTPACKET)
2426                                dprint(3, "%s: psiEvent %s\n", __FUNCTION__, DHL_PSIEventString(psiEvent));
2427                }
2428                return;
2429        }
2430
2431        // data recieved event´Â debug printÇÏÁö ¾Ê´Â´Ù.
2432        //
2433        err = DHL_PSI_ReadPSIData(psiCtl, &desc);
2434        if (err) {
2435                dprint(0, "%s: ReadPSIData returned %s\n", __FUNCTION__, ErrorString(err));
2436                return;
2437        }
2438
2439        status = PSITASK_SendCommand(ePSIM_CMD_TableReceived, (UINT32)tsport, (UINT32)desc, FALSE);
2440
2441        if (status) {
2442                // Q°¡ overflowµÇ¾î µé¾î°¡Áö ¾Ê¾Ò±â ¶§¹®¿¡
2443                // ÇÒ´çÇÑ Å×À̺íÀ» »èÁ¦Çؼ­ ¸Þ¸ð¸® ´©¼ö¸¦ ¸·´Â´Ù
2444                //if (g_Trace_bDmcPsiEvent)
2445                        dprint(0, "!! %s: DmcQ full\n", __FUNCTION__); 
2446                       
2447                DHL_PSI_FreePSIData(desc);
2448        }
2449}
2450
2451
2452
2453#if COMMENT
2454____Public____(){}
2455#endif
2456
2457/*
2458        ÇØ´ç @tsd Æ÷Æ®¿¡ ´ëÇØ¼­ @input ¼³Á¤À¸·Î psi scanÀ» ½ÃÀÛÇÑ´Ù.
2459*/
2460STATUS PSIE_StartPsiScan(S_PSIM_CONTEXT *pContext, tDHL_TSD tsd, S_PSIM_USER_INPUT *input)
2461{
2462        S_PSIM_PORT *tsport;
2463        int i; 
2464        STATUS status = statusOK;
2465
2466        // sanity test
2467        if (tsd == (tDHL_TSD)0 || input == NULL)
2468                return statusInvalidArgument;
2469
2470        dprint(2, "%s: input tsd %x, rf %d, #%d, $%d, mode %d, proc %x, param %x\n", 
2471                        __FUNCTION__, tsd, input->rf, input->program_number, input->source_id,
2472                        input->flags, input->userproc, input->userparam);
2473
2474        // ÁöÁ¤µÈ tsd °¡ ÀÌ¹Ì µ¿ÀÛ ÁßÀÎ °ÍÀÎÁö üũ.
2475       
2476        tsport = NULL;
2477        for (i=0; i<MAX_TS_INPUT; i++) {
2478                if (pContext->tsport[i].tsd == tsd) {
2479                        tsport = &pContext->tsport[i];
2480                        break;
2481                }
2482        }
2483        if (tsport) {
2484                dprint(0, "!! tsd %x already running. stop first!\n", tsd);
2485
2486                // ÀÌ¹Ì µ¿ÀÛ ÁßÀ̶ó¸é, ±âÁ¸ µ¿ÀÛ ÁßÁöÇÏ°í »õ·Ó°Ô ½ÃÀÛ.
2487
2488                PSIE_StopPsiScan(pContext, tsd);
2489        }
2490
2491        // ºó tsport entry¸¦ ã´Â´Ù.
2492        for (i=0; i<MAX_TS_INPUT; i++) {
2493                if (pContext->tsport[i].tsd == NULL) {
2494                        tsport = &pContext->tsport[i];
2495                        break;
2496                }
2497        }
2498
2499        if (tsport == NULL) {
2500                dprint(0, "!! no available tsport entry for tsd %x\n", tsd);
2501                return statusOutOfResource;
2502        }
2503       
2504        /*
2505                ÇÊ¿äÇϸé ÇöÀç task »óŸ¦ ¼³Á¤ÇÑ´Ù.
2506        */
2507#if 0
2508        if (pContext->state != ePSIM_TASK_STATE_Idle) {
2509                pContext->state = ePSIM_TASK_STATE_Idle;
2510        }
2511#endif
2512
2513        /*
2514                TransportInput port Á¤º¸¸¦ ÃʱâÈ­ ÇÑ´Ù.
2515                        TSD, rf, #, sid, mode,
2516        */
2517        memset(tsport, 0, sizeof(S_PSIM_PORT));
2518        tsport->tsd = tsd;
2519        tsport->input = *input;
2520       
2521        tsport->max_monitors = MAX_FILTERS_PER_PORT;
2522
2523        // use input's source_id as a start point.
2524        tsport->source_id = input->source_id;
2525
2526        // for program change monitor
2527        tsport->last_event_id = EVENT_ID_INIT;   // reset last information
2528
2529
2530        /*
2531                DB¿¡¼­ chinfo ±¸Á¶Ã¼ ÇÒ´ç.
2532        */
2533        status = PSIDB_AllocateChInfoNode(tsport->input.rf);
2534        if (status)
2535                return status;
2536
2537        // ½ÃÀÛÇϱâ Àü¿¡ Ç×»ó ¸ÕÀú stt invalidate.
2538        // ÀÌÈÄ ÃÖÃÊ ¼ö½ÅµÇ´Â stt´Â ÀÚµ¿ notify µÈ´Ù.
2539        //
2540        PSIDB_InvalidateStt(tsport->input.rf);
2541
2542
2543        /*
2544                1Â÷ Å×ÀÌºí ¼ö½Å ½ÃÀÛ
2545                PAT, MGT, VCT, STT, RRT, EAS
2546        */
2547
2548        StartMonitorPAT(tsport);
2549        // pmt will be started after pat is downloaded.
2550
2551        // psiUpdateMode may vary according to psi scan mode.
2552        // right now, this should be considered inside each function.
2553
2554        StartMonitorStt(tsport);
2555        StartMonitorMgt(tsport);
2556        StartMonitorTvct(tsport);
2557        StartMonitorCvct(tsport);
2558
2559        if (PSI_FLAGS_MODE(tsport->input.flags) != PSI_FLAGS_AUTOSCAN) {
2560                StartMonitorRrt(tsport);
2561        }
2562       
2563        return status;
2564}
2565
2566
2567/*
2568        ÇØ´ç @tsd Æ÷Æ®ÀÇ psi scan ÀÛ¾÷À» ÁßÁöÇÑ´Ù.
2569        ÇöÀç±îÁö °Ë»öµÈ °á°ú´Â ±×´ë·Î À¯ÁöµÈ´Ù.
2570*/
2571STATUS PSIE_StopPsiScan(S_PSIM_CONTEXT *pContext, tDHL_TSD tsd)
2572{
2573        S_PSIM_PORT *tsport;
2574        int i;
2575        STATUS status = statusOK;
2576
2577        // ÁÖ¾îÁø tsd Á¤º¸·ÎºÎÅÍ port Á¤º¸¸¦ ã´Â´Ù.
2578
2579        tsport = NULL;
2580        for (i=0; i<MAX_TS_INPUT; i++) {
2581                if (pContext->tsport[i].tsd == tsd) {
2582                        tsport = &pContext->tsport[i];
2583                        break;
2584                }
2585        }
2586
2587        if (tsport == NULL) {
2588                dprint(0, "!! no such tsd %x\n", tsd);
2589                return statusInvalidArgument;
2590        }
2591
2592        dprint(2, "stop psi scan: rf %d\n", tsport->input.rf);
2593
2594        // ¸ÕÀú monitor¸¦ ÁßÁö.
2595       
2596        StopAllPsiMonitors(tsport);
2597
2598        // Àӽà º¯¼ö, Å×ÀÌºí µé ÃʱâÈ­.
2599
2600        // user callback
2601        // Á¦´ë·Î ±¸ÇöÇÏÀÚ.. todo..
2602        SendUserCallback(tsport, epgEventStopped, 0);
2603
2604        memset(tsport, 0, sizeof(*tsport));
2605
2606        return status;
2607}
2608
2609/*
2610        ¸ðµç Æ÷Æ®ÀÇ psi scan ÀÛ¾÷À» ÁßÁöÇÑ´Ù.
2611*/
2612STATUS PSIE_StopAllPsiScan(S_PSIM_CONTEXT *pContext)
2613{
2614        //S_PSIM_PORT *tsport;
2615        int i;
2616        STATUS status = statusOK;
2617
2618        // ÁÖ¾îÁø tsd Á¤º¸·ÎºÎÅÍ port Á¤º¸¸¦ ã´Â´Ù.
2619
2620        //tsport = NULL;
2621        for (i=0; i<MAX_TS_INPUT; i++) 
2622        {
2623                if (pContext->tsport[i].tsd == NULL)
2624                        continue;
2625       
2626                status = PSIE_StopPsiScan(pContext, pContext->tsport[i].tsd);
2627                if (status)
2628                        dprint(0, "!! stop psi scan err %d\n", status);
2629        }
2630
2631        return status;
2632}
2633
2634/*
2635        ¸Þ¸ð¸®¿¡ °Ë»öµÇ¾î ÀúÀåµÇ¾î ÀÖ´Â psi data Áß¿¡¼­
2636        ÀÎÀÚ @id¿¡ ÇØ´çµÇ´Â °ÍµéÀ» ¸ðµÎ »èÁ¦ÇÑ´Ù.
2637*/
2638STATUS PSIE_DeleteTables(S_PSIM_CONTEXT *pContext, int id)
2639{
2640        /*
2641                todo :
2642                psi scan engineÀÌ µ¿ÀÛÇÏ´Â Áß¿¡ ÀϺΠdata°¡ »èÁ¦°¡ µÈ´Ù¸é
2643                ¹®Á¦°¡ »ý±æ °¡´É¼ºÀÌ Àִµ¥, À̸¦ api ³»ºÎ¿¡¼­ ó¸®ÇÏ´Â °ÍÀÌ ¹Ù¶÷Á÷ÇѰ¡?
2644        */
2645        PSIE_StopAllPsiScan(pContext);
2646
2647        if (id)
2648                PSIDB_DeleteTables(id);
2649        else 
2650                PSIDB_DeleteAllTables();
2651       
2652        return statusOK;
2653}
2654
2655/*
2656        ¼ö½Å µÈ psi data¸¦ ó¸®ÇÑ´Ù.
2657*/
2658STATUS PSIE_ProcessReceivedTable(S_PSIM_CONTEXT *pContext, S_PSIM_PORT *tsport, tDHL_PSI_DataArray *desc)
2659{
2660        //int err;
2661        UINT8 table_id;
2662        STATUS status = statusOK;
2663
2664        //dprint(2, "%s: \n", __FUNCTION__);
2665
2666        // sanity check
2667        if (tsport == NULL || desc == NULL) {
2668                return statusInvalidArgument;
2669        }
2670
2671        #if 0
2672        if (desc->psiCtl != tsport->tsd) {
2673                dprint(0, "!! tsd diff: desc %x, port %x\n", desc->psiCtl, tsport->tsd);
2674                return statusError;
2675        }
2676        #endif
2677
2678        if (desc->numSections < 1) {
2679                dprint(0, "!! invalid numSection %d\n", desc->numSections);
2680                return statusError;
2681        }
2682
2683        table_id = desc->sectPtr[0][0];
2684
2685        dprint(2, "============ pid %x, tid %02x (%s)\n", desc->pid, table_id, PSIUTIL_TidString(table_id));
2686
2687        /*
2688                °¢ Å×ÀÌºí º°·Î ³ª´²¼­ ó¸®ÇÑ´Ù.
2689        */
2690       
2691        switch (table_id)
2692        {
2693        case PROGRAM_ASSOCIATION_SECTION:
2694                status = ProcessPAT(tsport, desc);
2695                break;
2696
2697        case TS_PROGRAM_MAP_SECTION:
2698                status = ProcessPMT(tsport, desc);
2699                break;
2700
2701        case tid_master_guide_table:
2702                status = ProcessMgt(tsport, desc);
2703                break;
2704
2705        case tid_terr_virtual_chan_table:
2706        case tid_cable_virtual_chan_table:
2707                status = ProcessVct(tsport, desc);
2708                break;
2709       
2710        case tid_system_time_table:
2711                status = ProcessStt(tsport, desc);
2712                break;
2713
2714        //case tid_rating_region_table:
2715        //      break;
2716
2717        case tid_event_information_table:
2718                status = ProcessEit(tsport, desc);
2719                break;
2720
2721        case tid_extended_text_table:
2722                status = ProcessEtt(tsport, desc);
2723                break;
2724
2725        default:
2726                dprint(0, "!! unknown table..\n");
2727                break;
2728        };
2729
2730        DHL_PSI_FreePSIData(desc);
2731
2732        return status;
2733       
2734}
2735
2736
2737
2738
2739E_PSIM_MODULE_STATE PSIE_GetModuleState(S_PSIM_CONTEXT *pContext)
2740{
2741        return pContext->state;
2742}
2743
2744void PSIE_ChangeModuleState(S_PSIM_CONTEXT *pContext, E_PSIM_MODULE_STATE newState)
2745{
2746        pContext->state = newState;
2747}
2748
2749UINT32 PSIE_GetTimeout(S_PSIM_CONTEXT *pContext)
2750{
2751        // module state ¿¡ µû¶ó Àû´çÇÑ timeout À» °áÁ¤Çؼ­ ¸®ÅÏÇÑ´Ù.
2752        // periodic processing ÀÌ ÇÊ¿ä ¾ø´Â state¿¡¼­´Â wait_forever ¸¦ ¸®ÅÏ.
2753        //
2754
2755        return PSIM_WAIT_FOREVER; // wait forever
2756
2757}
2758
2759void PSIE_DoPeridicProcessing(S_PSIM_CONTEXT *pContext)
2760{
2761        // this task is stateless and don't have periodic processing.
2762
2763        //CheckPmtTimeout();
2764}
2765
2766/*
2767
2768*/
2769S_PSIM_CONTEXT *PSIE_GetEngine(void)
2770{
2771        return g_psi_engine;
2772}
2773
2774
2775
2776#if COMMENT
2777____Init____(){}
2778#endif
2779
2780void PSIE_DumpTsPort(int index);
2781
2782static DHL_SymbolTable __symbols[] =
2783{
2784        //---- func
2785        DHL_FNC_SYM_ENTRY2("psi_list", PSIDB_PrintAllTables),
2786        DHL_FNC_SYM_ENTRY2("psi_port", PSIE_DumpTsPort),
2787        DHL_FNC_SYM_ENTRY2("psi_delete", DMW_PSI_DeleteTables),
2788       
2789        //---- vars
2790        DHL_VAR_SYM_ENTRY(g_Trace_bPsiEvent),
2791        DHL_VAR_SYM_ENTRY(g_Trace_bPsiSttInfo),
2792        //DHL_VAR_SYM_ENTRY(g_Trace_PsiEngine),
2793};
2794
2795
2796/*
2797        psi scan engineÀ» ÃʱâÈ­ ÇÑ´Ù.
2798*/
2799S_PSIM_CONTEXT *PSIE_InitEngine(void)
2800{
2801        S_PSIM_CONTEXT *pContext;
2802        S_PSIM_PORT *tsport;
2803        int i;
2804
2805        dprint(2, "%s:\n", __FUNCTION__);
2806       
2807        // allow multiple init trying..
2808        // but we don't guarantee race condition. just for testing.
2809        if (g_psi_engine && g_psi_engine->magic == PSI_ENGINE_MAGICKEY  ) 
2810        {
2811                dprint(0, "already inited\n");
2812                return g_psi_engine;
2813        }
2814
2815        DHL_DBG_RegisterSymbols(__symbols, DHL_NUMSYMBOLS(__symbols));
2816       
2817        pContext = DHL_OS_Malloc(sizeof(S_PSIM_CONTEXT));
2818        if (!pContext)
2819                return NULL;
2820
2821        pContext->magic = PSI_ENGINE_MAGICKEY;
2822        pContext->state = ePSIM_MODULE_STATE_Init;
2823
2824        tsport = pContext->tsport;
2825       
2826        for (i=0; i<MAX_TS_INPUT; i++) 
2827        {
2828                memset(&tsport[i], 0, sizeof(S_PSIM_PORT));
2829               
2830                // do any other initializations..
2831                tsport[i].max_monitors = MAX_FILTERS_PER_PORT;
2832        }
2833
2834        dprint(2, "module context: %x\n", pContext);
2835
2836        g_psi_engine = pContext;
2837       
2838        return pContext;
2839       
2840}
2841
2842
2843
2844#if COMMENT
2845____Test____(){}
2846#endif
2847
2848/*
2849        ÁöÁ¤ÇÑ tsport ³»ºÎ Á¤º¸ Ãâ·Â..
2850        Å×½ºÆ® ¿ëµµ·Î¸¸ »ç¿ëÇÒ °Í!
2851*/
2852#define OS_DbgPrintf DHL_OS_Printf
2853
2854void PSIE_DumpTsPort(int index)
2855{
2856        int i;
2857        S_PSIM_PORT *tsport;
2858        S_PSIM_CONTEXT *pContext = PSIE_GetEngine();
2859
2860        if (pContext == NULL) return;
2861
2862        if (index < 0 || index >= MAX_TS_INPUT) {
2863                dprint(0, "!! invalid port index %d\n", index);
2864                return;
2865        }
2866
2867        tsport = &pContext->tsport[index];
2868
2869        OS_DbgPrintf("tsport [%d]:\n", index);
2870        OS_DbgPrintf("  tsd: 0x%x\n", tsport->tsd);
2871        OS_DbgPrintf("  input rf %d, # %d, sid %d, flags 0x%x, proc %x, param %x\n", 
2872                tsport->input.rf, tsport->input.program_number, tsport->input.source_id,
2873                tsport->input.flags, tsport->input.userproc, tsport->input.userparam);
2874
2875        OS_DbgPrintf("  # of active monitors %d / max %d\n", 
2876                tsport->n_active_monitors, tsport->max_monitors);
2877
2878        OS_DbgPrintf("  -- psictls --\n");
2879        OS_DbgPrintf("  pat %x, # pgm %d\n", tsport->patPsiCtl, tsport->num_programs);
2880        for (i=0; i<tsport->num_programs; i++)
2881                OS_DbgPrintf("    (%d) pmt %x\n", i, tsport->pmtPsiCtlArray[i]);
2882
2883        OS_DbgPrintf("  mgt %x, stt %x, tvct %x, cvct %x, rrt %x, eas %x\n",
2884                tsport->mgtPsiCtl, tsport->sttPsiCtl, tsport->tvctPsiCtl, tsport->cvctPsiCtl, 
2885                tsport->rrtPsiCtl, tsport->easPsiCtl);
2886
2887        OS_DbgPrintf("  source id %d\n", tsport->source_id);
2888        OS_DbgPrintf("  eits %x %x %x %x..\n", 
2889                tsport->eitPsiCtl[0], tsport->eitPsiCtl[1], tsport->eitPsiCtl[2], tsport->eitPsiCtl[3]);
2890        OS_DbgPrintf("  etts %x %x %x %x..\n", 
2891                tsport->ettPsiCtl[0], tsport->ettPsiCtl[1], tsport->ettPsiCtl[2], tsport->ettPsiCtl[3]);
2892        OS_DbgPrintf("  ett-v %x\n", tsport->ettvPsiCtl);
2893
2894}
2895
2896
2897/* End of file */
2898
Note: See TracBrowser for help on using the repository browser.