1 /*
2  * dvbscan.cpp
3  *
4  * Copyright (C) 2008-2011 Christoph Pfister <christophpfister@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 #include "../log.h"
22 
23 #include <QBitArray>
24 #include <QVector>
25 #include <stdint.h>
26 
27 #include "dvbdevice.h"
28 #include "dvbscan.h"
29 #include "dvbsi.h"
30 
31 class DvbPatEntry
32 {
33 public:
DvbPatEntry(int programNumber_,int pid_)34 	DvbPatEntry(int programNumber_, int pid_) : programNumber(programNumber_), pid(pid_) { }
~DvbPatEntry()35 	~DvbPatEntry() { }
36 
37 	int programNumber;
38 	int pid;
39 };
40 
41 Q_DECLARE_TYPEINFO(DvbPatEntry, Q_MOVABLE_TYPE);
42 
43 class DvbSdtEntry
44 {
45 public:
DvbSdtEntry(int serviceId_,int networkId_,bool scrambled_)46 	DvbSdtEntry(int serviceId_, int networkId_, bool scrambled_) : serviceId(serviceId_),
47 		networkId(networkId_), scrambled(scrambled_) { }
~DvbSdtEntry()48 	~DvbSdtEntry() { }
49 
50 	int serviceId;
51 	int networkId;
52 	bool scrambled;
53 	QString name;
54 	QString provider;
55 };
56 
57 class DvbScanFilter : public DvbSectionFilter, QObject
58 {
59 public:
DvbScanFilter(DvbScan * scan_,bool useOtherNit_)60 	DvbScanFilter(DvbScan *scan_, bool useOtherNit_) : scan(scan_), pid(-1), useOtherNit(useOtherNit_) { }
61 
~DvbScanFilter()62 	~DvbScanFilter()
63 	{
64 		stopFilter();
65 	}
66 
isActive() const67 	bool isActive() const
68 	{
69 		return (pid != -1);
70 	}
71 
72 	bool startFilter(int pid_, DvbScan::FilterType type_);
73 	void stopFilter();
74 
75 private:
76 	struct sectCheck {
77 		int id;
78 		QBitArray check;
79 	};
80 
81 	bool checkMultipleSection(const DvbStandardSection &section);
82 	bool isFinished();
83 	void processSection(const char *data, int size);
84 	void timerEvent(QTimerEvent *);
85 
86 	DvbScan *scan;
87 
88 	int pid;
89 	DvbScan::FilterType type;
90 	QVector<sectCheck> multipleSections;
91 	int timerId;
92 	bool useOtherNit;
93 };
94 
startFilter(int pid_,DvbScan::FilterType type_)95 bool DvbScanFilter::startFilter(int pid_, DvbScan::FilterType type_)
96 {
97 	Q_ASSERT(pid == -1);
98 
99 	pid = pid_;
100 	type = type_;
101 	multipleSections.clear();
102 
103 	if (!scan->device->addSectionFilter(pid, this)) {
104 		pid = -1;
105 		return false;
106 	}
107 
108 	// FIXME check timings
109 	if (type != DvbScan::NitFilter) {
110 		timerId = startTimer(5000);
111 	} else {
112 		timerId = startTimer(20000);
113 	}
114 
115 	return true;
116 }
117 
stopFilter()118 void DvbScanFilter::stopFilter()
119 {
120 	if (pid != -1) {
121 		killTimer(timerId);
122 		scan->device->removeSectionFilter(pid, this);
123 		multipleSections.clear();
124 
125 		pid = -1;
126 	}
127 }
128 
checkMultipleSection(const DvbStandardSection & section)129 bool DvbScanFilter::checkMultipleSection(const DvbStandardSection &section)
130 {
131 	int sectionCount = section.lastSectionNumber() + 1;
132 	int tableNumber = -1;
133 	int id = section.tableId() << 16 | section.tableIdExtension();
134 
135 	for (int i = 0; i < multipleSections.size(); i++) {
136 		if (multipleSections.at(i).id == id) {
137 			tableNumber = i;
138 			break;
139 		}
140 	}
141 	if (tableNumber < 0) {
142 		tableNumber = multipleSections.size();
143 		multipleSections.resize(tableNumber + 1);
144 		multipleSections[tableNumber].id = id;
145 		multipleSections[tableNumber].check.resize(sectionCount);
146 	}
147 
148 	if (section.sectionNumber() >= sectionCount) {
149 		qCWarning(logDvb, "Current section is bigger than the last one");
150 		sectionCount = section.sectionNumber() + 1;
151 	}
152 
153 	QBitArray *check = &multipleSections[tableNumber].check;
154 
155 	if (check->isEmpty()) {
156 		check->resize(sectionCount);
157 	} else {
158 		if (check->size() != sectionCount) {
159 			qCWarning(logDvb, "Inconsistent number of sections");
160 
161 			if (check->size() < sectionCount)
162 				check->resize(sectionCount);
163 		}
164 	}
165 
166 	if (check->testBit(section.sectionNumber())) {
167 		return false;
168 	}
169 
170 	check->setBit(section.sectionNumber());
171 	return true;
172 }
173 
isFinished()174 bool DvbScanFilter::isFinished()
175 {
176 	for (int i = 0; i < multipleSections.size(); i++) {
177 		if (multipleSections[i].check.count(false) != 0)
178 			return false;
179 	}
180 	return true;
181 }
182 
processSection(const char * data,int size)183 void DvbScanFilter::processSection(const char *data, int size)
184 {
185 	switch (type) {
186 	case DvbScan::PatFilter: {
187 		DvbPatSection patSection(data, size);
188 
189 		if (!patSection.isValid() || (patSection.tableId() != 0x0)) {
190 			return;
191 		}
192 
193 		if (!checkMultipleSection(patSection)) {
194 			// already read this part
195 			return;
196 		}
197 
198 		scan->processPat(patSection);
199 		break;
200 	    }
201 	case DvbScan::PmtFilter: {
202 		DvbPmtSection pmtSection(data, size);
203 
204 		if (!pmtSection.isValid() || (pmtSection.tableId() != 0x2)) {
205 			return;
206 		}
207 
208 		if (!checkMultipleSection(pmtSection)) {
209 			// already read this part
210 			return;
211 		}
212 
213 		scan->processPmt(pmtSection, pid);
214 		break;
215 	    }
216 	case DvbScan::SdtFilter: {
217 		// FIXME: should we also handle other SDT table?
218 
219 		DvbSdtSection sdtSection(data, size);
220 
221 
222 		if (!sdtSection.isValid() || (sdtSection.tableId() != 0x42)) {
223 			// there are also other tables in the SDT
224 			return;
225 		}
226 
227 		if (!checkMultipleSection(sdtSection)) {
228 			// already read this part
229 			return;
230 		}
231 
232 		scan->processSdt(sdtSection);
233 		break;
234 	    }
235 	case DvbScan::VctFilter: {
236 		AtscVctSection vctSection(data, size);
237 
238 		if (!vctSection.isValid() ||
239 		    ((vctSection.tableId() != 0xc8) && (vctSection.tableId() != 0xc9))) {
240 			// there are also other tables in the VCT
241 			return;
242 		}
243 
244 		if (!checkMultipleSection(vctSection)) {
245 			// already read this part
246 			return;
247 		}
248 
249 		scan->processVct(vctSection);
250 		break;
251 	    }
252 	case DvbScan::NitFilter: {
253 		DvbNitSection nitSection(data, size);
254 
255 
256 		if (!nitSection.isValid())
257 			return;
258 
259 		if (!((nitSection.tableId() == 0x40) || (useOtherNit && (nitSection.tableId() == 0x41))))
260 			return;
261 
262 		qCDebug(logDvb, "Handling NIT table ID 0x%02x, extension 0x%04x", nitSection.tableId(), nitSection.tableIdExtension());
263 
264 		if (!checkMultipleSection(nitSection)) {
265 			// already read this part
266 			return;
267 		}
268 
269 		scan->processNit(nitSection);
270 		break;
271 	    }
272 	}
273 
274 	if (isFinished())
275 		scan->filterFinished(this);
276 }
277 
timerEvent(QTimerEvent *)278 void DvbScanFilter::timerEvent(QTimerEvent *)
279 {
280 	qCWarning(logDvb, "Timeout while reading section; type = %d, PID = %d", type, pid);
281 	scan->filterFinished(this);
282 }
283 
DvbScan(DvbDevice * device_,const QString & source_,const DvbTransponder & transponder_,bool useOtherNit_)284 DvbScan::DvbScan(DvbDevice *device_, const QString &source_, const DvbTransponder &transponder_, bool useOtherNit_) :
285 	device(device_), source(source_), transponder(transponder_), isLive(true), isAuto(false), useOtherNit(useOtherNit_),
286 	transponderIndex(-1), state(ScanPat), patIndex(0), activeFilters(0)
287 {
288 	qCDebug(logDvb, "Use other NIT is %s", useOtherNit ? "enabled" : "disabled");
289 }
290 
DvbScan(DvbDevice * device_,const QString & source_,const QList<DvbTransponder> & transponders_,bool useOtherNit_)291 DvbScan::DvbScan(DvbDevice *device_, const QString &source_,
292 	const QList<DvbTransponder> &transponders_, bool useOtherNit_) : device(device_), source(source_),
293 	isLive(false), isAuto(false), useOtherNit(useOtherNit_), transponders(transponders_), transponderIndex(0),
294 	state(ScanTune), patIndex(0), activeFilters(0)
295 {
296 	qCDebug(logDvb, "Use other NIT is %s", useOtherNit ? "enabled" : "disabled");
297 }
298 
DvbScan(DvbDevice * device_,const QString & source_,const QString & autoScanSource,bool useOtherNit_)299 DvbScan::DvbScan(DvbDevice *device_, const QString &source_, const QString &autoScanSource, bool useOtherNit_) :
300 	device(device_), source(source_), isLive(false), isAuto(true), useOtherNit(useOtherNit_), transponderIndex(0),
301 	state(ScanTune), patIndex(0), activeFilters(0)
302 {
303 	qCDebug(logDvb, "Use other NIT is %s", useOtherNit ? "enabled" : "disabled");
304 
305 	// Seek for DVB-T transponders
306 
307 	if ((autoScanSource == QLatin1String("AUTO-T-Normal")) ||
308 	    (autoScanSource == QLatin1String("AUTO-T-Offsets")) ||
309 	    (autoScanSource == QLatin1String("AUTO-T2-Normal")) ||
310 	    (autoScanSource == QLatin1String("AUTO-T2-Offsets"))) {
311 		bool offsets = (autoScanSource == QLatin1String("AUTO-T-Offsets")) || (autoScanSource == QLatin1String("AUTO-T2-Offsets"));
312 
313 		for (int frequency = 177500000; frequency <= 226500000; frequency += 7000000) {
314 			DvbTransponder currentTransponder(DvbTransponderBase::DvbT);
315 			DvbTTransponder *dvbTTransponder = currentTransponder.as<DvbTTransponder>();
316 			dvbTTransponder->frequency = frequency;
317 			dvbTTransponder->bandwidth = DvbTTransponder::Bandwidth7MHz;
318 			dvbTTransponder->modulation = DvbTTransponder::ModulationAuto;
319 			dvbTTransponder->fecRateHigh = DvbTTransponder::FecAuto;
320 			dvbTTransponder->fecRateLow = DvbTTransponder::FecNone;
321 			dvbTTransponder->transmissionMode = DvbTTransponder::TransmissionModeAuto;
322 			dvbTTransponder->guardInterval = DvbTTransponder::GuardIntervalAuto;
323 			dvbTTransponder->hierarchy = DvbTTransponder::HierarchyNone;
324 			transponders.append(currentTransponder);
325 		}
326 
327 		for (int frequency = 474000000; frequency <= 858000000; frequency += 8000000) {
328 			for (int i = 0; i < 3; ++i) {
329 				if ((i != 0) && (!offsets)) {
330 					break;
331 				}
332 
333 				int offset = 0;
334 
335 				if (i == 1) {
336 					offset = -167000;
337 				} else if (i == 2) {
338 					offset = 167000;
339 				}
340 
341 				DvbTransponder currentTransponder(DvbTransponderBase::DvbT);
342 				DvbTTransponder *dvbTTransponder =
343 					currentTransponder.as<DvbTTransponder>();
344 				dvbTTransponder->frequency = frequency + offset;
345 				dvbTTransponder->bandwidth = DvbTTransponder::Bandwidth8MHz;
346 				dvbTTransponder->modulation = DvbTTransponder::ModulationAuto;
347 				dvbTTransponder->fecRateHigh = DvbTTransponder::FecAuto;
348 				dvbTTransponder->fecRateLow = DvbTTransponder::FecNone;
349 				dvbTTransponder->transmissionMode =
350 					DvbTTransponder::TransmissionModeAuto;
351 				dvbTTransponder->guardInterval =
352 					DvbTTransponder::GuardIntervalAuto;
353 				dvbTTransponder->hierarchy = DvbTTransponder::HierarchyNone;
354 				transponders.append(currentTransponder);
355 			}
356 		}
357 	} else if ((autoScanSource == QLatin1String("AUTO-T-Australia")) ||
358 		   (autoScanSource == QLatin1String("AUTO-T2-Australia"))) {
359 		for (int frequency = 177500000; frequency <= 226500000; frequency += 7000000) {
360 			for (int i = 0; i < 2; ++i) {
361 				int offset = 0;
362 
363 				if (i == 1) {
364 					offset = 125000;
365 				}
366 
367 				DvbTransponder currentTransponder(DvbTransponderBase::DvbT);
368 				DvbTTransponder *dvbTTransponder =
369 					currentTransponder.as<DvbTTransponder>();
370 				dvbTTransponder->frequency = frequency + offset;
371 				dvbTTransponder->bandwidth = DvbTTransponder::Bandwidth7MHz;
372 				dvbTTransponder->modulation = DvbTTransponder::ModulationAuto;
373 				dvbTTransponder->fecRateHigh = DvbTTransponder::FecAuto;
374 				dvbTTransponder->fecRateLow = DvbTTransponder::FecNone;
375 				dvbTTransponder->transmissionMode =
376 					DvbTTransponder::TransmissionModeAuto;
377 				dvbTTransponder->guardInterval =
378 					DvbTTransponder::GuardIntervalAuto;
379 				dvbTTransponder->hierarchy = DvbTTransponder::HierarchyNone;
380 				transponders.append(currentTransponder);
381 			}
382 		}
383 
384 		for (int frequency = 529500000; frequency <= 816500000; frequency += 7000000) {
385 			for (int i = 0; i < 2; ++i) {
386 				int offset = 0;
387 
388 				if (i == 1) {
389 					offset = 125000;
390 				}
391 
392 				DvbTransponder currentTransponder(DvbTransponderBase::DvbT);
393 				DvbTTransponder *dvbTTransponder =
394 					currentTransponder.as<DvbTTransponder>();
395 				dvbTTransponder->frequency = frequency + offset;
396 				dvbTTransponder->bandwidth = DvbTTransponder::Bandwidth7MHz;
397 				dvbTTransponder->modulation = DvbTTransponder::ModulationAuto;
398 				dvbTTransponder->fecRateHigh = DvbTTransponder::FecAuto;
399 				dvbTTransponder->fecRateLow = DvbTTransponder::FecNone;
400 				dvbTTransponder->transmissionMode =
401 					DvbTTransponder::TransmissionModeAuto;
402 				dvbTTransponder->guardInterval =
403 					DvbTTransponder::GuardIntervalAuto;
404 				dvbTTransponder->hierarchy = DvbTTransponder::HierarchyNone;
405 				transponders.append(currentTransponder);
406 			}
407 		}
408 	} else if ((autoScanSource == QLatin1String("AUTO-T-Italy")) ||
409 		   (autoScanSource == QLatin1String("AUTO-T2-Italy"))) {
410 		static const int italyVhf[] = { 177500000, 186000000, 194500000, 203500000,
411 						212500000, 219500000, 226500000 };
412 
413 		for (unsigned i = 0; i < (sizeof(italyVhf) / sizeof(italyVhf[0])); ++i) {
414 			for (int j = 0; j < 2; ++j) {
415 				DvbTransponder currentTransponder(DvbTransponderBase::DvbT);
416 				DvbTTransponder *dvbTTransponder =
417 					currentTransponder.as<DvbTTransponder>();
418 				dvbTTransponder->frequency = italyVhf[i];
419 				dvbTTransponder->bandwidth = ((j == 0) ?
420 					DvbTTransponder::Bandwidth7MHz :
421 					DvbTTransponder::Bandwidth8MHz);
422 				dvbTTransponder->modulation = DvbTTransponder::ModulationAuto;
423 				dvbTTransponder->fecRateHigh = DvbTTransponder::FecAuto;
424 				dvbTTransponder->fecRateLow = DvbTTransponder::FecNone;
425 				dvbTTransponder->transmissionMode =
426 					DvbTTransponder::TransmissionModeAuto;
427 				dvbTTransponder->guardInterval =
428 					DvbTTransponder::GuardIntervalAuto;
429 				dvbTTransponder->hierarchy = DvbTTransponder::HierarchyNone;
430 				transponders.append(currentTransponder);
431 			}
432 		}
433 
434 		for (int frequency = 474000000; frequency <= 858000000; frequency += 8000000) {
435 			DvbTransponder currentTransponder(DvbTransponderBase::DvbT);
436 			DvbTTransponder *dvbTTransponder =
437 				currentTransponder.as<DvbTTransponder>();
438 			dvbTTransponder->frequency = frequency;
439 			dvbTTransponder->bandwidth = DvbTTransponder::Bandwidth8MHz;
440 			dvbTTransponder->modulation = DvbTTransponder::ModulationAuto;
441 			dvbTTransponder->fecRateHigh = DvbTTransponder::FecAuto;
442 			dvbTTransponder->fecRateLow = DvbTTransponder::FecNone;
443 			dvbTTransponder->transmissionMode = DvbTTransponder::TransmissionModeAuto;
444 			dvbTTransponder->guardInterval = DvbTTransponder::GuardIntervalAuto;
445 			dvbTTransponder->hierarchy = DvbTTransponder::HierarchyNone;
446 			transponders.append(currentTransponder);
447 		}
448 	} else if ((autoScanSource == QLatin1String("AUTO-T-Taiwan"))||
449 		   (autoScanSource == QLatin1String("AUTO-T2-Taiwan"))) {
450 		for (int frequency = 527000000; frequency <= 599000000; frequency += 6000000) {
451 			DvbTransponder currentTransponder(DvbTransponderBase::DvbT);
452 			DvbTTransponder *dvbTTransponder =
453 				currentTransponder.as<DvbTTransponder>();
454 			dvbTTransponder->frequency = frequency;
455 			dvbTTransponder->bandwidth = DvbTTransponder::Bandwidth6MHz;
456 			dvbTTransponder->modulation = DvbTTransponder::ModulationAuto;
457 			dvbTTransponder->fecRateHigh = DvbTTransponder::FecAuto;
458 			dvbTTransponder->fecRateLow = DvbTTransponder::FecNone;
459 			dvbTTransponder->transmissionMode = DvbTTransponder::TransmissionModeAuto;
460 			dvbTTransponder->guardInterval = DvbTTransponder::GuardIntervalAuto;
461 			dvbTTransponder->hierarchy = DvbTTransponder::HierarchyNone;
462 			transponders.append(currentTransponder);
463 		}
464 	}
465 
466 	// Seek for DVB-T2 transponders
467 
468 	if ((autoScanSource == QLatin1String("AUTO-T2-Normal")) ||
469 		   (autoScanSource == QLatin1String("AUTO-T2-Offsets"))) {
470 		bool offsets = (autoScanSource == QLatin1String("AUTO-T2-Offsets"));
471 
472 		for (int frequency = 177500000; frequency <= 226500000; frequency += 7000000) {
473 			DvbTransponder currentTransponder(DvbTransponderBase::DvbT2);
474 			DvbT2Transponder *dvbT2Transponder = currentTransponder.as<DvbT2Transponder>();
475 			dvbT2Transponder->frequency = frequency;
476 			dvbT2Transponder->bandwidth = DvbT2Transponder::Bandwidth7MHz;
477 			dvbT2Transponder->modulation = DvbT2Transponder::ModulationAuto;
478 			dvbT2Transponder->fecRateHigh = DvbT2Transponder::FecAuto;
479 			dvbT2Transponder->fecRateLow = DvbT2Transponder::FecNone;
480 			dvbT2Transponder->transmissionMode = DvbT2Transponder::TransmissionModeAuto;
481 			dvbT2Transponder->guardInterval = DvbT2Transponder::GuardIntervalAuto;
482 			dvbT2Transponder->hierarchy = DvbT2Transponder::HierarchyNone;
483 			dvbT2Transponder->streamId = 0;
484 			transponders.append(currentTransponder);
485 		}
486 
487 		for (int frequency = 474000000; frequency <= 858000000; frequency += 8000000) {
488 			for (int i = 0; i < 3; ++i) {
489 				if ((i != 0) && (!offsets)) {
490 					break;
491 				}
492 
493 				int offset = 0;
494 
495 				if (i == 1) {
496 					offset = -167000;
497 				} else if (i == 2) {
498 					offset = 167000;
499 				}
500 
501 				DvbTransponder currentTransponder(DvbTransponderBase::DvbT2);
502 				DvbT2Transponder *dvbT2Transponder = currentTransponder.as<DvbT2Transponder>();
503 				dvbT2Transponder->frequency = frequency + offset;
504 				dvbT2Transponder->bandwidth = DvbT2Transponder::Bandwidth8MHz;
505 				dvbT2Transponder->modulation = DvbT2Transponder::ModulationAuto;
506 				dvbT2Transponder->fecRateHigh = DvbT2Transponder::FecAuto;
507 				dvbT2Transponder->fecRateLow = DvbT2Transponder::FecNone;
508 				dvbT2Transponder->transmissionMode = DvbT2Transponder::TransmissionModeAuto;
509 				dvbT2Transponder->guardInterval = DvbT2Transponder::GuardIntervalAuto;
510 				dvbT2Transponder->hierarchy = DvbT2Transponder::HierarchyNone;
511 				dvbT2Transponder->streamId = 0;
512 				transponders.append(currentTransponder);
513 			}
514 		}
515 	} else if (autoScanSource == QLatin1String("AUTO-T2-Australia")) {
516 		for (int frequency = 177500000; frequency <= 226500000; frequency += 7000000) {
517 			for (int i = 0; i < 2; ++i) {
518 				int offset = 0;
519 
520 				if (i == 1) {
521 					offset = 125000;
522 				}
523 
524 				DvbTransponder currentTransponder(DvbTransponderBase::DvbT2);
525 				DvbT2Transponder *dvbT2Transponder =
526 					currentTransponder.as<DvbT2Transponder>();
527 				dvbT2Transponder->frequency = frequency + offset;
528 				dvbT2Transponder->bandwidth = DvbT2Transponder::Bandwidth7MHz;
529 				dvbT2Transponder->modulation = DvbT2Transponder::ModulationAuto;
530 				dvbT2Transponder->fecRateHigh = DvbT2Transponder::FecAuto;
531 				dvbT2Transponder->fecRateLow = DvbT2Transponder::FecNone;
532 				dvbT2Transponder->transmissionMode =
533 					DvbT2Transponder::TransmissionModeAuto;
534 				dvbT2Transponder->guardInterval =
535 					DvbT2Transponder::GuardIntervalAuto;
536 				dvbT2Transponder->hierarchy = DvbT2Transponder::HierarchyNone;
537 				dvbT2Transponder->streamId = 0;
538 				transponders.append(currentTransponder);
539 			}
540 		}
541 
542 		for (int frequency = 529500000; frequency <= 816500000; frequency += 7000000) {
543 			for (int i = 0; i < 2; ++i) {
544 				int offset = 0;
545 
546 				if (i == 1) {
547 					offset = 125000;
548 				}
549 
550 				DvbTransponder currentTransponder(DvbTransponderBase::DvbT2);
551 				DvbT2Transponder *dvbT2Transponder =
552 					currentTransponder.as<DvbT2Transponder>();
553 				dvbT2Transponder->frequency = frequency + offset;
554 				dvbT2Transponder->bandwidth = DvbT2Transponder::Bandwidth7MHz;
555 				dvbT2Transponder->modulation = DvbT2Transponder::ModulationAuto;
556 				dvbT2Transponder->fecRateHigh = DvbT2Transponder::FecAuto;
557 				dvbT2Transponder->fecRateLow = DvbT2Transponder::FecNone;
558 				dvbT2Transponder->transmissionMode =
559 					DvbT2Transponder::TransmissionModeAuto;
560 				dvbT2Transponder->guardInterval =
561 					DvbT2Transponder::GuardIntervalAuto;
562 				dvbT2Transponder->hierarchy = DvbT2Transponder::HierarchyNone;
563 				dvbT2Transponder->streamId = 0;
564 				transponders.append(currentTransponder);
565 			}
566 		}
567 	} else if (autoScanSource == QLatin1String("AUTO-T2-Italy")) {
568 		static const int italyVhf[] = { 177500000, 186000000, 194500000, 203500000,
569 						212500000, 219500000, 226500000 };
570 
571 		for (unsigned i = 0; i < (sizeof(italyVhf) / sizeof(italyVhf[0])); ++i) {
572 			for (int j = 0; j < 2; ++j) {
573 				DvbTransponder currentTransponder(DvbTransponderBase::DvbT2);
574 				DvbT2Transponder *dvbT2Transponder =
575 					currentTransponder.as<DvbT2Transponder>();
576 				dvbT2Transponder->frequency = italyVhf[i];
577 				dvbT2Transponder->bandwidth = ((j == 0) ?
578 					DvbT2Transponder::Bandwidth7MHz :
579 					DvbT2Transponder::Bandwidth8MHz);
580 				dvbT2Transponder->modulation = DvbT2Transponder::ModulationAuto;
581 				dvbT2Transponder->fecRateHigh = DvbT2Transponder::FecAuto;
582 				dvbT2Transponder->fecRateLow = DvbT2Transponder::FecNone;
583 				dvbT2Transponder->transmissionMode =
584 					DvbT2Transponder::TransmissionModeAuto;
585 				dvbT2Transponder->guardInterval =
586 					DvbT2Transponder::GuardIntervalAuto;
587 				dvbT2Transponder->hierarchy = DvbT2Transponder::HierarchyNone;
588 				dvbT2Transponder->streamId = 0;
589 				transponders.append(currentTransponder);
590 			}
591 		}
592 
593 		for (int frequency = 474000000; frequency <= 858000000; frequency += 8000000) {
594 			DvbTransponder currentTransponder(DvbTransponderBase::DvbT2);
595 			DvbT2Transponder *dvbT2Transponder =
596 				currentTransponder.as<DvbT2Transponder>();
597 			dvbT2Transponder->frequency = frequency;
598 			dvbT2Transponder->bandwidth = DvbT2Transponder::Bandwidth8MHz;
599 			dvbT2Transponder->modulation = DvbT2Transponder::ModulationAuto;
600 			dvbT2Transponder->fecRateHigh = DvbT2Transponder::FecAuto;
601 			dvbT2Transponder->fecRateLow = DvbT2Transponder::FecNone;
602 			dvbT2Transponder->transmissionMode = DvbT2Transponder::TransmissionModeAuto;
603 			dvbT2Transponder->guardInterval = DvbT2Transponder::GuardIntervalAuto;
604 			dvbT2Transponder->hierarchy = DvbT2Transponder::HierarchyNone;
605 			dvbT2Transponder->streamId = 0;
606 			transponders.append(currentTransponder);
607 		}
608 	} else if (autoScanSource == QLatin1String("AUTO-T2-Taiwan")) {
609 		for (int frequency = 527000000; frequency <= 599000000; frequency += 6000000) {
610 			DvbTransponder currentTransponder(DvbTransponderBase::DvbT2);
611 			DvbT2Transponder *dvbT2Transponder =
612 				currentTransponder.as<DvbT2Transponder>();
613 			dvbT2Transponder->frequency = frequency;
614 			dvbT2Transponder->bandwidth = DvbT2Transponder::Bandwidth6MHz;
615 			dvbT2Transponder->modulation = DvbT2Transponder::ModulationAuto;
616 			dvbT2Transponder->fecRateHigh = DvbT2Transponder::FecAuto;
617 			dvbT2Transponder->fecRateLow = DvbT2Transponder::FecNone;
618 			dvbT2Transponder->transmissionMode = DvbT2Transponder::TransmissionModeAuto;
619 			dvbT2Transponder->guardInterval = DvbT2Transponder::GuardIntervalAuto;
620 			dvbT2Transponder->hierarchy = DvbT2Transponder::HierarchyNone;
621 			dvbT2Transponder->streamId = 0;
622 			transponders.append(currentTransponder);
623 		}
624 	}
625 
626 	// Seek for ISDB-T transponders
627 
628 	if (autoScanSource == QLatin1String("AUTO-UHF-6MHz")) {
629 		for (int frequency = 473142857; frequency <= 803142857; frequency += 6000000) {
630 			DvbTransponder currentTransponder(DvbTransponderBase::IsdbT);
631 			IsdbTTransponder *isdbTTransponder =
632 				currentTransponder.as<IsdbTTransponder>();
633 			isdbTTransponder->frequency = frequency;
634 			isdbTTransponder->bandwidth = IsdbTTransponder::Bandwidth6MHz;
635 			isdbTTransponder->transmissionMode = IsdbTTransponder::TransmissionModeAuto;
636 			isdbTTransponder->guardInterval = IsdbTTransponder::GuardIntervalAuto;
637 			isdbTTransponder->partialReception = IsdbTTransponder::PR_AUTO;
638 			isdbTTransponder->soundBroadcasting = IsdbTTransponder::SB_disabled;
639 			for (int i = 0; i < 3; i++) {
640 				isdbTTransponder->layerEnabled[i] = true;
641 				isdbTTransponder->modulation[i] = IsdbTTransponder::ModulationAuto;
642 				isdbTTransponder->fecRate[i] = IsdbTTransponder::FecAuto;
643 				isdbTTransponder->interleaving[i] = IsdbTTransponder::I_AUTO;
644 				isdbTTransponder->segmentCount[i] = 15;
645 			}
646 			transponders.append(currentTransponder);
647 		}
648 	}
649 }
650 
~DvbScan()651 DvbScan::~DvbScan()
652 {
653 	qDeleteAll(filters);
654 }
655 
start()656 void DvbScan::start()
657 {
658 	connect(device, SIGNAL(stateChanged()), this, SLOT(deviceStateChanged()));
659 	updateState();
660 }
661 
deviceStateChanged()662 void DvbScan::deviceStateChanged()
663 {
664 	if (device->getDeviceState() == DvbDevice::DeviceReleased) {
665 		qCWarning(logDvb, "Device was released. Stopping scan");
666 		emit scanFinished();
667 		return;
668 	}
669 
670 	if (state == ScanTuning) {
671 		updateState();
672 	}
673 }
674 
startFilter(int pid,FilterType type)675 bool DvbScan::startFilter(int pid, FilterType type)
676 {
677 	if (activeFilters != filters.size()) {
678 		foreach (DvbScanFilter *filter, filters) {
679 			if (!filter->isActive()) {
680 				if (!filter->startFilter(pid, type)) {
681 					return false;
682 				}
683 
684 				++activeFilters;
685 				return true;
686 			}
687 		}
688 
689 		Q_ASSERT(false);
690 	} else if (activeFilters < 10) {
691 		DvbScanFilter *filter = new DvbScanFilter(this, useOtherNit);
692 
693 		if (!filter->startFilter(pid, type)) {
694 			delete filter;
695 			return false;
696 		}
697 
698 		filters.append(filter);
699 		++activeFilters;
700 		return true;
701 	}
702 
703 	return false;
704 }
705 
updateState()706 void DvbScan::updateState()
707 {
708 	while (true) {
709 		switch (state) {
710 		case ScanPat: {
711 			if (!startFilter(0x0, PatFilter)) {
712 				return;
713 			}
714 
715 			snr = device->getSnr(scale);
716 
717 			state = ScanNit;
718 		    }
719 			// fall through
720 		case ScanNit: {
721 			if (!isLive && !isAuto &&
722 			    (transponder.getTransmissionType() != DvbTransponderBase::Atsc)) {
723 				if (!startFilter(0x10, NitFilter)) {
724 					return;
725 				}
726 			}
727 
728 			state = ScanSdt;
729 		    }
730 			// fall through
731 		case ScanSdt: {
732 			if (transponder.getTransmissionType() != DvbTransponderBase::Atsc) {
733 				if (!startFilter(0x11, SdtFilter)) {
734 					return;
735 				}
736 			} else {
737 				if (!startFilter(0x1ffb, VctFilter)) {
738 					return;
739 				}
740 			}
741 
742 			state = ScanPmt;
743 		    }
744 			// fall through
745 		case ScanPmt: {
746 			while (patIndex < patEntries.size()) {
747 				if (!startFilter(patEntries.at(patIndex).pid, PmtFilter)) {
748 					return;
749 				}
750 
751 				++patIndex;
752 			}
753 
754 			if (activeFilters != 0) {
755 				return;
756 			}
757 
758 			for (int i = 0; i < channels.size(); ++i) {
759 				DvbPreviewChannel &channel = channels[i];
760 
761 				foreach (const DvbSdtEntry &sdtEntry, sdtEntries) {
762 					if (channel.serviceId == sdtEntry.serviceId) {
763 						channel.name = sdtEntry.name;
764 						channel.networkId = sdtEntry.networkId;
765 						channel.isScrambled = sdtEntry.scrambled;
766 						channel.provider = sdtEntry.provider;
767 						break;
768 					}
769 				}
770 
771 				if (channel.name.isEmpty()) {
772 					channel.name = QString(QLatin1String("#0 %1:%2")).
773 						       arg(channel.transportStreamId).
774 						       arg(channel.serviceId);
775 				}
776 				qCDebug(logDvb, "Found channel %s", qPrintable(channel.name));
777 			}
778 
779 			if (!channels.isEmpty()) {
780 				emit foundChannels(channels);
781 			}
782 
783 			if (isLive) {
784 				qCInfo(logDvb, "Scanning while live stream. Can't change the transponder");
785 				emit scanFinished();
786 				return;
787 			}
788 
789 			patEntries.clear();
790 			patIndex = 0;
791 			sdtEntries.clear();
792 			channels.clear();
793 
794 			state = ScanTune;
795 		    }
796 			// fall through
797 		case ScanTune: {
798 			if (transponders.size() > 0) {
799 				emit scanProgress((100 * transponderIndex) / transponders.size());
800 			}
801 
802 			qCDebug(logDvb, "Transponder %d/%d", transponderIndex, transponders.size());
803 			if (transponderIndex >= transponders.size()) {
804 				emit scanFinished();
805 				return;
806 			}
807 
808 			transponder = transponders.at(transponderIndex);
809 			++transponderIndex;
810 
811 			state = ScanTuning;
812 
813 			if (!isAuto) {
814 				device->tune(transponder);
815 			} else {
816 				device->autoTune(transponder);
817 			}
818 
819 			return;
820 		    }
821 
822 		case ScanTuning: {
823 			switch (device->getDeviceState()) {
824 			case DvbDevice::DeviceIdle:
825 				state = ScanTune;
826 				break;
827 
828 			case DvbDevice::DeviceTuned:
829 				if (isAuto) {
830 					transponders[transponderIndex - 1] =
831 						device->getAutoTransponder();
832 				}
833 
834 				state = ScanPat;
835 				break;
836 
837 			default:
838 				return;
839 			}
840 
841 			break;
842 		    }
843 		}
844 	}
845 }
846 
processPat(const DvbPatSection & section)847 void DvbScan::processPat(const DvbPatSection &section)
848 {
849 	transportStreamId = section.transportStreamId();
850 
851 	for (DvbPatSectionEntry entry = section.entries(); entry.isValid(); entry.advance()) {
852 		if (entry.programNumber() != 0x0) {
853 			// skip 0x0 which has a special meaning
854 			patEntries.append(DvbPatEntry(entry.programNumber(), entry.pid()));
855 
856 			qCDebug(logDvb, "New PAT entry: pid %d, program %d", entry.pid(), entry.programNumber());
857 		}
858 	}
859 }
860 
processPmt(const DvbPmtSection & section,int pid)861 void DvbScan::processPmt(const DvbPmtSection &section, int pid)
862 {
863 	DvbPreviewChannel channel;
864 
865 	DvbPmtParser parser(section);
866 	channel.hasVideo = (parser.videoPid >= 0);
867 
868 	if (!parser.audioPids.isEmpty()) {
869 		channel.audioPid = parser.audioPids.at(0).first;
870 	}
871 
872 	if (channel.hasVideo || (channel.audioPid >= 0)) {
873 		channel.source = source;
874 		channel.transponder = transponder;
875 		channel.transportStreamId = transportStreamId;
876 		channel.pmtPid = pid;
877 		channel.pmtSectionData = section.toByteArray();
878 		channel.serviceId = section.programNumber();
879 		switch (scale) {
880 		case DvbBackendDevice::dBuV:
881 		case DvbBackendDevice::NotSupported: {
882 			channel.snr = "";
883 			break;
884 		}
885 		case DvbBackendDevice::Percentage: {
886 			channel.snr = QString::number(snr, 'f', 0) + '%';
887 			break;
888 		}
889 		case DvbBackendDevice::Decibel: {
890 			channel.snr = QString::number(snr, 'f', 2) + " dB";
891 			break;
892 		}
893 		};
894 		channels.append(channel);
895 
896 		qCDebug(logDvb, "New channel: PID %d, service ID %d", pid, section.programNumber());
897 	}
898 }
899 
processSdt(const DvbSdtSection & section)900 void DvbScan::processSdt(const DvbSdtSection &section)
901 {
902 	for (DvbSdtSectionEntry entry = section.entries(); entry.isValid(); entry.advance()) {
903 		DvbSdtEntry sdtEntry(entry.serviceId(), section.originalNetworkId(),
904 				     entry.isScrambled());
905 
906 		for (DvbDescriptor descriptor = entry.descriptors(); descriptor.isValid();
907 		     descriptor.advance()) {
908 			if (descriptor.descriptorTag() != 0x48) {
909 				continue;
910 			}
911 
912 			DvbServiceDescriptor serviceDescriptor(descriptor);
913 
914 			if (!serviceDescriptor.isValid()) {
915 				continue;
916 			}
917 
918 			sdtEntry.name = serviceDescriptor.serviceName();
919 			sdtEntry.provider = serviceDescriptor.providerName();
920 
921 			qCDebug(logDvb, "New SDT entry: service ID 0x%04x, name '%s', provider '%s'", entry.serviceId(), qPrintable(sdtEntry.name), qPrintable(sdtEntry.provider));
922 			sdtEntries.append(sdtEntry);
923 		}
924 	}
925 }
926 
processVct(const AtscVctSection & section)927 void DvbScan::processVct(const AtscVctSection &section)
928 {
929 	AtscVctSectionEntry entry = section.entries();
930 	int entryCount = section.entryCount();
931 
932 	for (int i = 0; i < entryCount && (entry.isValid()); i++) {
933 		QString majorminor = QString(QLatin1String("%1-%2 ")).
934 			arg(entry.majorNumber(), 3, 10, QLatin1Char('0')).arg(entry.minorNumber());
935 
936 		DvbSdtEntry sdtEntry(entry.programNumber(), entry.sourceId(), entry.isScrambled());
937 
938 		// Each VCT section has it's own list of descriptors
939 		// See A/65C table 6.25a for the list of descriptors
940 		for (DvbDescriptor descriptor = entry.descriptors(); descriptor.isValid();
941 		     descriptor.advance()) {
942 			if (descriptor.descriptorTag() == 0xa0) {
943 				// Extended Channel Name Descriptor
944 				AtscChannelNameDescriptor nameDescriptor(descriptor);
945 				if (!nameDescriptor.isValid()) {
946 					continue;
947 				}
948 				sdtEntry.name = majorminor + nameDescriptor.name();
949 			}
950 		}
951 
952 		if (sdtEntry.name.isEmpty()) {
953 			// Extended Channel name not available, fall back
954 			// to the short name
955 			QChar shortName[] = { entry.shortName1(),
956 						entry.shortName2(),
957 						entry.shortName3(),
958 						entry.shortName4(),
959 						entry.shortName5(),
960 						entry.shortName6(),
961 						entry.shortName7(), 0 };
962 			int nameLength = 0;
963 			while (shortName[nameLength] != 0) {
964 				++nameLength;
965 			}
966 			sdtEntry.name = majorminor + QString(shortName, nameLength);
967 		}
968 
969 		qCDebug(logDvb, "New SDT entry: name %s", qPrintable(sdtEntry.name));
970 		sdtEntries.append(sdtEntry);
971 
972 		if (i < entryCount - 1)
973 			entry.advance();
974 	}
975 }
976 
processNit(const DvbNitSection & section)977 void DvbScan::processNit(const DvbNitSection &section)
978 {
979 	for (DvbNitSectionEntry entry = section.entries(); entry.isValid(); entry.advance()) {
980 		for (DvbDescriptor descriptor = entry.descriptors(); descriptor.isValid();
981 		     descriptor.advance()) {
982 			processNitDescriptor(descriptor);
983 		}
984 	}
985 }
986 
extractDvbCModulation(const DvbCableDescriptor & descriptor)987 static DvbCTransponder::Modulation extractDvbCModulation(const DvbCableDescriptor &descriptor)
988 {
989 	switch (descriptor.modulation()) {
990 	case 1:
991 		return DvbCTransponder::Qam16;
992 	case 2:
993 		return DvbCTransponder::Qam32;
994 	case 3:
995 		return DvbCTransponder::Qam64;
996 	case 4:
997 		return DvbCTransponder::Qam128;
998 	case 5:
999 		return DvbCTransponder::Qam256;
1000 	default:
1001 		return DvbCTransponder::ModulationAuto;
1002 	}
1003 }
1004 
extractDvbCFecRate(const DvbCableDescriptor & descriptor)1005 static DvbCTransponder::FecRate extractDvbCFecRate(const DvbCableDescriptor &descriptor)
1006 {
1007 	switch (descriptor.fecRate()) {
1008 	case 1:
1009 		return DvbTransponderBase::Fec1_2;
1010 	case 2:
1011 		return DvbTransponderBase::Fec2_3;
1012 	case 3:
1013 		return DvbTransponderBase::Fec3_4;
1014 	case 4:
1015 		return DvbTransponderBase::Fec5_6;
1016 	case 5:
1017 		return DvbTransponderBase::Fec7_8;
1018 	case 6:
1019 		return DvbTransponderBase::Fec8_9;
1020 	case 7:
1021 		return DvbTransponderBase::Fec3_5;
1022 	case 8:
1023 		return DvbTransponderBase::Fec4_5;
1024 	case 9:
1025 		return DvbTransponderBase::Fec9_10;
1026 	case 15:
1027 		return DvbTransponderBase::FecNone;
1028 	default:
1029 		return DvbTransponderBase::FecAuto;
1030 	}
1031 }
1032 
extractDvbSPolarization(const DvbSatelliteDescriptor & descriptor)1033 static DvbSTransponder::Polarization extractDvbSPolarization(
1034 	const DvbSatelliteDescriptor &descriptor)
1035 {
1036 	switch (descriptor.polarization()) {
1037 	case 0:
1038 		return DvbSTransponder::Horizontal;
1039 	case 1:
1040 		return DvbSTransponder::Vertical;
1041 	case 2:
1042 		return DvbSTransponder::CircularLeft;
1043 	default:
1044 		return DvbSTransponder::CircularRight;
1045 	}
1046 }
1047 
extractDvbSFecRate(const DvbSatelliteDescriptor & descriptor)1048 static DvbSTransponder::FecRate extractDvbSFecRate(const DvbSatelliteDescriptor &descriptor)
1049 {
1050 	switch (descriptor.fecRate()) {
1051 	case 1:
1052 		return DvbTransponderBase::Fec1_2;
1053 	case 2:
1054 		return DvbTransponderBase::Fec2_3;
1055 	case 3:
1056 		return DvbTransponderBase::Fec3_4;
1057 	case 4:
1058 		return DvbTransponderBase::Fec5_6;
1059 	case 5:
1060 		return DvbTransponderBase::Fec7_8;
1061 	case 6:
1062 		return DvbTransponderBase::Fec8_9;
1063 	case 7:
1064 		return DvbTransponderBase::Fec3_5;
1065 	case 8:
1066 		return DvbTransponderBase::Fec4_5;
1067 	case 9:
1068 		return DvbTransponderBase::Fec9_10;
1069 	default:
1070 		return DvbTransponderBase::FecAuto;
1071 	}
1072 }
1073 
extractDvbS2Modulation(const DvbSatelliteDescriptor & descriptor)1074 static DvbS2Transponder::Modulation extractDvbS2Modulation(
1075 	const DvbSatelliteDescriptor &descriptor)
1076 {
1077 	switch (descriptor.modulation()) {
1078 	case 1:
1079 		return DvbS2Transponder::Qpsk;
1080 	case 2:
1081 		return DvbS2Transponder::Psk8;
1082 	default:
1083 		return DvbS2Transponder::ModulationAuto;
1084 	}
1085 }
1086 
extractDvbS2RollOff(const DvbSatelliteDescriptor & descriptor)1087 static DvbS2Transponder::RollOff extractDvbS2RollOff(const DvbSatelliteDescriptor &descriptor)
1088 {
1089 	switch (descriptor.rollOff()) {
1090 	case 0:
1091 		return DvbS2Transponder::RollOff35;
1092 	case 1:
1093 		return DvbS2Transponder::RollOff25;
1094 	case 2:
1095 		return DvbS2Transponder::RollOff20;
1096 	default:
1097 		return DvbS2Transponder::RollOffAuto;
1098 	}
1099 }
1100 
extractDvbTBandwidth(const DvbTerrestrialDescriptor & descriptor)1101 static DvbTTransponder::Bandwidth extractDvbTBandwidth(const DvbTerrestrialDescriptor &descriptor)
1102 {
1103 	switch (descriptor.bandwidth()) {
1104 	case 0:
1105 		return DvbTTransponder::Bandwidth8MHz;
1106 	case 1:
1107 		return DvbTTransponder::Bandwidth7MHz;
1108 	case 2:
1109 		return DvbTTransponder::Bandwidth6MHz;
1110 	case 3:
1111 		return DvbTTransponder::Bandwidth5MHz;
1112 	default:
1113 		return DvbTTransponder::BandwidthAuto;
1114 	}
1115 }
1116 
extractDvbTModulation(const DvbTerrestrialDescriptor & descriptor)1117 static DvbTTransponder::Modulation extractDvbTModulation(
1118 	const DvbTerrestrialDescriptor &descriptor)
1119 {
1120 	switch (descriptor.constellation()) {
1121 	case 0:
1122 		return DvbTTransponder::Qpsk;
1123 	case 1:
1124 		return DvbTTransponder::Qam16;
1125 	case 2:
1126 		return DvbTTransponder::Qam64;
1127 	default:
1128 		return DvbTTransponder::ModulationAuto;
1129 	}
1130 }
1131 
extractDvbTFecRateHigh(const DvbTerrestrialDescriptor & descriptor)1132 static DvbTTransponder::FecRate extractDvbTFecRateHigh(const DvbTerrestrialDescriptor &descriptor)
1133 {
1134 	switch (descriptor.fecRateHigh()) {
1135 	case 0:
1136 		return DvbTTransponder::Fec1_2;
1137 	case 1:
1138 		return DvbTTransponder::Fec2_3;
1139 	case 2:
1140 		return DvbTTransponder::Fec3_4;
1141 	case 3:
1142 		return DvbTTransponder::Fec5_6;
1143 	case 4:
1144 		return DvbTTransponder::Fec7_8;
1145 	default:
1146 		return DvbTTransponder::FecAuto;
1147 	}
1148 }
1149 
extractDvbTFecRateLow(const DvbTerrestrialDescriptor & descriptor)1150 static DvbTTransponder::FecRate extractDvbTFecRateLow(const DvbTerrestrialDescriptor &descriptor)
1151 {
1152 	switch (descriptor.fecRateLow()) {
1153 	case 0:
1154 		return DvbTTransponder::Fec1_2;
1155 	case 1:
1156 		return DvbTTransponder::Fec2_3;
1157 	case 2:
1158 		return DvbTTransponder::Fec3_4;
1159 	case 3:
1160 		return DvbTTransponder::Fec5_6;
1161 	case 4:
1162 		return DvbTTransponder::Fec7_8;
1163 	default:
1164 		return DvbTTransponder::FecAuto;
1165 	}
1166 }
1167 
extractDvbTTransmissionMode(const DvbTerrestrialDescriptor & descriptor)1168 static DvbTTransponder::TransmissionMode extractDvbTTransmissionMode(
1169 	const DvbTerrestrialDescriptor &descriptor)
1170 {
1171 	switch (descriptor.transmissionMode()) {
1172 	case 0:
1173 		return DvbTTransponder::TransmissionMode2k;
1174 	case 1:
1175 		return DvbTTransponder::TransmissionMode8k;
1176 	case 2:
1177 		return DvbTTransponder::TransmissionMode4k;
1178 	default:
1179 		return DvbTTransponder::TransmissionModeAuto;
1180 	}
1181 }
1182 
extractDvbTGuardInterval(const DvbTerrestrialDescriptor & descriptor)1183 static DvbTTransponder::GuardInterval extractDvbTGuardInterval(
1184 	const DvbTerrestrialDescriptor &descriptor)
1185 {
1186 	switch (descriptor.guardInterval()) {
1187 	case 0:
1188 		return DvbTTransponder::GuardInterval1_32;
1189 	case 1:
1190 		return DvbTTransponder::GuardInterval1_16;
1191 	case 2:
1192 		return DvbTTransponder::GuardInterval1_8;
1193 	default:
1194 		return DvbTTransponder::GuardInterval1_4;
1195 	}
1196 }
1197 
extractDvbTHierarchy(const DvbTerrestrialDescriptor & descriptor)1198 static DvbTTransponder::Hierarchy extractDvbTHierarchy(const DvbTerrestrialDescriptor &descriptor)
1199 {
1200 	switch (descriptor.hierarchy() & 0x3) {
1201 	case 0:
1202 		return DvbTTransponder::HierarchyNone;
1203 	case 1:
1204 		return DvbTTransponder::Hierarchy1;
1205 	case 2:
1206 		return DvbTTransponder::Hierarchy2;
1207 	default:
1208 		return DvbTTransponder::Hierarchy4;
1209 	}
1210 }
1211 
1212 // FIXME: Implement DvbT2Descriptor
1213 
processNitDescriptor(const DvbDescriptor & descriptor)1214 void DvbScan::processNitDescriptor(const DvbDescriptor &descriptor)
1215 {
1216 	DvbTransponder newTransponder(transponder.getTransmissionType());
1217 
1218 	switch (transponder.getTransmissionType()) {
1219 	case DvbTransponderBase::Invalid:
1220 		qCWarning(logDvb, "Invalid transponder type");
1221 		return;
1222 	case DvbTransponderBase::DvbC: {
1223 		if (descriptor.descriptorTag() != 0x44) {
1224 			return;
1225 		}
1226 
1227 		DvbCableDescriptor cableDescriptor(descriptor);
1228 
1229 		if (!cableDescriptor.isValid()) {
1230 			return;
1231 		}
1232 
1233 		newTransponder = DvbTransponder(DvbTransponderBase::DvbC);
1234 		DvbCTransponder *dvbCTransponder = newTransponder.as<DvbCTransponder>();
1235 		dvbCTransponder->frequency =
1236 			DvbDescriptor::bcdToInt(cableDescriptor.frequency(), 100);
1237 		dvbCTransponder->symbolRate =
1238 			DvbDescriptor::bcdToInt(cableDescriptor.symbolRate(), 100);
1239 		dvbCTransponder->modulation = extractDvbCModulation(cableDescriptor);
1240 		dvbCTransponder->fecRate = extractDvbCFecRate(cableDescriptor);
1241 
1242 		qCDebug(logDvb, "Added transponder: %.2f MHz", dvbCTransponder->frequency / 1000000.);
1243 		break;
1244 	    }
1245 	case DvbTransponderBase::DvbS:
1246 	case DvbTransponderBase::DvbS2: {
1247 		if (descriptor.descriptorTag() != 0x43) {
1248 			return;
1249 		}
1250 
1251 		DvbSatelliteDescriptor satelliteDescriptor(descriptor);
1252 
1253 		if (!satelliteDescriptor.isValid()) {
1254 			return;
1255 		}
1256 
1257 		DvbSTransponder *dvbSTransponder;
1258 
1259 		if (!satelliteDescriptor.isDvbS2()) {
1260 			newTransponder = DvbTransponder(DvbTransponderBase::DvbS);
1261 			dvbSTransponder = newTransponder.as<DvbSTransponder>();
1262 		} else {
1263 			if ((device->getTransmissionTypes() & DvbDevice::DvbS2) == 0) {
1264 				return;
1265 			}
1266 
1267 			newTransponder = DvbTransponder(DvbTransponderBase::DvbS2);
1268 			DvbS2Transponder *dvbS2Transponder = newTransponder.as<DvbS2Transponder>();
1269 			dvbS2Transponder->modulation = extractDvbS2Modulation(satelliteDescriptor);
1270 			dvbS2Transponder->rollOff = extractDvbS2RollOff(satelliteDescriptor);
1271 			dvbSTransponder = dvbS2Transponder;
1272 		}
1273 
1274 		dvbSTransponder->frequency =
1275 			DvbDescriptor::bcdToInt(satelliteDescriptor.frequency(), 10);
1276 		dvbSTransponder->polarization = extractDvbSPolarization(satelliteDescriptor);
1277 		dvbSTransponder->symbolRate =
1278 			DvbDescriptor::bcdToInt(satelliteDescriptor.symbolRate(), 100);
1279 		dvbSTransponder->fecRate = extractDvbSFecRate(satelliteDescriptor);
1280 
1281 		qCDebug(logDvb, "Added transponder: %.2f MHz", dvbSTransponder->frequency / 1000000.);
1282 		break;
1283 	    }
1284 	case DvbTransponderBase::DvbT2:
1285 		// FIXME: Implement T2_delivery_system_descriptor
1286 		// descriptor 0x7f, extension descriptor 0x04  or use libdvbv5
1287 
1288 	case DvbTransponderBase::DvbT: {
1289 		if (descriptor.descriptorTag() != 0x5a) {
1290 			return;
1291 		}
1292 
1293 		DvbTerrestrialDescriptor terrestrialDescriptor(descriptor);
1294 
1295 		if (!terrestrialDescriptor.isValid()) {
1296 			return;
1297 		}
1298 
1299 		newTransponder = DvbTransponder(DvbTransponderBase::DvbT);
1300 		DvbTTransponder *dvbTTransponder = newTransponder.as<DvbTTransponder>();
1301 		dvbTTransponder->frequency = terrestrialDescriptor.frequency() * 10;
1302 		dvbTTransponder->bandwidth = extractDvbTBandwidth(terrestrialDescriptor);
1303 		dvbTTransponder->modulation = extractDvbTModulation(terrestrialDescriptor);
1304 		dvbTTransponder->fecRateHigh = extractDvbTFecRateHigh(terrestrialDescriptor);
1305 		dvbTTransponder->fecRateLow = extractDvbTFecRateLow(terrestrialDescriptor);
1306 		dvbTTransponder->transmissionMode =
1307 			extractDvbTTransmissionMode(terrestrialDescriptor);
1308 		dvbTTransponder->guardInterval = extractDvbTGuardInterval(terrestrialDescriptor);
1309 		dvbTTransponder->hierarchy = extractDvbTHierarchy(terrestrialDescriptor);
1310 
1311 		if (dvbTTransponder->hierarchy == DvbTTransponder::HierarchyNone) {
1312 			dvbTTransponder->fecRateLow = DvbTTransponder::FecNone;
1313 		}
1314 
1315 		qCDebug(logDvb, "Added transponder: %.2f MHz", dvbTTransponder->frequency / 1000000.);
1316 		break;
1317 	    }
1318 	case DvbTransponderBase::Atsc:
1319 		return;
1320 	case DvbTransponderBase::IsdbT:
1321 		if (descriptor.descriptorTag() != 0xfa) {
1322 			return;
1323 		}
1324 
1325 		IsdbTerrestrialDescriptor IsdbTDescriptor(descriptor);
1326 
1327 		if (!IsdbTDescriptor.isValid()) {
1328 			return;
1329 		}
1330 
1331 		for (int i = 0; i < IsdbTDescriptor.frequencyLength(); i++) {
1332 			newTransponder = DvbTransponder(DvbTransponderBase::IsdbT);
1333 			IsdbTTransponder *isdbTTransponder = newTransponder.as<IsdbTTransponder>();
1334 
1335 			isdbTTransponder->frequency =
1336 				(uint32_t)((((uint64_t)IsdbTDescriptor.frequency(i)) * 1000000ul) / 7);
1337 			isdbTTransponder->bandwidth = IsdbTTransponder::Bandwidth6MHz;
1338 			isdbTTransponder->transmissionMode = IsdbTTransponder::TransmissionModeAuto;
1339 			isdbTTransponder->guardInterval = IsdbTTransponder::GuardIntervalAuto;
1340 			isdbTTransponder->partialReception = IsdbTTransponder::PR_AUTO;
1341 			isdbTTransponder->soundBroadcasting = IsdbTTransponder::SB_disabled;
1342 			for (int i = 0; i < 3; i++) {
1343 				isdbTTransponder->layerEnabled[i] = true;
1344 				isdbTTransponder->modulation[i] = IsdbTTransponder::ModulationAuto;
1345 				isdbTTransponder->fecRate[i] = IsdbTTransponder::FecAuto;
1346 				isdbTTransponder->interleaving[i] = IsdbTTransponder::I_AUTO;
1347 				isdbTTransponder->segmentCount[i] = 15;
1348 			}
1349 
1350 			bool duplicate = false;
1351 
1352 			foreach (const DvbTransponder &existingTransponder, transponders) {
1353 				if (existingTransponder.corresponds(newTransponder)) {
1354 					duplicate = true;
1355 					break;
1356 				}
1357 			}
1358 			if (duplicate)
1359 				continue;
1360 
1361 			transponders.append(newTransponder);
1362 			qCDebug(logDvb, "Added transponder: %.2f MHz", isdbTTransponder->frequency / 1000000.);
1363 		}
1364 		return;
1365 	}
1366 
1367 
1368 	// New transponder was found. Add it
1369 	foreach (const DvbTransponder &existingTransponder, transponders) {
1370 		if (existingTransponder.corresponds(newTransponder))
1371 			return;
1372 	}
1373 
1374 	transponders.append(newTransponder);
1375 }
1376 
filterFinished(DvbScanFilter * filter)1377 void DvbScan::filterFinished(DvbScanFilter *filter)
1378 {
1379 	filter->stopFilter();
1380 	--activeFilters;
1381 	updateState();
1382 }
1383