扫台

梳理一下扫台流程。

无论何种扫台方式,都会创建一个ScanThread线程:

1
2
3
4
5
6
/*
* vendor/realtek/frameworks/native/appclass/ \
* MediaControl/Component/Channel/Scan/TableScanner.cpp
*/

pthread_create(&m_thread, NULL, ScanThread, (void *)this);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
* vendor/realtek/frameworks/native/appclass/ \
* MediaControl/Component/Channel/Scan/ChScanner.cpp
*/

void* CChScanner::ScanThread(void *pParam)
{
CChScanner *pThis = (CChScanner *)pParam;
pThis->m_scanState = CH_SCAN_STATE_INIT;
pThis->m_threadIsRunning = true;
pThis->m_runThread = true;

while (pThis->m_runThread == true)
pThis->xWorkerThread();

// Manual/seekscan needs to set this variable before ending scan message is sent out.
pThis->m_threadIsRunning = false;
pThis->m_cancelScan = false;

return 0;
}

ScanThread线程的整个扫台状态机xWorkerThread:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*
* vendor/realtek/frameworks/native/appclass/ \
* MediaControl/Component/Channel/Scan/TableScanner.cpp
*/

void CTableScanner::xWorkerThread()
{
// Verify scan mode is valid.
if ((m_scanMode == CH_SCAN_MODE_IDLE) || (m_scanMode >= CH_SCAN_MODE_MAX))
goto EXIT_SCANNING;

switch (m_scanState)
{
case CH_SCAN_STATE_INIT:
xStageInit();
break;

case CH_SCAN_STATE_BEGIN_FREQ:
ALOGD("[%s %d] CH_SCAN_STATE_BEGIN_FREQ start\n", __func__, __LINE__);
xStageBeginFreq();
break;

case CH_SCAN_STATE_SCANNING:
// wait scan done
ALOGD("[%s %d] CH_SCAN_STATE_SCANNING start\n", __func__, __LINE__);
while (!m_pFreqScanDetector->Mf_IsScanDone())
{
if (m_cancelScan == true)
break;

m_pFreqScanDetector->RunStateProc();
if (m_cancelScan != true && !m_pFreqScanDetector->Mf_IsScanDone())
{
if(m_scanMode == CH_SCAN_MODE_BLIND_SCAN||m_scanMode == CH_SCAN_MODE_BLIND_SCAN_NETWORK)
{
int Index = 0, Total = 0;
UINT32 freq = m_pFreqScanDetector->Mf_GetFrequency(&Index,&Total);
if(freq>0)
{
m_curFreqIndex = Index;
m_freqListSize = Total;
m_curFreq = freq;
}
}
usleep(SCAN_THREAD_CS_TIME*1000);
}
}
ALOGD("[%s %d] CH_SCAN_STATE_SCANNING end\n", __func__, __LINE__);
m_scanState = CH_SCAN_STATE_END_FREQ;
break;

case CH_SCAN_STATE_END_FREQ:
ALOGD("[%s %d] CH_SCAN_STATE_END_FREQ begin\n", __func__, __LINE__);
xStageEndFreq();
break;

case CH_SCAN_STATE_SCAN_FAILED:
case CH_SCAN_STATE_EXIT:
xStageExit();
goto EXIT_SCANNING;
break;

case CH_SCAN_STATE_IDLE:
default:
goto EXIT_SCANNING;
}

if (m_cancelScan == true)
m_scanState = CH_SCAN_STATE_EXIT;

return;

EXIT_SCANNING:
m_runThread = false;
return;
}

CH_SCAN_STATE_INIT

xWorkerThread状态机运行前,ScanThread设置了状态机初始状态CH_SCAN_STATE_INIT,等状态机正式开始,xStageInit()函数做了一些初始化工作,比如:扫台模式设置、一些状态位初始化、si状态设置等等。大致涉及的函数:

1
2
3
4
5
6
7
8
9
10
11
12
/*
* vendor/realtek/frameworks/native/appclass/ \
* MediaControl/Component/Channel/Scan/TableScanner.cpp
*/

