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(¤t_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(¤t_byte, bi);
992 }
993 }
994 SortList(¤t_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