close Warning: Can't use blame annotator:
No changeset 2 in the repository

source: svn/newcon3bcm2_21bu/dst/dmw/src/Channel/DMW_ChannelScan.c

Last change on this file was 76, checked in by megakiss, 10 years ago

1W 대기전력을 만족시키기 위하여 POWEROFF시 튜너를 Standby 상태로 함

  • Property svn:executable set to *
File size: 110.2 KB
RevLine 
1/*******************************************************************
2 * DMW_ChannelScan.c
3 *
4 * Channel Auto Scan Module
5 *
6 * Copyright 2003 Digital STREAM Technology, Inc.
7 * All Rights Reserved
8 *
9 * $Id: DMW_ChannelScan.c,v 1.09 2004/01/14 cafrii Exp $
10 *
11 ********************************************************************/
12
13
14
15
16#include "DMW_Platform.h"
17
18#include "DHL_OSAL.h"
19#include "DHL_AVCAP.h"
20#include "DHL_DBG.h"
21
22#include "DMW_Config.h"
23#include "DMW_Status.h"
24#include "../System/DMW_MsgQue.h"
25
26#include "DMW_DebugUtil.h"
27#include "DMW_Channel.h" // cafrii 031230. for OnePartChannel APIs.
28#include "DMW_ChannelAPI.h"
29#include "DMW_ChannelDemux.h"  // cafrii 041130 add for Table Download
30
31
32#include "DMW_ChannelUtil.h"
33#include "dmw_channel_priv.h"
34#include "dmw_mcm_priv.h"
35#include "dmw_ucm_priv.h"
36
37//#include <string.h>
38
39
40DHL_MODULE("$scn", 1);
41
42
43#define max(a,b) (((a) > (b)) ? (a) : (b))
44#define min(a,b) (((a) < (b)) ? (a) : (b))
45
46//===========================================================================
47//
48//       Design Notes
49//
50//
51
52
53
54
55
56//===========================================================================
57//
58//      Configuration parameters
59//
60//   °¢Á¾ ¿É¼Ç ±â´ÉÀÇ On/Off ¼³Á¤, ÄÄÆÄÀÏ·¯ ¿É¼Ç ¼³Á¤,
61//   µå¶óÀ̹ö °ü·Ã ȯ°æ ¼³Á¤ µî..
62//
63
64#define USE_PSI_INDEX_FOR_MINOR 0
65        // cafrii 060630 add
66        // 1À̸é PSI ä³Î Æ©´×½Ã index¸¦ minor·Î »ç¿ë.
67        // ÀϹÝÀûÀ¸·Î´Â index ´ë½Å program number¸¦ »ç¿ëÇÑ´Ù.
68
69#define SUPPORT_CSD_UPDATE  0
70        // ƯÁ¤ platform ¿¡¼­ CSD ±â´ÉÀÌ ÇÊ¿äÄ¡ ¾Ê´Â °æ¿ì¿¡´Â ÀÌ flag¸¦ 0À¸·Î reset ÇÑ´Ù.
71        //
72
73
74#define  USE_DMW_EPGX_LIB  0
75        // 1 À̸é EPGX LIB ¿¡¼­ »ç¿ëÇÏ´Â MSS °ü·Ã ÇÔ¼öµéÀ» »ç¿ëÇÑ´Ù.
76
77
78#define TEST_AUTOSCAN 1
79        // Å×½ºÆ® ÄÚµå Æ÷ÇÔ ¿©ºÎ
80
81
82#define USE_PSI_RX_RETRY 0
83        // cafrii 070117 add
84        // óÀ½¿¡ download_tables¿¡¼­ ÃæºÐÇÑ ½Ã°£µ¿¾È ¸ðµç tableÀ» ¹Þ±â ¶§¹®¿¡
85        // ³ªÁß¿¡ ´Ù½Ã retry¸¦ ÇÒ ÇÊ¿ä´Â ¾øÀ» µí ÇÏ¿© skipÇϵµ·Ï ÇÑ´Ù.
86
87#define USE_RESOLUTION_GATHERING 1
88        // neverdai add 101018. scan½Ã video ÇØ»óµµ Á¤º¸¸¦ ¾ò¾î³½´Ù.
89
90
91
92int g_Timeout_PesPidCheck = 100;
93        //
94        // PES packet PID monitor timeout. ´ÜÀ§´Â millisecond
95        // Video/Audio PID¸¦ ¼öÁýÇÑ ´ÙÀ½ TSC bit check¸¦ À§ÇØ ÀÌ ½Ã°£ ¸¸Å­ packet ¼ö½ÅÀ» ±â´Ù¸°´Ù.
96        //
97
98BOOL g_TestAutoscanWithoutVct = FALSE;
99        // TRUE À̸é VCT°¡ ¾ø´Â ä³Î°ú °°Àº »óȲÀ» °¡Á¤ÇÏ¿© µ¿ÀÛÇÑ´Ù.
100        //
101
102
103#define CHANNEL_BMP_SIZE 5
104        // channel bitmap array size (in bytes)
105
106
107#define TEST_LARGE_PROGRAM_NUMBER 0
108        // cafrii 060728 test
109
110
111#define USE_UNIQUE_PSI_NUMBERING 1
112        // cafrii 070130 add for APRO-1
113        //
114
115//===========================================================================
116//
117//       Constants, Variables, Function declarations
118//
119
120
121
122// program number´Â 16 bit·Î Å« ¹üÀ§À̹ǷΠÀû´çÈ÷ assignÀ» ÇÏÀÚ.
123// ¼­·Î ´Ù¸¥ ÇÁ·Î±×·¥ÀÌ µ¿ÀÏÇÑ minor ¹øÈ£¸¦ °¡Áú ¼öµµ ÀÖÀ½¿¡ À¯ÀÇ.
124// Minor 0¹øÀº air¿¡¼­ analog programÀ̶ó´Â Àǹ̷Π»ç¿ëµÇ¹Ç·Î 0ÀÇ °ªÀº ÇÇÇÑ´Ù.
125//
126#define PROG_NUM_TO_MINOR(pn) \
127                ((pn <= 999) ? (pn) : ((((pn) - 1000) % 999) + 1))
128                //((pn <= 1023) ? (pn) : ((((pn) - 1024) % 1023) + 1))
129// cafrii 060630, restrict to 3 digits.
130
131
132
133
134#if TEST_LARGE_PROGRAM_NUMBER
135int g_TestLargeProgramNumber = 0;
136        // cafrii 060728 test
137#endif
138
139#define USE_DEFAULT_CB_FN 0
140        //
141        // »õ·Î¿î mw ±¸Á¶¿¡¼­´Â
142        // scan °úÁ¤ Áß¿¡ tuner ¼³Á¤ ºÎºÐÀº application¿¡¼­ ¼öÇàÇÏ´Â °ÍÀ» ¿øÄ¢À¸·Î Àç¼³°èµÊ.
143        // ±×·±µ¥ ¿©·¯°¡Áö ÀÌÀ¯·Î application¿¡¼­ ÀÌ Äڵ带 ±¸ÇöÇÒ ¼ö ¾ø´Â °æ¿ì
144        // mwÀÇ µðÆúÆ® ±¸ÇöÀ» »ç¿ëÇÒ ¼ö ÀÖÀ½.
145        // ÀÌ µðÆúÆ® Äݹé ÇÔ¼ö´Â ÄÚµå Å©±â°¡ ÀÛÁö ¾Ê±â ¶§¹®¿¡
146        // ÇÊ¿äÇÑ °æ¿ì¿¡¸¸ compile/link µÉ ¼ö ÀÖµµ·Ï Á¶°ÇºÎ·Î compile µÊ.
147
148
149#if USE_DEFAULT_CB_FN
150
151        void SCB_ScanStart(ScanStartedCbParam *param);
152        void SCB_ScanEnd(ScanCompleteCbParam *param);
153        void SCB_TunerSet(ScanTunerSetCbParam *param);
154
155#endif // USE_DEFAULT_CB_FN
156
157
158void SCB_SkipTunerSet(ScanTunerSetCbParam *param);
159        // ÀÌ ÇÔ¼ö´Â Default CB°¡ ¾Æ´Ï¶ó
160        // Ç×»ó compile µÇ¾î¾ß ÇÑ´Ù.
161
162
163//===========================================================================
164//
165//    Debugging Aids
166//
167
168
169
170
171
172
173
174//===========================================================================
175//
176// ä³Î½ºÄµ ÄÁÅØ½ºÆ®..
177// ä³Î °Ë»ö ÀÛ¾÷Áß¿¡ ÇÊ¿äÇÑ ¿©·¯°¡Áö Á¤º¸¸¦ ¸ð¾Æ³õÀº ±¸Á¶Ã¼.
178// ÇöÀç °Ë»öÁßÀΠä³Î ¹øÈ£, ÇöÀç FSMÀÇ »óÅ µîµî..
179
180
181typedef enum 
182{
183        CTS_IDLE,    // ä³Î °Ë»ö ŽºÅ©°¡ ½¬´Â Áß.
184       
185        CTS_RUNNING, // ä³Î °Ë»ö ÀÛ¾÷ÀÌ ÁøÇà Áß.
186
187        // analog / digital ºÐ¸®Çؼ­ scanÇÏ´Â °æ¿ì¿¡´Â ¾Æ·¡ state¸¦ °¡Áø´Ù.
188        CTS_RUNNING_ANALOG,
189        CTS_RUNNING_DIGITAL,
190       
191} ChannelScanState;  // ä³Î °Ë»ö ŽºÅ©ÀÇ »óÅÂ.
192
193
194typedef struct
195{
196        //------------------------------
197        // input variables
198        //
199        tDHL_TSD tsd;          // TS source
200       
201        UINT32 original_flag; // StartScan() API¿¡¼­ ³Ñ¾î¿Â Ç÷¡±×. CBTF_XXX »ó¼öµéÀÇ Á¶ÇÕ.
202        UINT32 flag;          // °¢ »óȲ¿¡ ¸Â°Ô ½ÇÁ¦ Àû¿ëÇÒ Ç÷¡±×.
203                // cafrii 060628, change to UINT32. bit flag °³¼ö ´Ã¾î³²..
204       
205        int start_channel;  // channel RF number to start to scan..
206        int end_channel;    // last channel RF number to scan..
207        int total_channel;  // number of channels to scan..
208       
209        UINT32 channel_bmp[CHANNEL_BMP_SIZE]; // channel bitmap to scan
210
211        BOOL quick_scan;  // ÇöÀç ÁøÇà ÁßÀÎ scan ÀÛ¾÷ÀÌ normal scan ÀÎÁö quick scan ÀÎÁö.
212                // normal scanÀÇ °æ¿ì scan start, scan end callback ÀÌ È£ÃâµÇÁö¸¸,
213                // quick scanÀÇ °æ¿ì ÀÌ·¯ÇÑ callback ¾øÀÌ È£ÃâµÈ´Ù.
214
215        ChannelScanCallback fnCallback;  // callback function pointer.
216       
217        ChannelScanCancelCheckFn fnCheck;  // cancel check function
218                // return TRUE if autoscan cancel is requested.
219       
220        //------------------------------
221        // state variables
222       
223        int cur_channel;    // current channel..  ÇöÀç ä³Î ȤÀº ´ÙÀ½ ´Ü°è¿¡¼­ °Ë»öÇÒ Ã¤³Î.
224                            // ÀÌ»ó ¸ðµÎ RF ¹øÈ£ÀÓ.
225                           
226        int channel_index;  // ¸î¹øÂ° ¼öÇàÇϴ ä³ÎÀÎÁö Ç¥½Ã.. 0 ~ total_channel-1 ÀÇ °ªÀ» °®´Â´Ù.
227                           
228        int freq_offset;      // ÇöÀç ä³ÎÀÇ frequncy offset (in Hz)
229       
230        int signal_strength;  // ÇöÀç ä³ÎÀÇ signal_strength;
231        int tuner_modulation_mode;  //    ,,      mod mode
232
233        ChannelScanState state;            // CTS_IDLE, CTS_RUNNING, ...
234       
235        tDHL_FreqStd cable_system;  // ¿ø·¡ÀÇ cable system
236
237        //--------------------------------
238        // ÀÛ¾÷ÁßÀÎ PSIP/PSI table pointers
239        // »ç¿ëÀÌ ³¡³ª¸é ¹Ýµå½Ã Free¸¦ ½Ã۰í NULL·Î ¸¸µé¾îÁà¾ß ÇÑ´Ù.
240        //
241        xvctPtr_t xvct;
242       
243        MPEG_PAT  *pat;
244        int        num_programs;
245        MPEG_PMT **pmtList;
246
247
248} ChannelScanContext;
249
250
251
252
253typedef struct
254{
255        UINT32 flag;
256        ChannelScanCallback pfnCallback;
257       
258        // ÇÑ Ã¤³Î¸¸ scanÇÏ´Â °æ¿ì¿¡´Â rf Çʵ带 ÀÌ¿ëÇϰí,
259        // µÑ ÀÌ»óÀÇ Ã¤³ÎÀ» scanÇÒ ¶§¿¡´Â bitmapÀ» »ç¿ëÇÑ´Ù.
260       
261        int rf;
262        UINT32 bitmap[CHANNEL_BMP_SIZE];
263       
264        //UINT32 userparam;
265        // userparamÀº one channel scan¿¡¼­ »ç¿ëµÇ°í ÀÖÀ½.
266        // ÀÌ parameter´Â memory pointerÀÌ¸é ¾ÈµÊ.
267        // command°¡ cancel µÉ °æ¿ì¿¡ ´ëÇÑ ´ëÀÀÀÌ ¾øÀ¸¹Ç·Î..
268       
269} ChannelScanCmdParam;
270
271
272
273typedef enum
274{
275        eScanStop_Completed = 0,
276                // scan ±¸°£À» ¸ðµÎ °Ë»öÇϰí Á¤»ó Á¾·á.
277        eScanStop_StopByUser,
278                // StopScan API°¡ È£ÃâµÇ¾î Á¤»ó Á¾·á.
279                // APIÀÇ ÀÎÀÚ¿¡ µû¶ó¼­ °Ë»öµÈ Á¤º¸°¡ cancel µÉ ¼öµµ ÀÖ´Ù.
280        eScanStop_Abnormal, 
281                // StopScan¿¡ ÀÇÇÏÁö ¾Ê°í ºñÁ¤»óÀûÀÎ Á¾·á. ±×·¯³ª DB ±¸¼º±îÁö´Â ¸¶¹«¸®ÇÑ´Ù.
282       
283}  ScanStopMode;
284
285
286
287#define STATIC
288
289
290
291
292#if COMMENT
293_____A_P_I_________(){}
294#endif
295
296
297//----------------------------------------------
298// M/W APIs
299
300
301STATUS DMW_ASC_StartScan(int flag, ChannelScanCallback fn, int chStart, int chEnd)
302{
303        ChannelScanSparseMap map;
304       
305        map.num_seg = 1;
306        map.seg[0].ch_start = min(chStart, chEnd);
307        map.seg[0].ch_num = max(chStart, chEnd) - min(chStart, chEnd) + 1;
308
309        return DMW_ASC_StartSparseScan(flag, fn, &map);
310
311}
312
313
314/*
315        scanÇÒ rf ¹øÈ£¸¦ Á÷Á¢ ÀÎÀÚ·Î ³Ñ°Ü¼­ ÇØ´ç rf¸¸ scanÇϵµ·Ï ÇÑ´Ù.
316        ÀÌ ¶§ rfMapÀÇ rf ¹øÈ£´Â ¿À¸§Â÷¼øÀ¸·Î Á¤·ÄÀÌ µÇ¾î ÀÖ¾î¾ß ÇÑ´Ù.
317*/
318STATUS DMW_ASC_StartScanEx(int flag, ChannelScanCallback fn, UINT8 *rfMap, int numRf)
319{
320        ChannelScanSparseMap map;
321        int i, idx; //mode 0 new, 1 normal
322       
323        for(i=0, idx=0; i<numRf; i++) {
324               
325                if(i==0) {
326                        map.seg[idx].ch_start=rfMap[i];
327                        map.seg[idx].ch_num=1;
328                }
329                else {
330                        if(rfMap[i]==rfMap[i-1]+1) { //¼øÂ÷ÀûÀÓ
331                                map.seg[idx].ch_num++;
332                        }
333                        else { //ºñ¼øÂ÷ÀûÀÓ
334                                idx++;
335                                map.seg[idx].ch_start=rfMap[i];
336                                map.seg[idx].ch_num=1;
337                        }
338                }
339        }
340       
341        map.num_seg=idx+1;
342       
343        return DMW_ASC_StartSparseScan(flag, fn, &map);
344}
345
346
347
348STATUS DMW_ASC_StartSparseScan(int flag, ChannelScanCallback fn, 
349                                                                ChannelScanSparseMap *map)
350{
351        // 0 ~ 135 ±îÁö ÃÑ 136°³ÀÇ Ã¤³ÎÀ» ±¸ºÐÇϱâ À§Çؼ­´Â
352        // 136/32 = 5°³ÀÇ 32-bit workd °¡ ÇÊ¿äÇÏ´Ù.
353        //
354        // °Å±â¿¡ flag¿Í fn ±îÁö ÃÑ 7°³ÀÇ d-word °¡ ÇÊ¿äÇÏ°Ô µÈ´Ù.
355        //
356        // ¸Þ½ÃÁö Å©±âÀÇ Á¦ÇÑÀÌ ÀÖ´Â ThreadX ÀÇ °æ¿ì¿¡´Â
357        // ÃÖ´ë 16°³ÀÇ Dword Å©±âÀÇ ¸Þ½ÃÁö¸¦ Ãë±ÞÇϹǷΠ¹®Á¦ ¾øÀ½.
358        //
359        STATUS status;
360        ChannelScanCmdParam *param;
361        UINT32 *bmpChannel;
362       
363        ChannelScanSparseMap _default;
364        int i, k, ch;
365       
366        dprint(1, "DMW_ASC_StartSparseScan(type 0x%x, fn 0x%x)\n", flag, fn);
367
368        if (map == NULL) 
369        {
370                dprint(1, "  SparseMap is not specified. do all channel scan\n");
371               
372                map = &_default;
373                map->num_seg = 1;
374               
375                if ((flag & CBTF_ChannelTypeMask) == CBTF_Air)
376                {
377                        map->seg[0].ch_start = 2;
378                        map->seg[0].ch_num = 68;     // 2 ~ 69
379                }
380                else
381                {
382                        map->seg[0].ch_start = 1;
383                        map->seg[0].ch_num = 135;    // 1 ~ 135
384                }
385        }
386
387        param = Dmc_ParamHeapAllocator(sizeof(ChannelScanCmdParam));
388        if (param == NULL) {
389                return statusOutOfMemory;
390        }
391       
392        param->flag = flag;
393        param->pfnCallback = fn;
394       
395        bmpChannel = &param->bitmap[0];
396       
397        for (i=0; i<map->num_seg; i++)
398        {
399                // ch_start ¿Í ch_num range°¡ 0 ~ 159 »çÀÌ¿¡ µé¾î¿Í¾ß ÇÔ.
400               
401                if (map->seg[i].ch_start < 0 ||
402                        map->seg[i].ch_start + map->seg[i].ch_num - 1 >= 160) {
403                        dprint(0, "!! seg[%d] (%d, %d) invalid range. skip\n", 
404                                        i, map->seg[i].ch_start, map->seg[i].ch_num);
405                        continue;
406                }
407               
408                for (k=0; k<map->seg[i].ch_num; k++)
409                {
410                        ch = map->seg[i].ch_start + k;
411                       
412                        if (ch >= 0 && ch < 160)   // 5 dword·Î Ç¥½Ã °¡´ÉÇÑ Å©±â´Â 0 ~ 160
413                                bmpChannel[ch/32] |= (0x80000000 >> (ch % 32));
414                       
415                        // µ¿ÀÏÇÑ Ã¤³ÎÀÌ ¿©·¯ segment¿¡ Áߺ¹ µÇ¾îµµ »ó°ü ¾ø´Ù
416                }
417        }
418       
419        status = Dmc_SendCommandEx(cmdScanStart, (UINT32)param, 
420                                                Dmc_ParamHeapDeallocator, //DMC_FN_CANCELFREE pfnFree,
421                                                FALSE, //BOOL bWaitForComplete,
422                                                NULL, 0, //DMC_FN_COMPLETED fn, UINT32 userparam,
423                                                FALSE); //BOOL bCancelPrevCommand
424                        // jump to SCN_ScanStart
425
426        if (status) {
427                Dmc_ParamHeapDeallocator((UINT32)param);
428        }
429       
430        return status;
431}
432
433
434//
435// ÀÚµ¿ ä³Î °Ë»öÀ» Á¾·áÇÑ´Ù.
436//
437STATUS DMW_ASC_StopScan(BOOL bUpdate)
438{
439        // bUpdate°¡ TRUEÀ̸é Áö±Ý±îÁöÀÇ °á°ú¸¦ updateÇÑ´Ù.
440
441        STATUS status;
442
443        dprint(1, "DMW_ASC_StopScan(%s)\n", bUpdate ? "update" : "cancel");
444       
445        status = Dmc_SendCommandEx(cmdScanStop, (UINT32)bUpdate, 
446                                                NULL, //DMC_FN_CANCELFREE pfnFree,
447                                                TRUE, //BOOL bWaitForComplete,
448                                                NULL, 0, //DMC_FN_COMPLETED fn, UINT32 userparam,
449                                                FALSE); //BOOL bCancelPrevCommand
450                        // jump to SCN_ScanStop
451
452        return status;
453}
454
455
456
457//STATUS DMW_ASC_ScanChannel(int rf, int flag, ChannelScanCallback eventcb, UINT32 userparam)
458STATUS DMW_ASC_ScanChannel(int rf, int flag, 
459                                BOOL bWaitComplete,
460                                ChannelScanCallback eventcb,
461                                DMC_FN_COMPLETED pfnComplete, UINT32 userParam,
462                                BOOL bCancelPrevCmds)
463{
464        STATUS status;
465        ChannelScanCmdParam *param;
466
467        dprint(1, "DMW_ASC_ScanChannel rf %d, flag 0x%x\n", rf, flag);
468
469        // cafrii 040920
470        // Air/Cable Ç÷¡±×°¡ ³»ºÎ ÇÔ¼öÀÎ ScanDigitalCableChannel ¾È¿¡¼­
471        //  °Ë»ç ¿ëµµ·Î »ç¿ëµÇ°í ÀÖ´Ù! µû¶ó¼­ ÀûÀýÇÑ ¼³Á¤À» ÇØÁÖÀÚ..
472        //
473        flag = (flag & ~CBTF_ChannelTypeMask) |   // ¸ÕÀú channel_type bitµéÀ» ¾ø¾Ö°í..
474                                (g_CurChannelType == ChannelType_Air ? CBTF_Air : CBTF_Cable);
475
476        Dmc_StopVideo(); 
477                // ¿ø·¡ caller°¡ stopÀ» ÇØ¾ß ÇÏ´Â°Ô ¸ÂÀ½.
478                // caller´Â ¸ðµç background ÀÛ¾÷ (CC, EPG, EA, Rating)À» stopÇÑ ´ÙÀ½¿¡
479                // ÀÌ ÇÔ¼ö¸¦ È£ÃâÇØ¾ß ÇÑ´Ù.
480       
481       
482        param = Dmc_ParamHeapAllocator(sizeof(ChannelScanCmdParam));
483        if (param == NULL) {
484                return statusOutOfMemory;
485        }
486       
487        param->flag = flag;
488        param->pfnCallback = eventcb;
489        param->rf = rf;
490        //param->userparam = userParam;
491
492        status = Dmc_SendCommandEx(cmdScanChannel, (UINT32)param, 
493                                                Dmc_ParamHeapDeallocator, //DMC_FN_CANCELFREE pfnFree,
494                                                bWaitComplete,
495                                                pfnComplete, userParam,
496                                                bCancelPrevCmds);
497                        // jump to SCN_ScanOneChannel
498
499        if (status) {
500                Dmc_ParamHeapDeallocator((UINT32)param);
501        }
502       
503        return status;
504}
505
506
507/*
508        background·Î ÇöÀç ä³Î °Ë»öÀ» ¼öÇàÇÑ´Ù.
509       
510        ÀÌ ÇÔ¼ö´Â Dmc task¿¡¼­ µ¿ÀÛÇÏ´Â updateÀÌ´Ù.
511        dmc task ³»¿¡¼­ »õ·Ó°Ô vct, psi µîÀ» ¼ö½ÅÇϱ⠶§¹®¿¡
512        EPG ¹× PsiMonitor°¡ ÁߴܵǾî ÀÖ¾î¾ß ÇÑ´Ù.
513        ¾È±×·¯¸é Çϵå¿þ¾î µ¿ÀÛ¿¡ µû¶ó ¸ðµÎ timeout ¿¡·¯°¡ ¹ß»ýÇÒ ¼ö ÀÖ´Ù.
514
515        DMW_CDB_UpdateChannel ÇÔ¼ö¿Í´Â »ç¿ë ¸ñÀûÀÌ Á» ´Ù¸£´Ù.
516*/
517STATUS DMW_ASC_UpdateChannel(int rf, int flag, 
518                                BOOL bWaitComplete, 
519                                DMC_FN_COMPLETED pfnComplete, UINT32 userParam,
520                                BOOL bCancelPrevCmds)
521{
522        STATUS status;
523        ChannelScanCmdParam *param;
524
525        dprint(1, "DMW_ASC_UpdateChannel rf %d, flag 0x%x\n", rf, flag);
526
527        // cafrii 040920
528        // Air/Cable Ç÷¡±×°¡ ³»ºÎ ÇÔ¼öÀÎ ScanDigitalCableChannel ¾È¿¡¼­
529        //  °Ë»ç ¿ëµµ·Î »ç¿ëµÇ°í ÀÖ´Ù! µû¶ó¼­ ÀûÀýÇÑ ¼³Á¤À» ÇØÁÖÀÚ..
530        //
531        flag = (flag & ~CBTF_ChannelTypeMask) |   // ¸ÕÀú channel_type bitµéÀ» ¾ø¾Ö°í..
532                                (g_CurChannelType == ChannelType_Air ? CBTF_Air : CBTF_Cable);
533
534        flag |= CBTF_SkipTunerSet;
535
536        //flag &= ~CBTF_CheckScrambleByVideoContext;
537        // ÀÌ flag´Â caller°¡ À¯ÀÇÇØ¼­ ºÒ·¯¾ß ÇÑ´Ù.
538        // update mode¿¡¼­ scramble check´Â ¾ÈÇÏ´Â°Ô ÁÁ´Ù.
539       
540        // ÇöÀç µðÄÚµù µ¿ÀÛ Áß¿¡ ÀÌ·ç¾îÁü¿¡ À¯ÀÇ..
541       
542        param = Dmc_ParamHeapAllocator(sizeof(ChannelScanCmdParam));
543        if (param == NULL) {
544                return statusOutOfMemory;
545        }
546       
547        param->flag = flag;
548        param->pfnCallback = NULL;
549        param->rf = rf;
550        //param->userparam = 0;
551
552        status = Dmc_SendCommandEx(cmdScanChannel, (UINT32)param, 
553                                                Dmc_ParamHeapDeallocator, //DMC_FN_CANCELFREE pfnFree,
554                                                bWaitComplete,
555                                                pfnComplete, userParam,
556                                                bCancelPrevCmds);
557
558        if (status) {
559                Dmc_ParamHeapDeallocator((UINT32)param);
560        }
561       
562        return status;
563}
564
565
566//
567// MW ³»ºÎ¿¡¼­ »ç¿ëµÇ´Â
568//  program_number --> minor º¯È¯ ½ÄÀÌ´Ù.
569//
570int DMW_ASC_ProgramNumberToMinor(UINT16 program_number)
571{
572        return PROG_NUM_TO_MINOR(program_number);
573}
574
575
576
577#if COMMENT
578___________________(){}
579#endif
580
581
582ChannelScanContext g_ScanContext;
583
584
585ChannelScanContext *get_scan_context(void)
586{
587        return &g_ScanContext;
588}
589
590
591void send_event_message(ChannelScanEventType evt, UINT32 param)
592{
593        ChannelScanContext *ctx = get_scan_context();
594       
595        if (ctx->fnCallback)
596                (ctx->fnCallback)(evt, param);
597}
598
599
600#if 0
601// cafrii 100128 comment
602// DHL_AV_VideoStart ÇÔ¼ö°¡ seqhdr ¼ö½Å üũ±îÁö ´ã´çÇÏÁö ¾Ê°í ±×³É start¸¸ ½ÃŰ´Â °ÍÀ¸·Î º¯°æµÇ¾úÀ¸¹Ç·Î
603// ÀÌ ÇÔ¼ö´Â Á¦´ë·Î µ¿ÀÛÇÏÁö ¾Ê´Â´Ù.
604// ÀÌ ³»ºÎ¿¡¼­ DHL_AV_GetSequenceHeader ¸¦ ÀÌ¿ëÇÑ wait code°¡ µé¾î°¡Áö ¾Ê´Â ÇÑ º° ÀÇ¹Ì ¾ø´Â ÇÔ¼öÀÓ.
605STATUS check_pes_scramble(tDHL_TSD tsd, MPEG_PMT *pmt, int vPid, int pPid)
606{
607        DHL_RESULT dhlResult = DHL_OK;
608        STATUS status = statusOK;
609        tDHL_VideoCodingType  vidType;
610
611        dprint(0, "\n!! %s not working. check!!\n\n", __func__);
612       
613        vidType=doDmc_SelectVideoStream(pmt, vPid);
614
615        // zooyouny 100701 : tDHL_VDID¸¦ 0À¸·Î °£ÁÖ, ´Ù¸¦ °æ¿ì ¹®Á¦ µÉ ¼ö ÀÖÀ½
616        dhlResult = DHL_AV_VideoStart(0, vPid, pPid, (tDHL_VideoCodingType)vidType);
617       
618        if (dhlResult == DHL_OK)
619                status = statusOK;
620        else if (dhlResult == DHL_WARN_SCRAMBLED)
621                status = statusScrambled;
622        else if (dhlResult == DHL_FAIL_CANCELLED_BY_USER)
623                status = statusCancelled;
624        else if (dhlResult == DHL_FAIL_TIMEOUT)
625                status = statusTimeout;
626        else
627                status = statusError;
628
629        dhlResult = DHL_AV_VideoStop(0);
630        if (dhlResult)
631                dprint(0, "!! Video Stop err %d\n", dhlResult);
632               
633        return status;
634
635}
636#endif
637
638
639
640#if COMMENT
641___________________(){}
642#endif
643
644
645
646//=======================================================================
647// MCM °ü¸® ·çƾ.
648//
649// MCM °ü·Ã ÆíÀÇ ÇÔ¼öµé..
650
651// MCMÀÇ ±¸Á¶´Â Çì´õ ÆÄÀÏ¿¡ °ø°³µÇ¾î ÀÖÁö¸¸, MCM DB ÀÚü´Â AutoScan °úÁ¤¿¡¼­¸¸ ÇÊ¿äÇÑ
652// Àӽà µ¥ÀÌÅÍÀ̱⠶§¹®¿¡ DB ÀÚüÀÇ access´Â application¿¡¼­´Â ±ÝÁöµÈ´Ù.
653//
654// °Ë»öµÈ ä³Î Á¤º¸´Â Áß°£Áß°£¿¡ callback ÇÔ¼ö¸¦ ÀÌ¿ëÇÏ¿© applicationÀ¸·Î º¸°íµÈ´Ù.
655// À̶§ Àü´ÞµÇ´Â µ¥ÀÌÅÍ´Â MCM DB itemÀÇ ¹øÁöÀÌ´Ù.
656// ±×·¯³ª callback ÇÔ¼ö ¾È¿¡¼­¸¸ »ç¿ëÇØ¾ß ÇÑ´Ù´Â Á¦¾àÁ¶°ÇÀÌ ÀÖÀ¸¹Ç·Î
657// "Àӽà µ¥ÀÌÅÍ"·Î¼­ÀÇ MCMÀ̶ó´Â ¿ø·¡ Á¤Ã¥À» À§¹ÝÇÏÁö´Â ¾Ê°ÔµÈ´Ù.
658//
659// MCMÀÇ ÀÚ·á ±¸Á¶´Â º°µµ ¸ðµâ¿¡¼­ ±¸ÇöÇϰí, ±× ±¸Á¶´Â Â÷ÈÄ º¯°æÀÌ °¡´ÉÇÏ´Ù.
660//     1Â÷¿ø array ¶Ç´Â linked list µî..
661// ÇØ´ç api¸¦ ÅëÇØ¼­ »ç¿ëÇϵµ·Ï ÇÑ´Ù.
662// MCMÀº Çʿ信 µû¶ó óÀ½ ÇÒ´çµÈ Å©±â ÀÌ»óÀ¸·Î Áõ°¡µÉ ¼ö ÀÖ´Ù. (¸Þ¸ð¸® ÀçÇÒ´ç)
663//
664
665static STATUS update_mcm_analog(int rfchannel, int strength, INT32 freq_offset, MCM_DB_T **ppmcm)
666{
667        // MCM DB table¿¡ ÇØ´ç ä³Î Á¤º¸¸¦ Ãß°¡ÇÑ´Ù.
668        // ¾Æ³¯·Î±× ä³Î °Ë»ö¿¡¼­ °Ë»öµÈ Á¤º¸ÀÏ °æ¿ì¿¡¸¸ »ç¿ëÇÑ´Ù.
669        // VCT¿¡ Æ÷ÇԵǾî ÀÖ´Â ¾Æ³¯·Î±× ä³Î Á¤º¸´Â ´Ù¸¥ ÇÔ¼ö ÀÌ¿ë.
670        // strength: ½ÅÈ£ ¼¼±â,  0~100
671
672        MCM_DB_T *m;
673        if (strength == 0) strength = 1;  // 0 °ªÀº Ưº°ÇÑ Àǹ̷Π»ç¿ëµÇ¹Ç·Î ÇÇÇÑ´Ù.
674
675        m = find_mcm_major_minor_rf_vf(rfchannel, 0, rfchannel, FALSE);
676                // VCT¿¡ µî·ÏµÇ¾î ÀÖ´Â analog ä³Î Á¤º¸´Â update_mcm_xvct() ÇÔ¼ö¿¡¼­ 󸮵ȴÙ.
677                // todo..
678                // find_mcm_major_minor_rf_vf(rfchannel, 0, rfchannel, TRUE);¸¦ ¸ÕÀú ã¾Æ¾ß ÇÑ´Ù.
679                //  ÀÌ°Ô ÀÖÀ¸¸é update¸¦ ÇÏ¸é ¾ÈµÈ´Ù. (¹æÄ§¿¡ µû¶ó)
680        if (m == NULL) {
681                m = new_mcm();
682                if (m == NULL)
683                        return statusOutOfMemory;
684        }
685
686        m->Major           = rfchannel;  // RF_channelÀ» major ¹øÈ£·Î µî·ÏÇÔ.
687        m->Minor           = 0;
688        m->RF              = rfchannel;
689        m->Service_type    = Modulation_NTSC; // cafrii 041122 change, from '0'
690        m->signal_strength = strength;
691
692        m->Skipped         = 0;
693        m->SurfIndex       = 0;
694        m->VctFlag         = FALSE;
695
696        m->freqOffset      = freq_offset;       // frequency offset Ãß°¡.
697
698        m->Uid = get_new_mcm_id(); // cafrii 060726 add
699
700        if (ppmcm)
701                *ppmcm = m;
702
703        return statusOK;
704}
705
706
707static STATUS update_psi_program(ChannelScanContext *ctx, UINT16 tsid, MPEG_PMT *pmt,
708                                                int programIndex, MCM_DB_T **ppmcm)
709{
710        // MCM DB table¿¡ ÇØ´ç ä³Î Á¤º¸¸¦ Ãß°¡ÇÑ´Ù.
711        //   PSIÁ¤º¸´Â VSB/QAM µîÀÇ modulation ¹æ½Ä°ú´Â ¹«°üÇϹǷÎ
712        //   ÇöÀçÀÇ ChannelType¿¡ ¸Â´Â °ªÀ» ServiceTypeÀ¸·Î °£ÁÖÇÑ´Ù.
713       
714        // programIndex´Â minor ¹øÈ£ ºÎ¿©¸¦ ÇÒ ¶§ Ȥ½Ã ÇÊ¿äÇÒ ¼ö ÀÖÀ¸¹Ç·Î °¡Á®¿Â´Ù.
715        // ppmcmÀº »ý¼ºµÈ mcm Æ÷ÀÎÅ͸¦ caller¿¡°Ô ³Ñ°ÜÁÖ±âÀ§ÇÑ place holer
716
717        int psiRF;
718        int psiFreqOffset; // cafrii 050817 add
719       
720        MCM_DB_T *m, *target, tmp;
721        STATUS status;
722        //DHL_RESULT err;
723        int k, strength;
724       
725        BOOL bScrambled = FALSE;
726
727        // cafrii 101206,
728        // m ÃʱâÈ­ ÄÚµå À§Ä¡¸¦ ¸Ç óÀ½À¸·Î À̵¿.
729        m = &tmp; // Àӽ÷ΠÇϳª ÁغñÇÑ ´ÙÀ½ ´Ù ÃʱâÈ­¸¦ ÇÏ°í ³ª¼­ MCM¿¡ º¹»çÇÑ´Ù.
730        memset(m, 0, sizeof(MCM_DB_T));
731
732
733        psiRF = ctx->cur_channel;
734        psiFreqOffset = ctx->freq_offset; // cafrii 050817 add
735        strength = ctx->signal_strength;
736       
737        if (strength == 0) strength = 1;  // 0 °ªÀº Ưº°ÇÑ Àǹ̷Π»ç¿ëµÇ¹Ç·Î ÇÇÇÑ´Ù.
738       
739        if (pmt == NULL)
740                return statusInvalidArgument;
741       
742        dprint(2, "update_psi_program: pmt [idx %d] #%d, rf %d, tsid %d, str %d\n", 
743                                programIndex, pmt->program_number, psiRF, tsid, strength);
744
745#if 0
746        // cafrii 041130 add
747        // rf, tsid, program_number µîÀÌ µ¿ÀÏÇϸ鼭 vct flag 1ÀΠä³ÎÀ» ã´Â´Ù.
748        // ÀÌ·± ä³ÎÀÌ ÀÌ¹Ì Á¸ÀçÇÑ´Ù¸é »õ·Î ä³ÎÀ» Ãß°¡ÇÒ Çʿ䰡 ¾ø´Ù.
749        //
750        target = find_mcm_rf_prognum_vf(psiRF, pmt->program_number, 1);
751       
752        if (target) {
753                dprint(2, "\tsame vct mcm already exist. no need to update..\n");
754               
755                if (ppmcm)
756                        *ppmcm = NULL;
757               
758                //return statusOK;
759                return statusChannelDuplicated; // cafrii 060725 bugfix
760        }
761#else
762        // cafrii 060725 change
763        // fresh field°¡ Ãß°¡µÇ¾úÀ¸¹Ç·Î À̸¦ Ȱ¿ëÇÑ´Ù.
764        // MCM¿¡¼­ ÀÏÄ¡ÇÏ´Â Á¤º¸¸¦ ¹ß°ßÇ߾ ScanÇϱâ Àü ¿¾³¯ µ¥ÀÌÅÍÀ̸é
765        // »õ·Ó°Ô overwriteÇØÁØ´Ù. pid µîÀÇ Á¤º¸µµ Àֱ⠶§¹®.
766        //
767        if (check_mcm_if_rf_prognum_exist(psiRF, pmt->program_number))
768        {
769                dprint(2, "\tsame vct mcm already exist. no need to update..\n");
770               
771                if (ppmcm)
772                        *ppmcm = NULL;
773               
774                return statusChannelDuplicated; // cafrii 060725 bugfix
775        }
776
777#endif
778
779        //------------- PID Á¤º¸ ÃßÃâ -----------------
780        // ÀÌÁ¦ pid Á¤º¸ ÃßÃâ ÀÛ¾÷Àº ignore ÇÒ ¼ö ¾ø´Ù.
781        // psipÀÇ °æ¿ì vct recover±â´ÉÀ» À§Çؼ­ Ç×»ó ¼öÇàÇÑ´Ù.
782#if 0
783        if (ctx->flag & CBTF_IgnorePidsInfo)  // PID Á¤º¸°¡ ÇÊ¿ä ¾ø´Â °æ¿ì.
784        {
785        }
786        else
787#endif
788        {
789                // cafrii 060728 change
790                PidInfo psiPid;
791
792                memset(&psiPid, 0, sizeof(psiPid));  // cafrii 041126 add
793
794                // get pid and stream type, using MW default decision logic.
795                status = Dmc_DecidePidInfo(pmt, NULL, &psiPid, 0);
796
797                // give application change to override settings.
798                doDmc_SelectAudioStream(pmt, NULL, &psiPid.audio, &psiPid.audioType);
799                doDmc_SelectVideoStream(pmt, NULL, &psiPid.video, &psiPid.videoType);
800               
801                // PCR pid °ªÀº ¹Ýµå½Ã ÀÖ¾î¾ß Çϸç, Video pid ¶Ç´Â Audio pid µÑ Áß Çϳª°¡ ÀÖ¾î¾ß ÇÑ´Ù.
802                //
803                if (status == statusOK && 
804                        psiPid.bValid && 
805                        psiPid.pcr && (psiPid.video || psiPid.audio)) 
806                {
807                        m->Pcr_pid   = psiPid.pcr;
808                        m->Video_pid = psiPid.video;
809                        m->Audio_pid = psiPid.audio;
810                        m->Video_type = psiPid.videoType;
811                        m->Audio_type = psiPid.audioType;
812                       
813                        dprint(2, "  pid(pva): 0x%x 0x%x 0x%x, pmt0x%x, vt%d at%d\n", 
814                                        m->Pcr_pid, m->Video_pid, m->Audio_pid, pmt->PID,
815                                        m->Video_type, m->Audio_type);
816                }
817                else 
818                {
819                        dprint(0, "!! cannot get pids in pmt[%d] #%d, err %s\n", 
820                                                programIndex, pmt->program_number,
821                                                DMW_CDB_ErrString(status));
822                        // cafrii 070117, too verbose.. remove
823                        //if (dprintable(3))
824                        //      PrintPMT(pmt);
825                       
826                        return statusPSIPError;
827                }
828        }
829
830
831        // ------------ ¾Ïȣȭ ¿©ºÎ üũ -----------------
832
833        if (g_CurChannelType == ChannelType_Cable) 
834        {
835               
836        #if 0
837                // cafrii 050124 fix
838                //
839                // Motorolla HE ¿¡¼­´Â °ÅÀÇ ´ëºÎºÐÀÇ Ã¤³ÎÀÌ CA descriptor°¡ Àֱ⠶§¹®¿¡
840                // ÀÌ ¹æ¹ýÀ» »ç¿ëÇϱⰡ ¾î·Æ´Ù.
841                //
842                // 1: CA descriptor¸¦ ã¾Æº¸±â
843               
844                if (GetMpegDescriptor(pmt->descriptors,pmt->descriptor_length,
845                                                CA_tag, 0, NULL) == DHL_OK) {
846                        dprint(2, " !! PMT main descriptor has CA descriptor\n");
847                        bScrambled = TRUE;
848                }
849
850                // 2: TSC bit¸¦ °Ë»çÇϱâ
851               
852                if (m->Video_pid || m->Audio_pid)  // PID Á¤º¸°¡ ÀÖ¾î¾ß ÀÌ ¹æ¹ýÀ» »ç¿ëÇÒ ¼ö ÀÖ´Ù.
853                {
854                        int pidArray[2] = {0, };  // video and audio..
855                        int tscArray[2] = {0, };
856                        int nPid = 0;
857                       
858                        if (m->Video_pid)
859                                pidArray[nPid++] = m->Video_pid;
860                       
861                        if (m->Audio_pid && m->Audio_pid != m->Video_pid)
862                                pidArray[nPid++] = m->Audio_pid;
863                       
864                        status = Dmc_GetMultipleTscBits(ctx->tsd, nPid, pidArray, tscArray,
865                                                        g_Timeout_PesPidCheck*1000/1000, ctx->fnCheck);
866                                                        // cafrii 041202, add cancel check function
867                                                        // cafrii 050305, timeout to 100ms
868                                                        // cafrii 050315, change timeout value to variables
869
870                        // statusCancelled, timeoutError, outOfCPUMemoryError, ...
871                       
872                        if (status == statusCancelled) {
873                                return statusCancelled;
874                        }
875                        else if (status == statusOK) {
876                                // cafrii 050228, remove tsc bit 255 case, which is not_found..
877                                if (tscArray[0] == 1 || tscArray[0] == 2 || tscArray[0] == 3 ||
878                                        tscArray[1] == 1 || tscArray[1] == 2 || tscArray[1] == 3 ) {
879                                        dprint(2, " !! one of stream is scrambled bit checked. 0x%x:%d, 0x%x:%d\n",
880                                                        pidArray[0], tscArray[0], pidArray[1], tscArray[1]);
881                                        bScrambled = TRUE;
882                                }
883                        }
884                        else
885                                dprint(0, "!! scrmabled bit check err %d\n", status);
886                }
887
888                // 3: Video context¸¦ Á÷Á¢ »ý¼ºÇغ¸±â..
889
890                if (1)
891                {
892                        // cafrii 031110 add
893                        // PSIP/PSI table·ÎºÎÅÍ scramble Á¤º¸¸¦ ¾ò´Â ¹æ¹ýÀÌ ½Å·ÚÇÒ ¼ö ¾ø´Â °æ¿ì¸¦ ´ëºñÇÏ¿©
894                        // Á÷Á¢ decodingÀ» ½ÃµµÇØ º¸°í ³ª¼­ scramble ¿©ºÎ¸¦ °áÁ¤ÇÑ´Ù.
895                        //
896                        if ((ctx->flag & CBTF_CheckScrambleByVideoContext) && m->Video_pid)
897                        {
898                                // cafrii 040114 bugfix #AudioOnlyChannelMissing
899                                // À̶§ AudioOnly ä³ÎÀÇ °æ¿ì VideoDecodingÀÌ Ç×»ó failÀÌ ³ª¼­ Ç×»ó scramble·Î °£ÁֵǴ ¹®Á¦°¡ ÀÖÀ¸¹Ç·Î
900                                // Audio only ä³ÎÀÇ °æ¿ì¿¡´Â ±×³É unscramble·Î °£ÁÖÇÑ´Ù.
901                               
902                                status = check_pes_scramble(ctx->tsd, pmt, m->Video_pid, m->Pcr_pid);
903                                if (status == statusScrambled) {
904                                       
905                                        if(ctx->flag &CBTF_IgnoreScrambledChannel) {
906                                                return status;
907                                        }
908                                       
909                                        bScrambled = TRUE;
910                                        dprint(1, "!! [ClearOnlyMode] PSI: PID v %d/p %d seems scrambled.\n",
911                                                                m->Video_pid, m->Pcr_pid);
912                                        //return statusPSIPError; // statusOK¸¸ ¾Æ´Ï¸é µÊ.
913                                        //
914                                        // cafrii 050614 remove 'return'
915                                        // scramble ä³Îµµ DB¿¡ ³Ö°í scramble Ç¥½Ã¸¦ ÇØ¾ß ÇÑ´Ù.
916                                        // µû¶ó¼­ ¿©±â¼­ returnÇÏÁö ¾Ê°í °è¼Ó ÁøÇàÇϵµ·Ï ÇÑ´Ù.
917                                }
918                                else if (status == statusOK) {
919                                        // good channel..
920                                }
921                                else {
922                                        dprint(0, "!! video ES seems invalid, status %d\n", status);
923                                }
924                        }
925                }
926        #endif
927       
928        }
929
930        m->Major   = psiRF;          // PMT·ÎºÎÅÍ ¾òÀº ä³Î Á¤º¸¿¡´Â Major/Minor°¡ ¾ø´Ù.
931       
932        // cafrii 050614 change numbering policy
933        // program number¸¦ Minor ¹øÈ£·Î ÇÒ´çÇÑ´Ù.
934        //
935#if USE_PSI_INDEX_FOR_MINOR
936        m->Minor   = programIndex+1;   // µû¶ó¼­ RF-index °ªÀ» »ç¿ëÇϵµ·Ï ÇÏÀÚ. index´Â 1,2,3...
937#else
938        m->Minor = PROG_NUM_TO_MINOR(pmt->program_number);
939#endif
940
941        m->Prog_number     = pmt->program_number;
942
943#if USE_UNIQUE_PSI_NUMBERING
944        // cafrii 070130 add
945        //  minor ¹øÈ£°¡ °ãÄ¡Áö ¾Êµµ·Ï Á¶Á¤ÇÑ´Ù. ¾îÂ¥ÇÇ PSI channel¿¡¼­´Â minor´Â º° Àǹ̰¡ ¾ø´Ù.
946
947        #if 0 // Fake overlapped program number test
948                dprint(0, "\n****** program number overlapping test\n\n");
949                m->Prog_number = 3 + programIndex*999;
950                m->Minor = PROG_NUM_TO_MINOR(pmt->program_number);
951        #endif
952
953        // program number°¡ 999 º¸´Ù Å« °æ¿ì´Â ÀÓÀÇ ÇÒ´çÀ» ÇÑ´Ù.
954        if (m->Prog_number > 999)
955        {
956                for (k=0; k<999; k++) // to avoid infinite loop, in case of all 1~999 is full.
957                {
958                        if (find_mcm_major_minor(m->Major, m->Minor) == 0)
959                                break;
960
961                        // already some channel has same M-m. increase minor number..
962                        if (k == 0)
963                                dprint(0, "!! minor ch %d (#%d) overlapped. adjusted\n", m->Minor, m->Prog_number);
964                        m->Minor = m->Minor < 998 ? m->Minor+1 : 1;
965                }
966
967                if (k >= 999) {
968                        // all 1~999 minor number is reserved???
969                        dprint(0, "!! full 1~999 minor reserved?\n");
970                        return statusPSIPError;
971                }
972                else if (k != 0) {
973                        dprint(0, "   minor adjusted to %d --> %d-%d\n", m->Minor, m->Major, m->Minor);
974                }
975        }
976
977#endif
978
979#if 0 // USE_RESOLUTION_GATHERING
980        //sequence Á¤º¸¸¦ ¾ò¾î¾ß ÇÔ
981        do {
982                #define MAX_SEQ_WAIT 5000 // ÃÖ´ë 5Ãʸ¦ ±â´Ù¸²
983               
984                tDHL_VideoSeqHdr seq;
985                tDHL_DispFormat disp=eDHL_DISP_720x480i;
986                UINT32 ms_start;
987               
988                if(m->Video_pid==0) break;
989               
990                DHL_AV_VideoHide(0, TRUE);
991                DMC_RegisterVideoCallback(FALSE);
992                DHL_AV_VideoStart(0, m->Video_pid, m->Pcr_pid, m->Video_type);
993               
994                for(ms_start=DHL_OS_GetMsCount();
995                        DHL_AV_VideoSeqInfo(0, &seq)!=DHL_OK && DHL_OS_GetMsCount()-ms_start < MAX_SEQ_WAIT;
996                        DHL_OS_Delay(100));
997               
998                if(DHL_OS_GetMsCount()-ms_start >=MAX_SEQ_WAIT) { //timeout
999                        ;
1000                }
1001                else {
1002                        if(seq.vertical_size>=1080)     disp=eDHL_DISP_1920x1080i;
1003                        else if(seq.vertical_size>=720) disp=eDHL_DISP_1280x720p;
1004                        else                            disp=eDHL_DISP_720x480i;
1005                }
1006               
1007                DHL_AV_VideoStop(0);
1008                DMC_RegisterVideoCallback(TRUE);
1009               
1010                m->video_format=disp;
1011        } while(0);
1012#endif
1013
1014        // cafrii 041122 add more conditions.
1015        if (ctx->tuner_modulation_mode == Modulation_8VSB) {
1016                m->Service_type = ctx->tuner_modulation_mode;
1017        }
1018        else if (ctx->tuner_modulation_mode == Modulation_64QAM || ctx->tuner_modulation_mode == Modulation_256QAM) {
1019                if (g_CurChannelType == ChannelType_Air) {
1020                        dprint(0, "!! QAM modulation detected in Air mode scan\n");
1021                        m->Service_type = Modulation_8VSB;
1022                }
1023                else 
1024                        m->Service_type = ctx->tuner_modulation_mode;
1025        }
1026        else {
1027                dprint(0, "!! wrong tuner modulation %d in psi scan\n", ctx->tuner_modulation_mode);
1028                m->Service_type = g_CurChannelType == ChannelType_Air ? Modulation_8VSB : Modulation_64QAM;
1029        }
1030
1031               
1032        m->RF              = psiRF;
1033        m->freqOffset      = psiFreqOffset; // cafrii 050817 add
1034        m->signal_strength = strength;
1035
1036        // pid Á¤º¸ ¹× codec Á¤º¸´Â À§¿¡¼­ ÀÌ¹Ì Á¤¸® ¿Ï·á.
1037
1038        m->pmt_pid = pmt->PID; // cafrii 070201 add
1039
1040        m->TSID            = tsid;  // ÇöÀç Æ©´×µÈ ä³Î (ÀÌ DB¸¦ Æ÷ÇÔÇϰí Àִ ä³Î)ÀÇ TSID
1041        m->source_id       = 0;
1042        m->channel_tsid    = tsid;  // ÀÌ ÇÁ·Î±×·¥ÀÇ TSID
1043
1044
1045        m->Skipped         = 0; // ÀÌ µÎ°¡Áö´Â ³ªÁß¿¡ ¿©·¯ ä³Î Áß¿¡¼­ ¼±ÅÃÇÏ¿© °áÁ¤ÇÒ ¹®Á¦ÀÌ´Ù.
1046        m->SurfIndex       = 0;
1047
1048        m->hidden          = FALSE;  // VCTÀÇ hidden Á¤º¸¸¦ º¸°üÇÑ´Ù. ¿©±â¼­´Â ¾Ë¼ö ¾øÀ½.
1049        m->VctFlag         = 0;      // cafrii, add. 030313.
1050       
1051        m->scrambled       = bScrambled;
1052
1053        // ÀÌÁ¦ tmp°¡ ´Ù ÁغñµÇ¾ú´Ù.
1054
1055        dprint(2, "  ====== found psichannel: %d-%d, rf %d, %s, #%d %s\n", 
1056                        m->Major, m->Minor, m->RF, ServiceTypeString(m->Service_type),
1057                        m->Prog_number, 
1058                        m->scrambled ? "scrambled " : "");
1059       
1060
1061        // cafrii 060808, minor Áߺ¹ °¡´É¼º ¶§¹®¿¡ prog numÀ» »ç¿ëÇÏ¿© °Ë»çÇÑ´Ù.
1062        //    psi ä³Î¿¡¼­ minor´Â Áß¿äÇÑ Á¤º¸°¡ ¾Æ´Ï´Ù.
1063        //
1064        //target = find_mcm_major_minor_rf_vf(m->Major, m->Minor, m->RF, 0);
1065        target = find_mcm_rf_prognum_vf(m->RF, m->Prog_number, 0);
1066
1067        if (target) 
1068        {
1069                // cafrii 060808 use 'fresh' field to determin overlapped channel
1070                //
1071                if (target->fresh == 0)
1072                {
1073                        // ÀÌ targetÀº ¿¹Àü DBÀ̹ǷΠ±×³É overwrit ÇØ¹ö¸®ÀÚ.
1074                        dprint(2, "  same psi mcm found. overwrite to old mcm.\n");
1075                        // ±âÁ¸ Á¤º¸°¡ ÀÖÀ¸¸é ±× MCM¿¡´Ù updateÇÑ´Ù.
1076                }
1077                else
1078                {
1079                        // targetÀº ¹æ±Ý Àü¿¡ Ãß°¡µÈ ½Å±Ô ä³ÎÀ̹ǷΠÀ̹ø Á¤º¸¸¦ ¹ö¸®ÀÚ.
1080                        dprint(2, "  overlapped channel (#d) ignored\n", m->Prog_number);
1081
1082                        // pat¿¡ ¶È°°Àº program number°¡ µÎ°³ ÀÌ»ó Á¸ÀçÇÏ´Â °æ¿ì
1083                        // ù¹øÂ° °Í¸¸ ¹Ý¿µµÇ°í ³ª¸ÓÁö´Â ¹ö¸°´Ù.
1084                       
1085                        return statusChannelDuplicated;
1086                }
1087        }
1088        else 
1089        {
1090                target = new_mcm(); // ±âÁ¸ MCM Á¤º¸°¡ ¾øÀ¸¸é »õ·Î MCM itemÀ» Çϳª ÇÒ´çÇÏ°í µî·ÏÇÑ´Ù.
1091                if (target == NULL)
1092                        return statusOutOfMemory;
1093        }
1094
1095        *target = *m;  // º¹»ç..  memcpy(target, m, sizeof(MCM_DB_T));
1096
1097        target->Uid = get_new_mcm_id(); // cafrii 060726 add
1098
1099        target->fresh = 1; // cafrii 060808 add
1100                // À̹ø¿¡ »õ·Ó°Ô updateµÈ DB entryÀÓÀ» ³ªÅ¸³½´Ù.
1101
1102        if (ppmcm)
1103                *ppmcm = target;
1104
1105        return statusOK;
1106}
1107
1108
1109//
1110//  update_psi
1111//
1112//  VCT°¡ ¼ö½ÅÀÌ ¾ÈµÈ »óÅÂÀ̰ųª, VCT°¡ ÀÖ´õ¶óµµ CBTF_ForcePSI ¿É¼ÇÀÌ »ç¿ëµÈ °æ¿ì,
1113//  PsiOnlyMode ÀÎ °æ¿ì¿¡ ÀÌ ÇÔ¼ö°¡ ¼öÇàµÈ´Ù.
1114//
1115//  VCT¸¸À¸·Î ä³Î DB ±¸¼º¿¡ ½ÇÆÐÇÑ °æ¿ì¿¡ PSI Á¤º¸·Î ä³Î DB¸¦ ±¸¼ºÇϰųª,
1116//  VCTÀÇ Á¤º¸¿¡ PSI Á¤º¸¸¦ Ãß°¡·Î º¸¿ÏÇÏ¿© ä³Î DB¸¦ Ãß°¡ ±¸¼ºÇÑ´Ù.
1117//
1118STATUS update_psi(ChannelScanContext *ctx)
1119{
1120        int i, k;
1121        STATUS status = statusOK;
1122        int _second = 1000;
1123       
1124        int program_index;   // sequencial program index.
1125        MPEG_PAT_program *program; // temporary..
1126
1127        MCM_DB_T *pmcm = NULL;
1128
1129        BOOL bMinorNumberAutoAdjust = FALSE; 
1130                // cafrii 060808 add
1131                // cafrii 070130 make false.
1132                // APRO1¿¡¼­´Â report ÇÒ ½ÃÁ¡ÀÌ ¹ú¼­ adjust°¡ µÇ¾î ÀÖ¾î¾ß ÇϹǷÎ
1133                // ÀÌ ¹æ¹ýÀ» »ç¿ëÇÒ ¼ö ¾ø´Ù.
1134                // ´ë½Å 2-pass ¹æ¹ýÀ» »ç¿ëÇÑ´Ù.
1135               
1136        int pass; // cafrii 070130 add
1137        ScanNewChannelCbParam cbparam;
1138       
1139        typedef struct 
1140        {
1141                UINT16 pn;  // program number
1142                UINT16 id;  // mcm id
1143                UINT16 minor;
1144               
1145        } _MinorAdjustParam;
1146
1147        _MinorAdjustParam *param2 = NULL;
1148        int n_param2 = 0;       
1149
1150        if (ctx->pat == NULL || ctx->num_programs <= 0) 
1151        {
1152                dprint(0, "!! no psi tables\n");
1153                return statusPSIPError;
1154        }
1155
1156        // cafrii 070130 add for new callback prototype
1157        memset(&cbparam, 0, sizeof(cbparam));
1158        cbparam.fn_lookup_mj_mn = (BOOL (*)(int, int))find_mcm_major_minor;
1159
1160
1161        //------ PAT ó¸®.
1162        // cafrii 060724 change 1->0
1163        //  PMTÀÇ index¶ó´Â Àǹ̷Π0ºÎÅÍ ½ÃÀÛÇÑ °ªÀ» °Ç³×ÁÖÀÚ.
1164        //  ÇÊ¿äÇÏ¸é ³»ºÎ¿¡¼­ non-zero interger·Î º¯È¯ÇÏ¸é µÈ´Ù.
1165        program_index = 0;
1166       
1167        dprint(2, "total %d programs in PAT\n", ctx->num_programs);
1168
1169
1170        // cafrii 070130 add 2-pass scan..
1171        //     
1172        // for (pass=0; pass<2; pass++)
1173        //
1174        pass = 0;
1175
1176label_pass_start:
1177
1178        if (pass >= 2) goto label_pass_end;
1179       
1180        for (i=0; i<ctx->num_programs; i++)
1181        {
1182                pmcm = NULL;
1183               
1184                program = &ctx->pat->programs[i];
1185
1186                // cafrii 070130 add
1187                //  1st scan, #1~999 processed. 2nd scan, #1000+ processed
1188                //
1189                if (pass == 0 && program->program_number > 999)
1190                        continue;
1191                if (pass == 1 && program->program_number <= 999)
1192                        continue;
1193               
1194                // ¸¸¾à ÀÌ¹Ì VCT¿¡ ÀÇÇØ¼­ Channel DB°¡ updateµÇ¾îÀÖ´Ù¸é ±»ÀÌ ¹ÞÀ» ÇÊ¿ä´Â ¾ø´Âµ¥....
1195                // MCM¿¡ Á¸ÀçÇÏ´Â DB°¡ À̹ø autoscan ¿¡¼­ »õ·Î ¹ÞÀº °ÍÀÎÁö,
1196                // ¿¾³¯ °ÍÀÎÁö ±¸ºÐÇÏ´Â flag°¡ ¾ø´Ù...
1197                //
1198                // if (find_mcm_xx(rf, program->program_number))
1199                //    continue;;
1200                //
1201                // ±×·¯³ª ÇØ´ç program numberÀÇ VCT channelÀÌ Á¸ÀçÇÑ´Ù°í ÇØ¼­
1202                // ±× Á¤º¸°¡ DB¿¡ Ãß°¡µÇ¾ú´Ù°í º¼ ¼ö´Â ¾ø´Ù!!
1203                // ¿Ö³ÄÇϸé VCT channelÀÇ Á¤º¸°¡ ¿Ïº®ÇÏÁö ¸øÇؼ­ skipµÇ¾úÀ» ¼öµµ Àֱ⠶§¹®..
1204                //
1205                // µû¶ó¼­ vctÀÇ processed flag¸¦ ÂüÁ¶ÇÏ¿© DB¿¡ Àû¿ëµÈ°ÍÀÎÁö ¾Ë¾Æ³½´Ù.
1206                //
1207        #if 0 // cafrii 060725 delete
1208                if (ctx->xvct)
1209                {
1210                        // ¿î³ª»Ú°Ô analog ä³ÎÁ¤º¸¿¡ program number°¡ Àִµ¥ °ªÀÌ ÀÏÄ¡Çϰųª
1211                        // ¶Ç´Â À߸øµÈ vct channel Á¤º¸°¡ ÀÖ¾ú´Ù¸é ºñ±³°¡ Á¤È®ÇÏÁö ¾Ê°Ô µÈ´Ù.
1212                        //
1213                        for (k=0; k<ctx->xvct->numChannels; k++)
1214                        {
1215                                if (ctx->xvct->channel[k].program_number == program->program_number)
1216                                        break;
1217                        }
1218                       
1219                        if (k < ctx->xvct->numChannels && ctx->xvct->channel[k].processed)
1220                        {
1221                                dprint(2, "**** same program number channel (#%d) exist. skip updating psi..\n",
1222                                                        program->program_number);
1223                                continue;
1224                        }
1225                }
1226        #else
1227                // cafrii 060725 change
1228                // cafrii 060808 comment: fresh mcm¸¸ °Ë»öÇϵµ·Ï ÇÑ´Ù.
1229                //
1230                if (check_mcm_if_rf_prognum_exist(ctx->cur_channel, program->program_number))
1231                {
1232                        dprint(2, "**** same program number channel (#%d) exist. skip updating psi..\n", 
1233                                                program->program_number);
1234                        continue;
1235                }
1236        #endif
1237       
1238                if (ctx->fnCheck && ctx->fnCheck()) {
1239                        status = statusCancelled;
1240                        goto label_end_scan;
1241                }
1242
1243                if (ctx->pmtList[i] == NULL) 
1244                {
1245                        // ÇöÀç ÀÌ PMT´Â ¾ÆÁ÷ ¼ö½ÅÀÌ ¾ÈµÇ¾úÀ½.. ÀÌÀü ¼ö½ÅÇÒ ¶§ timeout ½ÇÆÐÇßÀ» °¡´É¼ºÀÌ Å©´Ù.
1246
1247#if USE_PSI_RX_RETRY
1248                        // cafrii 050429 add
1249                        // ¾Õ¿¡¼­ TVCT/CVCT/PAT/PMT¸¦ ÇѲ¨¹ø¿¡ ¼ö½ÅÇÒ ¶§¿¡ ¾î¶°ÇÑ ÀÌÀ¯·Îµç PMT¸¦ ¸ðµÎ ¼ö½ÅÇÏÁö
1250                        // ¸øÇßÀ» °æ¿ì°¡ ÀÖÀ» ¼ö ÀÖ´Ù.
1251                        // ÀÌ °æ¿ì¸¦ º¸¿ÏÇϱâ À§Çؼ­ ¼ö½ÅÇÏÁö ¸øÇÑ PMT´Â ¿©±â¼­ ´Ù½Ã Çѹø Ãß°¡·Î ¼ö½Å½ÃµµÇÑ´Ù.
1252                       
1253                        dprint(2, "retry getting pmt[%d], pid 0x%x, #%d\n", i, 
1254                                                program->program_map_PID, program->program_number);
1255                                               
1256                        status = Dmc_GetPMT(ctx->tsd, program->program_map_PID,
1257                                                                program->program_number, &ctx->pmtList[i], 
1258                                                                g_Timeout_PmtLoading*_second/1000, ctx->fnCheck);
1259                                                               
1260                        if (status == statusCancelled) {
1261                                goto label_end_scan;
1262                        }
1263                       
1264                        if (status) {
1265                                dprint(0, "!! pmt[%d] pid 0x%x, #%d not loaded\n", i, 
1266                                                                program->program_map_PID, program->program_number);
1267                                continue;  // ´ÙÀ½ PMT·Î ÁøÇà..
1268                        }
1269
1270#else
1271                        _second = _second; // to avoid warning..
1272                        dprint(0, "!! pmt[%d] program number #%d not loaded\n", i, program->program_number);
1273                        continue;
1274               
1275#endif
1276                       
1277                }
1278
1279#if TEST_LARGE_PROGRAM_NUMBER
1280        // cafrii 060728 add for test
1281        //
1282        if (g_TestLargeProgramNumber)
1283        {
1284                if (i > 0 && ctx->pmtList[i-1] && ctx->pmtList[i]) {
1285                        ctx->pmtList[i]->program_number = ctx->pmtList[i-1]->program_number+999;
1286                        dprint(0, "!!!! large PN test: -> #%d\n", ctx->pmtList[i]->program_number);
1287                }
1288                else
1289                        dprint(0, "!!!! large PN test: \n");
1290        }
1291#endif
1292               
1293                status = update_psi_program(ctx, ctx->pat->transport_stream_id, 
1294                                                ctx->pmtList[i], program_index++, &pmcm);
1295
1296                if (status == statusCancelled) {
1297                        //return status;
1298                        goto label_end_scan;
1299                }
1300
1301                if (pmcm == NULL && status == statusOK)
1302                        status = statusError;
1303                       
1304                if (status) {
1305                       
1306                        // ±×¹ÛÀÇ ´Ù¸¥ ¿¡·¯.. ÀÏ´Ü ¸ØÃßÁö ¸»°í °è¼Ó ÁøÇàÇÏÀÚ.
1307                }
1308                else // no error and pmcm valid
1309                {
1310                        if (bMinorNumberAutoAdjust)
1311                        {
1312                                param2[n_param2].pn = pmcm->Prog_number;
1313                                param2[n_param2].id = pmcm->Uid;
1314                                param2[n_param2].minor = pmcm->Minor;
1315                                n_param2++;
1316                        }
1317
1318                        if (bMinorNumberAutoAdjust == FALSE)
1319                        {
1320                                if (pmcm) {  // »õ·Î ¹ß°ßµÈ ä³ÎÀÌ ¾øÀ» ¼öµµ ÀÖ´Ù. ±×·² °æ¿ì pmcm Àº NULL ÀÌ´Ù.
1321                                        //print_mcm();
1322
1323                                        cbparam.ucm = pmcm;
1324                                        send_event_message(evtNewChannel, (UINT32) &cbparam);
1325                                        // »õ·Î updateÇÑ mcm item Æ÷ÀÎÅ͸¦ ³Ñ°ÜÁØ´Ù.
1326                                }
1327                        }
1328                       
1329                }
1330        }
1331
1332        if (++pass < 2)
1333                goto label_pass_start;
1334
1335label_pass_end:
1336
1337        if (bMinorNumberAutoAdjust && n_param2 > 0)
1338        {
1339                _MinorAdjustParam tmp;
1340                int free_minor_number;
1341                int nAdjustedChannel = 0;
1342               
1343                int pn_threshold = 1000; // ÀÌ °ª ÀÌ»óÀÎ pnÀº adjust¸¦ ÇÑ´Ù.
1344               
1345                // program number·Î sorting.. ¿À¸§ Â÷¼ø..
1346                //
1347                for (i=0; i<n_param2-1; i++) {
1348                        for (k=i+1; k<n_param2; k++) {
1349                                if (param2[i].pn > param2[k].pn)
1350                                {
1351                                        tmp = param2[k];
1352                                        param2[k] = param2[i];
1353                                        param2[i] = tmp;
1354                                }
1355                        }
1356                }
1357
1358                // threshold º¸´Ù Å« pnÀº ÀÏ´Ü ¸ðµÎ minor 0À¸·Î Àӽà ÇÒ´ç.
1359                for (i=0; i<n_param2; i++)
1360                        param2[i].minor = (param2[i].pn >= pn_threshold) ? 0 : param2[i].pn;
1361
1362                // minor 0ÀÎ Àӽà ä³ÎÀ» ¼ø¼­´ë·Î Áߺ¹ ¾ÈµÇ°Ô ÇÒ´ç..
1363                free_minor_number = 1;
1364                for (i=0; i<n_param2; i++)
1365                {
1366                        if (param2[i].minor) continue; // ¹øÈ£ ÇÒ´ç ³¡.
1367
1368                        while (1)
1369                        {
1370                                // free minor·Î ÇÒ´ç ÇÒ »ý°¢Àε¥, ±× Àü¿¡ Áߺ¹ÀÌ µÇ´ÂÁö üũ.
1371
1372                                for (k=0; k<n_param2; k++) {
1373                                        if (param2[k].minor == free_minor_number) {
1374                                                dprint(2, "\t minor %d overlapped.\n", free_minor_number);
1375                                                break;
1376                                        }
1377                                }
1378
1379                                if (k < n_param2) {
1380                                        // Áߺ¹ÀÌ ÀÖÀ¸¸é ´Ù½Ã ½Ãµµ..
1381                                        free_minor_number++;
1382                                        continue;
1383                                }
1384                               
1385                                // Áߺ¹ ¾øÀ½.. OK..
1386                                param2[i].minor = free_minor_number;
1387                                dprint(2, "\t minor %d assigned for #%d \n", param2[i].minor, param2[i].pn);
1388                                nAdjustedChannel++;
1389                                free_minor_number++;
1390                                break;
1391                        }
1392
1393                }
1394
1395                if (nAdjustedChannel) {
1396                        dprint(2, " total %d minor adjusted / %d programs\n", nAdjustedChannel, n_param2);
1397                        for (i=0; i<n_param2; i++) {
1398                                pmcm = get_mcm_by_id(param2[i].id);
1399                                if (pmcm) {
1400                                        pmcm->Minor = param2[i].minor;
1401                                        dprint(2, "\t[%d] %d - %3d, #%d %s\n",
1402                                                        i, pmcm->Major, pmcm->Minor, pmcm->Prog_number,
1403                                                        pmcm->Minor != pmcm->Prog_number ? "<---" : "");
1404                                }
1405                        }
1406                }
1407        }
1408
1409
1410        if (1)
1411        {
1412                if (bMinorNumberAutoAdjust)
1413                {
1414                        for (i=0; i<n_param2; i++)
1415                        {
1416                                pmcm = get_mcm_by_id(param2[i].id);
1417                                if (pmcm) {
1418                                        dprint(2, " [%d] %d-%d, #%d scramble %d\n", i, 
1419                                                pmcm->Major, pmcm->Minor, pmcm->Prog_number, pmcm->scrambled);
1420                                        cbparam.ucm = pmcm;
1421                                        send_event_message(evtNewChannel, (UINT32)&cbparam);
1422                                }
1423                        }
1424                }
1425        }
1426
1427label_end_scan:
1428
1429        if (param2)
1430                DHL_OS_Free((void**)&param2);
1431
1432        return status; 
1433       
1434}
1435
1436
1437
1438//
1439//
1440// pat°¡ ¼ö½ÅÀÌ ¾ÈµÇ¸é statusNoPSI
1441//
1442STATUS get_pmt_by_program_number(ChannelScanContext *ctx, 
1443                                xvctChannelPtr_t p, int *pIndex)
1444{
1445        STATUS status = statusOK;
1446        int i;
1447        int idx = -1; // matched_pmt_index
1448
1449        if (ctx->pat == NULL)
1450        {
1451#if USE_PSI_RX_RETRY
1452                dprint(2, "\t no pat. get pat again..\n");
1453                status = Dmc_GetPAT(ctx->tsd, &(ctx->pat), 
1454                                g_Timeout_PatLoading*1000/1000, ctx->fnCheck);
1455
1456                if (status == statusCancelled) // cafrii 070117 add for bugfix
1457                        return statusCancelled;
1458               
1459                if (status || ctx->pat == NULL) {
1460                        dprint(0, "!! no pat..\n");
1461                        return statusNoPSI;
1462                }
1463#else
1464                if (ctx->pat == NULL) {
1465                        dprint(0, "!! no pat..\n");
1466                        return statusNoPSI;
1467                }
1468#endif
1469
1470        }
1471
1472        // matched pmt index¸¦ ã´Â´Ù.
1473        //
1474        for (i=0; i<ctx->num_programs; i++) 
1475        {
1476                if (ctx->pat->programs[i].program_number == p->program_number) 
1477                {
1478                        idx = i;
1479                        break;
1480                }
1481        }
1482
1483        if (idx >= 0)
1484        {
1485                // ÁÖÀÇ!! pmtList[i] °¡ NULL ÀÏ ¼öµµ ÀÖ´Ù!!
1486                //    PAT¿¡´Â µî·ÏµÇ¾î ÀÖÀ¸³ª ½ÇÁ¦·Î´Â Á¸ÀçÇÏÁö ¾Ê´Â °æ¿ì,
1487                //    ¶Ç´Â timeoutµÇ¾î¼­ PMT¸¦ ¼ö½ÅÇÏÁö ¸øÇÑ °æ¿ì..
1488                //
1489
1490                if (ctx->pmtList[idx] &&
1491                        ctx->pmtList[idx]->program_number != p->program_number)
1492                {
1493                        dprint(0, "!! received pmt[%d]'s pn #%d != vct ch pn#%d\n", 
1494                                        idx, ctx->pmtList[idx]->program_number, p->program_number);
1495                        FreePMT(ctx->pmtList[idx]);
1496                        ctx->pmtList[idx] = NULL;
1497                }
1498               
1499                if (ctx->pmtList[idx] == NULL) 
1500                {
1501#if USE_PSI_RX_RETRY
1502                        dprint(2, "\t no pmt yet. get pmt[%d] again..\n", idx);
1503                        status = Dmc_GetPmtByProgramNumber(&(ctx->pat),
1504                                        &(ctx->pmtList[idx]), 
1505                                        p->program_number, ctx->fnCheck);
1506
1507                        if (status == statusCancelled) // cafrii 070117 add for bugfix
1508                                return statusCancelled;
1509
1510                        if (status)
1511                                dprint(2, "\t pmt[%d] load failed %d\n", idx, status);
1512
1513#else
1514                        if (ctx->pmtList[idx] == NULL)
1515                                dprint(2, "!! no pmt[%d] loaded..\n", idx);
1516                               
1517#endif
1518                }
1519
1520                *pIndex = idx;
1521
1522                return status;
1523        }
1524
1525
1526        dprint(0, "!! pn #%d pmt not found. try recover vct..\n", p->program_number);
1527
1528        // recover vct!!
1529
1530        status = Dmc_RecoverVctProgramNumber(p,
1531                                        ctx->pat,        // IN
1532                                        ctx->pmtList,    // INOUT
1533                                        &idx,            // OUT
1534                                        ctx->fnCheck);
1535
1536        if (status == statusCancelled)
1537                return status;
1538       
1539        if (status)
1540                dprint(2, "!! recover failed, %d\n", status);
1541        else
1542        {
1543                // recover ¼º°ø..
1544                *pIndex = idx;
1545                status = statusOK;
1546        }
1547       
1548        return status;
1549
1550}
1551
1552#if 0
1553// cafrii 060728 delete. no more used.
1554//   »õ·Î¿î pid selection ruleÀ» »ç¿ëÇϱ⠶§¹®.
1555//
1556STATUS find_pids_from_psi(ChannelScanContext *ctx, MPEG_PMT *pmt,
1557                                                        UINT16 *pPid, UINT16 *vPid, UINT16 *aPid)
1558{
1559        int err = DHL_OK;
1560        UINT32 vidPid, audPid, pcrPid;
1561
1562        if (pmt == NULL) {
1563                return statusNotFound;
1564        }
1565
1566        //----- PMT ó¸®.
1567        err = GetElementaryPIDs(pmt, &vidPid, &audPid, &pcrPid,
1568                                NULL, NULL, NULL);
1569        // °¡´ÉÇÑ ¿¡·¯.. scrambledWarning, or notFoundError..
1570
1571        if (IsError(err)) {  // cafrii, 030506
1572                dprint(0, "!! cannot get pids in PMT #%d, err %s\n",
1573                                                pmt->program_number, ErrorString((DHL_RESULT)err));
1574                        // cafrii 050707 fix,  i -> pmt->program_number
1575
1576                if (dprintable(3))
1577                        PrintPMT(pmt);
1578               
1579                return statusPSIPError;
1580        }
1581
1582        if (pPid) *pPid = (UINT16) pcrPid;
1583        if (vPid) *vPid = (UINT16) vidPid;
1584        if (aPid) *aPid = (UINT16) audPid;
1585       
1586        return err;  // scrambledWarning °á°ú°¡ ±×´ë·Î Àü´ÞµÉ ¼ö ÀÖµµ·Ï..
1587       
1588}
1589#endif // 0
1590
1591
1592static STATUS update_vct_subchannel(ChannelScanContext *ctx, UINT16 tsid, 
1593                                                                        xvctChannelPtr_t p, BOOL is_cvct, MCM_DB_T **ppmcm)
1594{
1595        // »õ·Î ¹ÞÀº VCT Å×À̺íÀ» ä³Î DB¿¡ Ãß°¡Çϱâ À§Çؼ­ ƯÁ¤ minor ä³ÎÀ» ¼±ÅÃÇÑ ÈÄ (p)
1596        // ÀÌ ÇÔ¼ö¸¦ ºÒ·¯ MCM DB¿¡ µî·ÏÇÑ´Ù.
1597        //
1598        // VCTÀÇ ÇØ´ç minor ä³Î Å×ÀÌºí¿¡¼­ ¹ß°ßµÇ´Â ¸ðµç Á¤º¸¸¦ ±â·ÏÇÑ´Ù.
1599        // ±âÁ¸ ä³Î DB¿¡ (Mj/Mn/Rf/VctFlag)°¡ ÀÏÄ¡ÇÏ´Â Ç׸ñÀÌ ÀÖÀ¸¸é updateÇÑ´Ù.
1600        //
1601        // °¢ ä³Î ŸÀÔ È¯°æ¿¡ ¸ÂÃç update¸¦ ´Ù¸£°Ô ÇÑ´Ù.
1602        //
1603        // MCM DB¿¡ µî·ÏÇÑ ÈÄ »õ·Î µî·ÏµÈ MCM entryÀÇ pointer´Â ppmcmÀ» ÅëÇØ caller¿¡°Ô ÂüÁ¶¿ëÀ¸·Î ³Ñ°ÜÁø´Ù.
1604        // caller´Â ÀÌ Æ÷ÀÎÅ͸¦ ÀÌ¿ëÇÏ¿© ¾î¶² MCMÀÌ µî·ÏµÇ¾ú´ÂÁö ¾Ë ¼ö ÀÖ´Ù.
1605        // ´Ü¼øÈ÷ ÂüÁ¶¿ëÀ̸ç, caller´Â ÇÊ¿äÇÑ °æ¿ì MCM Á¤º¸¸¦ º¹»çÇØ¼­ »ç¿ëÇÒ ¼ö ÀÖ´Ù.
1606        //
1607        // Note: leon 2003.9.2
1608        //              ETM_location,access_controlled,hidden,hide_guideµµ °í·ÁÇÒ Çʿ䰡 ÀÖ´Ù.
1609        //              ¸ÞÀÌÀú ä³Î DB¸¦ »ç¿ëÇÒ °æ¿ì(rfµµ ´Ù¸¦ ¶§ ),
1610        //              ÀÌÀü¿¡ µî·ÏµÇ¾î ÀÖ´ø ¸ÞÀÌÀú ä³Î(10-1,10-2,10-3,10-4)¿Í »õ·Î Ãß°¡µÈ ä³Î
1611        //              °°Àº ¸ÞÀÌÀú ¹øÈ£ »ç¿ë(10-1,10-2)ÀÏ °æ¿ì,App°¡ ÀÌ·² °æ¿ì, ¸ÞÀÌÀú ¹øÈ£ 10À» µÎ°³ °¡Áö°Ô ÇØ¾ßµÊ
1612        //              ´Ù¸¥ ä³ÎÀ̴ϱñ ,,, ´Ù¸¥ ¸ÞÀÌÀú DB¿¡ µî·ÏÇÒ ¼ö ÀÖµµ·Ï ±¸ºÐ ÇÊ¿ä?? ¾î¶»°Ô ±¸ºÐÇÏÁö??
1613        //
1614        //
1615
1616        int strength;
1617        int vctRF; // vctRF´Â vct¸¦ ¼ö½ÅÇÑ Ã¤³Î, channelRF´Â VCT¿¡ ±âÀçµÈ virtual channelÀÇ RF
1618        int vctFreqOffset;  // cafrii 050603 add
1619
1620        MCM_DB_T *m, m_0, *target = NULL;
1621        STATUS status;
1622        extendedChannelNameDescriptorPtr_t xcnd = NULL;  // cafrii 041126 add
1623       
1624        BOOL is_cable = g_CurChannelType != ChannelType_Cable ? FALSE : TRUE;
1625        BOOL bScrambled = FALSE;          // TRUE program is scrambled..
1626
1627        UINT32 audioPID32 = 0;   // cafrii 060804 add
1628
1629        vctRF = ctx->cur_channel;          // ÀÌ VCT¸¦ ¼ö½ÅÇß´ø PTCÀÇ RF¹øÈ£
1630        vctFreqOffset = ctx->freq_offset;  // ÀÌ VCT¸¦ ¼ö½ÅÇÑ Ã¤³ÎÀÇ FreqOffset
1631                // cafrii 050603 add
1632               
1633        strength = ctx->signal_strength;  // ÇöÀç ÀÌ Ã¤³ÎÀÇ ½ÅÈ£ ¼¼±â
1634       
1635        if (strength == 0) strength = 1;  // 0 °ªÀº Ưº°ÇÑ Àǹ̷Π»ç¿ëµÇ¹Ç·Î ÇÇÇÑ´Ù.
1636       
1637        dprint(2, "update_vct_subchannel: %s, rf %d, tsid %d, str %d\n", 
1638                                        is_cvct ? "CVCT" : "TVCT", vctRF, tsid, strength);
1639
1640        // A65B specÀÇ ³»¿ëÀ» º¸¸é Air¿¡¼­µµ CVCTÀÇ »ç¿ëÀÌ ±ÝÁöµÈ °ÍÀº ¾Æ´Ñ°Í °°´Ù.
1641        // ´Ü, Air¿¡¼­´Â TVCT°¡ CVCT º¸´Ù ¿ì¼±µÇ´Â °Í »ÓÀÌ´Ù.
1642        // caller´Â µ¿½Ã¿¡ µÎ°³ÀÇ VCT°¡ ¼ö½ÅµÉ °æ¿ì Àû´çÇÑ VCT¸¦ ¼±ÅÃÇØ¼­ ÀÌ ÇÔ¼ö¸¦ È£ÃâÇØ¾ß ÇÑ´Ù.
1643        //
1644
1645        // cafrii 041130 add comment
1646        // MCM °ü¸® ±ÔÄ¢:
1647        // ¸ÕÀú local stack¿¡ Àӽà mcm À» ¸¸µé°í ÃʱâÈ­¸¦ ÇÏ°í ³ª¼­ ½ÇÁ¦ MCM list¿¡ Ãß°¡ÇÏ´Â ¹æ½ÄÀ¸·Î ÇÑ´Ù.
1648       
1649        m = &m_0;
1650        memset(m, 0, sizeof(MCM_DB_T));
1651
1652        m->Major = p->major_channel_number;
1653        m->Minor = p->minor_channel_number;
1654        m->Prog_number = p->program_number;
1655
1656        if (is_cvct && IsOnePartChannelNumber(m->Major))
1657        {
1658                if (!is_cable)
1659                        dprint(0, "!! OnePartChannel number in CVCT/Air.. maybe wrong\n");
1660       
1661                m->Major = ConvertToOnePartChannelNumber(m->Major, m->Minor);
1662                m->Minor = ONE_PART_CHANNEL_INDICATOR;
1663                        // ÀÌ Minor °ªÀ¸·ÎºÎÅÍ ¿ì¸®´Â ÀÌ Ã¤³ÎÀÌ OnePartChannelÀ̶ó´Â °ÍÀ» ¾Ë ¼ö ÀÖ´Ù.
1664
1665                dprint(2, "====== %d-%d (%d), #%d, mm 0x%x, st 0x%x, ch_tsid 0x%x\n", 
1666                                p->major_channel_number, p->minor_channel_number,
1667                                m->Major, // OnePart number
1668                                m->Prog_number, p->modulation_mode, 
1669                                p->service_type, p->channel_TSID);
1670        }
1671        else
1672        {
1673                // cafrii 060630 add
1674                //
1675                // for air TVCT,
1676                //  major number range: 1 ~ 99
1677                //  minor number range: 0 ~ 999
1678                //      for analog service, 0 is used.
1679                //      for digital or audio only, 1 ~ 99 is used.
1680                //      for databroadcasting and etc, 1 ~ 999 is used.
1681                //    we restrict minor number to 3 digits..
1682                //
1683                // for cable CVCT,
1684                //  major number range: 1 ~ 999
1685                //  minor number range: 0 ~ 999
1686                //
1687                // cable¿¡¼­ 1000 ~ 1007 ±îÁöÀÇ major,
1688                // air¿¡¼­ 1000 ÀÌ»óÀÇ major´Â ¾î¶»°Ô ó¸®ÇÒ °ÍÀΰ¡? --> ¿¡·¯ ó¸®.
1689                //
1690                if (!is_cable && m->Major > 99) {   // air À̸é tvctµç cvctµç 99Ãʰú ±ÝÁö.
1691                        dprint(0, "!! air mode, major %d invalid!\n", m->Major);
1692                        status = statusPSIPError;
1693                        goto label_exit;
1694                }
1695
1696                if (is_cable && m->Major > 999) {  // cableÀ̸é tvctµç cvctµç 999 Ãʰú ±ÝÁö.
1697                        dprint(0, "!! cable mode, major %d invalid!\n", m->Major);
1698                        status = statusPSIPError;
1699                        goto label_exit;
1700                }
1701
1702                // cafrii 060804, major 0 ±ÝÁö
1703                //
1704                if (m->Minor != ONE_PART_CHANNEL_INDICATOR && m->Major <= 0) {
1705                        dprint(0, "!! two part channel major 0 invalid\n");
1706                        status = statusPSIPError;
1707                        goto label_exit;
1708                }
1709               
1710               
1711                if (m->Minor > 999) {
1712                        dprint(0, "!! minor %d invalid!\n", m->Minor);
1713                        status = statusPSIPError;
1714                        goto label_exit;
1715                }
1716               
1717                dprint(2, "====== %d-%d, #%d, mm %d, st %d, ch_tsid 0x%x\n", 
1718                                m->Major, m->Minor, 
1719                                m->Prog_number, p->modulation_mode, 
1720                                p->service_type, p->channel_TSID);
1721        }
1722               
1723
1724        //--------------------------------------------------------
1725        // service_typeÀ» °áÁ¤.
1726       
1727        // modulation mode summary:
1728        // 00 : reserved
1729        // 01 : analog
1730        // 02 : SCTE_mode_1, 64QAM
1731        // 03 : SCTE_mode_2, 256QAM
1732        // 04 : ATSC 8VSB
1733        // 05 : ATSC 16VSB
1734        //
1735        // service type summary:
1736        // 00 : reserved
1737        // 01 : analog TV
1738        // 02 : ATSC digital TV
1739        // 03 : ATSC audio
1740        // 04 : ATSC data
1741        // 05 : ATSC sdds
1742        //
1743        if (p->modulation_mode == 1)  // analog
1744        {
1745                //
1746                // ¾Æ³¯·Î±×ÀÇ °æ¿ì, minor°¡ 0ÀÌ ¾Æ´Ï¸é ¹ö¸°´Ù.
1747                //
1748                if (p->minor_channel_number != 0) {
1749                        dprint(0, "!! Err! Analog channel's minor is non-zero? ignore it!\n");
1750                        status = statusPSIPError;
1751                        goto label_exit;
1752                }
1753                if (p->service_type != 1) {  // 1: analog service
1754                        dprint(0, "!! Err! modulation %d, service %d mismatch! ignore it!\n",
1755                                p->modulation_mode, p->service_type);
1756                        status = statusPSIPError;
1757                        goto label_exit;
1758                }
1759                m->Service_type = Modulation_NTSC;  // NTSC.
1760        }
1761        else if (p->modulation_mode == 2 || p->modulation_mode == 3 ||   // 64QAM / 256QAM
1762                        p->modulation_mode == 4)                                 // 8VSB
1763        {
1764                // ÁÖÀÇ! TVCT¿¡¼­µµ QAM modulationÀÌ °¡´ÉÇϵµ·Ï ÇØ¾ß ÇÔ.. (CableLab ATP Ç׸ñ)
1765                // µû¶ó¼­ TVCT/CVCT ÀÇ ¿©ºÎ°¡ Áß¿äÇÑ°Ô ¾Æ´Ï¶ó Air/Cable ¿©ºÎ°¡ ´õ Áß¿äÇÏ´Ù.
1766                //
1767                if (!is_cable &&                                             // Air ¸ðµå¿¡¼­
1768                        (p->modulation_mode == 2 || p->modulation_mode == 3)) {  // QAM ÀÎ °æ¿ì..
1769                        dprint(0, "!! QAM modulation in Air.. ignore!\n");
1770                        status = statusPSIPError;
1771                        goto label_exit;
1772                }
1773
1774                // cafrii 060630 change, allow minor 0 for cable cvct..
1775                //   we just check cvct or not.. do not check air/cable.
1776                //   because retransmission of terrestrial (tvct) is actually air case.
1777                //
1778                if (!is_cable &&        // Air À̰í, (tvctµç, cvctµç..)
1779                        m->Minor == 0) {    // minor°¡ 0ÀÎ °æ¿ì..
1780                        dprint(0, "!! Err! in air, digital minor is zero.. ignore!\n");
1781                        status = statusPSIPError;
1782                        goto label_exit;
1783                }
1784               
1785                if (p->service_type == 1) // Digital Modulation À̸鼭 analog service?
1786                        dprint(0, "!! Warning! modulation is 8VSB, but analog service? assume Digital!\n");
1787
1788        #if 0
1789                // VCT°ªÀ» »ç¿ëÇÏÁö ¾Ê°í detect µÈ °ªÀ» »ç¿ëÇÏÀÚ.
1790               
1791                m->Service_type = p->modulation_mode == 2 ? Modulation_64QAM :  // 2 ATSC-64QAM
1792                                  p->modulation_mode == 3 ? Modulation_256QAM : // 3 ATSC-256QAM
1793                                                            Modulation_8VSB ;   //   ATSC-VSB
1794        #else
1795                // cafrii 041122 add more conditions.
1796                if (ctx->tuner_modulation_mode == Modulation_8VSB) {
1797                        m->Service_type = ctx->tuner_modulation_mode;
1798                }
1799                else if (ctx->tuner_modulation_mode == Modulation_64QAM || ctx->tuner_modulation_mode == Modulation_256QAM) {
1800                        if (g_CurChannelType == ChannelType_Air) {
1801                                dprint(0, "!! QAM modulation detected in Air mode scan\n");
1802                                m->Service_type = Modulation_8VSB;
1803                        }
1804                        else 
1805                                m->Service_type = ctx->tuner_modulation_mode;
1806                }
1807                else {
1808                        dprint(0, "!! wrong tuner modulation %d in psi scan\n", ctx->tuner_modulation_mode);
1809                        m->Service_type = g_CurChannelType == ChannelType_Air ? Modulation_8VSB : Modulation_64QAM;
1810                }
1811        #endif
1812 
1813        }
1814        else // exceptions.. Áö¿øÇÏÁö ¾Ê´Â modulation mode. ´Ù¸¥ °ªµéÀ» ÀÌ¿ëÇØ¼­ ÃßÁ¤ÇÑ´Ù.
1815        {
1816                dprint(0, "!! Err! unknown modulation mode %d in vct\n", p->modulation_mode);
1817               
1818                // invalid VCT Á¤º¸¸¦ ¹ö¸®Áö ¾Ê°í ÃÖ´ëÇÑ »ç¿ëÇÏ·Á°í ½ÃµµÇÔ.
1819                // modulation mode °ªÀÌ Á¤È®ÇÏÁö ¾Ê´Ù¸é, service type °ªÀ¸·ÎºÎÅÍ ÃßÁ¤À» ÇÏÀÚ..
1820                //
1821                if (p->service_type == 1) { // NTSC..
1822                        m->Service_type = Modulation_NTSC;
1823                }
1824                else {  // 2, 3, 4, ... all digital services..
1825                        // Table¿¡ Á¦´ë·Î µÈ ModulationMode Á¤º¸°¡ ¾øÀ¸´Ï ¾Æ¹« °ªÀ̳ª »ç¿ëÇÏÀÚ..
1826                        //
1827                        // todo..
1828                        // --> cafrii 041122, tunerÀÇ modulation mode¸¦ »ç¿ëÇÏ´Â °ÍÀº ¾î¶²°¡?
1829                        //   self channel ÀÎ °æ¿ì¿¡´Â °¡´ÉÇϰÚÁö¸¸ remote channel ÀÎ °æ¿ì¿¡´Â ¹®Á¦°¡ µÈ´Ù.
1830
1831                        if (is_cable) {
1832                                // TVCT°¡ ¿Â °æ¿ì 8VSB·Î ÇÏ´Â°Ô ³ªÀ»±î?
1833                               
1834                                m->Service_type = Modulation_64QAM;
1835                        }
1836                        else  // Air ÀÎ °æ¿ì..
1837                                m->Service_type = Modulation_8VSB;
1838                }
1839        }
1840
1841        //--------------------------------------------------------
1842        // °¢ service_type º°·Î ó¸®..
1843       
1844        // VCTÀÇ service_type Àº ´ÙÀ½°ú °°´Ù.
1845        //   1: analog,  2: ATSC,  3: ATSC audio only, 4: ATSC data
1846        //
1847        // VCTÀÇ modulation_mode
1848        //   1: analog, 2: 64QAM, 3: 256QAM, 4: 8VSB, 5: 16VSB
1849        //
1850        // MCMÀÇ service typeÀº modulation mode¿¡ ´õ °¡±î¿î °³³äÀÌ´Ù.
1851        //
1852        //  NTSCÀÇ °æ¿ì´Â     RF, freqOffset À» °áÁ¤.
1853        //  DigialÀÇ °æ¿ì´Â   Pids, scrambled, RF, freqOffset À» °áÁ¤.
1854        //
1855        //
1856       
1857        dprint(2, "  service type %d (%s) decided\n", m->Service_type, ServiceTypeString(m->Service_type));
1858       
1859        if (m->Service_type == Modulation_NTSC) // NTSC
1860        {
1861                // cafrii 050902 change. no more support analog channel info in VCT
1862               
1863                dprint(0, "!! analog channel in VCT not support!\n");
1864                status = statusPSIPError;
1865                goto label_exit;               
1866
1867        }
1868        else   // digital.. ATSC_XXX. 8VSB/64QAM/256QAM
1869        {
1870                PidInfo vctPid;  // cafrii 041125 add
1871                int matched_pmt_index = -1;
1872               
1873                //dprint(3, "   pmtList 0x%x, num program %d\n", ctx->pmtList, ctx->num_programs);
1874
1875                //--------------- RF ¹øÈ£ °áÁ¤ ----------------------
1876                //
1877
1878                // cafrii 050817 change
1879                // tsid Á¤º¸¸¦ ¿ÏÀüÈ÷ ¹«½ÃÇϰí, Ç×»ó ÇöÀç PTC¿¡ Æ÷ÇÔµÈ Ã¤³Î·Î °£ÁÖÇÑ´Ù.
1880                //
1881                m->RF = vctRF;                 // ÀÌ VCT¸¦ ¼ö½ÅÇÑ RF ä³Î ¹øÈ£¸¦ »ç¿ëÇÑ´Ù.
1882                m->freqOffset = vctFreqOffset; //
1883
1884               
1885                //------------- PID ¹× CodingType Á¤º¸ ÃßÃâ -----------------
1886               
1887                status = get_pmt_by_program_number(ctx, p, &matched_pmt_index);
1888
1889                if (status == statusCancelled) // cafrii 070117 add for bugfix
1890                        goto label_exit;
1891               
1892                memset(&vctPid, 0, sizeof(vctPid));  // cafrii 041126 add
1893
1894                // cafrii 060727 add matched_pmt_index check code
1895                if (status == statusOK && matched_pmt_index >= 0) {
1896                        status = Dmc_DecidePidInfo2(ctx->pmtList[matched_pmt_index],
1897                                                p->descriptors, p->descriptor_length, &vctPid, 0);
1898
1899                        doDmc_SelectAudioStream(ctx->pmtList[matched_pmt_index], p, &vctPid.audio, &vctPid.audioType);
1900                        doDmc_SelectVideoStream(ctx->pmtList[matched_pmt_index], p, &vctPid.video, &vctPid.videoType);
1901                }
1902                else {
1903                        // pmt¿¡ ¹®Á¦°¡ ÀÖÀ¸¸é vct¸¸À¸·Î ¼öÇà.
1904                        status = Dmc_DecidePidInfo2(NULL, p->descriptors, p->descriptor_length, &vctPid, 0);
1905
1906                        doDmc_SelectAudioStream(NULL, p, &vctPid.audio, &vctPid.audioType);
1907                        doDmc_SelectVideoStream(NULL, p, &vctPid.video, &vctPid.videoType);
1908                }
1909
1910                // PCR pid °ªÀº ¹Ýµå½Ã ÀÖ¾î¾ß Çϸç, Video pid ¶Ç´Â Audio pid µÑ Áß Çϳª°¡ ÀÖ¾î¾ß ÇÑ´Ù.
1911                //
1912                if (status == statusOK && 
1913                        vctPid.bValid && 
1914                        vctPid.pcr && (vctPid.video || vctPid.audio)) 
1915                {
1916                        // ¼º°øÀûÀ¸·Î PID °ªÀÌ ÃßÃâµÇ¾úÀ½.
1917                        //
1918                        m->Pcr_pid = vctPid.pcr;
1919                        m->Video_pid = vctPid.video;
1920                        m->Audio_pid = vctPid.audio;
1921                        m->Video_type = vctPid.videoType;
1922                        m->Audio_type = vctPid.audioType;
1923                       
1924                        //neverdai 081002 && ctx->pmtList[matched_pmt_index] Ãß°¡.
1925                        //³í¸®ÀûÀ¸·Î ctx->pmtList[matched_pmt_index]´Â NULL °ªÀÌ µÉ ¼ö Àֱ⠶§¹®¿¡ Ã¼Å©ÇØ¾ß ÇÔ.
1926                        if (matched_pmt_index >= 0 && matched_pmt_index < ctx->num_programs && ctx->pmtList[matched_pmt_index])
1927                                m->pmt_pid = ctx->pmtList[matched_pmt_index]->PID;
1928                        else
1929                                m->pmt_pid = DMW_PID_NO_INFO;
1930
1931                        // vct recover ±â´É¿¡ ÀÇÇØ program number°¡ ¹Ù²î¾úÀ» ¼ö ÀÖ´Ù.
1932                        m->Prog_number = p->program_number;
1933
1934                        dprint(2, "  pid(pva): 0x%x 0x%x 0x%x, pmt 0x%x, vt%d at%d\n", 
1935                                        m->Pcr_pid, m->Video_pid, m->Audio_pid, m->pmt_pid,
1936                                        m->Video_type, m->Audio_type);
1937                }
1938                else {
1939                        dprint(0, "!! invalid pid info.. skip this subchannel\n");
1940
1941                        // cafrii 060728 add
1942                        // À¯È¿ÇÑ pid°¡ ¾øÀ¸¸é DB¿¡ ³ÖÁö ¾Ê´Â´Ù.
1943                        status = statusPSIPError;
1944                        goto label_exit;               
1945                }
1946               
1947
1948                // ------------ ä³Î Long Name -----------------
1949
1950        #if USE_DMW_EPGX_LIB
1951                status = Dmc_GetInfoFromVctDesc(p->descriptors, p->descriptor_length, NULL, &xcnd);
1952
1953                if (xcnd) {
1954                        dprint(2, "  extended channel name: \n");
1955
1956                        if (dprintable(2)) {
1957                                //memdump(xcnd->long_channel_name, xcnd->long_channel_name_length, "LongName");
1958                                Dmc_PrintMultipleString(xcnd->long_channel_name, xcnd->long_channel_name_length, 10, 0); // indent 10
1959                        }
1960                }
1961        #endif
1962               
1963                // ------------ ¾Ïȣȭ ¿©ºÎ üũ -----------------
1964                //
1965                if (is_cable) 
1966                {
1967                       
1968                #if 0
1969                        // cafrii 050124 fix
1970                        //
1971                        // Motorolla HE ¿¡¼­´Â °ÅÀÇ ´ëºÎºÐÀÇ Ã¤³ÎÀÌ CA descriptor°¡ Àֱ⠶§¹®¿¡
1972                        // ÀÌ ¹æ¹ýÀ» »ç¿ëÇϱⰡ ¾î·Æ´Ù.
1973                        //
1974                        // 1: CA descriptor¸¦ ã¾Æº¸±â
1975                       
1976                        if (matched_pmt_index >= 0)
1977                        {
1978                                // by MPEG system spec:
1979                                // If any elementary stream is scrambled, a CA descriptor shall be
1980                                // present for the program containing that elementary stream.
1981                               
1982                                MPEG_PMT *pmt = ctx->pmtList[matched_pmt_index];
1983                               
1984                                if (GetMpegDescriptor(pmt->descriptors,pmt->descriptor_length,
1985                                                                CA_tag, 0, NULL) == DHL_OK) {
1986                                        dprint(2, " !! PMT main descriptor has CA descriptor\n");
1987                                        bScrambled = TRUE;
1988                                }
1989                        }
1990               
1991                        // 2: TSC bit¸¦ °Ë»çÇϱâ
1992                       
1993                        if (m->Video_pid || m->Audio_pid)  // PID Á¤º¸°¡ ÀÖ¾î¾ß ÀÌ ¹æ¹ýÀ» »ç¿ëÇÒ ¼ö ÀÖ´Ù.
1994                        {
1995                                int pidArray[2] = {0, };  // video and audio..
1996                                int tscArray[2] = {0, };
1997                                int nPid = 0;
1998                               
1999                                if (m->Video_pid)
2000                                        pidArray[nPid++] = m->Video_pid;
2001                               
2002                                if (m->Audio_pid && m->Audio_pid != m->Video_pid)
2003                                        pidArray[nPid++] = m->Audio_pid;
2004                               
2005                                status = Dmc_GetMultipleTscBits(ctx->tsd, nPid, pidArray, tscArray,
2006                                                                g_Timeout_PesPidCheck*1000/1000, ctx->fnCheck);
2007                                                        // cafrii 041202, add cancel check function
2008                                                        // cafrii 050305, timeout to 100ms
2009                                                        // cafrii 050315, change timeout value to variables
2010       
2011                                // statusCancelled, timeoutError, outOfCPUMemoryError, ...
2012                               
2013                                if (status == statusCancelled) {
2014                                        goto label_exit;
2015                                }
2016                                else if (status == statusOK) {
2017                                        //dprint(2, " tsc bit of pid %d, %d : %d, %d\n",
2018                                        //              pidArray[0], pidArray[1], tscArray[0], tscArray[1]);
2019                                       
2020                                        // cafrii 050228, remove tsc bit 255 case, which is not_found..
2021                                        if (tscArray[0] == 1 || tscArray[0] == 2 || tscArray[0] == 3 ||
2022                                                tscArray[1] == 1 || tscArray[1] == 2 || tscArray[1] == 3 ) {
2023                                                dprint(2, " !! one of stream is scrambled bit checked. 0x%x:%d, 0x%x:%d\n",
2024                                                                pidArray[0], tscArray[0], pidArray[1], tscArray[1]);
2025                                                bScrambled = TRUE;
2026                                        }
2027                                }
2028                                else
2029                                        dprint(0, "!! scrmabled bit check err %d\n", status);
2030                        }
2031               
2032                       
2033                        // 3: Video context¸¦ Á÷Á¢ »ý¼ºÇغ¸±â..
2034
2035                        if (1)
2036                        {
2037                                if ((ctx->flag & CBTF_CheckScrambleByVideoContext) &&
2038                                        m->Video_pid)
2039                                {
2040                                        // cafrii 040114 bugfix #AudioOnlyChannelMissing
2041                                        // À̶§ AudioOnly ä³ÎÀÇ °æ¿ì VideoDecodingÀÌ Ç×»ó failÀÌ ³ª¼­ Ç×»ó scramble·Î °£ÁֵǴ ¹®Á¦°¡ ÀÖÀ¸¹Ç·Î
2042                                        // Audio only ä³ÎÀÇ °æ¿ì¿¡´Â ±×³É unscramble·Î °£ÁÖÇÑ´Ù.
2043                                       
2044                                       
2045                                        if (matched_pmt_index >= 0)
2046                                        {
2047                                                // by MPEG system spec:
2048                                                // If any elementary stream is scrambled, a CA descriptor shall be
2049                                                // present for the program containing that elementary stream.
2050                                                status = check_pes_scramble(ctx->tsd, ctx->pmtList[matched_pmt_index], m->Video_pid, m->Pcr_pid);
2051                                        }
2052                                        else
2053                                                status = check_pes_scramble(ctx->tsd, NULL, m->Video_pid, m->Pcr_pid);
2054                                       
2055                                        if (status == statusScrambled) {
2056                                               
2057                                                if(ctx->flag &CBTF_IgnoreScrambledChannel) {
2058                                                        return status;
2059                                                }
2060                                               
2061                                                bScrambled = TRUE;
2062                                                dprint(1, " !! video context (pid v %d/p %d) creation err. scrambled\n",
2063                                                                m->Video_pid, m->Pcr_pid);
2064                                        }
2065                                        else if (status == statusOK) {
2066                                                // good channel..
2067                                        }
2068                                        else {
2069                                                dprint(0, "!! video ES seems invalid.. status %d\n", status);
2070                                        }
2071                                }
2072                        }
2073                #endif
2074
2075                }
2076               
2077        } // end if Service_type
2078       
2079#if 0 // USE_RESOLUTION_GATHERING
2080        //sequence Á¤º¸¸¦ ¾ò¾î¾ß ÇÔ
2081        do {
2082                #define MAX_SEQ_WAIT 5000 // ÃÖ´ë 5Ãʸ¦ ±â´Ù¸²
2083               
2084                tDHL_VideoSeqHdr seq;
2085                tDHL_DispFormat disp=eDHL_DISP_720x480i;
2086                UINT32 ms_start;
2087               
2088                if(m->Video_pid==0) break; //video pid°¡ Á¸ÀçÇØ¾ß ¾Æ·¡ Äڵ带 ½ÇÇàÇÔ.
2089               
2090                DHL_AV_VideoHide(0, TRUE);
2091                DMC_RegisterVideoCallback(FALSE);
2092                DHL_AV_VideoStart(0, m->Video_pid, m->Pcr_pid, m->Video_type);
2093
2094                for(ms_start=DHL_OS_GetMsCount();
2095                        DHL_AV_VideoSeqInfo(0, &seq)!=DHL_OK && DHL_OS_GetMsCount()-ms_start < MAX_SEQ_WAIT;
2096                        DHL_OS_Delay(100));
2097               
2098                if(DHL_OS_GetMsCount()-ms_start >=MAX_SEQ_WAIT) { //timeout
2099                        ;
2100                }
2101                else {
2102                        if(seq.vertical_size>=1080)     disp=eDHL_DISP_1920x1080i;
2103                        else if(seq.vertical_size>=720) disp=eDHL_DISP_1280x720p;
2104                        else                            disp=eDHL_DISP_720x480i;
2105                }
2106               
2107                DHL_AV_VideoStop(0);
2108                DMC_RegisterVideoCallback(TRUE);
2109               
2110                m->video_format=disp;
2111        } while(0);
2112       
2113
2114#endif
2115       
2116
2117        m->signal_strength = m->RF == vctRF ? strength : 0;
2118                // ÇöÀç TSÀÇ Ã¤³Î Á¤º¸ÀÏ °æ¿ì¿¡¸¸ ½ÅÈ£ ¼¼±â ±â¾ï.
2119                // 0 : ÃøÁ¤ ¾ÈµÈ µ¥ÀÌÅÍ.
2120                // analogÀÇ °æ¿ìµµ 0.
2121
2122        m->TSID            = tsid;         // ÇöÀç Æ©´×µÈ ä³Î (ÀÌ VCT¸¦ Æ÷ÇÔÇϰí Àִ ä³Î)ÀÇ TSID
2123        m->source_id       = p->source_id;
2124        m->channel_tsid    = p->channel_TSID; // ÀÌ ÇÁ·Î±×·¥ÀÇ TSID
2125
2126        m->Skipped         = 0; // ÀÌ µÎ°¡Áö´Â ³ªÁß¿¡ ¿©·¯ ä³Î Áß¿¡¼­ ¼±ÅÃÇÏ¿© °áÁ¤ÇÒ ¹®Á¦ÀÌ´Ù.
2127        m->SurfIndex       = 0;
2128
2129        m->hidden          = p->hidden; // VCTÀÇ hidden Á¤º¸¸¦ º¸°üÇÑ´Ù.
2130        m->VctFlag         = 1;         // analog, digital °øÈ÷ VctFlag 1.
2131        m->scrambled       = bScrambled;
2132
2133        memcpy(m->ShortName, p->short_name, 14);
2134       
2135        dprint(2, "  found subchannel: %d-%d, rf %d, %s(%d), $%d, #%d %s%s\n", 
2136                        m->Major, m->Minor, 
2137                        m->RF, ServiceTypeString(m->Service_type), m->Service_type,
2138                        m->source_id, m->Prog_number,
2139                        m->hidden ? "hidden " : "",
2140                        m->scrambled ? "scrambled " : "");
2141       
2142        // cafrii 060724 delete
2143        // µÚ¿¡¼­ ¿ÏÀüÈ÷ DB¿¡ updateÇÏ°í ³ª¼­ flag ¼³Á¤ÇÑ´Ù.
2144        //p->processed = TRUE;  // ÀÌ vct channel Á¤º¸´Â Á¦´ë·Î DB¿¡ ¹Ý¿µ µÇ¾úÀ½À» Ç¥½Ã..
2145
2146        //------------------------------------------------------------------
2147        // ÀÌÁ¦ local stackÀÇ Àӽà MCMÀÌ ¸ðµÎ ÁغñµÇ¾ú´Ù.
2148
2149        // update Á¤Ã¥¿¡ µû¶ó updateÇÑ´Ù. Áߺ¹µÇ´Â Á¤º¸°¡ ÀÖÀ» °æ¿ì ¾Æ·¡ Á¶°ÇÀ» Àû¿ëÇÑ´Ù.
2150        //
2151        // 1. Analog ä³Î Á¤º¸ÀÇ °æ¿ì´Â VCT flag¸¦ ¿ì¼±ÇÑ´Ù. Á÷Á¢ °Ë»öÇÑ Ã¤³Î Á¤º¸º¸´Ù Á¤º¸°¡ ¸¹±â ¶§¹®.
2152        //     RF != majorÀÎ VctFlag=1ÀÇ Ã¤³Îµµ Çã¿ëÇÑ´Ù.
2153        // 2. µðÁöÅÐÀÇ °æ¿ì: [030317 cafrii, »èÁ¦..]
2154        //
2155
2156        // ASSERT (m->Service_type != Modulation_NTSC)  // NTSC
2157
2158        target = find_mcm_major_minor_rf_vf(m->Major, m->Minor, m->RF, 1);
2159               
2160        if (target == NULL) 
2161        {
2162                target = new_mcm(); // ±âÁ¸ MCM Á¤º¸°¡ ¾øÀ¸¸é »õ·Î MCM itemÀ» Çϳª ÇÒ´çÇÏ°í µî·ÏÇÑ´Ù.
2163                if (target == NULL) {
2164                        status = statusOutOfMemory;
2165                        goto label_exit;
2166                }
2167                       
2168                *target = *m;
2169                target->Uid = get_new_mcm_id(); // cafrii 060726 add
2170        }
2171        else 
2172        {
2173                // cafrii 060724 comment
2174                // »ç½Ç M,m,R,V °¡ ¸ðµÎ µ¿ÀÏÇϸ鼭 program number°¡ ´Ù¸¥ °æ¿ì´Â ¼­·Î ±¸ºÐÀÌ ¾ÈµÇ¹Ç·Î
2175                // ±¸ºÐ Æ©´×ÀÌ ºÒ°¡´ÉÇϰí, DB¿¡ Ãß°¡ÇÏ´Â °ÍÀÌ Àǹ̰¡ ¾ø°Ô µÈ´Ù.
2176                //
2177                // À̹ø¿¡ Ãß°¡µÈ ä³ÎÀÎÁö, ÀÌÀü¿¡ Ãß°¡µÇ¾ú´ø ä³ÎÀÎÁö ±¸ºÐÇÒ ¼ö ÀÖÀ¸¸é ÁÁÀ½.
2178                // fresh field¸¦ Ȱ¿ëÇÑ´Ù.
2179
2180                if (target->Prog_number == m->Prog_number)
2181                {
2182                        dprint(2, "    previous ch found. overwrite to old one.\n");
2183                }
2184                else
2185                {
2186                        if (target->fresh == 0)
2187                        {
2188                                // ÀÌ targetÀº ¿¹Àü DBÀ̹ǷΠ±×³É overwrit ÇØ¹ö¸®ÀÚ.
2189                                dprint(2, "    pn# mismatch, %d!=%d, but overwrite with new info\n",
2190                                                target->Prog_number, m->Prog_number);
2191                        }
2192                        else
2193                        {
2194                                // targetÀº ¹æ±Ý Àü¿¡ Ãß°¡µÈ ½Å±Ô ä³ÎÀ̹ǷΠÀ̹ø Á¤º¸¸¦ ¹ö¸®ÀÚ.
2195                                dprint(2, "   pn# mismatch. %d != %d, ignore this subchannel\n",
2196                                                target->Prog_number, m->Prog_number);
2197                                status = statusChannelDuplicated;
2198                                goto label_exit;
2199                        }
2200                }
2201
2202                m->csd     = target->csd;
2203                m->num_csd = target->num_csd;
2204                m->max_csd = target->max_csd;
2205
2206                *target = *m;
2207                target->Uid = get_new_mcm_id(); // cafrii 060726 add
2208        }
2209       
2210
2211#if SUPPORT_CSD_UPDATE
2212        if (xcnd)   // cafrii 041126 add
2213        {
2214                dprint(2, "  update_csd_entry: size %d\n", xcnd->long_channel_name_length);
2215                status = DMW_CDB_UpdateCsdEntry(&target->csd, &target->num_csd, &target->max_csd,
2216                                                CSD_TAG_EXTENDED_NAME, xcnd->long_channel_name_length, xcnd->long_channel_name);
2217               
2218                if (status) {
2219                        if (status != statusNotChanged)
2220                                dprint(0, "!! update_vct_subchannel: long name tag update err %d\n", status);
2221                }
2222        }
2223#endif // SUPPORT_CSD_UPDATE
2224
2225        target->fresh = 1; // cafrii 060724 add
2226                // À̹ø¿¡ »õ·Ó°Ô updateµÈ DB entryÀÓÀ» ³ªÅ¸³½´Ù.
2227
2228        p->processed = TRUE; // cafrii 060724 move position here
2229
2230        if (ppmcm)
2231                *ppmcm = target;
2232
2233        status = statusOK;
2234
2235label_exit:
2236
2237        if (xcnd)
2238                FreeMpegDescriptor(xcnd);
2239               
2240        return status;
2241}
2242
2243
2244//------------------------------------------------------
2245
2246
2247STATUS update_vct(ChannelScanContext *ctx)
2248{
2249        STATUS status = statusOK;
2250        int i = 0;
2251        MCM_DB_T *pmcm;
2252        xvctPtr_t vct = ctx->xvct;
2253        int pass;
2254        ScanNewChannelCbParam cbparam;
2255
2256        // cafrii 070130 add for new callback prototype
2257        memset(&cbparam, 0, sizeof(cbparam));
2258        cbparam.fn_lookup_mj_mn = (BOOL (*)(int, int))find_mcm_major_minor;
2259
2260        if (vct == NULL)
2261                return statusPSIPError;
2262
2263        if (vct->numChannels <= 0) {
2264                dprint(0, "!! VCT has 0 channel!\n");
2265                return statusPSIPError;
2266        }
2267
2268        if (vct->channel == NULL) {
2269                dprint(0, "!! [%d] NULL channel in VCT!\n", i);
2270                return statusPSIPError;
2271        }
2272       
2273        dprint(2, "update VCT. total %d channel. signal %d\n", vct->numChannels, ctx->signal_strength);
2274
2275        if (ctx->pat && ctx->pat->transport_stream_id != vct->transport_stream_id) {
2276                dprint(0, "!! pat tsid 0x%x != vct tsid 0x%x\n", 
2277                                ctx->pat->transport_stream_id, vct->transport_stream_id);
2278        }
2279
2280        // cafrii 050802 add
2281        for (i=0; i<vct->numChannels; i++) 
2282                vct->channel[i].processed = FALSE;
2283                // °¢ subchannel º°·Î process ¿©ºÎ¸¦ ±â¾ïÇÏ´Â flag.
2284                // óÀ½¿¡´Â default·Î FALSEÀ̰í, 󸮵Ǹé TRUE·Î ¼³Á¤µÈ´Ù.
2285
2286
2287        // ---------- first pass --------------
2288
2289        // VCTÀÇ ¸ðµç ä³ÎÀ» MCM¿¡ ¸ðµÎ updateÇÑ´Ù.
2290        //
2291        // cafrii 070130 add, use 2-pass mode
2292        //
2293        for (pass=0; pass<2; pass++)
2294        {
2295                for (i=0; i<vct->numChannels; i++) 
2296                {
2297                        pmcm = 0;  // user¿¡°Ô event callbackÀ» Çϱâ À§ÇØ, ÇöÀç ¼öÁýµÈ mcm Á¤º¸°¡ ÇÊ¿äÇÏ´Ù.
2298                       
2299                        if (ctx->fnCheck && ctx->fnCheck()) {
2300                                //dprint(2, "\t channel scan cancelled!!\n");
2301                                status = statusCancelled;
2302                                goto label_end_scan;  // cafrii 060617 fix memory leak
2303                        }
2304
2305                        // cafrii 070130 add
2306                        //  1st scan, #1~999 processed. 2nd scan, #1000+ processed
2307                        //
2308                        if (pass == 0 && vct->channel[i].program_number > 999) 
2309                                continue;
2310                        if (pass == 1 && vct->channel[i].program_number <= 999)
2311                                continue;
2312
2313                        if ((ctx->flag & CBTF_IgnoreNtscInVct) && vct->channel[i].modulation_mode == 1) { // 1:Analog
2314                                if (!pass) dprint(1, " [%d] analog channel! ignored by user\n", i);
2315                                continue;  // If this channel is analog, skip it.
2316                        }
2317
2318                        status = update_vct_subchannel(ctx, vct->transport_stream_id, 
2319                                                                &(vct->channel[i]), vct->is_cvct, &pmcm);
2320
2321                        if (status == statusCancelled) // cafrii 081006 add
2322                                goto label_end_scan;
2323                               
2324                        if (1) {
2325                                if (status == statusOK) {
2326                                        //print_mcm();
2327                                        cbparam.ucm = pmcm;
2328                                        send_event_message(evtNewChannel, (UINT32)&cbparam);
2329                                        // »õ·Î updateÇÑ mcm item Æ÷ÀÎÅ͸¦ ³Ñ°ÜÁØ´Ù.
2330                                }
2331                                else {
2332                                        // ¼³·É ÇÑ Ã¤³ÎÀÌ À߸øµÇ¾ú´Ù°í ÇÏ´õ¶óµµ
2333                                        // ´ÙÀ½ ä³ÎÀº ±¦ÂúÀ» ¼ö ÀÖÀ¸¹Ç·Î °è¼Ó ÁøÇàÇØ¾ß ÇÑ´Ù.
2334                                }
2335                        }
2336                       
2337                } // for
2338        }
2339
2340label_end_scan:
2341
2342        return status;
2343}
2344
2345
2346
2347
2348#if COMMENT
2349___________________(){}
2350#endif
2351
2352//
2353// ChannelScanContext ³»ÀÇ °¢Á¾ Å×À̺íµéÀ» ¸ðµÎ free½ÃŲ´Ù.
2354//
2355//
2356static void free_tables_in_context(ChannelScanContext *ctx)
2357{
2358        int i;
2359       
2360        Dmc_FreeAtscTable(&ctx->xvct);
2361       
2362        Dmc_FreeAtscTable(&ctx->pat);
2363
2364        if (ctx->pmtList) {
2365                for (i=0; i<ctx->num_programs; i++) {
2366                        Dmc_FreeAtscTable(&ctx->pmtList[i]);
2367                }
2368                DHL_OS_Free((void**)&ctx->pmtList);
2369                ctx->num_programs = 0;
2370        }
2371}
2372
2373
2374
2375
2376static STATUS download_tables(ChannelScanContext *ctx)
2377{
2378        DmcMainTables tbls;
2379        xvctPtr_t vct = NULL;
2380        STATUS status;
2381        int _second = 1000;
2382       
2383        memset(&tbls, 0, sizeof(tbls));
2384
2385        // todo..
2386        // CBTF_PsiOnlyMode ¿¡¼­´Â VCT¸¦ ÀüÇô »ç¿ëÇÏÁö ¾ÊÀ» °ÍÀ̱⠶§¹®¿¡
2387        // ´Ù¿î·Îµå ½Ãµµ¸¦ ÇÒ ÇÊ¿äÁ¶Â÷µµ ¾ø´Ù.
2388        // ±×·¯³ª ÇöÀç PAT/PMT¸¸ ´Ù¿î·Îµå ¹Þ´Â ÇÔ¼ö°¡ ¾øÀ½..
2389        //
2390
2391        status = Dmc_GetMainChannelTables(ctx->tsd, &tbls, 
2392                                                g_Timeout_VctLoading*_second/1000, ctx->fnCheck);
2393
2394        if (status == statusCancelled) {
2395                // µµÁß¿¡ Ãë¼Ò°¡ µÈ °æ¿ì¶ó ÇÏ´õ¶óµµ
2396                // ÀϺΠ¼ö½ÅµÈ tableÀÌ ÀÖÀ» ¼ö ÀÖÀ½. ÇØÁ¦½ÃÄÑ¾ß ÇÑ´Ù.
2397                Dmc_FreeMainChannelTables(&tbls);               
2398                return statusCancelled;
2399        }
2400
2401        if (g_TestAutoscanWithoutVct) {
2402               
2403                dprint(0, "**** test mode: NO VCT case, only psi available ****\n");
2404                Dmc_FreeAtscTable(&tbls.tvct);
2405                Dmc_FreeAtscTable(&tbls.cvct);
2406        }
2407       
2408        // Antenna ¸ðµå¿¡¼­´Â CVCT°¡ ¼ö½ÅÀÌ µÇ¾ú¾îµµ À̰ÍÀ» »ç¿ëÇÏÁö ¾Êµµ·Ï ÇÑ´Ù.
2409       
2410        if (tbls.cvct && g_CurChannelType == ChannelType_Cable)
2411        {
2412                status = Dmc_TranslateCvct(tbls.cvct, &vct);
2413                dprint(2, "\tCVCT found. total %d channels\n", vct->numChannels);
2414        }
2415        else if (tbls.tvct)
2416        {
2417                status = Dmc_TranslateTvct(tbls.tvct, &vct);
2418                dprint(2, "\tTVCT found. total %d channels\n", vct->numChannels);
2419        }
2420       
2421        if (tbls.tvct)
2422                FreeAtscTable(tbls.tvct);
2423        if (tbls.cvct)
2424                FreeAtscTable(tbls.cvct);
2425
2426        // context¿¡ ÇÊ¿äÇÑ table ¸ðµÎ À̵¿..
2427
2428        ctx->xvct = vct;
2429       
2430        ctx->pat = tbls.pat;
2431        ctx->num_programs = tbls.num_programs;
2432        ctx->pmtList = tbls.pmtList;
2433
2434        if (dprintable(2)) // cafrii 070117 add
2435        {
2436                char buf[100];
2437                int i, n_pmt = 0, n;
2438               
2439                n = ctx->num_programs;
2440                for (i=0; i<n; i++)     // count how many real pmt is received..
2441                        if (ctx->pmtList[i]) n_pmt++;
2442               
2443                dprint(2, "\t pat %d, pmt %d/%d\n", ctx->pat ? 1 : 0, n_pmt, ctx->num_programs);
2444               
2445                buf[0] = 0;
2446                n = min(80, ctx->num_programs);  // print max 80 pmts..
2447                for (i=0; i<n; i++)
2448                        sprintf(buf + strlen(buf), "%s%c", i%5==0 ? " " : "", ctx->pmtList[i] ? '1' : '.');
2449                        // print each pmt's existance..
2450               
2451                dprint(2, "\t rx map: %s\n", buf);
2452        }
2453       
2454        return statusOK;
2455}
2456
2457//-----------------------------------------------------
2458//  ScanCableChannel
2459//
2460//  ÄÉÀÌºí ¸ðµå¿¡¼­ ÇÑ Ã¤³ÎÀ» °Ë»öÇÑ´Ù.
2461//
2462//  bSetTuner °¡ FALSEÀ̸é Tuner setÀ» ÇÏÁö ¾Ê´Â´Ù.
2463//     caller Ãø¿¡¼­ ÀÌ¹Ì Æ©´×À» ÇÑ °æ¿ì¿¡ »ç¿ëµÈ´Ù.
2464//
2465static STATUS scan_one_channel(ChannelScanContext *ctx)
2466{
2467        //  TableÀÇ ¿ì¼±¼øÀ§´Â CVCT -> TVCT -> PSI ÀÌ´Ù.
2468        //
2469        //  ¿É¼Ç¿¡ µû¶ó¼­ Cable ȯ°æ¿¡¼­´Â TVCT¸¦ ¹«½ÃÇÒ ¼öµµ ÀÖ´Ù.
2470        //  Antenna ¸ðµå¿¡¼­´Â CVCT´Â ¹«½ÃµÈ´Ù.
2471        //
2472
2473        STATUS status = statusOK;
2474        ScanTunerSetCbParam param;
2475        BOOL bCable;
2476        ScanNewChannelCbParam cbparam;
2477
2478        memset(&cbparam, 0, sizeof(cbparam));
2479       
2480        bCable = (ctx->flag & CBTF_ChannelTypeMask) == CBTF_Cable ? TRUE : FALSE;
2481
2482
2483        dprint(1, "scan_one_channel (%s %d)\n", bCable ? "cable" : "air", ctx->cur_channel);
2484
2485
2486        //-------------------------------------------
2487        // user¿¡°Ô callbackÀ» º¸³»¼­ Æ©³Ê/Demod ¼³Á¤À» Çϵµ·Ï ÇÑ´Ù.
2488        // flag¿¡ µû¶ó skipÇÒ ¼öµµ ÀÖÀ½.
2489        //
2490
2491        memset(&param, 0, sizeof(param));
2492       
2493        if ((ctx->flag & CBTF_SkipTunerSet) == 0)
2494        {
2495                // skip optionÀÌ ¾Æ´Ñ °æ¿ì, callbackÀ» ºÒ·¯¼­ tuner ¼³Á¤À» ¼öÇàÇÑ´Ù.
2496               
2497                param.channel = ctx->cur_channel;
2498
2499                // cafrii 061219 add
2500                //   analog separate scan Áö¿ø..
2501                //
2502                if (ctx->state == CTS_RUNNING_ANALOG)   // analog only scan stage
2503                        param.flag = (ctx->flag & ~(CBTF_8VSB | CBTF_QAM)); // remove digital flag
2504               
2505                else if (ctx->state == CTS_RUNNING_DIGITAL) // digital only scan stage
2506                        param.flag = (ctx->flag & ~CBTF_NTSC);  // remove analog flag
2507
2508                else
2509                        param.flag = ctx->flag;  // pass all flag untouched
2510               
2511                param.one_channel_scan = ctx->quick_scan; // app ¿¡¼­ ÀûÀýÇÑ ´ëÀÀÀ» ÇÒ ¼ö ÀÖµµ·Ï quick scan ÀÓÀ» ¾Ë·ÁÁÜ.
2512                param.chkfn   = ctx->fnCheck;
2513                param.return_value = statusNotImpl;
2514               
2515                send_event_message(evtScanTunerSet, (UINT32)&param); // execute tuner set
2516
2517                if (param.return_value == statusCancelled)
2518                        goto label_cancelled;
2519
2520                if (param.return_value == statusNotImpl) {
2521                        dprint(0, " !! scan tune callback not implemented\n");
2522
2523                #if USE_DEFAULT_CB_FN
2524                        SCB_TunerSet(&param);
2525                        if (param.return_value == statusCancelled)
2526                                goto label_cancelled;
2527                #else
2528                        status = statusNotImpl;
2529                        goto label_end_scan;
2530                #endif
2531
2532                }
2533        }
2534        else
2535        {
2536                SCB_SkipTunerSet(&param);
2537        }
2538
2539        if (param.return_value == statusCancelled)
2540                goto label_cancelled;
2541
2542        if (! param.locked) {
2543                dprint(3, "  !! rf signal unlocked..\n");
2544                goto label_end_scan;
2545        }
2546
2547        // cafrii 060814 add
2548        // analog¸¦ ÁöÁ¤ÇÏÁö ¾Ê¾Ò´Âµ¥ analog¶ó¸é unlock°ú °°À½.
2549        if ((ctx->flag & CBTF_NTSC) == 0 && param.mode == Modulation_NTSC) {
2550                dprint(3, "  !! ntsc detected..\n");
2551                goto label_end_scan;
2552        }
2553       
2554        // ¾Æ³¯·Î±× ä³ÎÀÎÁö ¸ÕÀú üũ
2555        //
2556        if (param.mode == Modulation_NTSC)
2557        {
2558                MCM_DB_T *pmcm = NULL;
2559
2560                dprint(2, "  Analog signal locked.  offset %d, strength %d\n", 
2561                                        param.freq_offset, param.strength);
2562               
2563                status = update_mcm_analog(ctx->cur_channel, param.strength, 
2564                                                        param.freq_offset, &pmcm);
2565                        // possible err: statusOutOfMemory
2566                       
2567                if (status == statusOK) {
2568                        //print_mcm();
2569                        cbparam.ucm = pmcm;
2570                        send_event_message(evtNewChannel, (UINT32)&cbparam);
2571                }
2572                goto label_end_scan;
2573        }
2574       
2575        // ÀÌÇÏ µðÁöÅРä³ÎÀÓ.
2576
2577        ctx->freq_offset           = param.freq_offset;
2578        ctx->tuner_modulation_mode = param.mode;
2579        ctx->signal_strength       = param.strength;
2580       
2581        dprint(2, "   digital signal locked! offset %d, mode %d, strength %d\n",
2582                                        param.freq_offset, param.mode, param.strength);
2583
2584        if (ctx->fnCheck && ctx->fnCheck())
2585                goto label_cancelled;
2586
2587        //-------------------------------------------
2588        dprint(2, "   Start loading VCT, PSI..\n");
2589
2590        status = download_tables(ctx);
2591
2592        if (status == statusCancelled)
2593                goto label_cancelled;
2594               
2595        if (ctx->flag & CBTF_PsiOnlyMode)
2596                goto label_psi_scan;
2597
2598        status = update_vct(ctx);
2599
2600        if (status == statusCancelled)
2601                goto label_cancelled;
2602
2603        // cafrii 060808, vct¿¡¼­ failÀ̸é flag¿¡ »ó°ü ¾øÀÌ psi scanÀ» ¼öÇà.
2604        if (status)
2605                goto label_psi_scan;
2606               
2607        if (ctx->flag & CBTF_ForcePSI)
2608                // CVCT¸¦ ¼º°øÀûÀ¸·Î ¼ö½ÅÇß´õ¶óµµ flag¿¡ µû¶ó PSI¸¦ Ãß°¡Çϱ⵵ ÇÑ´Ù.
2609                goto label_psi_scan;
2610        else 
2611                goto label_end_scan;
2612
2613label_psi_scan:
2614
2615        if (ctx->fnCheck && ctx->fnCheck())
2616                goto label_cancelled;
2617
2618        status = update_psi(ctx);
2619       
2620        goto label_end_scan;
2621
2622
2623label_cancelled:
2624        dprint(2, "\tchannel scan cancelled!!\n");
2625        status = statusCancelled;
2626
2627label_end_scan:
2628
2629        free_tables_in_context(ctx);
2630
2631        return status;
2632}
2633
2634
2635static STATUS process_mcm(BOOL bSelectMaxChannel)
2636{
2637        // MCM Á¤º¸¸¦ ÀÌ¿ëÇÏ¿© UCMÀ» ¸¸µç´Ù.
2638        // ÀÌ ÇÔ¼ö´Â Ç×»ó ChannelScan ŽºÅ©¿¡¼­¸¸ ºÒ¸®µµ·Ï µÇ¾î ÀÖÀ¸¸ç, staticÀÌ´Ù.
2639        // ÀÌ ÇÔ¼ö¿Í ºñ½ÁÇÑ ¿ªÇÒÀ» ÇÏ´Â ÇÔ¼ö·Î update_current_scan() ÇÔ¼ö°¡ ÀÖ´Ù.
2640        //   À̰ÍÀº ÇöÀç ä³Î¿¡ ´ëÇØ¼­ background¿¡¼­ ä³Î ½ºÄµÀ» ÇÏ¿© update¸¦ ÇÏ´Â ÇÔ¼öÀÌ´Ù.
2641        //
2642        // Áߺ¹µÇ´Â ä³ÎÀº signal strength °ªÀ» ºñ±³ÇÏ¿© Çϳª¸¸ ¼±ÅÃÇÑ´Ù. "´ëǥä³Î¼±ÅÃ"
2643        //
2644        //
2645        // ÁÖÀÇ! UCM¿¡µµ ¸ðµç ä³Î Á¤º¸°¡ µé¾î°¡¾ß ÇÑ´Ù.
2646        // UCMÀº Major/Minor¸¦ ±âÁØÀ¸·Î ¿À¸§Â÷¼øÀ¸·Î Á¤·ÄµÇ¾î¾ß ÇÑ´Ù.
2647
2648        print_mcm();
2649
2650        // 1. MCMÀ» Á¤·ÄÇÑ´Ù. updateÇϸ鼭 Á¤·ÄÀÌ µÇ¾î ÀÖ´Â »óŶó¸é ¿©±â¼­ ÇÒ ÇÊ¿ä´Â ¾ø´Ù.
2651        dprint(2, "*** Sort MCM..\n");
2652        sort_mcm();
2653
2654        print_mcm();
2655
2656        // cafrii 050721 add condition
2657        if (bSelectMaxChannel) {
2658                // 2. µ¿ÀÏÇÑ Mj/Mn/Vf Á¶ÇÕÀÌ ÀÖÀ¸¸é ½ÅÈ£ ¼¼±â°¡ °¡Àå Å« °ÍÀ» ¼±ÅÃÇϰí,
2659                //     ³ª¸ÓÁö´Â skip flag¸¦ ¼¼ÆÃÇÑ´Ù.
2660                dprint(2, "*** Select favorite channels.\n");
2661                select_max_mcms();
2662                print_mcm();
2663        }
2664
2665        // 3. UCMÀ¸·Î º¹»çÇÑ´Ù. (skip flag ¼¼ÆÃµÈ °Í Æ÷ÇÔ)
2666        dprint(2, "*** Generate UCM.\n");
2667        copy_to_ucm();
2668
2669        // 4. mcm Á¦°Å.
2670        free_all_mcm();
2671
2672        return statusOK;
2673}
2674
2675
2676void post_process_ucm(int flag)
2677{
2678        int i;
2679       
2680        DMW_MSC_LockUcm();
2681
2682        for (i=0; i<g_UCM_number; i++) 
2683        {
2684                // scrambled channelÀº °¨Ã߾ º¸ÀÌÁö ¾Êµµ·Ï..
2685                //
2686
2687#if 1
2688        /* neverdai 100721 ÃßÈÄ¿¡ koreaview¿ë ½ºÆ®¸²°ú hidden ½ºÆ®¸²ÀÇ ±¸ºÐÀ» À§ÇØ
2689    Ãß°¡ÀÇ Á¶°Ç(PID µî)À» Ãß°¡ÇÑ´Ù. */
2690                if((flag & CBTF_IncludeSpecialHidden) && g_UCM[i].hidden) {
2691                        g_UCM[i].hidden=FALSE;
2692                }
2693#endif
2694                if (g_UCM[i].scrambled)
2695                        g_UCM[i].Skipped = TRUE;
2696
2697                // cafrii 060725 add
2698                else if (g_UCM[i].hidden)
2699                        g_UCM[i].Skipped = TRUE;
2700
2701                // cafrii 060725 add
2702                // cafrii 070103 bugfix. only for digital channel..
2703                else if (g_UCM[i].Service_type != 0 &&
2704                        g_UCM[i].Pcr_pid == 0 && g_UCM[i].Video_pid == 0 && g_UCM[i].Audio_pid == 0)
2705                        g_UCM[i].Skipped = TRUE;
2706        }
2707
2708        DMW_MSC_UnlockUcm();
2709}
2710
2711
2712
2713
2714void decide_channel_range(UINT32 *bitmap)
2715{
2716        // find min/max, number of channel
2717        //
2718        int min_ch = 999;
2719        int max_ch = 0;
2720        int num_ch = 0;
2721        int i;
2722       
2723        ChannelScanContext *ctx = get_scan_context();
2724       
2725        for (i=0; i<CHANNEL_BMP_SIZE; i++)
2726                ctx->channel_bmp[i] = bitmap[i];
2727       
2728        for (i=0; i<160; i++)
2729        {
2730                if (ctx->channel_bmp[i/32] & (0x80000000 >> (i%32)))
2731                {
2732                        if (i < min_ch) min_ch = i;
2733                        if (i > max_ch) max_ch = i;
2734                        num_ch ++;
2735                }
2736        }
2737       
2738        if (num_ch)
2739        {
2740                ctx->start_channel = min_ch;
2741                ctx->end_channel = max_ch;
2742                ctx->total_channel = num_ch;
2743        }
2744        else
2745                ctx->start_channel = ctx->end_channel = ctx->total_channel = 0;
2746
2747        dprint(2, "\tscan channel %d ~ %d, total %d channels   %s\n", 
2748                        ctx->start_channel, ctx->end_channel, ctx->total_channel,
2749                        max_ch - min_ch + 1 != num_ch ? "(SparseMode)" : "");
2750                       
2751}
2752
2753
2754
2755static void notify_scan_started(ChannelScanContext *ctx)
2756{
2757        ScanStartedCbParam ssparam;
2758        memset(&ssparam, 0, sizeof(ssparam));
2759       
2760        ssparam.flag = ctx->flag;
2761        ssparam.stage = 
2762                        ctx->state == CTS_RUNNING_ANALOG ? ScanAnalogStage : 
2763                        ctx->state == CTS_RUNNING_DIGITAL ? ScanDigitalStage : ScanOnePassStage;
2764                        // cafrii 070118 bugfix. ScanDigitalStage was missing.
2765                       
2766        send_event_message(evtScanStarted, (UINT32)&ssparam);
2767       
2768#if USE_DEFAULT_CB_FN
2769        SCB_ScanStart(&ssparam);
2770#endif
2771
2772}
2773
2774static void notify_scan_completed(ChannelScanContext *ctx, BOOL bUpdate, ScanStopMode nStopMode)
2775{
2776        ScanCompleteCbParam scparam;
2777
2778        memset(&scparam, 0, sizeof(scparam));
2779       
2780        scparam.bStoppedByUser = nStopMode == eScanStop_Completed ? FALSE : TRUE;
2781        scparam.bUpdate = bUpdate ? TRUE : FALSE;
2782        scparam.flag = ctx->flag;
2783
2784        scparam.stage = ctx->state == CTS_RUNNING_ANALOG ? ScanAnalogStage : ScanOnePassStage;
2785
2786        send_event_message(evtScanComplete, (UINT32)&scparam);
2787
2788#if USE_DEFAULT_CB_FN
2789        SCB_ScanEnd(&scparam);
2790#endif
2791
2792}
2793
2794
2795// ä³Î °Ë»ö ÀÛ¾÷À» Á¾·áÇÑ´Ù. ¾Æ·¡ µÎ ±ºµ¥¼­ ºÒ¸°´Ù.
2796// - ScanTask¿¡¼­ ä³Î °Ë»öÀÌ Á¤»óÀûÀ¸·Î ¸ðµÎ ¿Ï·áÇÑ °æ¿ì.
2797// - User°¡ ScanStop (¶Ç´Â ´Ù¸¥ command)À» È£ÃâÇÏ¿© Áß°£¿¡ Áß´ÜµÈ °æ¿ì.
2798// µÎ °æ¿ì ó¸® °úÁ¤Àº µ¿ÀÏÇϹǷΠÀÌ ÇÔ¼ö¿¡¼­ ó¸®ÇÑ´Ù.
2799//
2800static STATUS scan_completed(ChannelScanContext *ctx, BOOL bUpdate, ScanStopMode nStopMode)
2801{
2802        if (bUpdate)
2803        {
2804                // NoTE!!!
2805                // ÇöÀç±îÁö scanµÈ µ¥ÀÌÅ͸¦ Á¤¸®Çؼ­ ³Ñ°ÜÁØ´Ù.
2806                // partialchannelscan()¿¡¼­µµ ´Ù ³¡³ª¸é ÀÚµ¿À¸·Î processmcmÀ» ÇÑ´Ù.
2807                // ±×·¯³ª ¸ðµÎ °°Àº task¿¡¼­ ÀÌ·ç¾îÁö¹Ç·Î Å« ¹®Á¦°¡ µÇÁö ¾Ê´Â´Ù.
2808                //
2809                // À̰÷¿¡¼­ process_mcm()À» ¿Ï·áÇϸé mcmÀº ó¸® ÈÄ »ç¶óÁú °ÍÀ̰í,
2810                // context°¡ IDLEÀ̹ǷΠ´õÀÌ»ó PartialChannelScan()ÀÌ ºÒ¸®Áö ¾Ê´Â´Ù.
2811
2812                process_mcm((ctx->flag & CBTF_DontSelectMaxChannel) == 0 ? TRUE : FALSE);
2813               
2814                post_process_ucm(ctx->flag);
2815               
2816        }
2817        else {
2818                // discard channel info..
2819                free_all_mcm();
2820        }
2821        unlock_mcm();
2822
2823        notify_scan_completed(ctx, bUpdate, nStopMode);
2824
2825        ctx->state = CTS_IDLE;
2826
2827        return statusOK;
2828}
2829
2830
2831BOOL scan_check_cancel()
2832{
2833        // channel scan ÀÛ¾÷À» cancelÇÒ ¼ö ÀÖ´Â °æ¿ì´Â
2834        //
2835        // - scan stop command°¡ ¿À´Â °æ¿ì
2836        // - cancel ¸í·ÉÀÌ ¿À´Â °æ¿ì (cancel Q)
2837        //
2838        BOOL bCancel = doDmc_CheckCancel();
2839        BOOL bStop = doDmc_CheckMsgExist(cmdScanStop);
2840
2841        return (bCancel || bStop);
2842}
2843
2844
2845
2846
2847#if COMMENT
2848___________________(){}
2849#endif
2850
2851
2852
2853BOOL SCN_ScanRunning(void)
2854{
2855        ChannelScanContext *ctx;
2856       
2857        ctx = get_scan_context();
2858
2859        if (ctx->state != CTS_IDLE)
2860                return TRUE;
2861        else
2862                return FALSE;
2863}
2864
2865void SCN_ScanInit(void)
2866{
2867        ChannelScanContext *ctx;
2868       
2869        ctx = get_scan_context();
2870       
2871        ctx->state = CTS_IDLE;
2872       
2873}
2874
2875
2876STATUS SCN_ScanStart(DmcMessage *pMsg)
2877{
2878        ChannelScanContext *ctx;
2879        ChannelScanCmdParam *param = (ChannelScanCmdParam *)pMsg->param; // msgparam;
2880       
2881        UINT32 flag = param->flag;
2882        ChannelScanCallback pfnCallback = param->pfnCallback;
2883        UINT32 *chbmp = param->bitmap;
2884       
2885        ctx = get_scan_context();
2886       
2887        dprint(1, "ChannelScanStart: (flag 0x%x, callback 0x%x)\n", flag, pfnCallback);
2888        if (ctx->state != CTS_IDLE)
2889                dprint(2, "\t!! not stopped state. parameter will be overwritten.\n");
2890
2891        // some init code here..
2892        ctx->state = CTS_IDLE;
2893       
2894        ctx->tsd = Dmc_GetCurrentTsd();
2895       
2896        ctx->fnCheck = scan_check_cancel;
2897                // register function to check cancel
2898
2899        ctx->flag = ctx->original_flag = flag;
2900        ctx->fnCallback = pfnCallback;
2901
2902        ctx->quick_scan = FALSE;
2903
2904        ctx->cable_system = g_CableSystem;
2905                // ¿ø·¡ÀÇ cable system typeÀ» backupÇÑ´Ù.
2906                // µµÁß¿¡ AutoscanÀÌ cancel µÉ ¶§¿¡´Â ÀÌ cable systemÀ¸·Î ´Ù½Ã º¹±ÍÇØ¾ß Çϱ⠶§¹®.
2907       
2908        if ((ctx->flag & CBTF_ChannelTypeMask) == CBTF_Air)
2909                DMW_CDB_InitializeChannelLib(ChannelType_Air, 0);
2910        else
2911                DMW_CDB_InitializeChannelLib(ChannelType_Cable, 0);
2912       
2913        // todo
2914        // ¹«Á¶°Ç standard·Î ½ÃÀÛÇØ¾ß ÇÏ´Â°Í ¾Æ´Ñ°¡?
2915        DMW_HAL_SetChannelStandard(ctx->cable_system);
2916
2917        dprint(2, "\tchannel library initialized to '%s', frqStd %d '%s'\n", 
2918                                ChannelTypeString(g_CurChannelType), 
2919                                g_CableSystem, FreqStdString(ctx->cable_system));
2920                // ÁÖÀÇ!!
2921                // ÇöÀçÀÇ channel type°ú ´Ù¸¥ °ªÀ» ÀÎÀÚ·Î ÇÏ¿© autoscanÀ» ½ÃÀÛÇϸé
2922                // ±âÁ¸ÀÇ ucmÀº ¸ðµÎ »èÁ¦µÇ¹Ç·Î ÁÖÀÇÇÑ´Ù.
2923                //  ¿¹) ÇöÀç Air channelÀε¥, ScanStart(CBTF_Cable, ..) Çϸé
2924                //      cable ¸ðµå·Î º¯°æµÇ¸é¼­ ÇöÀç Air¿ë UCMÀº ¸Þ¸ð¸®¿¡¼­ Á¦°ÅµÇ¾î ¹ö¸°´Ù.
2925
2926       
2927        // ½ÃÀÛä³Î ¹øÈ£¿Í ³¡ ä³Î ¹øÈ£¸¦ °áÁ¤ÇÑ´Ù.
2928        //
2929        decide_channel_range(chbmp);
2930       
2931        ctx->cur_channel = ctx->start_channel;
2932        ctx->channel_index = 0;
2933       
2934        //ctx->flag &= ~CBTF_EnableNewChannelInUpdateMode;
2935                        // autoscan ¸ðµå¿¡¼­´Â ³»ºÎ "´ëǥä³Î¼±ÅÃ" ¾Ë°í¸®ÁòÀÌ Àû¿ëµÈ´Ù.
2936
2937        // free caller memory
2938        Dmc_ParamHeapDeallocator((UINT32)pMsg->param);
2939                       
2940        dprint(2, "\tlock mcm..\n");
2941        if (lock_mcm(1000) != statusOK) {
2942                dprint(0, "!! mcm is already locked by other task %x\n", get_mcm_owner());
2943                return statusError;
2944        }
2945
2946        ucm_to_mcm();   // ±âÁ¸ÀÇ UCMÀ» ±â¹ÝÀ¸·Î MCMÀ» ±¸¼ºÇÑ´Ù.
2947                                // »õ·Î ¹ß°ßµÈ ä³ÎÀº MCM¿¡ updateµÉ °ÍÀÌ´Ù.
2948
2949        if ((ctx->flag & CBTF_NTSC) && 
2950                (ctx->flag & CBTF_AnalogSeparateScan)) {
2951                dprint(2, "\tanalog separate scan mode\n");
2952                 ctx->state = CTS_RUNNING_ANALOG;
2953        }
2954        else
2955                ctx->state = CTS_RUNNING;
2956
2957        notify_scan_started(ctx);
2958       
2959        return statusOK;
2960}
2961
2962
2963
2964//
2965//  PartialChannelScan
2966//
2967//  ÀÌ ÇÔ¼ö´Â ChannelScan task°¡ °Ë»ö ÀÛ¾÷À» ½ÃÀÛÇÑ ÀÌÈÄ¿¡
2968//  user·ÎºÎÅÍ command message¸¦ ¹ÞÁö ¾Ê´Â idle »óÅ¿¡¼­ ÁÖ±âÀûÀ¸·Î ºÒ¸°´Ù.
2969//  ä³Î °Ë»öÀ» ´Ü°èÀûÀ¸·Î ¼öÇàÇÑ´Ù.
2970//
2971void SCN_ScanTask(void)
2972{
2973        STATUS status;
2974        ChannelScanContext *ctx = get_scan_context();
2975        ScanProgressCbParam param;
2976        ScanStage stage;
2977       
2978        //dprint(0, "PartialChannelScan (state %d, channel %d)\n",
2979        //                                              ctx->state, ctx->cur_channel);
2980
2981        if (ctx->state == CTS_IDLE) // Idle »óŶó¸é ÁøÇà ¾ÈÇÔ.
2982                return;
2983
2984        if (ctx->cur_channel < ctx->start_channel || ctx->cur_channel > ctx->end_channel)
2985        {
2986                // ¿¡¿Ü»óȲÀÓ..
2987                dprint(0, "!! PartailChannelScan(): invalid channel index %d!\n", ctx->cur_channel);
2988                ctx->state = CTS_IDLE;
2989                return;
2990        }
2991
2992        if (ctx->state == CTS_RUNNING_ANALOG)
2993                stage = ScanAnalogStage;
2994        else if (ctx->state == CTS_RUNNING_DIGITAL)
2995                stage = ScanDigitalStage;
2996        else
2997                stage = ScanOnePassStage;
2998
2999        dprint(1, "\n-------------- RF %d (%s)-------------------\n", 
3000                        ctx->cur_channel, ScanStageString(stage));
3001
3002               
3003        // rf ä³Î °Ë»ö ½ÃÀÛ event notify
3004        //
3005        memset(&param, 0, sizeof(param));
3006        param.current_rf = ctx->cur_channel;
3007        param.channel_idx = ctx->channel_index;
3008        param.total_channel = ctx->total_channel;
3009        param.after_scan = 0;
3010        param.stage = stage;
3011       
3012        send_event_message(evtOnProgress, (UINT32)&param);
3013       
3014        status = scan_one_channel(ctx);
3015
3016        // rf ä³Î °Ë»ö Á¾·á event notify
3017        //
3018        memset(&param, 0, sizeof(param));
3019        param.current_rf = ctx->cur_channel;
3020        param.channel_idx = ctx->channel_index;
3021        param.total_channel = ctx->total_channel;
3022        param.after_scan = 1;
3023        param.stage = stage; // cafrii 061220 add bugfix
3024       
3025        send_event_message(evtOnProgress, (UINT32)&param);
3026       
3027        if (ctx->cur_channel >= ctx->end_channel)
3028        {
3029                if (ctx->state == CTS_RUNNING_ANALOG) 
3030                {
3031                        dprint(2, "# Analog end. now scan digital..\n");
3032
3033                        notify_scan_completed(ctx, FALSE, eScanStop_Completed);
3034
3035                        ctx->cur_channel = ctx->start_channel;
3036                        ctx->channel_index = 0;
3037                        ctx->state = CTS_RUNNING_DIGITAL;
3038
3039                        notify_scan_started(ctx);                       
3040                }
3041                else 
3042                {
3043                        // ÀÌ°Ô ¸¶Áö¸· ä³ÎÀ̾úÀ¸¹Ç·Î, ´Ù ³¡³­°ÍÀÌ´Ù.
3044                        dprint(2, "# End channel. postprocess..\n");
3045                       
3046                        scan_completed(ctx, TRUE, eScanStop_Completed); // update TRUE
3047                }
3048        }
3049        else if (status == statusCancelled) 
3050        {
3051                // command¿¡ ÀÇÇØ cancelÀÌ µÈ °æ¿ìÀ̹ǷÎ
3052                // ´ÙÀ½ command¿¡ ÀÇÇØ stop 󸮰¡ ÁøÇàµÈ´Ù. ¿©±â¼­´Â ±×³É ÁøÇà.
3053               
3054                // note!!
3055                // ´ÙÀ½ command°¡ ScanStopÀÌ ¾Æ´Ï¶ó ´Ù¸¥ ¸í·É (¿¹: tuning..) À̶ó¸é
3056                // scan Á¾·á¸¦ ¿©±â¼­ ÇØ¾ß ÇÑ´Ù.
3057               
3058                if (doDmc_CheckMsgExist(cmdScanStop) == FALSE) {
3059                        dprint(0, "!! next command is not scanstop! do emergency stop here\n");
3060                        scan_completed(ctx, TRUE, eScanStop_Abnormal);
3061                }
3062        }
3063        else 
3064        {
3065                int i;
3066
3067                // channel bitmapÀ» Á¶»çÇÏ¿© ´ÙÀ½ ä³ÎÀ» ã´Â´Ù.
3068                //             
3069                for (i=ctx->cur_channel+1; i<=ctx->end_channel; i++) {
3070                        if (ctx->channel_bmp[i/32] & (0x80000000 >> i%32))
3071                                break;
3072                }
3073               
3074                ctx->cur_channel = i;
3075                ctx->channel_index++;
3076               
3077                dprint(2, "\tnext channel: [%d] rf %d ..\n", 
3078                                        ctx->channel_index, ctx->cur_channel);
3079        }
3080
3081        return;
3082}
3083
3084
3085STATUS SCN_ScanStop(DmcMessage *pMsg)
3086{
3087        ChannelScanContext *ctx;
3088        BOOL bUpdate = pMsg->param;
3089       
3090        ctx = get_scan_context();
3091       
3092        dprint(2, "command: ScanStop. bUpdate %x\n", bUpdate);
3093        if (ctx->state == CTS_IDLE) {
3094                dprint(0, "!! scan already stopped.\n");
3095                //return statusInvalidState;
3096                return statusOK;  // ÀÌ¹Ì Á¾·áµÈ °ÍÀ̹ǷÎ..
3097        }
3098       
3099        return scan_completed(ctx, bUpdate, eScanStop_StopByUser);
3100}
3101
3102
3103STATUS SCN_ScanOneChannel(DmcMessage *pMsg)
3104{
3105        ChannelScanContext *ctx;
3106        int nUid = 0, *uidBuf = NULL;
3107        STATUS status;
3108        ChannelScanCmdParam *param = (ChannelScanCmdParam *)pMsg->param;
3109        //UINT32 userparam;
3110
3111        ctx = get_scan_context();
3112
3113        dprint(1, "ChannelScanOneChannel:\n");
3114       
3115        if (ctx->state != CTS_IDLE) {
3116                dprint(0, "!! not stopped state. ignored\n");
3117                status = statusInvalidState;
3118                goto label_end;
3119        }
3120       
3121        ctx->tsd = Dmc_GetCurrentTsd();
3122
3123        ctx->cur_channel = ctx->start_channel = ctx->end_channel = param->rf;
3124                // ¿©±â¼­ ÁöÁ¤ÇÏ´Â cur_channel °ªÀÌ ½ÇÁ¦·Î DB¿¡ µé¾î°¡°Ô µÉ ä³Î ¹øÈ£Àε¥,
3125                // ²À Á¤È®ÇÑ °ªÀ» ÁöÁ¤ÇØ¾ß ÇÑ´Ù.
3126
3127        ctx->fnCallback = param->pfnCallback; // event callback
3128        ctx->fnCheck = Dmc_CheckCancel; // cafrii 060808 add
3129       
3130        ctx->flag = param->flag;
3131        ctx->original_flag = param->flag;
3132
3133        ctx->quick_scan = TRUE;
3134       
3135        //ctx->flag |= CBTF_IgnoreRemoteChannelInVct;
3136                // ÀÌ Ç÷¡±×´Â Ç×»ó TRUE·Î ÇÏÀÚ!!
3137
3138        //userparam = param->userparam;
3139                // scan callback¿¡ Àü´ÞµÇ´Â userparamÀ¸·Î
3140                // complete callback¿¡ Àü´ÞµÇ´Â pMsg->userparam°ú´Â ´Ù¸£´Ù.
3141       
3142        // ÀÌÁ¦ paramÀº ¸ðµÎ ´Ù »ç¿ëÇßÀ¸¹Ç·Î ÇØÁ¦ÇÑ´Ù.
3143        // ³ªÁß¿¡ ÇÊ¿äÇÑ º¯¼ö´Â stack¿¡ ÀúÀåÀ» ÇØ ³õ´Â´Ù.
3144        //
3145        Dmc_ParamHeapDeallocator((UINT32)pMsg->param);
3146
3147        if (lock_mcm(1000) != statusOK) {
3148                dprint(0, "!! update_cur_scan: other task %x owns mcm\n", get_mcm_owner());
3149                //return statusOutOfResource;  // ÇöÀç mcm resource¸¦ »ç¿ëÇÒ ¼ö ¾øÀ½.
3150                status = statusOutOfResource; // cafrii 060627 bugfix
3151                goto label_end;
3152        }
3153
3154        free_all_mcm();
3155
3156        status = scan_one_channel(ctx);
3157       
3158        if (status == statusCancelled)
3159                goto label_end;
3160
3161        // cafrii 070117 add.. Ưº°È÷ error·Î report¸¦ ÇÏÁö ¾Ê´Â´Ù.
3162        status = statusOK; 
3163       
3164        dprint(2, "*** Sort MCM..\n");
3165        sort_mcm();
3166        print_mcm();
3167
3168        // update ÇÔ¼ö¿¡¼­´Â max select¸¦ ÀüÇô ¾ÈÇϱâ·Î Çß´Ù.
3169
3170        dprint(2, "*** Update UCM.\n");
3171
3172        uidBuf = NULL;
3173        uidBuf = update_to_ucm(TRUE, &nUid, 
3174                        (ctx->flag & CBTF_EnableNewChannelInUpdateMode) ? TRUE : FALSE);
3175                // we want to get UID data.
3176               
3177        // ¼º°øÀûÀ¸·Î µ¿ÀÛÇߴµ¥µµ nUid°¡ 0ÀÏ ¼ö Àִ°¡??
3178        //
3179        dprint(2, "\t %d channels updated\n", nUid);
3180
3181label_end:
3182
3183        if (1)
3184        {
3185                OneChannelScanCompleteParam addparam;
3186       
3187                memset(&addparam, 0, sizeof(OneChannelScanCompleteParam));
3188               
3189                addparam.status = status;
3190                addparam.rf = ctx->start_channel;
3191                addparam.flag = ctx->flag;
3192                //addparam.userparam = userparam;
3193               
3194                addparam.nUid = nUid;
3195                addparam.uidBuf = uidBuf;
3196
3197                // scan event proc callback¿¡ ÀÇÇÑ report
3198                //send_event_message(evtOneChannelComplete, (UINT32)&addparam);
3199
3200                // pfn complete callback¿¡ ÀÇÇÑ report.
3201                // one channel scan mode ¿¡¸¸ Àִ Ưº°ÇÑ ¹æ½ÄÀÌ´Ù.
3202                if (pMsg->pfnCompleted)
3203                        (pMsg->pfnCompleted)(status, pMsg->userParam, (UINT32 *)&addparam);
3204
3205        }
3206
3207        if (uidBuf) {
3208                DHL_OS_Free((void**)&uidBuf);
3209        }
3210
3211        free_all_mcm();
3212        unlock_mcm();
3213
3214        return statusOK;
3215
3216}
3217
3218
3219
3220#if COMMENT
3221___________________(){}
3222#endif
3223
3224
3225
3226
3227STATUS SCN_UpdateUcmVct(xvctPtr_t vct, MPEG_PAT *pat, MPEG_PMT **pmtlist, 
3228                                                int rf, int scan_flag, 
3229                                                int *pnUid, int **puidBuf)
3230{
3231        // ÀÎÀÚ·Î ¹Þ´Â rf´Â ½ÇÁ¦·Î Æ©´×À» Çϱâ À§ÇѰÍÀÌ ¾Æ´Ï°í,
3232        // DB¿¡ µî·ÏÇÒ¶§ ÇÊ¿äÇÑ ÀÚ·á·Î¼­ ÇÊ¿äÇÑ °ÍÀÌ´Ù.
3233
3234//      STATUS status;
3235        ChannelScanContext *ctx;
3236        int nUid, *uidBuf;
3237
3238        ctx = get_scan_context();
3239
3240        dprint(1, "SCN_UpdateUcmFromVct:\n");
3241
3242        //»õ·Î Ãß°¡µÈ ÀϺΠapi¿¡¼­´Â ÀÌ ÇÔ¼ö¸¦ ÀÏ¹Ý task¿¡¼­µµ È£ÃâÇÑ´Ù.
3243        //ÀÏ´Ü ¸·°í Å×½ºÆ® ÇØ º¸ÀÚ.
3244/*
3245        if (Dmc_IsDmcTask() == FALSE) {
3246                dprint(0, "!! %s: not dmc task\n");
3247                return statusInvalidState;             
3248        }
3249*/
3250
3251#if 0 // megakiss
3252        if (vct == NULL || vct->channel == NULL || vct->numChannels <= 0) {
3253                dprint(0, "!! vct %x NULL or no channel\n", vct);
3254                return statusInvalidArgument;
3255        }
3256#endif
3257
3258        ctx->flag = scan_flag; // CBTF_XXX »ó¼öµéÀÇ Á¶ÇÕ.
3259
3260        ctx->cur_channel = ctx->start_channel = ctx->end_channel = rf;
3261                // ¿©±â¼­ ÁöÁ¤ÇÏ´Â cur_channel °ªÀÌ ½ÇÁ¦·Î DB¿¡ µé¾î°¡°Ô µÉ ä³Î ¹øÈ£Àε¥,
3262                // ²À Á¤È®ÇÑ °ªÀ» ÁöÁ¤ÇØ¾ß ÇÑ´Ù.
3263        ctx->total_channel = 1;
3264        ctx->signal_strength = DMW_HAL_GetSignalStrength();
3265        ctx->tuner_modulation_mode = DMW_HAL_GetModulationMode();
3266
3267        ctx->fnCallback = NULL;  // no callback.
3268       
3269        //ctx->force_psi = FALSE;  // PSI´Â ÇÊ¿ä¾ø´Ù.
3270        ctx->flag &= ~CBTF_ForcePSI;
3271
3272        //ctx->flag |= CBTF_IgnoreRemoteChannelInVct;
3273                // ÀÌ Ç÷¡±×´Â Ç×»ó TRUE·Î ÇÏÀÚ!!
3274
3275        if ((ctx->flag & CBTF_IgnoreTvctInCable) &&
3276                vct->is_cvct &&
3277                g_CurChannelType == ChannelType_Cable) { // TVCT ¹«½Ã ¿É¼ÇÀÌ ONÀÌ¸é ´õÀÌ»ó ÁøÇàÇÏÁö ¾Ê´Â´Ù.
3278                if (pnUid)
3279                        *pnUid = 0;
3280                return statusOK;
3281        }
3282
3283        if (lock_mcm(1000) != statusOK) {
3284                dprint(0, "!! some other task %x owns mcm lock.\n", get_mcm_owner());
3285                return statusOutOfResource;  // ÇöÀç mcm resource¸¦ »ç¿ëÇÒ ¼ö ¾øÀ½.
3286        }
3287
3288        free_all_mcm();
3289       
3290        ctx->xvct = vct;
3291        ctx->pat = pat;
3292        ctx->num_programs = pat ? pat->numPrograms : 0;
3293        ctx->pmtList = pmtlist;
3294       
3295        // Ȥ½Ã ÀÌ¹Ì ¹Þ¾ÆÁ® ÀÖ´Â pat, pmtµµ ÀÖÀ¸¸é µî·ÏÇØÁØ´Ù.
3296        // ±×·¯¸é Ãß°¡·Î ¹ÞÁö ¾ÊÀ¸´Ï È¿À²ÀûÀÌ´Ù.
3297        // ctx->pat = pat;
3298        // ctx->pmtlist[?] = pmt;
3299
3300        //      status = update_vct(ctx); // mcm¿¡ Àû¿ëÇÑ´Ù.
3301        (vct) ? update_vct(ctx) : update_psi(ctx);
3302
3303        sort_mcm();
3304        //print_mcm();
3305
3306        // max select¸¦ ÀüÇô ¾ÈÇϱâ·Î ÇÑ´Ù.
3307
3308        uidBuf = update_to_ucm(TRUE, &nUid, (ctx->flag & CBTF_EnableNewChannelInUpdateMode) ? TRUE : FALSE);
3309                // we want to get UID data.
3310
3311        if (uidBuf && puidBuf) {
3312                dprint(2, "  updated %d channels from tvct.\n", nUid);
3313                *puidBuf = uidBuf;
3314        }
3315        else {                 // ½ÇÁ¦·Î ¹ß°ßµÈ °ÍÀÌ ¾ø°Å³ª, out of memory error.
3316                if (uidBuf) 
3317                        DHL_OS_Free((void**)&uidBuf);
3318                nUid = 0;
3319        }
3320
3321        if (pnUid)
3322                *pnUid = nUid;
3323
3324        free_all_mcm();
3325        unlock_mcm();
3326
3327        // ÀÎÀÚ·Î ¹ÞÀº table µéÀº ¿ì¸®ÀÇ °ÍÀÌ ¾Æ´Ï¹Ç·Î free ½ÃŰ¸é ¾ÈµÊ!! ±×³É reset¸¸..
3328        ctx->xvct = NULL;
3329        ctx->pat = NULL;
3330        ctx->num_programs = 0;
3331        ctx->pmtList = NULL;
3332       
3333        return statusOK;
3334}
3335
3336
3337#if 0
3338
3339STATUS update_ucm_from_cvct(cvctPtr_t cvct, int rf, int scan_flag, int *pnUid, int **puidBuf)
3340{
3341        // ÀÎÀÚ·Î ¹Þ´Â rf´Â ½ÇÁ¦·Î Æ©´×À» Çϱâ À§ÇѰÍÀÌ ¾Æ´Ï°í,
3342        // DB¿¡ µî·ÏÇÒ¶§ ÇÊ¿äÇÑ ÀÚ·á·Î¼­ ÇÊ¿äÇÑ °ÍÀÌ´Ù.
3343
3344        STATUS status;
3345        ChannelScanContext tmp, *ctx = &tmp;
3346        int nUid, *uidBuf;
3347
3348        // cafrii 041130 add
3349        if (cvct == NULL || cvct->channel == NULL || cvct->numChannels <= 0) {
3350                dprint(0, "!! cvct %x NULL or no channel\n", cvct);
3351                return statusInvalidArgument;
3352        }
3353
3354
3355        // This is trick.. cheat following functions to assume this is channel scan task..
3356        memset(ctx, 0, sizeof(tmp));
3357
3358        ctx->flag = scan_flag; // CBTF_XXX »ó¼öµéÀÇ Á¶ÇÕ.
3359
3360        ctx->cur_channel = ctx->start_channel = ctx->end_channel = rf;
3361                // ¿©±â¼­ ÁöÁ¤ÇÏ´Â cur_channel °ªÀÌ ½ÇÁ¦·Î DB¿¡ µé¾î°¡°Ô µÉ ä³Î ¹øÈ£Àε¥,
3362                // ²À Á¤È®ÇÑ °ªÀ» ÁöÁ¤ÇØ¾ß ÇÑ´Ù.
3363        ctx->total_channel = 1;  // ÀÌ Ã¤³Î ÇѰ³¸¸ °Ë»ö.
3364        ctx->signal_strength = DMW_HAL_GetSignalStrength();
3365
3366        ctx->fnCallback = NULL;  // channelscan event callbackµµ ÇÊ¿ä ¾øÀ½.
3367       
3368        ctx->flag &= ~CBTF_ForcePSI;
3369
3370        //ctx->flag |= CBTF_IgnoreRemoteChannelInVct;
3371                // ÀÌ Ç÷¡±×´Â Ç×»ó TRUE·Î ÇÏÀÚ!!
3372
3373        if (lock_mcm(1000) != statusOK) {
3374                dprint(0, "!! some other task %x owns mcm lock.\n", get_mcm_owner());
3375                return statusOutOfResource;  // ÇöÀç mcm resource¸¦ »ç¿ëÇÒ ¼ö ¾øÀ½.
3376        }
3377
3378        free_all_mcm();
3379
3380        ctx->cvct = cvct;
3381        cvct = NULL;
3382       
3383        //status = Dmc_TranslateCvct(ctx->cvct, &xvct);
3384        status = Dmc_TranslateCvct(ctx->cvct, &ctx->xvct);
3385        if (status) {
3386                dprint(0, "!! TranslateTvct err %d, %s\n", status, DMW_CDB_ErrString(status));
3387        }
3388
3389        //status = update_vct(ctx, xvct);
3390        status = update_vct(ctx);
3391                // mcm¿¡ Àû¿ëÇÑ´Ù.
3392
3393        sort_mcm();
3394        //print_mcm();
3395
3396        // max select¸¦ ÀüÇô ¾ÈÇϱâ·Î ÇÑ´Ù.
3397
3398        uidBuf = update_to_ucm(TRUE, &nUid, (ctx->flag & CBTF_EnableNewChannelInUpdateMode) ? TRUE : FALSE);
3399                // we want to get UID data.
3400
3401        if (uidBuf && puidBuf) {
3402                dprint(2, "  updated %d channels from cvct.\n", nUid);
3403                *puidBuf = uidBuf;
3404        }
3405        else {                 // ½ÇÁ¦·Î ¹ß°ßµÈ °ÍÀÌ ¾ø°Å³ª, out of memory error.
3406                if (uidBuf) DHL_OS_Free((void**)&uidBuf);
3407                nUid = 0;
3408        }
3409
3410        if (pnUid)
3411                *pnUid = nUid;
3412
3413        free_all_mcm();
3414        unlock_mcm();
3415       
3416        Dmc_FreeAtscTable(&ctx->xvct);
3417
3418        return statusOK;
3419}
3420
3421#endif
3422
3423
3424
3425
3426#if COMMENT
3427____HAL_wrapper____(){}
3428#endif
3429
3430
3431static BOOL GetDigitalLockStatus()
3432{
3433        DHL_RESULT dhlResult;
3434        UINT32 lock;
3435        dhlResult = DHL_FE_GetSignalStatus(DEFAULT_TUNER_ID, eDHL_SIGNAL_LOCK, &lock);
3436       
3437        if (dhlResult==DHL_OK && lock)
3438                return TRUE;
3439        else
3440                return FALSE;
3441}
3442
3443static BOOL GetAnalogLockStatus()
3444{
3445        DHL_RESULT dhlResult;
3446        UINT32 lock;
3447        dhlResult = DHL_FE_GetSignalStatus(DEFAULT_TUNER_ID, eDHL_SIGNAL_NTSC_LOCK, &lock);
3448       
3449        if (dhlResult==DHL_OK && lock)
3450                return TRUE;
3451        else
3452                return FALSE;
3453}
3454
3455
3456// lockÀÌ µÈ »óÅ¿¡¼­¸¸ ÀÌ ÇÔ¼ö°¡ Á¦´ë·Î µ¿ÀÛÇÑ´Ù°í ÇÔ.
3457//
3458static ModulationType GetModulationMode()
3459{
3460        ModulationType mode;
3461        mode = DMW_HAL_GetModulationMode();
3462       
3463        // lock ÀÌ µÇ¾úÀ½¿¡µµ °¡²û¾¿ modulation mode¸¦ ¸øÀâ´Â °æ¿ì¸¦ À§ÇØ Àç½Ãµµ..
3464       
3465        if (mode == Modulation_Invalid)
3466                mode = DMW_HAL_GetModulationMode();
3467       
3468        return mode;
3469}
3470
3471
3472
3473
3474#if COMMENT
3475____Example____(){}
3476#endif
3477
3478
3479
3480#if USE_DEFAULT_CB_FN
3481
3482//--------------------------------------------------------
3483
3484// Cable systemÀ» detect Çϱâ À§ÇØ ÇÊ¿äÇÑ ÀÚ·áµé.
3485// ÀÌ °ªµéÀº °¢ ScanTune ÇÒ ¶§¸¶´Ù ±× °á°ú¿¡ µû¶ó ÀûÀýÈ÷ °»½ÅµÈ´Ù.
3486//
3487
3488typedef struct 
3489{
3490        int score_std, score_hrc, score_irc;
3491       
3492} CsdContext;
3493
3494static CsdContext g_CsdContext;
3495
3496
3497#define  CS_DETECT_THRESHOLD    5 
3498        // Cable System Score Threshold for Detection
3499        // ÀÛ¾÷Áß, Standard °£¿¡ ÀÌ Á¡¼ö ÀÌ»ó Â÷À̳ª¸é °Ë»ö Á¾·á.
3500        //
3501
3502
3503typedef struct
3504{
3505        char *name;        // demodulation name for debug
3506       
3507        ModulationType mod;  // µå¶óÀ̹ö¿¡¼­ »ç¿ëÇÏ´Â Demod »ó¼ö °ª
3508       
3509        int timeout_in_ms; //
3510       
3511} DemodDescriptor;
3512
3513       
3514int last_successful_mod = -1;
3515       
3516
3517// ÇØ´ç Á֯ļö·Î Æ©´×ÇÏ¿© signalÀÌ ÀÖ´ÂÁö °Ë»çÇÑ´Ù.
3518//
3519// °¨ÁöµÈ modulation mode °ªÀ» ¸®ÅÏ.
3520//
3521STATUS CheckSignalLock(UINT32 freqInKHz, 
3522                                        ChannelScanCancelCheckFn fnCheck, 
3523                                        DemodDescriptor *pDemodDesc, int nDemod,
3524                                        ModulationType *pModType)
3525{
3526        int i, mod_idx, timeout, err;
3527        UINT32 tickStart;
3528        BOOL bCheckNtscAlso;
3529        int _second = 1000;
3530        ModulationType mod;
3531       
3532        if (pModType) 
3533                *pModType = (ModulationType)-1;
3534       
3535        //
3536        // ÇØ´ç Á֯ļö·Î ¼¼°¡Áö demodulation mode·Î ¸ðµÎ try¸¦ ÇØº»´Ù.
3537        //
3538        // °Ë»ö ½Ã°£À» ÁÙÀ̱â À§ÇØ ¸¶Áö¸·À¸·Î lock µÈ demod ¹æ½ÄÀ» ±â¾ïÇϰí ÀÖ´Ù°¡
3539        // ±× ¹æ½ÄÀ¸·Î ¸ÕÀú try¸¦ ÇÑ´Ù.
3540        // ÀÎÁ¢ ä³ÎÀÇ °æ¿ì °°Àº modulation ¹æ½ÄÀ» »ç¿ëÇÒ È®·üÀÌ ³ô±â ¶§¹®.
3541        //
3542        mod_idx = last_successful_mod >= 0 ? last_successful_mod : 0;
3543                //
3544                // check¸¦ ½ÃÀÛÇÒ modulation index.
3545
3546        for (i=0; i<nDemod; i++) 
3547        {
3548                dprint(2, "\t  freq %u KHz, '%s' modulation\n", 
3549                                                freqInKHz, pDemodDesc[mod_idx].name);
3550                                               
3551                err = DMW_HAL_TunerSetFrequency(freqInKHz, pDemodDesc[mod_idx].mod, fnCheck);
3552
3553                // Oren Demodulator´Â VSB Æ©´×À» ½ÃµµÇÏ¸é µ¿½Ã¿¡ NTSC À¯¹«¸¦ °Ë»çÇÒ ¼ö ÀÖ´Ù.
3554                // Á¦Ç°ÀÌ NTSC¸¦ Áö¿øÇÏÁö ¾Ê´õ¶óµµ ÀÌ ±â´ÉÀ» »ç¿ëÇϸé scan ¼Óµµ¸¦ ³ôÀÏ ¼ö ÀÖ´Ù.
3555                //
3556                if (pDemodDesc[mod_idx].mod == Modulation_8VSB)
3557                        bCheckNtscAlso = TRUE;
3558                else
3559                        bCheckNtscAlso = FALSE;
3560
3561                // wait until signal lock with timeout
3562                //
3563                timeout = pDemodDesc[mod_idx].timeout_in_ms;
3564               
3565                tickStart = OS_GetTickCount();
3566               
3567                while (OS_GetTickCount() - tickStart < timeout*_second/1000) 
3568                {
3569                        if (GetDigitalLockStatus()) 
3570                        {
3571                                mod = GetModulationMode();
3572                                last_successful_mod = mod_idx;
3573                                goto label_done;
3574                        }
3575                       
3576                        if (bCheckNtscAlso && GetAnalogLockStatus()) 
3577                        {
3578                                mod = Modulation_NTSC;
3579                                last_successful_mod = mod_idx;
3580                                goto label_done;
3581                        }
3582                       
3583                        if (fnCheck && fnCheck())
3584                                return statusCancelled;
3585                       
3586                        DHL_OS_Delay(1000/20); // ±â´Ù·È´Ù°¡ ´Ù½Ã ½Ãµµ..
3587                }
3588               
3589                mod_idx = (mod_idx + 1) % nDemod;  // ´ÙÀ½ modulation ¹æ½ÄÀ¸·Î retry..
3590        }
3591       
3592        return statusNotFound;
3593       
3594label_done:
3595
3596        if (pModType)
3597                *pModType = mod;
3598
3599        dprint(2, "\tsignal locked with demod[%d] %d, '%s'\n", 
3600                                        mod_idx, mod, ServiceTypeString(mod));
3601       
3602        return statusOK;
3603       
3604}
3605
3606
3607//----------------------------------------------------------------
3608//  Air
3609//
3610
3611#define N_AIR_DEMOD 1
3612
3613static DemodDescriptor s_AirDemodDesc[N_AIR_DEMOD] = 
3614{
3615        "8VSB",    Modulation_8VSB,  500,
3616};
3617
3618
3619void SetTunerAir(ScanTunerSetCbParam *csdp)
3620{
3621        UINT32 freq;
3622        ModulationType mode;
3623        STATUS status;
3624
3625        freq = FindCenterFrequency(csdp->channel, 0, eDHL_FREQ_AIR);
3626
3627        status = CheckSignalLock(freq/1000, csdp->chkfn, 
3628                                                s_AirDemodDesc, N_AIR_DEMOD, &mode);
3629
3630        if (status == statusCancelled) {
3631                csdp->return_value = statusCancelled;
3632                return;
3633        }
3634       
3635        if (status == statusNotFound) {
3636                csdp->locked = FALSE;
3637                csdp->return_value = statusOK;
3638                return;
3639        }
3640
3641        if (mode == Modulation_NTSC) {
3642                csdp->locked = FALSE;
3643                csdp->return_value = statusOK;
3644                return;
3645        }
3646
3647        csdp->locked = TRUE;
3648        csdp->mode = mode;
3649        csdp->strength = DMW_HAL_GetSignalStrength();
3650        csdp->freq_offset = 0;
3651        csdp->return_value = statusOK;
3652
3653}
3654
3655//----------------------------------------------------------------
3656//  Cable
3657//
3658
3659// note!
3660//  64QAM°ú 256QAMÀ» ¿ÏÀüÈ÷ ±¸ºÐÇÏ´Â demodulator¶ó¸é
3661//  ¾Æ·¡ Å×À̺íÀ» ¼öÁ¤ÇØ¾ß ÇÑ´Ù.
3662//
3663
3664#define N_CABLE_DEMOD 2
3665
3666static DemodDescriptor s_CableDemodDesc[N_CABLE_DEMOD] = 
3667{
3668        "QAM",     Modulation_QAM,       500,
3669        "8VSB",    Modulation_8VSB,      500,
3670};
3671
3672
3673void SetTunerCable(ScanTunerSetCbParam *csdp)
3674{
3675        UINT32 freq_STD, freq_HRC, freq_IRC;  // °¢ system ¿¡¼­ÀÇ center frequency
3676        BOOL bSTD_IRC_Dominant = FALSE, bHRC_Dominant = FALSE;
3677                // ÁøÇà Áß¿¡ ÇÑ ±×·ìÀÌ Dominant ÇØÁö¸é ÇØ´ç flag°¡ TRUE°¡ µÈ´Ù.
3678                // ±× ÀÌÈÄ¿¡´Â dominant ÇÑ ¸ðµå·Î¸¸ Æ©´×À» ½ÃµµÇÑ´Ù.
3679               
3680        BOOL bChannel_5_6;
3681        ModulationType mode;
3682        STATUS status;
3683
3684        CsdContext *ctx = &g_CsdContext;
3685       
3686        if (csdp == NULL) {
3687                dprint(0, "!! critical context param NULL\n");
3688                csdp->return_value = statusInvalidArgument;
3689                return;
3690        }
3691
3692        csdp->locked = FALSE;
3693        csdp->freq_offset = 0;
3694       
3695        if (ctx->score_std >= ctx->score_hrc + CS_DETECT_THRESHOLD)
3696                bSTD_IRC_Dominant = TRUE;
3697        else if (ctx->score_hrc >= ctx->score_std + CS_DETECT_THRESHOLD)
3698                bHRC_Dominant = TRUE;
3699       
3700
3701        freq_STD = FindCenterFrequency(csdp->channel, 0, eDHL_FREQ_STD);
3702        freq_HRC = FindCenterFrequency(csdp->channel, 0, eDHL_FREQ_HRC);
3703        freq_IRC = FindCenterFrequency(csdp->channel, 0, eDHL_FREQ_IRC);
3704
3705        // ÇÊ¿äÇÑ ÃʱâÈ­ ¼öÇà..
3706       
3707        if (csdp->channel == 5 || csdp->channel == 6)
3708                bChannel_5_6 = TRUE;
3709        else
3710                bChannel_5_6 = FALSE;
3711       
3712        //------------------------
3713        //  STD
3714       
3715        if (!bHRC_Dominant)
3716        {
3717                dprint(2, "\t$$ try Cable %s..\n", bChannel_5_6 ? "STD" : "STD/IRC");
3718               
3719                status = CheckSignalLock(freq_STD/1000, csdp->chkfn, 
3720                                                s_CableDemodDesc, N_CABLE_DEMOD, &mode);
3721
3722                if (status == statusCancelled) goto label_cancelled;
3723
3724                if (mode == Modulation_NTSC) {
3725                        ctx->score_std++;   // Cable system ¼±Åÿ¡´Â µµ¿òÀÌ µÇµµ·Ï..
3726                        csdp->locked = FALSE;
3727                        goto label_end;
3728                }
3729
3730                if (status == statusOK) {
3731                        ctx->score_std++;
3732                        csdp->freq_offset = 0; // freq_STD - freq_STD;
3733                        csdp->locked = TRUE;
3734                        csdp->mode = mode;
3735                        goto label_end;
3736                }
3737               
3738                //------------------------
3739                //  IRC
3740               
3741                // 5¹ø 6¹ø ä³ÎÀ» Á¦¿ÜÇÑ ´Ù¸¥ ä³Î¿¡¼­´Â STD¿Í IRC´Â ±¸ºÐÀÌ µÇÁö ¾Ê´Â´Ù.
3742                // 5, 6¹ø ¿¡¼­¸¸ µû·Î IRC¸¦ üũÇÑ´Ù.
3743                //
3744                if (bChannel_5_6)
3745                {
3746                        dprint(2, "\t$$ try Cable IRC..\n");
3747                        status = CheckSignalLock(freq_IRC/1000, csdp->chkfn, 
3748                                                        s_CableDemodDesc, N_CABLE_DEMOD, &mode);
3749       
3750                        if (status == statusCancelled) goto label_cancelled;
3751       
3752                        if (mode == Modulation_NTSC) {
3753                                ctx->score_irc++;
3754                                csdp->locked = FALSE;
3755                                goto label_end;
3756                        }
3757                       
3758                        if (status == statusOK) {
3759                                ctx->score_irc++;
3760                                csdp->freq_offset = freq_IRC - freq_STD;
3761                                csdp->locked = TRUE;
3762                                csdp->mode = mode;
3763                                goto label_end;
3764                        }
3765                }
3766        }
3767
3768        //------------------------
3769        //  HRC
3770       
3771        if (!bSTD_IRC_Dominant)
3772        {
3773                dprint(2, "\t$$ try Cable HRC..\n");
3774                status = CheckSignalLock(freq_HRC/1000, csdp->chkfn, 
3775                                                s_CableDemodDesc, N_CABLE_DEMOD, &mode);
3776
3777                if (status == statusCancelled) goto label_cancelled;
3778
3779                if (mode == Modulation_NTSC) {
3780                        ctx->score_hrc++;
3781                        csdp->locked = FALSE;
3782                        goto label_end;
3783                }
3784
3785                if (status == statusOK) {
3786                        ctx->score_hrc++;
3787                        csdp->freq_offset = freq_HRC - freq_STD;
3788                        csdp->locked = TRUE;
3789                        csdp->mode = mode;
3790                        goto label_end;
3791                }
3792        }
3793
3794
3795label_end:
3796
3797        dprint(2, "\t$$ lock %d, current score:  STD %d,  HRC %d,  IRC %d\n", 
3798                                csdp->locked, ctx->score_std, ctx->score_hrc, ctx->score_irc);
3799
3800        // ¾î´À Çϳª°¡ ¿ì¼¼ÇØ Áö´Â ÃÖÃÊÀÇ ¼ø°£¿¡ ¸Þ½ÃÁö¸¦ Ç¥½Ã.
3801        // ÀÌÁ¦ºÎÅʹ ƯÁ¤ system¸¸ °Ë»öÀ» ¼öÇàÇÒ °ÍÀÌ´Ù.
3802        //
3803        if (ctx->score_std == ctx->score_hrc + CS_DETECT_THRESHOLD)
3804                dprint(2, "\t#### STD/IRC is now dominant ####\n");
3805               
3806        else if (ctx->score_hrc == ctx->score_std + CS_DETECT_THRESHOLD)
3807                dprint(2, "\t#### HRC is now dominant ####\n");
3808
3809        if (csdp->locked)
3810                csdp->strength = DMW_HAL_GetSignalStrength();
3811       
3812        csdp->return_value = statusOK;
3813        return;
3814       
3815label_cancelled:
3816        csdp->return_value = statusCancelled;
3817        return;
3818
3819}
3820
3821
3822
3823void SCB_ScanStart(ScanStartedCbParam *param)
3824{
3825        CsdContext *ctx = &g_CsdContext;
3826
3827        memset(ctx, 0, sizeof(CsdContext));
3828       
3829        last_successful_mod = -1;
3830
3831        if ((param->flag & CBTF_ChannelTypeMask) == CBTF_Air)
3832                return;
3833       
3834        dprint(2, "\t[SCB] cable autoscan start. set to STD..\n");
3835        DMW_HAL_SetChannelStandard(eDHL_FREQ_STD);
3836       
3837}
3838
3839void SCB_ScanEnd(ScanCompleteCbParam *param)
3840{
3841        CsdContext *ctx = &g_CsdContext;
3842
3843        if ((param->flag & CBTF_ChannelTypeMask) == CBTF_Air)
3844                return;
3845
3846        dprint(2, "\t[SCB] cable autoscan end\n");
3847
3848        dprint(2, "\t std %d, irc %d, hrc %d\n", 
3849                                ctx->score_std, ctx->score_irc, ctx->score_hrc);
3850       
3851        if (ctx->score_hrc > (ctx->score_std + ctx->score_irc))
3852        {
3853                dprint(2, "\t --> CableSystem is HRC\n");
3854        } 
3855        else if (ctx->score_irc > 0)
3856        {
3857                // irc´Â 5,6¹ø¿¡¼­¸¸ countµÇ´Âµ¥, irc°¡ Çϳª ÀÌ»ó Á¸ÀçÇϸé ÀÌ systemÀº irc·Î ºÁµµ µÈ´Ù.
3858                //
3859                dprint(2, "\t --> CableSystem is IRC\n");
3860        } 
3861        else
3862        {
3863                dprint(2, "\t --> CableSystem is STD\n");
3864        }
3865       
3866}
3867
3868
3869void SCB_TunerSet(ScanTunerSetCbParam *param)
3870{
3871        dprint(2, "\t[SCB] tuner set rf %d\n", param->channel);
3872       
3873        if ((param->flag & CBTF_ChannelTypeMask) == CBTF_Air)
3874                SetTunerAir(param);
3875        else
3876                SetTunerCable(param);
3877}
3878
3879#endif // USE_DEFAULT_CB_FN
3880
3881
3882
3883void SCB_SkipTunerSet(ScanTunerSetCbParam *param)
3884{
3885        dprint(2, "  skip tuner setting.\n");
3886
3887        // ÇöÀç »óÅ¿¡¼­ lock check¸¸ ¼öÇàÇÑ´Ù.
3888        // digital ¿ì¼± ó¸®Çϵµ·Ï ÇÏÀÚ.
3889
3890        param->strength = 0; // Á¦°øÇÏÁö ¾Ê´Â´Ù.
3891       
3892        if (GetDigitalLockStatus())
3893        {
3894                param->locked = TRUE;
3895                param->mode = GetModulationMode();
3896        }
3897        else if (GetAnalogLockStatus())
3898        {
3899                param->locked = TRUE;
3900                param->mode = Modulation_NTSC;
3901        }
3902        else
3903                param->locked = FALSE;
3904
3905        param->return_value = statusOK;
3906}
3907
3908
3909
3910
3911
3912#if COMMENT
3913____TEST____(){}
3914#endif
3915
3916#if TEST_AUTOSCAN
3917
3918/*
3919        Å×½ºÆ® ÇÏ´Â ¹æ¹ý..
3920
3921        -- ¸ÕÀú channel type ¼±ÅÃÀ» ÇØ¾ß ÇÔ.
3922        Shell> DMW_CDB_InitializeChannelLib 0 ¶Ç´Â 1
3923
3924        --- ucm Áö¿ì±â..
3925        Shell> DMW_CDB_ClearAll
3926
3927        -- autoscan ½ÃÀÛ..     
3928        Shell> TestDigitalScan 14 18  // air
3929        Shell> TestDigitalScan 81 85  // cable VSB
3930
3931        --- ucm È®ÀÎ..
3932        Shell> DMW_CDB_PrintUcm
3933
3934
3935*/
3936
3937void TestPrintScanContext()
3938{
3939        ChannelScanContext *ctx = get_scan_context();
3940       
3941        DHL_OS_Printf("\t flag 0x%08x ", ctx->flag);
3942        DHL_OS_Printf("\t cur ch %d,  start ch %d ~ end ch %d\n", ctx->cur_channel, ctx->start_channel, ctx->end_channel);
3943        DHL_OS_Printf("\t state %d\n", ctx->state);
3944        DHL_OS_Printf("\n");
3945}
3946
3947#if 0
3948STATUS TestCheckScramble(int vPid, int pPid)
3949{
3950        return check_pes_scramble(Dmc_GetCurrentTsd(), NULL, vPid, pPid);
3951}
3952#endif
3953
3954#define USE_GET_SCAN_INFO 1
3955
3956#if USE_GET_SCAN_INFO /*progress bar¸¦ ±×¸®±â À§ÇÑ º¯¼ö*/
3957static int p_scan_percentage = -1; /* µ¿ÀÛ Áß¿¡´Â 0¿¡¼­ 100»çÀÌÀÇ °ªÀ» °¡Áü */
3958        /* -1 ÀÌ¸é ¾ÆÁ÷ ½ÃÀÛ ¾È ÇßÀ½. 101 ÀÌ¸é ¿Ï·á ÇßÀ½. */
3959static int p_scan_channels;
3960#endif
3961
3962
3963STATUS _TestScanCallback(ChannelScanEventType evt, UINT32 param)
3964{
3965       
3966        if (evt == evtScanStarted) {
3967                // ä³Î °Ë»ö ÀÛ¾÷ÀÌ ½ÃÀ۵ǾúÀ½.
3968                // test ¿ì¼±Àº cable std·Î¸¸ Å×½ºÆ®
3969                //DHL_FE_SetChannelStandard(DEFAULT_TUNER_ID, g_CurChannelType);
3970
3971                //ScanStartedCbParam *sscb = (ScanStartedCbParam *)param;
3972#if USE_GET_SCAN_INFO
3973                p_scan_percentage=0;
3974                p_scan_channels=0;
3975#endif
3976                DHL_OS_Printf("#### scan start: \n"); 
3977        }
3978        else if (evt == evtScanComplete) {
3979                // ä³Î °Ë»öÀÌ ¸ðµÎ ³¡³µÀ½. UCM »ý¼º ÀÛ¾÷µµ ¸ðµÎ ¿Ï·á µÇ¾ú±â ¶§¹®¿¡ ÀÌÈÄ application¿¡¼­
3980                // UCM µ¥ÀÌÅ͸¦ »ç¿ëÇÒ ¼ö ÀÖ´Ù.
3981                ScanCompleteCbParam *sccb = (ScanCompleteCbParam *)param;
3982#if USE_GET_SCAN_INFO
3983                p_scan_percentage=101;
3984#endif
3985                DHL_OS_Printf("#### scan completed by %s\n", sccb->bStoppedByUser ? "by user" : "normally"); 
3986        }
3987        else if (evt == evtNewChannel) {
3988                // »õ·Î¿î ä³ÎÀÌ ¹ß°ßµÇ¾úÀ½.
3989                //UCM_DB_T *ucm = (UCM_DB_T *) param;
3990                UCM_DB_T *ucm = ((ScanNewChannelCbParam *)param)->ucm;
3991                DHL_OS_Printf("#### new channel: RF %d, %d-%d\n", (int)ucm->RF, (int)ucm->Major, (int)ucm->Minor); 
3992#if USE_GET_SCAN_INFO
3993                p_scan_channels++;
3994#endif
3995        }
3996        else if (evt == evtOnProgress) {
3997                // ä³Î °Ë»ö ÁøÃ´ »óȲ. »óÅ ÁøÇà ±×·¡ÇÁ¸¦ Ç¥½ÃÇϱâ À§Çؼ­ »ç¿ëÇÑ´Ù.
3998                // param1: ÇöÀç ÁøÇàÁßÀΠä³ÎÀÇ RF °ª.
3999                // param2: Àüü °Ë»öÇÒ Ã¤³Î °¹¼ö.
4000                //
4001                ScanProgressCbParam *spcb = (ScanProgressCbParam *)param;
4002                if (spcb->after_scan==0)
4003                        DHL_OS_Printf("#### scan progress: %d\n", spcb->channel_idx*100/spcb->total_channel);; 
4004#if USE_GET_SCAN_INFO
4005                p_scan_percentage=spcb->current_rf*100/spcb->total_channel;
4006#endif
4007        }
4008        else if (evt == evtScanTunerSet)
4009        {
4010                ScanTunerSetCbParam *cbParam = (ScanTunerSetCbParam *)param;
4011                int i;
4012                UINT8 bLocked;
4013                UINT32 freq;
4014                tDHL_Demod demod;
4015
4016                freq=DHL_FE_ChannelToFrequency(cbParam->channel, (tDHL_FreqStd)g_CurChannelType);
4017               
4018                DHL_FE_Start(DEFAULT_TUNER_ID, freq, eDHL_DEMOD_8VSB, NULL);
4019               
4020                for(i=0, bLocked=FALSE; i<20; i++) {
4021                        DHL_FE_GetLockStatus(DEFAULT_TUNER_ID, &bLocked, &demod);
4022                       
4023                        if(bLocked) break;
4024                       
4025                        DHL_OS_Delay(100);
4026                }
4027               
4028                cbParam->locked=bLocked;
4029                cbParam->mode=Modulation_8VSB;
4030                cbParam->freq_offset = 0;
4031                cbParam->return_value=statusOK;
4032
4033        }
4034
4035        return statusOK;
4036}
4037
4038#if 0
4039void TestAnalogScan(int start, int end, BOOL bAnalogCableDetect)
4040{
4041        // g_CurChannelType¿¡ µû¶ó¼­
4042
4043        int flag = 0;
4044       
4045        if (g_CurChannelType == ChannelType_Air)
4046                flag |= CBTF_Air;
4047        else
4048                flag |= CBTF_Cable;
4049       
4050        flag |= CBTF_NTSC;
4051       
4052        flag |= (bAnalogCableDetect ? CBTF_AnalogCableSystemDetect : 0);
4053       
4054        DMW_ASC_StartScan(flag, _TestScanCallback, start, end);
4055}
4056#endif
4057
4058void TestDigitalScan(int start, int end)
4059{
4060        int flag = 0;
4061
4062        printf(" g_CurChannelType %d \n", g_CurChannelType);
4063       
4064        if (g_CurChannelType == ChannelType_Air)
4065                flag |= CBTF_Air;
4066        else
4067                flag |= CBTF_Cable;
4068       
4069        flag |= (CBTF_8VSB | CBTF_QAM);
4070
4071        p_scan_percentage = 0; // temp for rs show
4072       
4073        DMW_ASC_StartScan(flag, _TestScanCallback, start, end);
4074}
4075
4076void TestStopScan(BOOL bCancel)
4077{
4078        DMW_ASC_StopScan(!bCancel);
4079}
4080
4081int TestScanGetProgress()
4082{
4083        return p_scan_percentage;
4084}
4085
4086int TestScanGetFoundChannel()
4087{
4088        return p_scan_channels;
4089}
4090
4091
4092#endif // TEST_AUTOSCAN
4093
4094
4095
4096
4097
4098
4099
4100#if COMMENT
4101________(){}
4102#endif
4103
4104#if DMW_REGISTER_DEBUG_SYMBOL
4105
4106static DHL_SymbolTable symbols[] =
4107{
4108        #if TEST_AUTOSCAN
4109                //DHL_FNC_SYM_ENTRY(TestCheckScramble),
4110                DHL_FNC_SYM_ENTRY(TestPrintScanContext),
4111        #endif
4112
4113        //DHL_VAR_SYM_ENTRY(g_Trace_ChannelScan),
4114        DHL_VAR_SYM_ENTRY(g_TestAutoscanWithoutVct),
4115
4116};
4117
4118#endif
4119
4120void RegisterChannelScanSymbols(void)
4121{
4122       
4123#if DMW_REGISTER_DEBUG_SYMBOL
4124        DHL_DBG_RegisterSymbols(symbols, DHL_NUMSYMBOLS(symbols));
4125#endif
4126
4127}
4128
4129
4130
4131
4132
4133/********************************************************************
4134
4135  $Log: DMW_ChannelScan.c,v $
4136
4137        1.34 2005/4/29  GetMainChannel ¿¡¼­ ¹ÞÁö ¸øÇÑ PMT°¡ ÀÖ´Â °æ¿ì¸¦ ´ëºñÇØ¼­ update_psi¿¡¼­ ´Ù½ÃÇѹø ¼ö½Å,
4138                        xvctµµ ScanContext¿¡ µî·Ï. update_vct prototype º¯°æ
4139                        ForcePsi ¿É¼Ç»ç¿ë½Ã xvct¿¡ ÀÖ´Â PMT´Â skipÇϵµ·Ï ¼öÁ¤
4140       
4141        1.33 2005/4/22  ScanVsbChannel À» ScanDigitalAirChannel À¸·Î À̸§ º¯°æ. È¥µ· ¹æÁö¸ñÀû
4142        1.32 2005/4/12  ScanAnalogChannel ¿¡¼­ freq_HRC ´ë½Å freq_IRC »ç¿ëÇÏ´ø ¹ö±× ¼öÁ¤
4143       
4144        1.31 2005/3/28  DMW_HAL_AfcSearchMultiple ¿¡ timeout param Ãß°¡
4145        1.30 2005/3/25  DMW_HAL_AfcSearchMultiple °á°ú üũ
4146        1.29 2005/3/15  »ç¿ëÇÏÁö ¾Ê´Â º¯¼ö »èÁ¦,
4147                        ParseXXX »ç¿ë ÈÄ ¸®ÅϰªÀÌ ¿¡·¯À̸é pointer¸¦ NULL·Î ¼³Á¤Çϵµ·Ï ¼öÁ¤
4148                        tsc bit üũ ½Ã°£À» g_Timeout_PesPidCheck º¯¼ö·Î ¼³Á¤
4149                        CBTF_AnalogCableSystemDetect Ç÷¡±×¸¦ Ãß°¡Çϰí AUTO_DETECT_CABLE_STD »èÁ¦
4150        1.28 2005/3/5   TSC bit monitor ½Ã°£À» 100ms·Î. tsc bit°á°ú üũ Á¶°Ç º¯°æ
4151        1.27 2005/1/26  StartScan ÇÒ ¶§ g_CableSystem °ªÀÌ À¯Áö µÇÁö ¾Ê´ø ¹®Á¦ ¼öÁ¤
4152        1.26 2005/1/24  ca_desc¸¦ ÀÌ¿ëÇÑ °Ë»ç ¹æ¹ý »èÁ¦
4153        1.25 2004/12/09 add bSetTuner argument in update_current_scan
4154                        Analog/VSB/DigitalCableScan: bLocked adjustment
4155                        update_vct_subchannel: pmtList[i] °¡ NULL ÀÎÁöµµ üũ..
4156
4157        1.24 2004/12/07 CableSystem Detect °ü·Ã ±â´É Ãß°¡ ¿Ï¼º.
4158
4159        1.23 2004/12/03 get_pid_info_from_sld ¿¡¼­ MPEG-1/MPEG-2 audio Áö¿ø
4160
4161        1.22 2004/12/01 Dmc_GetMultipleTscBits ¿¡¼­µµ cancel check Ãß°¡
4162        1.21 2004/11/30 Àüü ±¸Á¶¸¦ ¼öÁ¤
4163                        update_tvct/cvct --> update_xvct ÅëÇÕ
4164                        ScanQamChannel »èÁ¦, VSB ¹× DigitalCable ¸¸ »ç¿ë
4165        1.20 2004/11/27 update_*vct_subchannel ¿¡¼­ ±âÁ¸ mcmÀÇ csd¸¦ º¸Á¸Çϱâ À§ÇÏ¿©
4166                        xcndÀÇ update À§Ä¡ ¼öÁ¤.
4167        1.19 2004/11/26 ÀÚü ChannelScanDebugPrint Ãß°¡, g_Trace_bChannelScan´Â »èÁ¦. debug level Ãß°¡
4168                        get_info_from_vct_desc ¸¦ Ãß°¡ÇÏ°í ºñ½ÁÇÑ apiµé Á¤¸®.
4169                        update_*vct_subchannel ¿¡¼­ xcnd Ãß°¡, update_csd Ãß°¡
4170
4171        1.18 2004/11/22 update_psi_program ¿¡¼­ detected modulation °ª üũ Çѹø ´õ..
4172                        tuner modulation mode »ó¼ö°ª »ç¿ë ±ÝÁö.. ¸ðµÎ Modulation_XX »ç¿ë.
4173                        SUPPORT_MODULATION_AUTODETECT »èÁ¦.. HAL ÇÔ¼ö »ç¿ë.
4174       
4175        1.17 2004/11/4  ScanXXXChannel ¿¡¼­ °¢ modulationÀ» ´Ù¸£°Ô ÁöÁ¤ÇÏ¿© Æ©´×..
4176                        ScanContextÀÇ tuner_modulation_mode À̸§ º¯°æ (vctÀÇ °Í°ú È¥µ·µÇ±â ¶§¹®)
4177        1.16 2004/11/1  update_current_scan ¿¡¼­ scan_flag°¡ ÃʱâÈ­ µÇ¾î ÀÖÁö ¾ÊÀº ¹®Á¦ ¼öÁ¤
4178        1.15 2004/9/20  DMW_Config µµÀÔ, config »çÇ× À̵¿
4179        1.14 2004/8/31  g_CableSystem moved to Channel HAL
4180        1.13 2004/8/12  AUTO_DETECT_CABLE_STD added
4181
4182        1.12 2004/7/26  debug print level add
4183        1.11 2004/05/21 decimal print bugfix
4184        1.10 2004/02/24 import changed in PCE
4185        1.09 2004/01/14 add #AudioOnlyChannelMissing
4186                        change support TVCT in Cable again
4187        1.08 2004/01/13 #SupplementPidsFromPSI
4188        1.07 2003/12/31 ModulationMode detect, OnePartChNum system, delete unused codes
4189
4190        1.06 2003/12/05 UCM_CORE Backup/Restore ±â´É Ãß°¡
4191        1.05 2003/6/10  caller¿¡¼­ Á¦°øÇÏ´Â cvct, tvct¸¦ ÀÌ¿ëÇÏ¿© UCM updateÇÏ´Â ÇÔ¼ö Ãß°¡.
4192        1.04            g_IgnoreVctCarrierFrequencyInfo °ü·Ã ÄÚµå Ãß°¡. update_mcm_xxx() ºÎºÐ..
4193        1.03 2003/3/5   ScanDigitalCableChannel() Ãß°¡.
4194                        g_MixedCableDigitalChannel º¯¼ö Ãß°¡. ±âº»À¸·Î TRUEÀÓ.
4195
4196        1.02 2003/2/24  ScanQamChannel Ãß°¡. tvct->cvct º¯°æ.
4197                        StopScan(kill)À» ÇÏ´õ¶óµµ task¸¸ Á×ÀÌ°í ±×¿Ü ´Ù¸¥ accessary´Â ¾È Á×ÀÓ.
4198                        Autoscan ½ÃÀÛÇÒ¶§ InitializeChannelLib() ¼öÇà.
4199        1.01 2003/02/17 message is replaced to callback function.
4200                        command, event ¿Ï·á..
4201        1.00 2003/01/13 Initial coding from ground, based on M/W API document
4202
4203 ********************************************************************/
Note: See TracBrowser for help on using the repository browser.