1 /*
2  * Simple MPEG/DVB parser to achieve network/service information without initial tuning data
3  *
4  * Copyright (C) 2006, 2007, 2008, 2009 Winfried Koehler
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (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
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  */
21 
22 #include <strings.h>
23 #include "extended_frontend.h"
24 #include "scan.h"
25 #include "dvbscan.h"
26 
27 #define STRUCT_COUNT(struct_list) (sizeof(struct_list)/sizeof(struct init_item))
28 
29 /********************************************************************
30  * dvbscan.c
31  *
32  * import / export of initial_tuning_data for dvbscan
33  * see doc/README.file_formats
34  *
35  ********************************************************************/
36 
37 /********************************************************************
38  * DVB-T
39  ********************************************************************/
40 
41 struct init_item terr_bw_list[] = {
42 	{"8MHz", 8000000},
43 	{"7MHz", 7000000},
44 	{"6MHz", 6000000},
45 	{"5MHz", 5000000},
46 	{"10MHz", 10000000},
47 	{"1.712MHz", 1712000},
48 	{"AUTO", 8000000}
49 };
50 
51 struct init_item terr_fec_list[] = {
52 	{"NONE", FEC_NONE},
53 	{"1/2", FEC_1_2},
54 	{"2/3", FEC_2_3},
55 	{"3/4", FEC_3_4},
56 	{"4/5", FEC_4_5},
57 	{"5/6", FEC_5_6},
58 	{"6/7", FEC_6_7},
59 	{"7/8", FEC_7_8},
60 	{"3/5", FEC_3_5},
61 	{"4/5", FEC_4_5},
62 	{"AUTO", FEC_AUTO}
63 };
64 
65 struct init_item terr_mod_list[] = {
66 	{"QPSK", QPSK},
67 	{"QAM16", QAM_16},
68 	{"QAM64", QAM_64},
69 	{"QAM256", QAM_256},
70 	{"AUTO", QAM_AUTO}
71 };
72 
73 struct init_item terr_mod_list_v5[] = {
74 	{"QPSK", QPSK},
75 	{"QAM/16", QAM_16},
76 	{"QAM/64", QAM_64},
77 	{"QAM/256", QAM_256},
78 	{"QAM/AUTO", QAM_AUTO}
79 };
80 
81 struct init_item terr_transmission_list[] = {
82 	{"2k", TRANSMISSION_MODE_2K},
83 	{"8k", TRANSMISSION_MODE_8K},
84 	{"4k", TRANSMISSION_MODE_4K},
85 	{"1k", TRANSMISSION_MODE_1K},
86 	{"16k", TRANSMISSION_MODE_16K},
87 	{"32k", TRANSMISSION_MODE_32K},
88 	{"AUTO", TRANSMISSION_MODE_AUTO}
89 };
90 
91 struct init_item terr_guard_list[] = {
92 	{"1/32", GUARD_INTERVAL_1_32},
93 	{"1/16", GUARD_INTERVAL_1_16},
94 	{"1/8", GUARD_INTERVAL_1_8},
95 	{"1/4", GUARD_INTERVAL_1_4},
96 	{"1/128", GUARD_INTERVAL_1_128},
97 	{"19/128", GUARD_INTERVAL_19_128},
98 	{"19/256", GUARD_INTERVAL_19_256},
99 	{"AUTO", GUARD_INTERVAL_AUTO}
100 };
101 
102 struct init_item terr_hierarchy_list[] = {
103 	{"NONE", HIERARCHY_NONE},
104 	{"1", HIERARCHY_1},
105 	{"2", HIERARCHY_2},
106 	{"4", HIERARCHY_4},
107 	{"AUTO", HIERARCHY_AUTO}
108 };
109 
110 /* convert text to identifiers */
111 
txt_to_terr_bw(const char * txt)112 int txt_to_terr_bw(const char *txt)
113 {
114 	unsigned int i;
115 
116 	for (i = 0; i < STRUCT_COUNT(terr_bw_list); i++)
117 		if (!strcasecmp(txt, terr_bw_list[i].name))
118 			return terr_bw_list[i].id;
119 	return 8000000;		// fallback. should never happen.
120 }
121 
txt_to_terr_fec(const char * txt)122 int txt_to_terr_fec(const char *txt)
123 {
124 	unsigned int i;
125 
126 	for (i = 0; i < STRUCT_COUNT(terr_fec_list); i++)
127 		if (!strcasecmp(txt, terr_fec_list[i].name))
128 			return terr_fec_list[i].id;
129 	return FEC_AUTO;	// fallback. should never happen.
130 }
131 
txt_to_terr_mod(const char * txt)132 int txt_to_terr_mod(const char *txt)
133 {
134 	unsigned int i;
135 
136 	for (i = 0; i < STRUCT_COUNT(terr_mod_list); i++)
137 		if (!strcasecmp(txt, terr_mod_list[i].name))
138 			return terr_mod_list[i].id;
139 	return QAM_AUTO;	// fallback. should never happen.
140 }
141 
txt_to_terr_transmission(const char * txt)142 int txt_to_terr_transmission(const char *txt)
143 {
144 	unsigned int i;
145 
146 	for (i = 0; i < STRUCT_COUNT(terr_transmission_list); i++)
147 		if (!strcasecmp(txt, terr_transmission_list[i].name))
148 			return terr_transmission_list[i].id;
149 	return TRANSMISSION_MODE_AUTO;	// fallback. should never happen.
150 }
151 
txt_to_terr_guard(const char * txt)152 int txt_to_terr_guard(const char *txt)
153 {
154 	unsigned int i;
155 
156 	for (i = 0; i < STRUCT_COUNT(terr_guard_list); i++)
157 		if (!strcasecmp(txt, terr_guard_list[i].name))
158 			return terr_guard_list[i].id;
159 	return GUARD_INTERVAL_AUTO;	// fallback. should never happen.
160 }
161 
txt_to_terr_hierarchy(const char * txt)162 int txt_to_terr_hierarchy(const char *txt)
163 {
164 	unsigned int i;
165 
166 	for (i = 0; i < STRUCT_COUNT(terr_hierarchy_list); i++)
167 		if (!strcasecmp(txt, terr_hierarchy_list[i].name))
168 			return terr_hierarchy_list[i].id;
169 	return HIERARCHY_AUTO;	// fallback. should never happen.
170 }
171 
172 /*convert identifier to text */
173 
terr_bw_to_txt(int id)174 const char *terr_bw_to_txt(int id)
175 {
176 	unsigned int i;
177 
178 	for (i = 0; i < STRUCT_COUNT(terr_bw_list); i++)
179 		if (id == terr_bw_list[i].id)
180 			return terr_bw_list[i].name;
181 	return "AUTO";		// fallback. should never happen.
182 }
183 
terr_fec_to_txt(int id)184 const char *terr_fec_to_txt(int id)
185 {
186 	unsigned int i;
187 
188 	for (i = 0; i < STRUCT_COUNT(terr_fec_list); i++)
189 		if (id == terr_fec_list[i].id)
190 			return terr_fec_list[i].name;
191 	return "AUTO";		// fallback. should never happen.
192 }
193 
terr_mod_to_txt(int id)194 const char *terr_mod_to_txt(int id)
195 {
196 	unsigned int i;
197 
198 	for (i = 0; i < STRUCT_COUNT(terr_mod_list); i++)
199 		if (id == terr_mod_list[i].id)
200 			return terr_mod_list[i].name;
201 	return "AUTO";		// fallback. should never happen.
202 }
203 
terr_mod_to_txt_v5(int id)204 const char *terr_mod_to_txt_v5(int id)
205 {
206 	unsigned int i;
207 
208 	for (i = 0; i < STRUCT_COUNT(terr_mod_list_v5); i++)
209 		if (id == terr_mod_list_v5[i].id)
210 			return terr_mod_list_v5[i].name;
211 	return "QAM/AUTO";		// fallback. should never happen.
212 }
213 
terr_transmission_to_txt(int id)214 const char *terr_transmission_to_txt(int id)
215 {
216 	unsigned int i;
217 
218 	for (i = 0; i < STRUCT_COUNT(terr_transmission_list); i++)
219 		if (id == terr_transmission_list[i].id)
220 			return terr_transmission_list[i].name;
221 	return "AUTO";		// fallback. should never happen.
222 }
223 
terr_guard_to_txt(int id)224 const char *terr_guard_to_txt(int id)
225 {
226 	unsigned int i;
227 
228 	for (i = 0; i < STRUCT_COUNT(terr_guard_list); i++)
229 		if (id == terr_guard_list[i].id)
230 			return terr_guard_list[i].name;
231 	return "AUTO";		// fallback. should never happen.
232 }
233 
terr_hierarchy_to_txt(int id)234 const char *terr_hierarchy_to_txt(int id)
235 {
236 	unsigned int i;
237 
238 	for (i = 0; i < STRUCT_COUNT(terr_hierarchy_list); i++)
239 		if (id == terr_hierarchy_list[i].id)
240 			return terr_hierarchy_list[i].name;
241 	return "AUTO";		// fallback. should never happen.
242 }
243 
244 /********************************************************************
245  * DVB-C
246  ********************************************************************/
247 
248 struct init_item cable_fec_list[] = {
249 	{"NONE", FEC_NONE},
250 	{"1/2", FEC_1_2},
251 	{"2/3", FEC_2_3},
252 	{"3/4", FEC_3_4},
253 	{"4/5", FEC_4_5},
254 	{"5/6", FEC_5_6},
255 	{"6/7", FEC_6_7},
256 	{"7/8", FEC_7_8},
257 	{"8/9", FEC_8_9},
258 	{"3/5", FEC_3_5},
259 	{"9/10", FEC_9_10},
260 	{"AUTO", FEC_AUTO}
261 };
262 
263 struct init_item cable_mod_list[] = {
264 	{"QAM16", QAM_16},
265 	{"QAM32", QAM_32},
266 	{"QAM64", QAM_64},
267 	{"QAM128", QAM_128},
268 	{"QAM256", QAM_256},
269 #ifdef   SYS_DVBC2		//currently not supported by Linux DVB API
270 	{"QAM512", QAM_512},
271 	{"QAM1024", QAM_1024},
272 	{"QAM4096", QAM_4096},
273 #endif
274 };
275 
276 struct init_item cable_mod_list_v5[] = {
277 	{"QAM/16", QAM_16},
278 	{"QAM/32", QAM_32},
279 	{"QAM/64", QAM_64},
280 	{"QAM/128", QAM_128},
281 	{"QAM/256", QAM_256},
282 #ifdef   SYS_DVBC2		//currently not supported by Linux DVB API
283 	{"QAM/512", QAM_512},
284 	{"QAM/1024", QAM_1024},
285 	{"QAM/4096", QAM_4096},
286 #endif
287 };
288 
289 /* convert text to identifiers */
290 
txt_to_cable_fec(const char * txt)291 int txt_to_cable_fec(const char *txt)
292 {
293 	unsigned int i;
294 
295 	for (i = 0; i < STRUCT_COUNT(cable_fec_list); i++)
296 		if (!strcasecmp(txt, cable_fec_list[i].name))
297 			return cable_fec_list[i].id;
298 	return FEC_AUTO;	// fallback. should never happen.
299 }
300 
txt_to_cable_mod(const char * txt)301 int txt_to_cable_mod(const char *txt)
302 {
303 	unsigned int i;
304 
305 	for (i = 0; i < STRUCT_COUNT(cable_mod_list); i++)
306 		if (!strcasecmp(txt, cable_mod_list[i].name))
307 			return cable_mod_list[i].id;
308 	return QAM_AUTO;	// fallback. should never happen.
309 }
310 
311 /*convert identifier to text */
312 
cable_fec_to_txt(int id)313 const char *cable_fec_to_txt(int id)
314 {
315 	unsigned int i;
316 
317 	for (i = 0; i < STRUCT_COUNT(cable_fec_list); i++)
318 		if (id == cable_fec_list[i].id)
319 			return cable_fec_list[i].name;
320 	return "AUTO";		// fallback. should never happen.
321 }
322 
cable_mod_to_txt(int id)323 const char *cable_mod_to_txt(int id)
324 {
325 	unsigned int i;
326 
327 	for (i = 0; i < STRUCT_COUNT(cable_mod_list); i++)
328 		if (id == cable_mod_list[i].id)
329 			return cable_mod_list[i].name;
330 	return "AUTO";		// fallback. should never happen.
331 }
332 
cable_mod_to_txt_v5(int id)333 const char *cable_mod_to_txt_v5(int id)
334 {
335 	unsigned int i;
336 
337 	for (i = 0; i < STRUCT_COUNT(cable_mod_list_v5); i++)
338 		if (id == cable_mod_list_v5[i].id)
339 			return cable_mod_list_v5[i].name;
340 	return "QAM/AUTO";		// fallback. should never happen.
341 }
342 
343 /********************************************************************
344  * ATSC
345  ********************************************************************/
346 
347 struct init_item atsc_mod_list[] = {
348 	{"QAM64", QAM_64},
349 	{"QAM256", QAM_256},
350 	{"8VSB", VSB_8},
351 	{"16VSB", VSB_16},
352 };
353 
354 struct init_item atsc_mod_list_v5[] = {
355 	{"QAM/64", QAM_64},
356 	{"QAM/256", QAM_256},
357 	{"VSB/8", VSB_8},
358 	{"VSB/16", VSB_16},
359 };
360 
361 /* convert text to identifiers */
362 
txt_to_atsc_mod(const char * txt)363 int txt_to_atsc_mod(const char *txt)
364 {
365 	unsigned int i;
366 
367 	for (i = 0; i < STRUCT_COUNT(atsc_mod_list); i++)
368 		if (!strcasecmp(txt, atsc_mod_list[i].name))
369 			return atsc_mod_list[i].id;
370 	return QAM_AUTO;	// fallback. should never happen.
371 }
372 
373 /*convert identifier to text */
374 
atsc_mod_to_txt(int id)375 const char *atsc_mod_to_txt(int id)
376 {
377 	unsigned int i;
378 
379 	for (i = 0; i < STRUCT_COUNT(atsc_mod_list); i++)
380 		if (id == atsc_mod_list[i].id)
381 			return atsc_mod_list[i].name;
382 	return "AUTO";		// fallback. should never happen.
383 }
384 
atsc_mod_to_txt_v5(int id)385 const char *atsc_mod_to_txt_v5(int id)
386 {
387 	unsigned int i;
388 
389 	for (i = 0; i < STRUCT_COUNT(atsc_mod_list_v5); i++)
390 		if (id == atsc_mod_list_v5[i].id)
391 			return atsc_mod_list_v5[i].name;
392 	return "QAM/AUTO";		// fallback. should never happen.
393 }
394 
395 /********************************************************************
396  * DVB-S
397  ********************************************************************/
398 
399 struct init_item sat_delivery_system_list[] = {
400 	{"S", SYS_DVBS},
401 	{"S1", SYS_DVBS},
402 	{"S2", SYS_DVBS2},
403 };
404 
405 struct init_item sat_pol_list[] = {
406 	{"H", POLARIZATION_HORIZONTAL},
407 	{"V", POLARIZATION_VERTICAL},
408 	{"R", POLARIZATION_CIRCULAR_RIGHT},
409 	{"L", POLARIZATION_CIRCULAR_LEFT},
410 };				// NOTE: no AUTO used here.
411 
412 struct init_item sat_pol_list_v5[] = {
413 	{"HORIZONTAL", POLARIZATION_HORIZONTAL},
414 	{"VERTICAL", POLARIZATION_VERTICAL},
415 	{"RIGHT", POLARIZATION_CIRCULAR_RIGHT},
416 	{"LEFT", POLARIZATION_CIRCULAR_LEFT},
417 };				// NOTE: no AUTO used here.
418 
419 struct init_item sat_fec_list[] = {
420 	{"NONE", FEC_NONE},
421 	{"1/2", FEC_1_2},
422 	{"2/3", FEC_2_3},
423 	{"3/4", FEC_3_4},
424 	{"4/5", FEC_4_5},
425 	{"5/6", FEC_5_6},
426 	{"6/7", FEC_6_7},
427 	{"7/8", FEC_7_8},
428 	{"8/9", FEC_8_9},
429 	{"3/5", FEC_3_5},	//S2
430 	{"9/10", FEC_9_10},	//S2
431 	{"AUTO", FEC_AUTO}
432 };
433 
434 struct init_item sat_rolloff_list[] = {
435 	{"35", ROLLOFF_35},
436 	{"25", ROLLOFF_25},
437 	{"20", ROLLOFF_20},
438 	{"AUTO", ROLLOFF_AUTO},
439 };				// NOTE: "AUTO" == 0,35 in w_scan2 !
440 
441 struct init_item sat_mod_list[] = {
442 	{"QPSK", QPSK},
443 	{"8PSK", PSK_8},
444 	{"16APSK", APSK_16},
445 	{"32APSK", APSK_32},
446 	{"AUTO", QPSK},
447 };				// NOTE: "AUTO" == QPSK in w_scan2 !
448 
449 struct init_item sat_mod_list_v5[] = {
450 	{"QPSK", QPSK},
451 	{"PSK/8", PSK_8},
452 	{"APSK/16", APSK_16},
453 	{"APSK/32", APSK_32},
454 	{"AUTO", QPSK},
455 };				// NOTE: "AUTO" == QPSK in w_scan2 !
456 
457 /* convert text to identifiers */
458 
txt_to_sat_delivery_system(const char * txt)459 int txt_to_sat_delivery_system(const char *txt)
460 {
461 	unsigned int i;
462 
463 	for (i = 0; i < STRUCT_COUNT(sat_delivery_system_list); i++)
464 		if (!strcasecmp(txt, sat_delivery_system_list[i].name))
465 			return sat_delivery_system_list[i].id;
466 	return SYS_DVBS;	// fallback. should never happen.
467 }
468 
txt_to_sat_pol(const char * txt)469 int txt_to_sat_pol(const char *txt)
470 {
471 	unsigned int i;
472 
473 	for (i = 0; i < STRUCT_COUNT(sat_pol_list); i++)
474 		if (!strcasecmp(txt, sat_pol_list[i].name))
475 			return sat_pol_list[i].id;
476 	return POLARIZATION_HORIZONTAL;	// fallback. should never happen.
477 }
478 
txt_to_sat_fec(const char * txt)479 int txt_to_sat_fec(const char *txt)
480 {
481 	unsigned int i;
482 
483 	for (i = 0; i < STRUCT_COUNT(sat_fec_list); i++)
484 		if (!strcasecmp(txt, sat_fec_list[i].name))
485 			return sat_fec_list[i].id;
486 	return FEC_AUTO;	// fallback. should never happen.
487 }
488 
txt_to_sat_rolloff(const char * txt)489 int txt_to_sat_rolloff(const char *txt)
490 {
491 	unsigned int i;
492 
493 	for (i = 0; i < STRUCT_COUNT(sat_rolloff_list); i++)
494 		if (!strcasecmp(txt, sat_rolloff_list[i].name))
495 			return sat_rolloff_list[i].id;
496 	return ROLLOFF_35;	// fallback. should never happen.
497 }
498 
txt_to_sat_mod(const char * txt)499 int txt_to_sat_mod(const char *txt)
500 {
501 	unsigned int i;
502 
503 	for (i = 0; i < STRUCT_COUNT(sat_mod_list); i++)
504 		if (!strcasecmp(txt, sat_mod_list[i].name))
505 			return sat_mod_list[i].id;
506 	return QPSK;		// fallback. should never happen.
507 }
508 
509 /*convert identifier to text */
510 
sat_delivery_system_to_txt(int id)511 const char *sat_delivery_system_to_txt(int id)
512 {
513 	unsigned int i;
514 
515 	for (i = 0; i < STRUCT_COUNT(sat_delivery_system_list); i++)
516 		if (id == sat_delivery_system_list[i].id)
517 			return sat_delivery_system_list[i].name;
518 	return "S";		// fallback. should never happen.
519 }
520 
sat_pol_to_txt(int id)521 const char *sat_pol_to_txt(int id)
522 {
523 	unsigned int i;
524 
525 	for (i = 0; i < STRUCT_COUNT(sat_pol_list); i++)
526 		if (id == sat_pol_list[i].id)
527 			return sat_pol_list[i].name;
528 	return "H";		// fallback. should never happen.
529 }
530 
sat_pol_to_txt_v5(int id)531 const char *sat_pol_to_txt_v5(int id)
532 {
533 	unsigned int i;
534 
535 	for (i = 0; i < STRUCT_COUNT(sat_pol_list_v5); i++)
536 		if (id == sat_pol_list_v5[i].id)
537 			return sat_pol_list_v5[i].name;
538 	return "HORIZONTAL";		// fallback. should never happen.
539 }
540 
sat_fec_to_txt(int id)541 const char *sat_fec_to_txt(int id)
542 {
543 	unsigned int i;
544 
545 	for (i = 0; i < STRUCT_COUNT(sat_fec_list); i++)
546 		if (id == sat_fec_list[i].id)
547 			return sat_fec_list[i].name;
548 	return "AUTO";		// fallback. should never happen.
549 }
550 
sat_rolloff_to_txt(int id)551 const char *sat_rolloff_to_txt(int id)
552 {
553 	unsigned int i;
554 
555 	for (i = 0; i < STRUCT_COUNT(sat_rolloff_list); i++)
556 		if (id == sat_rolloff_list[i].id)
557 			return sat_rolloff_list[i].name;
558 	return "35";		// fallback. should never happen.
559 }
560 
sat_mod_to_txt(int id)561 const char *sat_mod_to_txt(int id)
562 {
563 	unsigned int i;
564 
565 	for (i = 0; i < STRUCT_COUNT(sat_mod_list); i++)
566 		if (id == sat_mod_list[i].id)
567 			return sat_mod_list[i].name;
568 	return "QPSK";		// fallback. should never happen.
569 }
570 
sat_mod_to_txt_v5(int id)571 const char *sat_mod_to_txt_v5(int id)
572 {
573 	unsigned int i;
574 
575 	for (i = 0; i < STRUCT_COUNT(sat_mod_list_v5); i++)
576 		if (id == sat_mod_list_v5[i].id)
577 			return sat_mod_list_v5[i].name;
578 	return "QPSK";		// fallback. should never happen.
579 }
580 
581 /********************************************************************
582  * non-frontend specific part
583  *
584  ********************************************************************/
585 
586 struct init_item scantype_list[] = {
587 	{"TERRCABLE_ATSC", SCAN_TERRCABLE_ATSC},
588 	{"CABLE", SCAN_CABLE},
589 	{"TERRESTRIAL", SCAN_TERRESTRIAL},
590 	{"SATELLITE", SCAN_SATELLITE},
591 };				// NOTE: "AUTO" == SCAN_TERRESTRIAL in w_scan2 !
592 
593 /* convert text to identifiers */
594 
txt_to_scantype(const char * txt)595 int txt_to_scantype(const char *txt)
596 {
597 	unsigned int i;
598 
599 	for (i = 0; i < STRUCT_COUNT(scantype_list); i++)
600 		if (!strcasecmp(txt, scantype_list[i].name))
601 			return scantype_list[i].id;
602 	return SCAN_TERRESTRIAL;	// fallback. should never happen.
603 }
604 
605 /*convert identifier to text */
606 
scantype_to_txt(int id)607 const char *scantype_to_txt(int id)
608 {
609 	unsigned int i;
610 
611 	for (i = 0; i < STRUCT_COUNT(scantype_list); i++)
612 		if (id == scantype_list[i].id)
613 			return scantype_list[i].name;
614 	return "TERRESTRIAL";	// fallback. should never happen.
615 }
616