1 /*
2  * Simple MPEG/DVB parser to achieve network/service information without initial tuning data
3  *
4  * Copyright (C) 2006 - 2014 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 <stdio.h>
23 #include <stdlib.h>
24 #include <stdint.h>
25 #include <string.h>
26 #include "scan.h"
27 #include "tools.h"
28 
29 /*******************************************************************************
30  * common typedefs && logging.
31  ******************************************************************************/
32 int verbosity = 2;		// need signed -> use of fatal()
33 
34 /*******************************************************************************
35  * new implementation of double linked list since 20140118.
36  *
37  ******************************************************************************/
38 // #define LIST_DEBUG 1
39 
40 #ifdef LIST_DEBUG
41 #define dbg(s...) info(s)
42 
43 // debugging purposes only. do not use in distributed versions.
report(pList list)44 void report(pList list)
45 {
46 	dbg("--------------------------------------------------------------\n");
47 	dbg("list '%s'@%p: count=%u; first=%p; last=%p\n",
48 		list->name, list, list->count, list->first, list->last);
49 
50 	pItem p = list->first;
51 	while (p != NULL) {
52 		verbose("    item%.2u: prev = %p, ptr = %p: next = %p\n",
53 			p->index, p->prev, p, p->next);
54 		p = p->next;
55 	}
56 	dbg("--------------------------------------------------------------\n");
57 }
58 #else
59 #define dbg(s...)
60 #define report(s...)
61 #endif
62 
63 #if 0
64 // an compare function for testing purposes only.
65 int alphabetically(void *a, void *b, int ascending)
66 {
67 	pStringItem s_a, s_b;
68 	s_a = a;
69 	s_b = b;
70 	if (ascending != 0)
71 		return strcmp(s_a->buf, s_b->buf, 255) > 0;
72 	else
73 		return strcmp(s_a->buf, s_b->buf, 255) < 0;
74 }
75 #endif
76 
77 // initializes a list before first use
NewList(pList const list,const char * name)78 void NewList(pList const list, const char *name)
79 {
80 	dbg("%s %d: list:'%s'\n", __FUNCTION__, __LINE__, name);
81 	list->first = NULL;
82 	list->last = NULL;
83 	list->count = 0;
84 	list->name = calloc(1, strlen(name) + 1);
85 	sprintf(list->name, "%s", name);
86 	report(list);
87 }
88 
89 // returns true, if a pointer is part of list.
IsMember(pList list,void * item)90 bool IsMember(pList list, void *item)
91 {
92 	pItem p;
93 	for (p = list->first; p; p = p->next) {
94 		if (p == item) {
95 			return true;
96 		}
97 	}
98 	return false;
99 }
100 
101 // remove all items from list && free allocated memory.
ClearList(pList list)102 void ClearList(pList list)
103 {
104 	while (list->lock) ;
105 	list->lock = true;
106 	dbg("%s %d: list:'%s'\n", __FUNCTION__, __LINE__, list->name);
107 	pItem p = list->last;
108 
109 	while (p != NULL) {
110 		list->last = p->prev;
111 		free(p);
112 		p = list->last;
113 		if (p != NULL) {
114 			p->next = NULL;
115 		}
116 	}
117 	list->first = NULL;
118 	list->count = 0;
119 	list->lock = false;
120 	report(list);
121 }
122 
123 // returns item specified by zero-based index.
GetItem(pList list,uint32_t index)124 void *GetItem(pList list, uint32_t index)
125 {
126 	dbg("%s %d: list:'%s'\n", __FUNCTION__, __LINE__, list->name);
127 	pItem p;
128 	for (p = list->first; p; p = p->next) {
129 		dbg("    item%.2u: (prev=%p, p=%p, next=%p)\n", p->index,
130 			p->prev, p, p->next);
131 		if (p->index == index)
132 			return p;
133 	}
134 	return NULL;
135 }
136 
137 // append item at end of list.
AddItem(pList list,void * item)138 void AddItem(pList list, void *item)
139 {
140 	pItem p = item;
141 	while (list->lock) ;
142 	list->lock = true;
143 
144 	dbg("%s %d: list:'%s' add item: (prev=%p, p=%p, next=%p)\n",
145 		__FUNCTION__, __LINE__, list->name, p->prev, p, p->next);
146 
147 	p->index = list->count;
148 	p->prev = list->last;
149 	p->next = NULL;
150 
151 	if (list->count == 0) {
152 		list->first = p;
153 	} else {
154 		p = list->last;
155 		p->next = item;
156 	}
157 
158 	list->last = item;
159 	list->count++;
160 	list->lock = false;
161 	report(list);
162 }
163 
164 // insert item to list. index is zero-based pos of new item.
165 // if index greater as (list.count-1), item will be appended instead.
InsertItem(pList list,void * item,uint32_t index)166 void InsertItem(pList list, void *item, uint32_t index)
167 {
168 	while (list->lock) ;
169 	list->lock = true;
170 
171 	dbg("%s %d: list:'%s' item=%p, index=%u\n",
172 		__FUNCTION__, __LINE__, list->name, item, index);
173 
174 	pItem prev, next, p = item;
175 	p->index = 0;
176 	p->prev = NULL;
177 	p->next = NULL;
178 
179 	if (index >= list->count) {
180 		dbg("insert at end of list.\n");
181 		AddItem(list, item);
182 	} else if (index == 0) {
183 		dbg("insert at begin of list.\n");
184 		p->prev = NULL;
185 		p->next = list->first;
186 		p->index = 0;
187 		next = list->first;
188 		next->prev = p;
189 		p = list->first;
190 		while (p != NULL) {
191 			p->index++;
192 			p = p->next;
193 		}
194 		list->first = item;
195 		list->count++;
196 	} else {
197 		dbg("insert somewhere in the middle.\n");
198 		next = GetItem(list, index);
199 		prev = next->prev;
200 		prev->next = p;
201 		next->prev = p;
202 		p->prev = prev;
203 		p->next = next;
204 		p->index = prev->index;
205 		list->count++;
206 		while (p != NULL) {
207 			p->index++;
208 			p = p->next;
209 		}
210 	}
211 	list->lock = false;
212 	report(list);
213 }
214 
215 // remove item from list. free allocated memory if release_mem non-zero.
UnlinkItem(pList list,void * item,bool freemem)216 void UnlinkItem(pList list, void *item, bool freemem)
217 {
218 	while (list->lock) ;
219 	list->lock = true;
220 
221 	pItem prev, next, p = item;
222 
223 	dbg("%s %d: list:'%s' item=%p, freemem = %d\n",
224 		__FUNCTION__, __LINE__, list->name, item, freemem);
225 	if (IsMember(list, item) == false) {
226 		warning("Cannot %s: item %p is not member of list %s.\n",
227 			freemem ? "delete" : "unlink", item, list->name);
228 		return;
229 	} else if (item == list->first) {
230 		dbg("delete at begin of list.\n");
231 		list->first = p->next;
232 		list->count--;
233 		if (freemem) {
234 			free(p);
235 		}
236 		p = list->first;
237 		if (p != NULL)
238 			p->prev = NULL;
239 		while (p != NULL) {
240 			p->index--;
241 			p = p->next;
242 		}
243 	} else if (item == list->last) {
244 		dbg("delete at end of list.\n");
245 		list->last = p->prev;
246 		list->count--;
247 		if (freemem) {
248 			free(p);
249 		}
250 		p = list->last;
251 		if (p != NULL) {
252 			p->next = NULL;
253 		}
254 	} else {
255 		dbg("delete somewhere in the middle.\n");
256 		prev = p->prev;
257 		next = p->next;
258 		prev->next = next;
259 		next->prev = prev;
260 		list->count--;
261 		if (freemem) {
262 			free(p);
263 		}
264 		p = next;
265 		while (p != NULL) {
266 			p->index--;
267 			p = p->next;
268 		}
269 	}
270 	list->lock = false;
271 }
272 
273 // remove item from list and free allocated memory.
DeleteItem(pList list,void * item)274 void DeleteItem(pList list, void *item)
275 {
276 	dbg("%s %d: list:'%s' item=%p\n", __FUNCTION__, __LINE__, list->name,
277 		index);
278 	UnlinkItem(list, item, true);
279 }
280 
281 // exchange two items in list.
SwapItem(pList list,pItem a,pItem b)282 void SwapItem(pList list, pItem a, pItem b)
283 {
284 	while (list->lock) ;
285 	list->lock = true;
286 
287 	dbg("%s %d: list:'%s' a:(prev=%p,p=%p,next=%p) <-> b:(prev=%p,p=%p,next=%p)\n", __FUNCTION__, __LINE__, list->name, a->prev, a, a->next, b->prev, b, b->next);
288 	uint32_t index_a, index_b;
289 	if (a == b) {
290 		list->lock = false;
291 		return;
292 	}
293 
294 	index_a = a->index;
295 	index_b = b->index;
296 
297 	if (index_a < index_b) {
298 		UnlinkItem(list, b, 0);
299 		UnlinkItem(list, a, 0);
300 		InsertItem(list, b, index_a);
301 		InsertItem(list, a, index_b);
302 	} else {
303 		UnlinkItem(list, a, 0);
304 		UnlinkItem(list, b, 0);
305 		InsertItem(list, a, index_b);
306 		InsertItem(list, b, index_a);
307 	}
308 	list->lock = false;
309 }
310 
311 // sort the list. assign sort criteria function
312 // 'compare' to list before first use.
313 // warning: procedure is *slow* for large lists.
SortList(pList list,cmp_func compare)314 void SortList(pList list, cmp_func compare)
315 {
316 	dbg("%s %d: list:'%s'\n", __FUNCTION__, __LINE__, list->name);
317 	pItem c, d;
318 	if (compare == NULL) {
319 		warning("sort function not assigned.\n");
320 		return;
321 	}
322 
323 redo:
324 	c = list->first;
325 	while (c != NULL) {
326 		d = c;
327 		while (d != NULL) {
328 			if (d->next == NULL) {
329 				break;
330 			}
331 			if (compare(d, d->next) > 0) {
332 				SwapItem(list, d, d->next);
333 				goto redo;
334 			}
335 			d = d->next;
336 		}
337 		c = c->next;
338 	}
339 }
340 
FindItem(pList list,void * prev,fnd_func criteria)341 void *FindItem(pList list, void *prev, fnd_func criteria)
342 {
343 	pItem p;
344 	for (p = prev ? prev : list->first; p; p = p->next) {
345 		if (criteria(p))
346 			return p;
347 	}
348 	return NULL;
349 }
350 
351 /*******************************************************************************
352  * time related support functions.
353  *
354  * NOTE: clock_gettime needs linking against librt.
355  *       Therefore librt is dependency for w_scan > 20140118.
356  ******************************************************************************/
357 
358 #ifdef CLOCK_MONOTONIC_COARSE
359 #define CLK_SPEC CLOCK_MONOTONIC_COARSE	/* faster, but only linux since kernel 2.6.32 */
360 #else
361 #define CLK_SPEC CLOCK_MONOTONIC
362 #endif
363 
elapsed(struct timespec * from,struct timespec * to)364 double elapsed(struct timespec *from, struct timespec *to)
365 {
366 	double Result;
367 	int32_t nsec = to->tv_nsec - from->tv_nsec;
368 	if (nsec < 0) {
369 		Result = -1.0 + to->tv_sec - from->tv_sec;
370 		nsec += 1000000000;
371 	} else
372 		Result = to->tv_sec - from->tv_sec;
373 	Result += (nsec / 1e9);
374 	return Result;
375 }
376 
get_time(struct timespec * dest)377 void get_time(struct timespec *dest)
378 {
379 	clock_gettime(CLK_SPEC, dest);
380 }
381 
set_timeout(uint16_t msec,struct timespec * dest)382 void set_timeout(uint16_t msec, struct timespec *dest)
383 {
384 	struct timespec t;
385 	uint32_t nsec;
386 	uint8_t sec;
387 
388 	clock_gettime(CLK_SPEC, &t);
389 	sec = (t.tv_nsec + msec * 1000000U) / 1000000000U;
390 	nsec = (t.tv_nsec + msec * 1000000U) % 1000000000U;
391 	dest->tv_sec = t.tv_sec + sec;
392 	dest->tv_nsec = nsec;
393 //dbg("now = %ld.%.9li timeout = %ld.%.9li\n", t.tv_sec, t.tv_nsec, dest->tv_sec, dest->tv_nsec);
394 }
395 
timeout_expired(struct timespec * src)396 int timeout_expired(struct timespec *src)
397 {
398 	struct timespec t;
399 	int expired;
400 	clock_gettime(CLK_SPEC, &t);
401 
402 	expired = (t.tv_sec > src->tv_sec) ||
403 		((t.tv_sec == src->tv_sec) && (t.tv_nsec > src->tv_nsec));
404 //dbg("now = %ld.%.9li; expired=%d\n", t.tv_sec, t.tv_nsec, expired);
405 	return expired;
406 }
407 
408 /*******************************************************************************
409  * debug helpers.
410  ******************************************************************************/
411 struct timespec starttime = { 0, 0 };
412 
run_time_init()413 void run_time_init()
414 {
415 	get_time(&starttime);
416 }
417 
run_time()418 const char *run_time()
419 {
420 	static char rtbuf[12];
421 	struct timespec now;
422 	double t;
423 	int sec, msec;
424 	get_time(&now);
425 	t = elapsed(&starttime, &now);
426 
427 	sec = (int)t;
428 	msec = 1000.0 * (t - sec);
429 	sprintf(&rtbuf[0], "%.2d:%.2d.%.3d", sec / 60, sec % 60, msec);
430 	return &rtbuf[0];
431 }
432 
hexdump(const char * intro,const unsigned char * buf,int len)433 void hexdump(const char *intro, const unsigned char *buf, int len)
434 {
435 	int i, j;
436 	char sbuf[17];
437 
438 	if (verbosity < 4)
439 		return;
440 
441 	memset(&sbuf, 0, 17);
442 
443 	info("\t===================== %s ", intro);
444 	for (i = strlen(intro) + 1; i < 50; i++)
445 		info("=");
446 	info("\n");
447 	info("\tlen = %d\n", len);
448 	for (i = 0; i < len; i++) {
449 		if ((i % 16) == 0) {
450 			info("%s0x%.2X: ", i ? "\n\t" : "\t", (i / 16) * 16);
451 		}
452 		info("%.2X ", (uint8_t) * (buf + i));
453 		sbuf[i % 16] = *(buf + i);
454 		if (((i + 1) % 16) == 0) {
455 			// remove non-printable chars
456 			for (j = 0; j < 16; j++)
457 				if (!((sbuf[j] > 31) && (sbuf[j] < 127)))
458 					sbuf[j] = ' ';
459 
460 			info(": %s", sbuf);
461 			memset(&sbuf, 0, 17);
462 		}
463 	}
464 	if (len % 16) {
465 		for (i = 0; i < (len % 16); i++)
466 			if (!((sbuf[i] > 31) && (sbuf[i] < 127)))
467 				sbuf[i] = ' ';
468 		for (i = (len % 16); i < 16; i++)
469 			info("   ");
470 		info(": %s", sbuf);
471 	}
472 	info("\n");
473 	info("\t========================================================================\n");
474 }
475 
inversion_name(int inversion)476 const char *inversion_name(int inversion)
477 {
478 	switch (inversion) {
479 	case INVERSION_OFF:
480 		return "INVERSION_OFF";
481 	case INVERSION_ON:
482 		return "INVERSION_ON";
483 	default:
484 		return "INVERSION_AUTO";
485 	}
486 }
487 
coderate_name(int coderate)488 const char *coderate_name(int coderate)
489 {
490 	switch (coderate) {
491 	case FEC_NONE:
492 		return "FEC_NONE";
493 	case FEC_2_5:
494 		return "FEC_2_5";
495 	case FEC_1_2:
496 		return "FEC_1_2";
497 	case FEC_3_5:
498 		return "FEC_3_5";
499 	case FEC_2_3:
500 		return "FEC_2_3";
501 	case FEC_3_4:
502 		return "FEC_3_4";
503 	case FEC_4_5:
504 		return "FEC_4_5";
505 	case FEC_5_6:
506 		return "FEC_5_6";
507 	case FEC_6_7:
508 		return "FEC_6_7";
509 	case FEC_7_8:
510 		return "FEC_7_8";
511 	case FEC_8_9:
512 		return "FEC_8_9";
513 	case FEC_9_10:
514 		return "FEC_9_10";
515 	default:
516 		return "FEC_AUTO";
517 	}
518 }
519 
modulation_name(int modulation)520 const char *modulation_name(int modulation)
521 {
522 	switch (modulation) {
523 	case QPSK:
524 		return "QPSK";
525 	case QAM_16:
526 		return "QAM_16";
527 	case QAM_32:
528 		return "QAM_32";
529 	case QAM_64:
530 		return "QAM_64";
531 	case QAM_128:
532 		return "QAM_128";
533 	case QAM_256:
534 		return "QAM_256";
535 	case QAM_AUTO:
536 		return "QAM_AUTO";
537 	case VSB_8:
538 		return "VSB_8";
539 	case VSB_16:
540 		return "VSB_16";
541 	case PSK_8:
542 		return "PSK_8";
543 	case APSK_16:
544 		return "APSK_16";
545 	case APSK_32:
546 		return "APSK_32";
547 	case DQPSK:
548 		return "DQPSK";
549 	case QAM_4_NR:
550 		return "QAM_4_NR";
551 	default:
552 		return "QAM_AUTO";
553 	}
554 }
555 
transmission_mode_name(int transmission_mode)556 const char *transmission_mode_name(int transmission_mode)
557 {
558 	switch (transmission_mode) {
559 	case TRANSMISSION_MODE_1K:
560 		return "TRANSMISSION_MODE_1K";
561 	case TRANSMISSION_MODE_2K:
562 		return "TRANSMISSION_MODE_2K";
563 	case TRANSMISSION_MODE_4K:
564 		return "TRANSMISSION_MODE_4K";
565 	case TRANSMISSION_MODE_8K:
566 		return "TRANSMISSION_MODE_8K";
567 	case TRANSMISSION_MODE_16K:
568 		return "TRANSMISSION_MODE_16K";
569 	case TRANSMISSION_MODE_32K:
570 		return "TRANSMISSION_MODE_32K";
571 	case TRANSMISSION_MODE_C1:
572 		return "TRANSMISSION_MODE_C1";
573 	case TRANSMISSION_MODE_C3780:
574 		return "TRANSMISSION_MODE_C3780";
575 	default:
576 		return "TRANSMISSION_MODE_AUTO";
577 	}
578 }
579 
guard_interval_name(int guard_interval)580 const char *guard_interval_name(int guard_interval)
581 {
582 	switch (guard_interval) {
583 	case GUARD_INTERVAL_1_32:
584 		return "GUARD_INTERVAL_1_32";
585 	case GUARD_INTERVAL_1_16:
586 		return "GUARD_INTERVAL_1_16";
587 	case GUARD_INTERVAL_1_8:
588 		return "GUARD_INTERVAL_1_8";
589 	case GUARD_INTERVAL_1_4:
590 		return "GUARD_INTERVAL_1_4";
591 	case GUARD_INTERVAL_1_128:
592 		return "GUARD_INTERVAL_1_128";
593 	case GUARD_INTERVAL_19_128:
594 		return "GUARD_INTERVAL_19_128";
595 	case GUARD_INTERVAL_19_256:
596 		return "GUARD_INTERVAL_19_256";
597 	case GUARD_INTERVAL_PN420:
598 		return "GUARD_INTERVAL_PN420";
599 	case GUARD_INTERVAL_PN595:
600 		return "GUARD_INTERVAL_PN595";
601 	case GUARD_INTERVAL_PN945:
602 		return "GUARD_INTERVAL_PN945";
603 	default:
604 		return "GUARD_INTERVAL_AUTO";
605 	}
606 }
607 
hierarchy_name(int hierarchy)608 const char *hierarchy_name(int hierarchy)
609 {
610 	switch (hierarchy) {
611 	case HIERARCHY_NONE:
612 		return "HIERARCHY_NONE";
613 	case HIERARCHY_1:
614 		return "HIERARCHY_1";
615 	case HIERARCHY_2:
616 		return "HIERARCHY_2";
617 	case HIERARCHY_4:
618 		return "HIERARCHY_4";
619 	default:
620 		return "HIERARCHY_AUTO";
621 	}
622 }
623 
interleaving_name(int interleaving)624 const char *interleaving_name(int interleaving)
625 {
626 	switch (interleaving) {
627 	case INTERLEAVING_NONE:
628 		return "INTERLEAVING_NONE";
629 	case INTERLEAVING_240:
630 		return "INTERLEAVING_240";
631 	case INTERLEAVING_720:
632 		return "INTERLEAVING_720";
633 	default:
634 		return "INTERLEAVING_AUTO";
635 	}
636 }
637 
delivery_system_name(int delsys)638 const char *delivery_system_name(int delsys)
639 {
640 	switch (delsys) {
641 	case SYS_DVBC_ANNEX_A:
642 		return "SYS_DVBC_ANNEX_A";
643 	case SYS_DVBC_ANNEX_B:
644 		return "SYS_DVBC_ANNEX_B";
645 	case SYS_DVBT:
646 		return "SYS_DVBT";
647 	case SYS_DSS:
648 		return "SYS_DSS";
649 	case SYS_DVBS:
650 		return "SYS_DVBS";
651 	case SYS_DVBS2:
652 		return "SYS_DVBS2";
653 	case SYS_DVBH:
654 		return "SYS_DVBH";
655 	case SYS_ISDBT:
656 		return "SYS_ISDBT";
657 	case SYS_ISDBS:
658 		return "SYS_ISDBS";
659 	case SYS_ISDBC:
660 		return "SYS_ISDBC";
661 	case SYS_ATSC:
662 		return "SYS_ATSC";
663 	case SYS_ATSCMH:
664 		return "SYS_ATSCMH";
665 	case SYS_DTMB:
666 		return "SYS_DTMB";
667 	case SYS_CMMB:
668 		return "SYS_CMMB";
669 	case SYS_DAB:
670 		return "SYS_DAB";
671 	case SYS_DVBT2:
672 		return "SYS_DVBT2";
673 	case SYS_TURBO:
674 		return "SYS_TURBO";
675 	case SYS_DVBC_ANNEX_C:
676 		return "SYS_DVBC_ANNEX_C";
677 	default:
678 		return "SYS_UNDEFINED";
679 	}
680 }
681 
property_name(int property)682 const char *property_name(int property)
683 {
684 	switch (property) {
685 	case DTV_UNDEFINED:
686 		return "DTV_UNDEFINED";
687 	case DTV_TUNE:
688 		return "DTV_TUNE";
689 	case DTV_CLEAR:
690 		return "DTV_CLEAR";
691 	case DTV_FREQUENCY:
692 		return "DTV_FREQUENCY";
693 	case DTV_MODULATION:
694 		return "DTV_MODULATION";
695 	case DTV_BANDWIDTH_HZ:
696 		return "DTV_BANDWIDTH_HZ";
697 	case DTV_INVERSION:
698 		return "DTV_INVERSION";
699 	case DTV_DISEQC_MASTER:
700 		return "DTV_DISEQC_MASTER";
701 	case DTV_SYMBOL_RATE:
702 		return "DTV_SYMBOL_RATE";
703 	case DTV_INNER_FEC:
704 		return "DTV_INNER_FEC";
705 	case DTV_VOLTAGE:
706 		return "DTV_VOLTAGE";
707 	case DTV_TONE:
708 		return "DTV_TONE";
709 	case DTV_PILOT:
710 		return "DTV_PILOT";
711 	case DTV_ROLLOFF:
712 		return "DTV_ROLLOFF";
713 	case DTV_DISEQC_SLAVE_REPLY:
714 		return "DTV_DISEQC_SLAVE_REPLY";
715 	case DTV_FE_CAPABILITY_COUNT:
716 		return "DTV_FE_CAPABILITY_COUNT";
717 	case DTV_FE_CAPABILITY:
718 		return "DTV_FE_CAPABILITY";
719 	case DTV_DELIVERY_SYSTEM:
720 		return "DTV_DELIVERY_SYSTEM";
721 	case DTV_ISDBT_PARTIAL_RECEPTION:
722 		return "DTV_ISDBT_PARTIAL_RECEPTION";
723 	case DTV_ISDBT_SOUND_BROADCASTING:
724 		return "DTV_ISDBT_SOUND_BROADCASTING";
725 	case DTV_ISDBT_SB_SUBCHANNEL_ID:
726 		return "DTV_ISDBT_SB_SUBCHANNEL_ID";
727 	case DTV_ISDBT_SB_SEGMENT_IDX:
728 		return "DTV_ISDBT_SB_SEGMENT_IDX";
729 	case DTV_ISDBT_SB_SEGMENT_COUNT:
730 		return "DTV_ISDBT_SB_SEGMENT_COUNT";
731 	case DTV_ISDBT_LAYERA_FEC:
732 		return "DTV_ISDBT_LAYERA_FEC";
733 	case DTV_ISDBT_LAYERA_MODULATION:
734 		return "DTV_ISDBT_LAYERA_MODULATION";
735 	case DTV_ISDBT_LAYERA_SEGMENT_COUNT:
736 		return "DTV_ISDBT_LAYERA_SEGMENT_COUNT";
737 	case DTV_ISDBT_LAYERA_TIME_INTERLEAVING:
738 		return "DTV_ISDBT_LAYERA_TIME_INTERLEAVING";
739 	case DTV_ISDBT_LAYERB_FEC:
740 		return "DTV_ISDBT_LAYERB_FEC";
741 	case DTV_ISDBT_LAYERB_MODULATION:
742 		return "DTV_ISDBT_LAYERB_MODULATION";
743 	case DTV_ISDBT_LAYERB_SEGMENT_COUNT:
744 		return "DTV_ISDBT_LAYERB_SEGMENT_COUNT";
745 	case DTV_ISDBT_LAYERB_TIME_INTERLEAVING:
746 		return "DTV_ISDBT_LAYERB_TIME_INTERLEAVING";
747 	case DTV_ISDBT_LAYERC_FEC:
748 		return "DTV_ISDBT_LAYERC_FEC";
749 	case DTV_ISDBT_LAYERC_MODULATION:
750 		return "DTV_ISDBT_LAYERC_MODULATION";
751 	case DTV_ISDBT_LAYERC_SEGMENT_COUNT:
752 		return "DTV_ISDBT_LAYERC_SEGMENT_COUNT";
753 	case DTV_ISDBT_LAYERC_TIME_INTERLEAVING:
754 		return "DTV_ISDBT_LAYERC_TIME_INTERLEAVING";
755 	case DTV_API_VERSION:
756 		return "DTV_API_VERSION";
757 	case DTV_CODE_RATE_HP:
758 		return "DTV_CODE_RATE_HP";
759 	case DTV_CODE_RATE_LP:
760 		return "DTV_CODE_RATE_LP";
761 	case DTV_GUARD_INTERVAL:
762 		return "DTV_GUARD_INTERVAL";
763 	case DTV_TRANSMISSION_MODE:
764 		return "DTV_TRANSMISSION_MODE";
765 	case DTV_HIERARCHY:
766 		return "DTV_HIERARCHY";
767 	case DTV_ISDBT_LAYER_ENABLED:
768 		return "DTV_ISDBT_LAYER_ENABLED";
769 	case DTV_STREAM_ID:
770 		return "DTV_STREAM_ID";
771 	case DTV_DVBT2_PLP_ID_LEGACY:
772 		return "DTV_DVBT2_PLP_ID_LEGACY";
773 	case DTV_ENUM_DELSYS:
774 		return "DTV_ENUM_DELSYS";
775 	case DTV_ATSCMH_FIC_VER:
776 		return "DTV_ATSCMH_FIC_VER";
777 	case DTV_ATSCMH_PARADE_ID:
778 		return "DTV_ATSCMH_PARADE_ID";
779 	case DTV_ATSCMH_NOG:
780 		return "DTV_ATSCMH_NOG";
781 	case DTV_ATSCMH_TNOG:
782 		return "DTV_ATSCMH_TNOG";
783 	case DTV_ATSCMH_SGN:
784 		return "DTV_ATSCMH_SGN";
785 	case DTV_ATSCMH_PRC:
786 		return "DTV_ATSCMH_PRC";
787 	case DTV_ATSCMH_RS_FRAME_MODE:
788 		return "DTV_ATSCMH_RS_FRAME_MODE";
789 	case DTV_ATSCMH_RS_FRAME_ENSEMBLE:
790 		return "DTV_ATSCMH_RS_FRAME_ENSEMBLE";
791 	case DTV_ATSCMH_RS_CODE_MODE_PRI:
792 		return "DTV_ATSCMH_RS_CODE_MODE_PRI";
793 	case DTV_ATSCMH_RS_CODE_MODE_SEC:
794 		return "DTV_ATSCMH_RS_CODE_MODE_SEC";
795 	case DTV_ATSCMH_SCCC_BLOCK_MODE:
796 		return "DTV_ATSCMH_SCCC_BLOCK_MODE";
797 	case DTV_ATSCMH_SCCC_CODE_MODE_A:
798 		return "DTV_ATSCMH_SCCC_CODE_MODE_A";
799 	case DTV_ATSCMH_SCCC_CODE_MODE_B:
800 		return "DTV_ATSCMH_SCCC_CODE_MODE_B";
801 	case DTV_ATSCMH_SCCC_CODE_MODE_C:
802 		return "DTV_ATSCMH_SCCC_CODE_MODE_C";
803 	case DTV_ATSCMH_SCCC_CODE_MODE_D:
804 		return "DTV_ATSCMH_SCCC_CODE_MODE_D";
805 	case DTV_INTERLEAVING:
806 		return "DTV_INTERLEAVING";
807 	case DTV_LNA:
808 		return "DTV_LNA";
809 	case DTV_STAT_SIGNAL_STRENGTH:
810 		return "DTV_STAT_SIGNAL_STRENGTH";
811 	case DTV_STAT_CNR:
812 		return "DTV_STAT_CNR";
813 	case DTV_STAT_PRE_ERROR_BIT_COUNT:
814 		return "DTV_STAT_PRE_ERROR_BIT_COUNT";
815 	case DTV_STAT_PRE_TOTAL_BIT_COUNT:
816 		return "DTV_STAT_PRE_TOTAL_BIT_COUNT";
817 	case DTV_STAT_POST_ERROR_BIT_COUNT:
818 		return "DTV_STAT_POST_ERROR_BIT_COUNT";
819 	case DTV_STAT_POST_TOTAL_BIT_COUNT:
820 		return "DTV_STAT_POST_TOTAL_BIT_COUNT";
821 	case DTV_STAT_ERROR_BLOCK_COUNT:
822 		return "DTV_STAT_ERROR_BLOCK_COUNT";
823 	case DTV_STAT_TOTAL_BLOCK_COUNT:
824 		return "DTV_STAT_TOTAL_BLOCK_COUNT";
825 	default:
826 		return "(unknown dtv property)";
827 	}
828 }
829 
ofdm_symbol_duration_name(fe_ofdm_symbol_duration_t ofdm_symbol_duration)830 const char *ofdm_symbol_duration_name(fe_ofdm_symbol_duration_t ofdm_symbol_duration) {
831 	switch (ofdm_symbol_duration) {
832 	case FFT_4K_8MHZ:
833 		return "FFT_4K_8MHZ";
834 	case FFT_4K_6MHZ:
835 		return "FFT_4K_6MHZ";
836 	default:
837 		return "(unknown ofdm symbol duration)";
838 	}
839 }
840 
rolloff_name(fe_rolloff_t rolloff)841 const char *rolloff_name(fe_rolloff_t rolloff) {
842 	switch (rolloff) {
843 	case ROLLOFF_35:
844 		return "ROLLOFF_35";
845 	case ROLLOFF_25:
846 		return "ROLLOFF_25";
847 	case ROLLOFF_20:
848 		return "ROLLOFF_20";
849 	case ROLLOFF_AUTO:
850 		return "ROLLOFF_AUTO";
851 	default:
852 		return "(unknown rolloff)";
853 	}
854 }
855 
pilot_name(fe_pilot_t pilot)856 const char *pilot_name(fe_pilot_t pilot) {
857 	switch (pilot) {
858 	case PILOT_ON:
859 		return "PILOT_ON";
860 	case PILOT_OFF:
861 		return "PILOT_OFF";
862 	case PILOT_AUTO:
863 		return "PILOT_AUTO";
864 	default:
865 		return "(unknown pilot)";
866 	}
867 }
868 
frequency_type_name(fe_frequency_type_t frequency_type)869 const char *frequency_type_name(fe_frequency_type_t frequency_type) {
870 	switch (frequency_type) {
871 	case DATA_SLICE_TUNING_FREQUENCY:
872 		return "DATA_SLICE_TUNING_FREQUENCY";
873 	case C2_SYSTEM_CENTER_FREQUENCY:
874 		return "C2_SYSTEM_CENTER_FREQUENCY";
875 	case INITIAL_TUNING_FOR_STATIC_DATA_SLICE:
876 		return "INITIAL_TUNING_FOR_STATIC_DATA_SLICE";
877 	default:
878 		return "(unknown frequency type)";
879 	}
880 }
881 
west_east_flag_name(fe_west_east_flag_t west_east_flag)882 const char *west_east_flag_name(fe_west_east_flag_t west_east_flag) {
883 	switch (west_east_flag) {
884 	case EAST_FLAG:
885 		return "E";
886 	case WEST_FLAG:
887 		return "W";
888 	default:
889 		return "(unknown west east flag)";
890 	}
891 }
892 
polarization_name(fe_polarization_t polarization)893 const char *polarization_name(fe_polarization_t polarization) {
894 	switch (polarization) {
895 	case POLARIZATION_HORIZONTAL:
896 		return "HORIZONTAL";
897 	case POLARIZATION_VERTICAL:
898 		return "VERTICAL";
899 	case POLARIZATION_CIRCULAR_LEFT:
900 		return "CIRCULAR_LEFT";
901 	case POLARIZATION_CIRCULAR_RIGHT:
902 		return "CIRCULAR_RIGHT";
903 	default:
904 		return "(unknown polarization)";
905 	}
906 }
907 
bool_name(bool t)908 const char *bool_name(bool t)
909 {
910 	if (t == false)
911 		return "false";
912 	return "true";
913 }
914 
freq_scale(uint32_t freq,double scale)915 uint32_t freq_scale(uint32_t freq, double scale)
916 {
917 	return (uint32_t) (0.5 + freq * scale);
918 }
919 
alpha_name(int alpha)920 const char *alpha_name(int alpha)
921 {
922 	switch (alpha) {
923 	case ALPHA_1:
924 		return "ALPHA_1";
925 	case ALPHA_2:
926 		return "ALPHA_2";
927 	case ALPHA_4:
928 		return "ALPHA_4";
929 	default:
930 		return "ALPHA_AUTO";
931 	}
932 }
933 
interleaver_name(int i)934 const char *interleaver_name(int i)
935 {
936 	switch (i) {
937 	case INTERLEAVE_NATIVE:
938 		return "INTERLEAVE_NATIVE";
939 	case INTERLEAVE_IN_DEPTH:
940 		return "INTERLEAVE_IN_DEPTH";
941 	default:
942 		return "INTERLEAVE_AUTO";
943 	}
944 }
945 
946 /*******************************************************************************
947  * fuzzy bit error recovery.
948  ******************************************************************************/
949 #include "si_types.h"
950 
951 typedef struct {
952 	void *prev;
953 	void *next;
954 	uint32_t index;
955 	uint8_t value;
956 	uint8_t count;
957 } byte_item;
958 
sort_by_count(void * a,void * b)959 static int sort_by_count(void *a, void *b)
960 {
961 	return ((byte_item *) a)->count > ((byte_item *) b)->count;
962 }
963 
fuzzy_section(void * s)964 bool fuzzy_section(void *s)
965 {
966 	struct section_buf *section = (struct section_buf *)s;
967 	cList current_byte;
968 	unsigned char *buf;
969 	unsigned i, j;
970 
971 	if (section->garbage == NULL)
972 		return false;
973 
974 	buf = (unsigned char *)calloc(1, SECTION_BUF_SIZE);
975 	for (i = 0; i < SECTION_BUF_SIZE; i++) {
976 		byte_item *bi;
977 		NewList(&current_byte, "fuzzy_section: current_byte");
978 
979 		for (j = 0; j < (section->garbage)->count; j++) {
980 			buf = GetItem(section->garbage, j) + sizeof(cList);
981 			for (bi = current_byte.first; bi; bi = bi->next) {
982 				if (bi->value == buf[i]) {
983 					bi->count++;
984 					break;
985 				}
986 			}
987 			if (bi == NULL) {
988 				bi = (byte_item *) calloc(1, sizeof(*bi));
989 				bi->value = buf[i];
990 				bi->count++;
991 				AddItem(&current_byte, bi);
992 			}
993 		}
994 		SortList(&current_byte, &sort_by_count);
995 		buf[i] = ((byte_item *) current_byte.first)->value;
996 	}
997 
998 	hexdump(__FUNCTION__, buf, 1024);
999 	return false;		// fail.
1000 }
1001