void CTableScanner::xStageInit()
{
// 省略代码段
m_pFreqScanDetector->Mf_ScanInit(scanMode, param, m_bDelNosignalMux,scanModeEx);
// 省略代码段
m_scanState = CH_SCAN_STATE_BEGIN_FREQ;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/* 
* vendor/realtek/frameworks/native/appclass/ \
* MediaControl/Component/Channel/Scan/DtvFreqDetector.cpp
*/

void CDtvFreqDetector::Mf_ScanInit(
CH_SCAN_MODE scanMode,
UINT32 param,
bool bDelNoSignalMux,
CH_SCAN_MODE_EX modeEx
)
{
// 省略代码段
m_pIDtvMedia->GetSiMgr()->ScanInit(getSiScanType(scanMode), param, typeEx);
// 省略代码段
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
* vendor/realtek/frameworks/native/appclass/ \
* MediaControl/Component/Si/DvbSiMgr.cpp
*/

void CDvbSiMgr::ScanInit(
SI_MGR_SCAN_TYPE type,
int antennaIndex,
SI_MGR_SCAN_TYPE_EX typeEx
)
{
SI *siHandle = (SI*)m_pTvMedia->GetDtvFlow()->GetSiHandle();
// 省略代码段
SI_SetState(siHandle, SI_STATE_AUTOSCAN);
SI_AutoScanInit(siHandle,antennaIndex,type==SI_MGR_SCAN_TYPE_AUTO_QUICK?TRUE:FALSE,FALSE);
// 省略代码段
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*
* vendor/realtek/frameworks/native/appclass/ \
* Si/liveTV_SiDvb/librtd/si4/api/SI_Api.c
*/

ErrCode SI_AutoScanInit(
SI *pSI,
int antennaIndex,
BOOL bSkipPMT,
BOOL bUpdateMode
)
{
// 省略代码段
if(bSkipPMT||SI_IS_UNITYMEDIA(pSI))
{
pSI->bSkipPMT=TRUE;
}
else
{
pSI->bSkipPMT=FALSE;
}
// 省略代码段
SI_Database_Reset(pSI->db,antennaIndex,TRUE);
SI_Channel_Reset(pSI->chMgr,antennaIndex,pSI->spec,pSI,SI_IS_SATELLITE(pSI));
// 省略代码段
setRelocatedService(pSI,-1,-1,0,-1,-1,0);
// 省略代码段
SiMessage_Reset(&pSI->mq);
// 省略代码段
}

最后把状态设置为CH_SCAN_STATE_BEGIN_FREQ

CH_SCAN_STATE_BEGIN_FREQ

在这个状态里,xStageBeginFreq()函数好像也是做一些初始化工作而已,如果是DVB-S盲扫,则在这里根据LNB Type设置不同的盲扫流程,以及根据本振频率设定扫台的起始频率和范围:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
* vendor/realtek/frameworks/native/appclass/ \
* MediaControl/Component/Channel/Scan/TableScanner.cpp
*/

void CTableScanner::xStageBeginFreq()
{
#ifdef ENABLE_SUPPORT_DVB_S
if(m_scanMode == CH_SCAN_MODE_BLIND_SCAN||m_scanMode == CH_SCAN_MODE_BLIND_SCAN_NETWORK)
{
// 省略代码段
/*Low/Horizontal,Low/Vertical,High/Horizontal,High/Vertical*/
if(lnbType != LNB_TYPE_KU_UNIVERSAL) // 单本振盲扫
{
m_blindScanTotalStep=2;
if(m_blindScanStep==0) // 单本振盲扫 第一阶段
{
m_curLoHz = loLow*100000;
m_curPolarization=0;
m_blindScanStep++;
}
else if(m_blindScanStep==1) // 单本振盲扫 第二阶段
{
m_curLoHz = loLow*100000;
m_curPolarization=1;
m_blindScanStep++;
}
else
{
m_scanState = CH_SCAN_STATE_EXIT;
return;
}
}
else // 双本振盲扫
{
bool bIsCBand = false;
if((loLow == 5150) && (loHigh == 5750))
{
/*Low/Horizontal,,High/Vertical*/
bIsCBand = true;
m_blindScanTotalStep=2;
}
else
{
m_blindScanTotalStep=4;
}

if(m_blindScanStep==0) // 双本振盲扫 C波段和Ku波段 第一阶段 Low/Horizontal
{
m_curLoHz = loLow*100000;
m_curPolarization=0;
m_blindScanStep++;
}
else if(m_blindScanStep==1)
{
if(bIsCBand) // 双本振盲扫 C波段 第二阶段 High/Vertical
{
m_curLoHz = loHigh*100000;
m_curPolarization=1;
}
else // 双本振盲扫 Ku波段 第二阶段 Low/Vertical
{
/* coverity[copy_paste_error : FALSE] */
m_curLoHz = loLow*100000;
m_curPolarization=1;
}
m_blindScanStep++;
}
else if(m_blindScanStep>=m_blindScanTotalStep)
{
m_scanState = CH_SCAN_STATE_EXIT;
return;
}
else if(m_blindScanStep==2) // 双本振盲扫 Ku波段 第三阶段 High/Horizontal
{
m_curLoHz = loHigh*100000;
m_curPolarization=0;
m_blindScanStep++;
}
else if(m_blindScanStep==3) // 双本振盲扫 Ku波段 第四阶段 High/Vertical
{
m_curLoHz = loHigh*100000;
m_curPolarization=1;
m_blindScanStep++;
}
else
{
m_scanState = CH_SCAN_STATE_EXIT;
return;
}
}

/*
#define kCBandMinFreq 950
#define kCBandMaxFreq 1750
#define kCBandScanRange (kCBandMaxFreq-kCBandMinFreq)

#define kKuBandLowIFMinFreq 950
#define kKuBandLowIFMaxFreq 1950
#define kKuBandHightMinFreq 1100
#define kKuBandHightMaxFreq 2150
#define kKuBandLowScanRange (kKuBandLowIFMaxFreq-kKuBandLowIFMinFreq)
#define kKuBandHighScanRange (kKuBandHightMaxFreq-kKuBandHightMinFreq)
#define kKuBandFullScanRange (kKuBandHightMaxFreq - kKuBandLowIFMinFreq)
*/
if(satInfo.bandType==SATELLITE_BAND_C)
{
((CDtvFreqDetector*) m_pFreqScanDetector)->SetBlindScanRange(kCBandScanRange); // 1750 - 950 //这里有点不懂
((CDtvFreqDetector*) m_pFreqScanDetector)->SetBlindScanStartFreq(kCBandMinFreq); // 950
}
else if(satInfo.bandType==SATELLITE_BAND_KU)
{
if(m_curLoHz == loLow*kFreqUnit)
{
((CDtvFreqDetector*) m_pFreqScanDetector)->SetBlindScanRange(kKuBandLowScanRange); // 1950 - 950
((CDtvFreqDetector*) m_pFreqScanDetector)->SetBlindScanStartFreq(kKuBandLowIFMinFreq); // 950
}
else
{
((CDtvFreqDetector*) m_pFreqScanDetector)->SetBlindScanRange(kKuBandHighScanRange); // 2150 - 1100
((CDtvFreqDetector*) m_pFreqScanDetector)->SetBlindScanStartFreq(kKuBandHightMinFreq); // 1100
}
}
else
{
((CDtvFreqDetector*) m_pFreqScanDetector)->SetBlindScanRange(kKuBandFullScanRange); // 2150 - 950
((CDtvFreqDetector*) m_pFreqScanDetector)->SetBlindScanStartFreq(kKuBandLowIFMinFreq); // 950
}
// 省略代码段
m_pFreqScanDetector->Mf_BlindScan(m_satelliteIndex,m_curLoHz, m_curPolarization);
m_scanState = CH_SCAN_STATE_SCANNING;
return;
}
#endif

// 省略代码段
if(m_curFreq!=0)
{
m_pFreqScanDetector->Mf_ScanFrequency(m_curFreq, m_curBandwidth, m_curChNum,m_curModulation,m_curSymbolRate,CH_SCAN_MODE_MANUAL==m_scanMode ? m_serviceID : 0,(CH_SCAN_MODE_UPDATE==m_scanMode||CH_SCAN_MODE_NETWORK_UPDATE==m_scanMode||CH_SCAN_MODE_ASU==m_scanMode)?false:true);
}

m_scanState = CH_SCAN_STATE_SCANNING;

// 省略代码段
}

最后把xWorkerThread状态机设置为CH_SCAN_STATE_SCANNING(该状态会建立一个另一个状态机RunStateProc)之前,把RunStateProc状态机初始设置为FREQ_SCAN_STATE_BEGIN_FREQ(Mf_ScanFrequency函数行为)或FREQ_SCAN_STATE_BEGIN_BLIND_SCAN(Mf_BlindScan函数行为)(DVB-S盲扫)。

CH_SCAN_STATE_SCANNING

RunStateProc的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/*
* vendor/realtek/frameworks/native/appclass/ \
* MediaControl/Component/Channel/Scan/DtvFreqDetector.cpp
*/

void CDtvFreqDetector::RunStateProc()
{
switch (m_scanState)
{
#ifdef ENABLE_SUPPORT_DVB_S
case FREQ_SCAN_STATE_BEGIN_BLIND_SCAN:
xStageBeginBlindScan();
break;
case FREQ_SCAN_STATE_BLIND_COLLECT_TP:
xStageBlindCollectTP();
break;
case FREQ_SCAN_STATE_BLIND_SCAN_TP:
xStageBlindScanTP();
break;
#endif
case FREQ_SCAN_STATE_BEGIN_FREQ:
xStageBeginFreq();
break;

case FREQ_SCAN_STATE_CHECK_FRONTEND:
xStageCheckFrontend();
break;

case FREQ_SCAN_STATE_CHECK_SI:
xStageCheckSi();
break;

case FREQ_SCAN_STATE_END_FREQ:
xStageEndFreq();
break;

default:
break;
}

if (m_bCancelScan == true)
{
#ifdef ENABLE_SUPPORT_DVB_S
if(m_curLoHz!=0)
{
DTV_STACK::TunerMgr* tuner = DTV_STACK::TunerMgr::getInstance();
unsigned char tunerId = -1;
tuner->getTunerId(tunerId);
m_curBlindFreq=0;
m_curLoHz=0;
TunerControlBlindScanEnd(tunerId);
}
#endif
m_scanState = FREQ_SCAN_STATE_IDLE;
}
}

xWorkerThread状态机CH_SCAN_STATE_BEGIN_FREQ阶段,已经初始化了RunStateProc的状态。

FREQ_SCAN_STATE_BEGIN_FREQ

对于每个频点,率先运行FREQ_SCAN_STATE_BEGIN_FREQ,xStageBeginFreq()这里主要干的事情:

  1. stop SI

    1
    2
    3
    4
    5
    6
    7
    /*
    * vendor/realtek/frameworks/native/appclass/ \
    * MediaControl/Component/Channel/Scan/DtvFreqDetector.cpp
    */

    m_pIDtvMedia->GetSiMgr()->SetMode(SI_MGR_MODE_INACTIVE);
    m_pIDtvMedia->GetSiMgr()->ResetTp();
  2. 把Tuner相关参数下给Demod,让Demod设置好Tuner,然后去check Tuner lock status

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    /*
    * vendor/realtek/frameworks/native/appclass/ \
    * MediaControl/Component/Channel/Scan/DtvFreqDetector.cpp
    */

    bool ret = tuner->tune(m_curFreq, m_curBandwidth, m_feType, m_modulation, RT_INVERSION_AUTO, true, m_symbolrate, &satInfo);
    // 省略代码段
    if (ret)
    {
    ret = tuner->isLocked();
    if (ret)
    {
    ALOGD("signal LOCKED !!!!!!!!\n");
    }
    else{
    ALOGD("signal UNLOCKD!!!!!!!!!\n");
    }
    }
    else //SetTuner fail or GetLock fail
    {
    ret = false;
    ALOGD("get lock Status FAIL!!!!! ERROR\n");
    }

    if(ret)
    {
    m_curPlpIndex = 0;
    m_scanState = FREQ_SCAN_STATE_CHECK_FRONTEND;
    }
    else // Lock fail case
    {
    if(m_bDelNoSignalMux)
    {
    m_pIDtvMedia->GetSiMgr()->RemoveCh(m_curFreq, m_bDelManualScanService);
    }
    else
    {
    m_pIDtvMedia->GetSiMgr()->SetSignalInfo(0, 0, m_curFreq);
    }

    m_scanState = FREQ_SCAN_STATE_END_FREQ;
    return;
    }

    这一阶段算是完了。

    关注一下这个tune函数(以下用到的代码主要以DVB-T扫台为例,当然也有制式共用的):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    /*
    * vendor/realtek/frameworks/native/appclass/ \
    * DriverBasedDtvApp/TunerMgr.cpp
    */

    bool TunerMgr::tune(
    UINT32 frequency,
    UINT32 bandwidth,
    RT_FRONTEND_TYPE feType,
    RT_MODULATION modulation,
    RT_SPECTRAL_INVERSION inversion,
    bool isScanMode,
    UINT32 symbolRate,
    SatelliteInfo *pSatelliteInfo
    )
    {
    mFreq = frequency;
    mBandwidth = bandwidth;
    return FrontendLib_SetTuner(frequency, bandwidth, mTunerId, feType, modulation, inversion, isScanMode, symbolRate, pSatelliteInfo);
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    /*
    * vendor/realtek/frameworks/native/appclass/ \
    * DriverBasedDtvApp/FrontendLib.cpp
    */

    bool FrontendLib_SetTuner(
    UINT32 frequency,
    UINT32 bandwidth,
    UINT8 tunerId,
    RT_FRONTEND_TYPE feType,
    RT_MODULATION modulation,
    RT_SPECTRAL_INVERSION inversion,
    bool isScanMode,
    UINT32 symbolRate,
    SatelliteInfo* pSatelliteInfo
    )
    {
    int tuner_ctrl_status;
    TV_SIG_INFO signalInfo;
    unsigned int buf;

    if (frequency == 0)
    return false;

    memset(&signalInfo,0,sizeof(signalInfo));

    /*
    re-adjust feType!?
    */
    if (feType == RT_FRONTEND_DVB_TERRESTRIAL || feType == RT_FRONTEND_DVB_T2)
    {
    if (FRONTENDLIB_GET_DVB_T2_PLP_INDEX(frequency) >= 0)
    {
    feType = RT_FRONTEND_DVB_T2;
    }
    else
    {
    feType = RT_FRONTEND_DVB_TERRESTRIAL;
    }
    }

    #ifdef ENABLE_PROFILE
    RtProfile_TimeBegin(RT_PROFILE_1);
    #endif

    TV_SYSTEM tvSystem = xFrontendLib_GetTunerSystem(feType, bandwidth);
    ALOGD("[FrontendLib_SetTuner %d] frequency=%d bandwidth=%d tvSystem=%d\n", __LINE__, frequency,bandwidth,tvSystem);

    if (feType == RT_FRONTEND_DVB_TERRESTRIAL)
    {
    if (!FrontendLib_getDVBT_IsSupported()) return false;

    signalInfo.dvbt2_ofdm.scan_mode = isScanMode;
    signalInfo.mod=TV_MODULATION_OFDM;
    if (FRONTENDLIB_IS_HIERARCHY_MODE(frequency) != 0)
    {
    signalInfo.ofdm.hierarchy=HIERARCHY_MODE_LOW;
    }
    else
    {
    signalInfo.ofdm.hierarchy=HIERARCHY_MODE_HIGH;
    }

    if (isScanMode == true)
    {
    if(tvSystem == TV_SYS_DVBT_6M)
    tvSystem = TV_SYS_AUTOSCAN_6M;
    else if(tvSystem==TV_SYS_DVBT_7M)
    tvSystem = TV_SYS_AUTOSCAN_7M;
    else
    tvSystem = TV_SYS_AUTOSCAN_8M;
    }

    buf = FRONTENDLIB_GET_FREQUENCY(frequency);
    tuner_ctrl_status = TunerControlSetFrontendEx(tunerId,buf,tvSystem,&signalInfo,isScanMode);
    }
    else if (feType == RT_FRONTEND_DVB_T2)
    {
    if (!FrontendLib_getDVBT2_IsSupported()) return false;

    signalInfo.dvbt2_ofdm.scan_mode = isScanMode;

    int plpId = FRONTENDLIB_GET_DVB_T2_PLP_INDEX(frequency);
    if (plpId >= 0)
    {
    signalInfo.dvbt2_ofdm.plp_select = plpId;
    if(isScanMode == true)
    {
    if(tvSystem == TV_SYS_DVBT2_1D7M)
    tvSystem = TV_SYS_DVBT2_1D7M_PLP;
    else if(tvSystem == TV_SYS_DVBT2_6M)
    tvSystem = TV_SYS_DVBT2_6M_PLP;
    else if(tvSystem == TV_SYS_DVBT2_7M)
    tvSystem = TV_SYS_DVBT2_7M_PLP;
    else
    tvSystem = TV_SYS_DVBT2_8M_PLP;
    }
    }
    else
    {
    if(isScanMode == true)
    {
    if(tvSystem==TV_SYS_DVBT2_6M)
    tvSystem = TV_SYS_AUTOSCAN_6M;
    else if(tvSystem==TV_SYS_DVBT2_7M)
    tvSystem = TV_SYS_AUTOSCAN_7M;
    else
    tvSystem = TV_SYS_AUTOSCAN_8M;
    }
    signalInfo.dvbt2_ofdm.plp_select=-1;
    }

    buf=FRONTENDLIB_GET_FREQUENCY(frequency);
    tuner_ctrl_status = TunerControlSetFrontendEx(tunerId,buf,tvSystem,&signalInfo,isScanMode);
    }
    else if (feType == RT_FRONTEND_DVB_CABLE)
    {
    if (!FrontendLib_getDVBC_IsSupported()) return false;

    unsigned short qam_const = QAM_CONST_64;

    signalInfo.dvbc_qam.scan_mode = isScanMode;
    signalInfo.dvbc_qam.alpha = QAM_ALPHA_15;

    switch (modulation)
    {
    case RT_MOD_QAM4 : qam_const = QAM_CONST_4; signalInfo.dvbc_qam.alpha = QAM_ALPHA_13; break;
    case RT_MOD_QAM16 : qam_const = QAM_CONST_16; signalInfo.dvbc_qam.alpha = QAM_ALPHA_13; break;
    case RT_MOD_QAM32 : qam_const = QAM_CONST_32; signalInfo.dvbc_qam.alpha = QAM_ALPHA_13; break;
    case RT_MOD_QAM64 : qam_const = QAM_CONST_64; signalInfo.dvbc_qam.alpha = QAM_ALPHA_15; break;
    case RT_MOD_QAM128 : qam_const = QAM_CONST_128; signalInfo.dvbc_qam.alpha = QAM_ALPHA_15; break;
    case RT_MOD_QAM256 : qam_const = QAM_CONST_256; signalInfo.dvbc_qam.alpha = QAM_ALPHA_15; break;
    case RT_MOD_QAM512 : qam_const = QAM_CONST_512; signalInfo.dvbc_qam.alpha = QAM_ALPHA_15; break;
    case RT_MOD_QAM1024: qam_const = QAM_CONST_1024;signalInfo.dvbc_qam.alpha = QAM_ALPHA_15; break;
    default: break;
    }

    buf = FRONTENDLIB_GET_FREQUENCY(frequency);

    signalInfo.mod = TV_MODULATION_DVBC_QAM;
    signalInfo.dvbc_qam.constellation = qam_const;
    signalInfo.dvbc_qam.symbol_rate = 6875000;

    tuner_ctrl_status = TunerControlSetFrontendEx(tunerId, buf, tvSystem, &signalInfo, isScanMode);
    }
    else if (feType == RT_FRONTEND_ABS_S)
    {
    if (!FrontendLib_getDVBS_IsSupported()) return false;

    //assert(symbolRate);
    if(symbolRate == 0)
    printf("[FrontendLib_SetTuner]:ABS_S:SymbolRate=%d,tuner can't lock!\n",symbolRate);

    buf = FRONTENDLIB_GET_FREQUENCY(frequency);

    signalInfo.abss.mod = TV_MODULATION_ABSS;
    signalInfo.abss.symbol_rate = symbolRate ;
    signalInfo.abss.spectrum_inv = inversion == RT_INVERSION_OFF ? 0 : 1 ;
    signalInfo.abss.scan_mode = isScanMode;
    tuner_ctrl_status = TunerControlSetFrontendEx(tunerId, buf, tvSystem, &signalInfo, isScanMode);
    }
    else if(feType == RT_FRONTEND_DVB_SATELLITE)
    {
    if (FRONTENDLIB_IS_DVB_S2_MODE(frequency))
    {
    if (!FrontendLib_getDVBS2_IsSupported()) return false;
    tvSystem = TV_SYS_DVBS2;
    }
    else
    {
    if (!FrontendLib_getDVBS_IsSupported()) return false;
    tvSystem = TV_SYS_DVBS;
    }

    signalInfo.dvbs.symbol_rate=FRONTENDLIB_GET_SYMBOLRATE(symbolRate);
    signalInfo.dvbs.scan_mode = isScanMode;
    if(FRONTENDLIB_GET_DVB_S_MODULATION(symbolRate) > 0)
    {
    signalInfo.dvbs.zapping_mode = 1;
    signalInfo.dvbs.modulation = FRONTENDLIB_GET_DVB_S_MODULATION(symbolRate)-1;
    signalInfo.dvbs.code_rate = FRONTENDLIB_GET_DVB_S_CODERATE(symbolRate);
    signalInfo.dvbs.pilot_onoff = FRONTENDLIB_GET_DVB_S_PILOT(symbolRate);
    signalInfo.dvbs.spec_invert = FRONTENDLIB_GET_DVB_S_SPEC_INVERT(symbolRate);
    }


    bool bLong_Cable = false;
    bool bIsSingleCable = false;

    if(pSatelliteInfo == 0)
    {
    ALOGD("[FrontendLib_SetTuner %d] satellite info is not available\n", __LINE__);
    return false;
    }
    ENUM_ANTENNA_SYSTEM vAntenna_system = pSatelliteInfo->antennaConfig.antenna_system;
    bLong_Cable = (bool)pSatelliteInfo->antennaConfig.longcable;
    bIsSingleCable = (vAntenna_system == ANTENNA_SINGLE_CABLE) || (pSatelliteInfo->unicableConfig.UB_State);
    int scrChannel = pSatelliteInfo->unicableConfig.UB_Index;

    if(vAntenna_system == ANTENNA__MAX)
    {
    ALOGD("[FrontendLib_SetTuner %d] antenna system is not available\n", __LINE__);
    return false;
    }

    if(bIsSingleCable)
    {
    // ALOGD(" --> UniCable case");
    unsigned char lock = 0;
    if (TunerControlGetLockStatus(tunerId, &lock) == TUNER_CTRL_OK && lock)
    {
    unsigned char data[5] = {0xE0, 0x10, 0x5A, (unsigned char)(((scrChannel-1) & 0x7) << 5), 0};

    TunerControlSetLnbConfig(tunerId, 1, 1, 0, bLong_Cable);
    TunerControlSetDiseqcContinue22kOnOff(tunerId, 0);
    TunerSetUniCableDiseqcControl(tunerId, 5, data, bLong_Cable);//send ODU_PowerOFF
    if (TunerControlGetLockStatus(tunerId, &lock) == TUNER_CTRL_OK && lock)
    TunerSetUniCableDiseqcControl(tunerId, 5, data, bLong_Cable);
    }
    }

    // Setup LNB and get IF value
    uint32_t IF = 0;
    FrontendLib_SetDiSEqCAndLnb(tunerId, frequency, IF, signalInfo, false, pSatelliteInfo);
    if(( IF >= dvb_s_tuner_freq_start * 100000 && IF <= dvb_s_tuner_freq_end * 100000) || IF == 0)
    {
    tuner_ctrl_status = TunerControlSetFrontendEx(tunerId, IF * 10, tvSystem, &signalInfo, isScanMode);
    ALOGD("[FrontendLib_SetTuner %d] IF = %d, tuner_ctrl_status = %d\n", __LINE__, IF, tuner_ctrl_status);
    }
    else
    {
    ALOGD("[FrontendLib_SetTuner %d] IF = %d\n", __LINE__, IF);
    FrontendLib_SetDiSEqCAndLnb(tunerId, frequency, IF, signalInfo, true, pSatelliteInfo);
    tuner_ctrl_status=TUNER_CTRL_FAIL;
    }
    ALOGD("[FrontendLib_SetTuner %d] tuner_ctrl_status = %d\n", __LINE__, tuner_ctrl_status);
    }
    else if (feType == RT_FRONTEND_DMBTH)
    {
    if (!FrontendLib_getDTMB_IsSupported()) return false;

    buf = FRONTENDLIB_GET_FREQUENCY(frequency);
    signalInfo.mod = TV_MODULATION_DTMB_OFDM;
    signalInfo.dtmb_ofdm.mod = TV_MODULATION_DTMB_OFDM;
    signalInfo.dtmb_ofdm.scan_mode = isScanMode;
    tuner_ctrl_status = TunerControlSetFrontendEx(tunerId, buf, tvSystem, &signalInfo, isScanMode);
    }
    else if (feType == RT_FRONTEND_ATSC)
    {
    signalInfo.mod = TV_MODULATION_VSB;
    signalInfo.vsb.scan_mode = isScanMode;
    buf = FRONTENDLIB_GET_FREQUENCY(frequency);
    tuner_ctrl_status = TunerControlSetFrontendEx(tunerId, buf, tvSystem, &signalInfo, isScanMode);
    }
    else if (feType == RT_FRONTEND_OPCABLE)
    {
    signalInfo.mod = TV_MODULATION_QAM;
    signalInfo.qam.scan_mode = isScanMode;
    buf = FRONTENDLIB_GET_FREQUENCY(frequency);
    tuner_ctrl_status = TunerControlSetFrontendEx(tunerId, buf, tvSystem, &signalInfo, isScanMode);
    }
    else
    {
    buf=FRONTENDLIB_GET_FREQUENCY(frequency);

    if (isScanMode)
    tuner_ctrl_status = TunerControlSetFrontend(tunerId, buf, tvSystem);
    else
    {
    tuner_ctrl_status = TunerControlSetFrontendEx(tunerId, buf, tvSystem, NULL, 0);
    }
    }

    if (tuner_ctrl_status != TUNER_CTRL_OK)
    return false;

    return true;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    /*
    * vendor/realtek/frameworks/native/rtkhal/ \
    * rhal_tvfe/src/api/src/DTVTunerControl.cpp
    */

    int TunerControlSetFrontendEx(
    unsigned char id,
    unsigned long frequency,
    TV_SYSTEM sys,
    const TV_SIG_INFO* pSigInfo,
    unsigned char WaitSignalLock
    )
    {
    Frontend* pFE = GetTunerHandle(id);
    unsigned long cur_time;
    int ret;

    if (pFE != NULL) {
    SET_THREAD_MUTE();
    cur_time = pli_getMilliseconds();

    ret = pFE->SetFrontendEx(frequency, sys, pSigInfo, (WaitSignalLock) ? DTV_FE_FLAG_WAIT_SIGNAL_LOCK : 0);
    TunerControlSavingLog("FE%d,OP,SET_FE,%lu,%d,%d,%lu", id, frequency, sys, ret, tv_osal_time() - cur_time);

    CLR_THREAD_MUTE();
    return TunerControlErrorHandler(id, ret);
    }

    return TUNER_CTRL_ENODEV;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    /*
    * vendor/realtek/frameworks/native/rtkhal/ \
    * rhal_tvfe/src/frontend/src/frontend.cpp
    */

    int Frontend::SetFrontendEx(
    unsigned long freq,
    TV_SYSTEM sys,
    const TV_SIG_INFO * pSigInfo,
    unsigned long Flags
    )
    {
    // 省略代码段
    return SetDemod(freq, sys, pSigInfo, Flags);
    // 省略代码段
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    /*
    * vendor/realtek/frameworks/native/rtkhal/ \
    * rhal_tvfe/src/frontend/src/frontend.cpp
    */

    /*=======================================================
    * Func : SetDemod
    *
    * Desc : Set Demod
    *
    * Parm : freq : current frequency
    * sys : Target TV System
    * pSigInfo : Signal info that previous known to help
    * accelerate acquiring signals.
    * Flags : control flag for set frontend
    * 0: acuire signal but no wait lock
    * 1: acuire signal wait signal lock
    * 0xff: no acquire signal
    *
    * Retn : TUNER_CTRL_OK / TUNER_CTRL_FAIL
    *=======================================================*/
    int Frontend::SetDemod(
    unsigned long freq,
    TV_SYSTEM sys,
    const TV_SIG_INFO * pSigInfo,
    unsigned long Flags
    )
    {
    int ret = TUNER_CTRL_OK;
    unsigned char lock;

    if (m_op_mode == TV_OP_MODE_TP_ONLY)
    return TUNER_CTRL_OK;

    Lock();

    if (m_op_mode == TV_OP_MODE_STANDBY) {
    ret = TUNER_CTRL_FAIL;
    goto end_proc;
    }

    DTVFE_INFO("SetDemod : freq=%lu, tv_sys=%s(%d)\n", freq, tv_sys_name(sys), sys);

    set_demod:

    //if ((m_tv_sys != sys) || (pSigInfo != NULL)) {
    ret = m_pDemod->SetTVSysEx(sys, pSigInfo);

    if (ret != TUNER_CTRL_OK)
    goto end_proc;
    //}
    if (Flags < 2)
    ret = m_pDemod->AcquireSignal((Flags & DTV_FE_FLAG_WAIT_SIGNAL_LOCK) ? 1 : 0);

    end_proc:

    // If Just No Signal, We Keep The TV Sys Setting, We can save 200ms to SetTVSysEx()
    if ((ret == TUNER_CTRL_OK) || (ret == TUNER_CTRL_NO_SIGNAL) || (Flags >= 2))
    _UpdateFEParam(sys, freq);
    else
    _UpdateFEParam(TV_SYS_UNKNOWN, 0);

    Unlock();

    return ret;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    /*
    * vendor/realtek/frameworks/native/rtkhal/ \
    * rhal_tvfe/src/demod/src/demod_realtek_dtv.cpp
    */

    int REALTEK_DTV::AcquireSignal(unsigned char WaitSignalLock)
    {
    int ret;
    RTK_DEMOD_SET_ACQ_SIG set_acq_sig_data;
    set_acq_sig_data.WaitSignalLock = WaitSignalLock;
    set_acq_sig_data.return_value = 0;
    Lock();

    RHAL_DEMOD_ACQUIRESIGNAL(&set_acq_sig_data);
    Unlock();

    return set_acq_sig_data.return_value;
    //return TUNER_CTRL_OK;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /*
    * vendor/realtek/frameworks/native/rtkhal/ \
    * hal_src/hal/src/demod/rhal_demod_adtv.cpp
    */

    int RHAL_DEMOD_ACQUIRESIGNAL (RTK_DEMOD_SET_ACQ_SIG* pset_acq_sig_data)
    {
    int ret;
    ret = ioctl(hDevHandle, IOCTL_RTK_DEMOD_ACQUIRESIGNAL, pset_acq_sig_data);
    return ret;
    }

    到这就要跑到驱动了:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    /*
    * drivers/rtk_kdriver/demod/DemodMgr.c
    */

    static long rtk_demod_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
    {
    // 省略代码段
    switch (cmd)
    {
    // 省略代码段
    case IOCTL_RTK_DEMOD_ACQUIRESIGNAL:
    if (copy_from_user((void *)&pDemod_globe->set_acq_sig_data, (const void __user *)arg, sizeof(RTK_DEMOD_SET_ACQ_SIG)))
    {
    ret = 0;
    DEMOD_MGR_WARNING("RTKDEMOD[%d]: ioctl IOCTL_RTK_DEMOD_ACQUIRESIGNAL failed !!!!!!!!!!!!!!!\n", __LINE__);
    }
    else
    {
    pDemod_globe->set_acq_sig_data.return_value = pDemod_globe->m_pDemod->AcquireSignal(pDemod_globe->m_pDemod, pDemod_globe->set_acq_sig_data.WaitSignalLock);
    if (copy_to_user((void __user *)arg, &pDemod_globe->set_acq_sig_data, sizeof(RTK_DEMOD_SET_ACQ_SIG)))
    ret = 0;
    else
    ret = -EFAULT;
    }
    break;
    // 省略代码段
    }
    // 省略代码段
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    /*
    * drivers/rtk_kdriver/demod/demod_rtk_a_dvbtx.c
    */

    int REALTEK_A_DVBTX_AcquireSignal(DEMOD* pDemodKernel, unsigned char WaitSignalLock)
    {

    #ifdef CONFIG_RTK_KDRV_DEMOD_SCAN_THREAD_ENABLE
    unsigned long cur_time;
    #endif

    REALTEK_A_DVBTX* pRealtekADVBTX;
    DVBTX_DEMOD_MODULE* pDemod;
    pRealtekADVBTX = (REALTEK_A_DVBTX*)(pDemodKernel->private_data);
    pDemod = ((REALTEK_A_DVBTX_DRIVER_DATA*) pRealtekADVBTX->m_private)->pDemod;


    #ifdef CONFIG_RTK_KDRV_DEMOD_SCAN_THREAD_ENABLE
    cur_time = tv_osal_time();

    while ((tv_osal_time() - cur_time) <= 15) {

    if (pRealtekADVBTX->m_acquire_sig_en == 0)
    return TUNER_CTRL_OK;

    tv_osal_msleep(5);
    }

    return TUNER_CTRL_FAIL;

    #else
    REALTEK_A_DVBTX_AcquireSignalThread(pDemodKernel);
    pRealtekADVBTX->m_autotune_stime = tv_osal_time() + AUTODETECT_SIG_UPDATE_INTERVAL_MS;
    pRealtekADVBTX->m_autotune_TsTime = tv_osal_time() + AUTOTUNE_UPDATE_TS_CLK_INTERVAL_MS;
    pRealtekADVBTX->m_dvbt2_PLPcheck_stime = tv_osal_time() + AUTOTUNE_T2PLP_CHECK_INTERVAL_MS;
    return TUNER_CTRL_OK;
    #endif
    }

    接下来,细节好多,只能省略了:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    /*
    * drivers/rtk_kdriver/demod/demod_rtk_a_dvbtx.c
    */

    int REALTEK_A_DVBTX_AcquireSignalThread(DEMOD* pDemodKernel)
    {
    // 省略代码段
    pDemod->IsSignalLocked(pDemod, &FecLockFlag)
    // 省略代码段
    }

    再下来,几乎是最底层的部分了:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    /*
    * drivers/rtk_kdriver/demod/demodcore/dvbtx_demod_rtk_a.c
    */

    int realtek_a_dvbtx_IsSignalLocked(DVBTX_DEMOD_MODULE *pDemod, int *pAnswer)
    {
    RTK_A_DVBTX_STATUS status = RTK_A_DVBTX_SUCCESSFUL;
    unsigned char u8BlockFEC = 0;
    unsigned char u8DVBTxMode = 0, u8TPSDone = 0, u8DvbtFecLock = 0;
    unsigned char u8Read_data = 0;
    int i = 0, cnt= 0;

    *pAnswer = 0;

    if (realtek_a_dvbtx_GetDVBTxMode(pDemod, &u8DVBTxMode) != FUNCTION_SUCCESS)
    return FUNCTION_ERROR;
    //DVBT mode
    if (u8DVBTxMode == RTK_A_DVBTX_DVBT_MODE) {
    for(i=0;i<=4;i++){ //check 5 time locked
    status |= RTK_A_DVBTX_Read(pDemod, 0x28, 0x2c, &u8TPSDone);
    status |= RTK_A_DVBTX_Read(pDemod, 0x95, 0x37, &u8DvbtFecLock);

    if ((u8DvbtFecLock & 0x01) && (u8TPSDone & 0x01)) { /*TPS done and FEC lock, DVB-T locked*/
    cnt++;
    if(cnt >= 5){
    *pAnswer = 1;
    return (status == RTK_A_DVBTX_SUCCESSFUL) ? FUNCTION_SUCCESS : FUNCTION_ERROR;
    }
    }
    tv_osal_msleep(1);
    }

    status |= RTK_A_DVBTX_Read(pDemod, 0x17, 0xD9, &u8Read_data); //Check FEC RST bit OFF
    if (((u8Read_data & 0x08) != 0x08) && (u8TPSDone & 0x01)) { /*TPS done and FEC Reset Off , DVB-T locked*/
    *pAnswer = 1;
    return (status == RTK_A_DVBTX_SUCCESSFUL) ? FUNCTION_SUCCESS : FUNCTION_ERROR;
    }
    }

    //DVBT2 mode
    if (u8DVBTxMode == RTK_A_DVBTX_DVBT2_MODE) {
    status |= RTK_A_DVBTX_Read(pDemod, 0x17, 0xEC, &u8BlockFEC);
    if (u8BlockFEC & 0x01) { //DVB-T2 FEC locked
    *pAnswer = 1;
    return (status == RTK_A_DVBTX_SUCCESSFUL) ? FUNCTION_SUCCESS : FUNCTION_ERROR;
    }
    }

    return status;
    }

    这是在干啥?应该就是I2C读取Tuner状态吧?看看:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    /*
    * drivers/rtk_kdriver/demod/demodcore/dvbtx_demod_rtk_a_base.c
    */

    /****************************************************************************
    Function: RTK_A_DVBSX_RbusRead
    Parameters: u8BaseAddr Chip Base Address,eg.0x88; u8OffsetAddr:Chip Sub Address;
    u8RegValue:The Pointer Which Return The Data Read Form Chip.
    Return: Read Status:RTK_DEMOD_SUCCESSFUL is Normal and other is abnormal.

    Description:
    This function used to read data form chip register
    ****************************************************************************/
    RTK_A_DVBSX_STATUS RTK_A_DVBSX_Read(
    DVBSX_DEMOD_MODULE *pDemod,
    unsigned char u8BaseAddr,
    unsigned char u8OffsetAddr,
    unsigned char *u8RegValue
    )
    {
    RTK_A_DVBSX_STATUS ui8Status = RTK_DEMOD_SUCCESSFUL;

    ui8Status |= RTK_A_DVBSX_I2CRead(pDemod, u8BaseAddr, u8OffsetAddr, u8RegValue);
    //ui8Status |= rbus_demod_read(u8BaseAddr, u8OffsetAddr, u8RegValue);

    return ui8Status;
    }

    大致就是这样,完了。

FREQ_SCAN_STATE_CHECK_FRONTEND

如果锁到信号,状态就更新为FREQ_SCAN_STATE_CHECK_FRONTEND了,这个阶段,xStageCheckFrontend()的工作:

  1. Update modulation(DVB-S,DVB-C,DVB-T), bandwidth, and symbol rate

  2. Notify SI to start scanning

    1
    2
    3
    4
    5
    6
    7
    8
    /*
    * vendor/realtek/frameworks/native/appclass/ \
    * MediaControl/Component/Channel/Scan/DtvFreqDetector.cpp
    */

    m_pIDtvMedia->GetSiMgr()->ScanStart(m_curFreq, m_modulation, m_curBandwidth, symbolrate, m_curPhyChNum, tuner->getRFStrength(), tuner->getSignalSNR(), m_serviceID);

    m_scanState = FREQ_SCAN_STATE_CHECK_SI;

FREQ_SCAN_STATE_CHECK_SI

frontend设置好后,把状态更新为FREQ_SCAN_STATE_CHECK_SI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/*
* vendor/realtek/frameworks/native/appclass/ \
* MediaControl/Component/Channel/Scan/DtvFreqDetector.cpp
*/

/*
* stage of check SI
* step 1: retry until SI scanning is done
* step 2: handle T and T2 case if it needs
*/
void CDtvFreqDetector::xStageCheckSi()
{
DTV_STACK::TunerMgr* tuner = DTV_STACK::TunerMgr::getInstance();

RETRY:
if (m_pIDtvMedia->GetSiMgr()->ScanIsDone(&m_bIsGetService) == false)
{
m_pIDtvMedia->GetSiMgr()->SetSignalInfo(tuner->getRFStrength(), tuner->getSignalSNR());
usleep(10000);

#ifdef ENABLE_SUPPORT_DVB_S
if(m_curLoHz != 0)
{
if(!m_bCancelScan)
goto RETRY;
}
#endif
return;
}

// Terrestrial case :
// We should check if we need to check current frequency again with different parameters
if (HasHandleCurFreqAgainInDvbT())
{
return;
}

// Fill modulation to each channel to prevent error when playing channel
m_pIDtvMedia->GetSiMgr()->SetModulation(m_curFreq, m_modulation);
m_scanState = FREQ_SCAN_STATE_END_FREQ;

#ifdef ENABLE_SUPPORT_DVB_S
if(m_curLoHz != 0)
{
UpdateChInfo();
SendEvent(RT_SCAN_EVENT_FREQ_DONE, m_curFreq);
m_scanState = FREQ_SCAN_STATE_BLIND_SCAN_TP;
}
#endif

return;
}

FREQ_SCAN_STATE_END_FREQ

等SI搞掂之后,状态变更为FREQ_SCAN_STATE_END_FREQ,这个频点就算是扫完了:

1
2
3
4
5
6
7
8
9
10
11
12
13
/*
* vendor/realtek/frameworks/native/appclass/ \
* MediaControl/Component/Channel/Scan/DtvFreqDetector.cpp
*/

void CDtvFreqDetector::xStageEndFreq()
{
m_curPlpIndex = 0;

// Reset tuner to force doing "set tuner" when playing channel after scan-ch.
DTV_STACK::TunerMgr* tuner = DTV_STACK::TunerMgr::getInstance();
tuner->reset();
}

至此,对于一个频点的扫台,RunStateProc状态机算是完成了使命。但是DVB-S盲扫略有不同,它的初始状态不是FREQ_SCAN_STATE_BEGIN_FREQ,而是FREQ_SCAN_STATE_BEGIN_BLIND_SCAN

FREQ_SCAN_STATE_BEGIN_BLIND_SCAN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
* vendor/realtek/frameworks/native/appclass/ \
* MediaControl/Component/Channel/Scan/DtvFreqDetector.cpp
*/

void CDtvFreqDetector::xStageBeginBlindScan()
{
// 省略代码段
//Blind Scan switch to LNB_POWER_ON temporarily, let curBlindFreq to decide the H/V settings.
m_satInfo.antennaConfig.power = LNB_POWER_ON;

tuner->tune(m_curBlindFreq, 0, m_feType, RT_MOD_DVB_S2, RT_INVERSION_AUTO, false, 0, &m_satInfo);

if(m_satInfo.antennaConfig.type == LNB_TYPE_C)
{
FrontendLib_BlindScan_Init(tunerId,CBAND_MIN_FREQ,CBAND_MAX_FREQ); // 950 1750 // 这里有点不懂
}
else
{
if(m_curLoHz == kKuBandLnbOscLow)
{
FrontendLib_BlindScan_Init(tunerId,kKuBandLowIFMinFreq,kKuBandLowIFMaxFreq); // 950 1950
}
else
{
FrontendLib_BlindScan_Init(tunerId,kKuBandHightMinFreq,kKuBandHightMaxFreq); // 1100 2150
}
}

m_scanState = FREQ_SCAN_STATE_BLIND_COLLECT_TP;
}

FREQ_SCAN_STATE_BLIND_COLLECT_TP

FREQ_SCAN_STATE_BLIND_COLLECT_TP阶段,全频段步进收集中频,很多操作都是跟以上分析的tune函数差不多流程,一步一步控制到Tuner,就不一一列举分析了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
* vendor/realtek/frameworks/native/appclass/ \
* MediaControl/Component/Channel/Scan/DtvFreqDetector.cpp
*/

void CDtvFreqDetector::xStageBlindCollectTP()
{
// 省略代码段
if(bBlindScanEnd!=0)
{
TunerControlBlindScanEnd(tunerId);
m_blindIndex=-1;
m_scanState = FREQ_SCAN_STATE_BLIND_SCAN_TP;
PickTPFromFreqTable();
}
// 省略代码段
}

FREQ_SCAN_STATE_BLIND_SCAN_TP

FREQ_SCAN_STATE_BLIND_SCAN_TP阶段,中频+TP list 扫台。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
* vendor/realtek/frameworks/native/appclass/ \
* MediaControl/Component/Channel/Scan/DtvFreqDetector.cpp
*/

void CDtvFreqDetector::xStageBlindScanTP()
{
// 省略代码段
FrontendLib_BlindScan_AcquireSignal(tunerId,&FreqMhz,&SymbolRateKhz,&bBlindScanLock);
if(bBlindScanLock)
{
// 省略代码段
m_scanState = FREQ_SCAN_STATE_CHECK_FRONTEND;
// 省略代码段
}
// 省略代码段
if(bBlindScanEnd)
{
// 省略代码段
m_scanState = FREQ_SCAN_STATE_END_FREQ;
}
}

接下来的流程就跟正常扫台一样了,直到RunStateProc状态机跑完。

CH_SCAN_STATE_END_FREQ

当前频点扫完了,判断是扫下一个频点还是直接退出扫台:

1
2
3
4
5
6
7
8
9
/*
* vendor/realtek/frameworks/native/appclass/ \
* MediaControl/Component/Channel/Scan/TableScanner.cpp
*/

void CTableScanner::xStageEndFreq()
{
// 省略代码段
}

CH_SCAN_STATE_EXIT

退出扫台:

1
2
3
4
5
6
7
8
9
10
/*
* vendor/realtek/frameworks/native/appclass/ \
* MediaControl/Component/Channel/Scan/TableScanner.cpp
*/

void CTableScanner::xStageExit()
{
m_pFreqScanDetector->Mf_ScanDeInit();
// 省略代码段
}

m_runThread标志位被置为false,xWorkerThread状态机结束,ScanThread线程销毁。