1 /*
2 * TV Input - DVB - Support/Conversion functions
3 * Copyright (C) 2007 Andreas Öman
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <sys/ioctl.h>
22 #include <errno.h>
23
24 #include <stdio.h>
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "tvheadend.h"
30 #include "dvb.h"
31 #include "dvb_charset_tables.h"
32 #include "input.h"
33 #include "intlconv.h"
34 #include "lang_str.h"
35 #include "settings.h"
36
37 static int convert_iso_8859[16] = {
38 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -1, 11, 12, 13
39 };
40 #define convert_utf8 14
41 #define convert_iso6937 15
42 #define convert_ucs2 16
43 #define convert_gb 17
44
conv_gb(const uint8_t * src,size_t srclen,char * dst,size_t * dstlen)45 static inline size_t conv_gb(const uint8_t *src, size_t srclen,
46 char *dst, size_t *dstlen)
47 {
48 ssize_t len;
49 len = intlconv_to_utf8(dst, *dstlen, "gb2312", (char *)src, srclen);
50 if (len < 0 || len > *dstlen)
51 return -1;
52 *dstlen -= len;
53 return 0;
54 }
55
encode_utf8(unsigned int c,char * outb,int outleft)56 static inline int encode_utf8(unsigned int c, char *outb, int outleft)
57 {
58 if (c <= 0x7F && outleft >= 1) {
59 *outb = c;
60 return 1;
61 } else if (c <= 0x7FF && outleft >=2) {
62 *outb++ = ((c >> 6) & 0x1F) | 0xC0;
63 *outb++ = ( c & 0x3F) | 0x80;
64 return 2;
65 } else if (c <= 0xFFFF && outleft >= 3) {
66 *outb++ = ((c >> 12) & 0x0F) | 0xE0;
67 *outb++ = ((c >> 6) & 0x3F) | 0x80;
68 *outb++ = ( c & 0x3F) | 0x80;
69 return 3;
70 } else if (c <= 0x10FFFF && outleft >= 4) {
71 *outb++ = ((c >> 18) & 0x07) | 0xF0;
72 *outb++ = ((c >> 12) & 0x3F) | 0x80;
73 *outb++ = ((c >> 6) & 0x3F) | 0x80;
74 *outb++ = ( c & 0x3F) | 0x80;
75 return 4;
76 } else {
77 return -1;
78 }
79 }
80
conv_UCS2(const uint8_t * src,size_t srclen,char * dst,size_t * dstlen)81 static inline size_t conv_UCS2(const uint8_t *src, size_t srclen,char *dst, size_t *dstlen)
82 {
83 while (srclen>0 && (*dstlen)>0){
84 uint16_t uc = *src<<8|*(src+1);
85 if (uc >= 0xe080 && uc <= 0xe09f) {
86 // codes 0xe080 - 0xe09f (control codes) are ignored except CR/LF
87 if (uc == 0xe08a) {
88 *dst = '\n';
89 (*dstlen)--;
90 dst++;
91 }
92 } else {
93 int len = encode_utf8(uc, dst, *dstlen);
94 if (len == -1) {
95 errno = E2BIG;
96 return -1;
97 } else {
98 (*dstlen) -= len;
99 dst += len;
100 }
101 }
102 srclen-=2;
103 src+=2;
104 }
105 if (srclen>0) {
106 errno = E2BIG;
107 return -1;
108 }
109 return 0;
110 }
111
conv_utf8(const uint8_t * src,size_t srclen,char * dst,size_t * dstlen)112 static inline size_t conv_utf8(const uint8_t *src, size_t srclen,
113 char *dst, size_t *dstlen)
114 {
115 while (srclen>0 && (*dstlen)>0) {
116 *dst = (char) *src;
117 srclen--; (*dstlen)--;
118 src++; dst++;
119 }
120 if (srclen>0) {
121 errno = E2BIG;
122 return -1;
123 }
124 return 0;
125 }
126
conv_8859(int conv,const uint8_t * src,size_t srclen,char * dst,size_t * dstlen)127 static inline size_t conv_8859(int conv,
128 const uint8_t *src, size_t srclen,
129 char *dst, size_t *dstlen)
130 {
131 uint16_t *table = conv_8859_table[conv];
132
133 while (srclen>0 && (*dstlen)>0) {
134 uint8_t c = *src;
135 if (c <= 0x7f) {
136 // lower half of iso-8859-* is identical to utf-8
137 *dst = (char) *src;
138 (*dstlen)--;
139 dst++;
140 } else if (c <= 0x9f) {
141 // codes 0x80 - 0x9f (control codes) are ignored except CR/LF
142 if (c == 0x8a) {
143 *dst = '\n';
144 (*dstlen)--;
145 dst++;
146 }
147 } else {
148 // map according to character table, skipping
149 // unmapped chars (value 0 in the table)
150 uint16_t uc = table[c-0xa0];
151 if (uc != 0) {
152 int len = encode_utf8(uc, dst, *dstlen);
153 if (len == -1) {
154 errno = E2BIG;
155 return -1;
156 } else {
157 (*dstlen) -= len;
158 dst += len;
159 }
160 }
161 }
162 srclen--;
163 src++;
164 }
165 if (srclen>0) {
166 errno = E2BIG;
167 return -1;
168 }
169 return 0;
170 }
171
conv_6937(const uint8_t * src,size_t srclen,char * dst,size_t * dstlen)172 static inline size_t conv_6937(const uint8_t *src, size_t srclen,
173 char *dst, size_t *dstlen)
174 {
175 while (srclen>0 && (*dstlen)>0) {
176 uint8_t c = *src;
177 if (c <= 0x7f) {
178 // lower half of iso6937 is identical to utf-8
179 *dst = (char) *src;
180 (*dstlen)--;
181 dst++;
182 } else if (c <= 0x9f) {
183 // codes 0x80 - 0x9f (control codes) are ignored except CR/LF
184 if (c == 0x8a) {
185 *dst = '\n';
186 (*dstlen)--;
187 dst++;
188 }
189 } else {
190 uint16_t uc;
191 if (c >= 0xc0 && c <= 0xcf) {
192 // map two-byte sequence, skipping illegal combinations.
193 if (srclen<2) {
194 errno = EINVAL;
195 return -1;
196 }
197 srclen--;
198 src++;
199 uint8_t c2 = *src;
200 if (c2 == 0x20) {
201 uc = iso6937_lone_accents[c-0xc0];
202 } else if (c2 >= 0x41 && c2 <= 0x5a) {
203 uc = iso6937_multi_byte[c-0xc0][c2-0x41];
204 } else if (c2 >= 0x61 && c2 <= 0x7a) {
205 uc = iso6937_multi_byte[c-0xc0][c2-0x61+26];
206 } else {
207 uc = 0;
208 }
209 } else {
210 // map according to single character table, skipping
211 // unmapped chars (value 0 in the table)
212 uc = iso6937_single_byte[c-0xa0];
213 }
214 if (uc != 0) {
215 int len = encode_utf8(uc, dst, *dstlen);
216 if (len == -1) {
217 errno = E2BIG;
218 return -1;
219 } else {
220 (*dstlen) -= len;
221 dst += len;
222 }
223 }
224 }
225 srclen--;
226 src++;
227 }
228 if (srclen>0) {
229 errno = E2BIG;
230 return -1;
231 }
232 return 0;
233 }
234
dvb_convert(int conv,const uint8_t * src,size_t srclen,char * dst,size_t * dstlen)235 static inline size_t dvb_convert(int conv,
236 const uint8_t *src, size_t srclen,
237 char *dst, size_t *dstlen)
238 {
239 switch (conv) {
240 case convert_utf8: return conv_utf8(src, srclen, dst, dstlen);
241 case convert_iso6937: return conv_6937(src, srclen, dst, dstlen);
242 case convert_gb: return conv_gb(src,srclen,dst,dstlen);
243 case convert_ucs2:return conv_UCS2(src,srclen,dst,dstlen);
244 default: return conv_8859(conv, src, srclen, dst, dstlen);
245 }
246 }
247
248 /*
249 * DVB String conversion according to EN 300 468, Annex A
250 * Not all character sets are supported, but it should cover most of them
251 */
252
253 int
dvb_get_string(char * dst,size_t dstlen,const uint8_t * src,size_t srclen,const char * dvb_charset,dvb_string_conv_t * conv)254 dvb_get_string
255 (char *dst, size_t dstlen, const uint8_t *src, size_t srclen,
256 const char *dvb_charset, dvb_string_conv_t *conv)
257 {
258 int ic = -1;
259 size_t len, outlen;
260 int i, auto_pl_charset = 0;
261
262 if(srclen < 1) {
263 *dst = 0;
264 return 0;
265 }
266
267 /* Check custom conversion */
268 while (conv && conv->func) {
269 if (conv->type == src[0])
270 return conv->func(dst, &dstlen, src, srclen);
271 conv++;
272 }
273
274 // check for automatic polish charset detection
275 if (dvb_charset && strcmp("AUTO_POLISH", dvb_charset) == 0) {
276 auto_pl_charset = 1;
277 dvb_charset = NULL;
278 }
279
280 // automatic charset detection
281 switch(src[0]) {
282 case 0:
283 *dst = 0; // empty string (confirmed!)
284 return 0;
285
286 case 0x01 ... 0x0b:
287 if (auto_pl_charset && (src[0] + 4) == 5)
288 ic = convert_iso6937;
289 else
290 ic = convert_iso_8859[src[0] + 4];
291 src++; srclen--;
292 break;
293
294 case 0x0c ... 0x0f:
295 src++; srclen--;
296 break;
297
298 case 0x10: /* Table A.4 */
299 if(srclen < 3 || src[1] != 0 || src[2] == 0 || src[2] > 0x0f)
300 return -1;
301
302 ic = convert_iso_8859[src[2]];
303 src+=3; srclen-=3;
304 break;
305
306 case 0x11:
307 ic = convert_ucs2;
308 src++; srclen--;
309 break;
310
311 case 0x13:
312 ic = convert_gb;
313 src++; srclen--;
314 break;
315
316 case 0x12:
317 src++; srclen--;
318 break;
319
320 case 0x14:
321 ic = convert_ucs2;
322 src++; srclen--;
323 break;
324
325 case 0x15:
326 ic = convert_utf8;
327 src++; srclen--;
328 break;
329
330 case 0x16 ... 0x1f:
331 src++; srclen--;
332 break;
333
334 default:
335 if (auto_pl_charset)
336 ic = convert_iso_8859[2];
337 else
338 ic = convert_iso6937;
339 break;
340 }
341
342 // manual charset override
343 if (dvb_charset != NULL && dvb_charset[0] != 0) {
344 if (!strcmp(dvb_charset, "AUTO")) {
345 // ignore
346 } else if (sscanf(dvb_charset, "ISO-8859-%d", &i) > 0 && i > 0 && i < 16) {
347 ic = convert_iso_8859[i];
348 } else if (!strcmp(dvb_charset, "ISO-6937")) {
349 ic = convert_iso6937;
350 } else if (!strcmp(dvb_charset, "UTF-8")) {
351 ic = convert_utf8;
352 } else if (!strcmp(dvb_charset, "GB2312")) {
353 ic = convert_gb;
354 } else if (!strcmp(dvb_charset, "UCS2")) {
355 ic = convert_ucs2;
356 }
357 }
358
359 if(srclen < 1) {
360 *dst = 0;
361 return 0;
362 }
363
364 if(ic == -1)
365 return -1;
366
367 outlen = dstlen - 1;
368
369 if (dvb_convert(ic, src, srclen, dst, &outlen) == -1)
370 return -1;
371
372 len = dstlen - outlen - 1;
373 dst[len] = 0;
374 return 0;
375 }
376
377
378 int
dvb_get_string_with_len(char * dst,size_t dstlen,const uint8_t * buf,size_t buflen,const char * dvb_charset,dvb_string_conv_t * conv)379 dvb_get_string_with_len(char *dst, size_t dstlen,
380 const uint8_t *buf, size_t buflen, const char *dvb_charset,
381 dvb_string_conv_t *conv)
382 {
383 int l = buf[0];
384
385 if(l + 1 > buflen)
386 return -1;
387
388 if(dvb_get_string(dst, dstlen, buf + 1, l, dvb_charset, conv))
389 return -1;
390
391 return l + 1;
392 }
393
394
395 /**
396 *
397 */
398 void
atsc_utf16_to_utf8(const uint8_t * src,int len,char * buf,int buflen)399 atsc_utf16_to_utf8(const uint8_t *src, int len, char *buf, int buflen)
400 {
401 int i, c, r;
402
403 for(i = 0; i < len; i++) {
404 c = (src[i * 2 + 0] << 8) | src[i * 2 + 1];
405
406 if(buflen >= 7) {
407 r = put_utf8(buf, c);
408 buf += r;
409 buflen -= r;
410 }
411 }
412 *buf = 0;
413 }
414
415 lang_str_t *
atsc_get_string(const uint8_t * src,size_t srclen)416 atsc_get_string
417 (const uint8_t *src, size_t srclen)
418 {
419 lang_str_t *ls = NULL;
420 int i, j, stringcount, segmentcount;
421 int compressiontype, mode, bytecount;
422 char langcode[4];
423 char buf[256];
424
425 stringcount = src[0];
426 tvhtrace(LS_MPEGTS, "atsc-str: %d strings", stringcount);
427
428 src++;
429 srclen--;
430
431 langcode[3] = '\0';
432
433 for (i = 0; i < stringcount && srclen >= 4; i++) {
434 langcode[0] = src[0];
435 langcode[1] = src[1];
436 langcode[2] = src[2];
437 segmentcount = src[3];
438
439 tvhtrace(LS_MPEGTS, "atsc-str: %d: lang '%s', segments %d", i, langcode, segmentcount);
440
441 src += 4;
442 srclen -= 4;
443
444 for (j = 0; j < segmentcount && srclen >= 3; j++) {
445 compressiontype = src[0];
446 mode = src[1];
447 bytecount = src[2];
448
449 src += 3;
450 srclen -= 3;
451
452 if (bytecount > srclen)
453 return ls;
454
455 if (mode == 0 && compressiontype == 0) {
456 tvhtrace(LS_MPEGTS, "atsc-str: %d: comptype 0x%02x, mode 0x%02x, %d bytes: '%.*s'",
457 j, compressiontype, mode, bytecount, bytecount, src);
458 memcpy(buf, src, bytecount);
459 buf[bytecount] = '\0';
460 if (ls == NULL)
461 ls = lang_str_create();
462 lang_str_append(ls, buf, langcode);
463 } else {
464 tvhtrace(LS_MPEGTS, "atsc-str: %d: comptype 0x%02x, mode 0x%02x, %d bytes",
465 j, compressiontype, mode, bytecount);
466 }
467
468 /* FIXME: read compressed bytes */
469 src += bytecount; srclen -= bytecount; // skip for now
470 }
471 }
472
473 return ls;
474 }
475
476 /*
477 *
478 */
479
480 static struct strtab dvb_timezone_strtab[] = {
481 { N_("UTC"), 0 },
482 { N_("Local (server) time"), 1 },
483 { N_("UTC- 1"), -1*60 },
484 { N_("UTC- 2"), -2*60 },
485 { N_("UTC- 2:30"), -2*60-30 },
486 { N_("UTC- 3"), -3*60 },
487 { N_("UTC- 3:30"), -3*60-30 },
488 { N_("UTC- 4"), -4*60 },
489 { N_("UTC- 4:30"), -4*60-30 },
490 { N_("UTC- 5"), -5*60 },
491 { N_("UTC- 6"), -6*60 },
492 { N_("UTC- 7"), -7*60 },
493 { N_("UTC- 8"), -8*60 },
494 { N_("UTC- 9"), -9*60 },
495 { N_("UTC- 9:30"), -9*60-30 },
496 { N_("UTC-10"), -10*60 },
497 { N_("UTC-11"), -11*60 },
498 { N_("UTC+ 1"), 1*60 },
499 { N_("UTC+ 2"), 2*60 },
500 { N_("UTC+ 3"), 3*60 },
501 { N_("UTC+ 4"), 4*60 },
502 { N_("UTC+ 4:30"), 4*60+30 },
503 { N_("UTC+ 5"), 5*60 },
504 { N_("UTC+ 5:30"), 5*60+30 },
505 { N_("UTC+ 5:45"), 5*60+45 },
506 { N_("UTC+ 6"), 6*60 },
507 { N_("UTC+ 6:30"), 6*60+30 },
508 { N_("UTC+ 7"), 7*60 },
509 { N_("UTC+ 8"), 8*60 },
510 { N_("UTC+ 8:45"), 8*60+45 },
511 { N_("UTC+ 9"), 9*60 },
512 { N_("UTC+ 9:30"), 9*60+30 },
513 { N_("UTC+10"), 10*60 },
514 { N_("UTC+10:30"), 10*60+30 },
515 { N_("UTC+11"), 11*60 },
516 { N_("UTC+12"), 12*60 },
517 { N_("UTC+12:45"), 12*60+45 },
518 { N_("UTC+13"), 13*60 },
519 { N_("UTC+14"), 14*60 }
520 };
521
522 htsmsg_t *
dvb_timezone_enum(void * p,const char * lang)523 dvb_timezone_enum ( void *p, const char *lang )
524 {
525 return strtab2htsmsg(dvb_timezone_strtab, 1, lang);
526 }
527
528 /*
529 * DVB time and date functions
530 */
531
532 time_t
dvb_convert_date(const uint8_t * dvb_buf,int tmzone)533 dvb_convert_date(const uint8_t *dvb_buf, int tmzone)
534 {
535 int i;
536 int year, month, day, hour, min, sec;
537 long int mjd;
538 struct tm dvb_time;
539
540 mjd = (dvb_buf[0] & 0xff) << 8;
541 mjd += (dvb_buf[1] & 0xff);
542 hour = bcdtoint(dvb_buf[2] & 0xff);
543 min = bcdtoint(dvb_buf[3] & 0xff);
544 sec = bcdtoint(dvb_buf[4] & 0xff);
545 /*
546 * Use the routine specified in ETSI EN 300 468 V1.4.1,
547 * "Specification for Service Information in Digital Video Broadcasting"
548 * to convert from Modified Julian Date to Year, Month, Day.
549 */
550 year = (int) ((mjd - 15078.2) / 365.25);
551 month = (int) ((mjd - 14956.1 - (int) (year * 365.25)) / 30.6001);
552 day = mjd - 14956 - (int) (year * 365.25) - (int) (month * 30.6001);
553 if (month == 14 || month == 15)
554 i = 1;
555 else
556 i = 0;
557 year += i;
558 month = month - 1 - i * 12;
559
560 dvb_time.tm_sec = sec;
561 dvb_time.tm_min = min;
562 dvb_time.tm_hour = hour;
563 dvb_time.tm_mday = day;
564 dvb_time.tm_mon = month - 1;
565 dvb_time.tm_year = year;
566 dvb_time.tm_isdst = -1;
567 dvb_time.tm_wday = 0;
568 dvb_time.tm_yday = 0;
569
570 if (tmzone == 0) /* UTC */
571 return timegm(&dvb_time);
572 if (tmzone == 1) /* Local time */
573 return mktime(&dvb_time);
574
575 /* apply offset */
576 return timegm(&dvb_time) - tmzone * 60;
577 }
578
579 static time_t _gps_leap_seconds[17] = {
580 362793600,
581 394329600,
582 425865600,
583 489024000,
584 567993600,
585 631152000,
586 662688000,
587 709948800,
588 741484800,
589 773020800,
590 820454400,
591 867715200,
592 915148800,
593 1136073600,
594 1230768000,
595 1341100800,
596 1435708800,
597 };
598
599 time_t
atsc_convert_gpstime(uint32_t gpstime)600 atsc_convert_gpstime(uint32_t gpstime)
601 {
602 int i;
603 time_t out = gpstime + 315964800; // Add Unix - GPS epoch
604
605 for (i = (sizeof(_gps_leap_seconds)/sizeof(time_t)) - 1; i >= 0; i--) {
606 if (out > _gps_leap_seconds[i]) {
607 out -= i+1;
608 break;
609 }
610 }
611
612 return out;
613 }
614
615 /*
616 * DVB API helpers
617 */
618 #if ENABLE_MPEGTS_DVB
619
620 htsmsg_t *satellites;
621
622 #define dvb_str2val(p)\
623 const char *dvb_##p##2str (int p) { return val2str(p, p##tab); }\
624 int dvb_str2##p (const char *p) { return str2val(p, p##tab); }
625
626 #define DVB_EOD -10 /* end-of-data */
627
dvb_common2str(int p)628 static const char *dvb_common2str(int p)
629 {
630 if (p == 0)
631 return "NONE";
632 if (p == 1)
633 return "AUTO";
634 return NULL;
635 }
636
dvb_str2common(const char * p)637 static int dvb_str2common(const char *p)
638 {
639 if (strcmp(p, "NONE") == 0)
640 return 0;
641 if (strcmp(p, "AUTO") == 0)
642 return 1;
643 return DVB_EOD;
644 }
645
dvb_verify(int val,int * table)646 static int dvb_verify(int val, int *table)
647 {
648 while (*table != DVB_EOD) {
649 if (val == *table)
650 return val;
651 table++;
652 }
653 return 0; /* NONE */
654 }
655
dvb_rolloff2str(int p)656 const char *dvb_rolloff2str(int p)
657 {
658 static __thread char buf[16];
659 const char *res = dvb_common2str(p);
660 if (res)
661 return res;
662 sprintf(buf, "%02i", p / 10);
663 return buf;
664 }
665
dvb_str2rolloff(const char * p)666 int dvb_str2rolloff(const char *p)
667 {
668 static int rolloff_table[] = {
669 DVB_ROLLOFF_20,
670 DVB_ROLLOFF_25,
671 DVB_ROLLOFF_35,
672 DVB_EOD,
673 };
674 int res = dvb_str2common(p);
675 if (res != DVB_EOD)
676 return res;
677 return dvb_verify(atoi(p) * 10, rolloff_table);
678 }
679
680 static const struct strtab delsystab[] = {
681 { "NONE", DVB_SYS_NONE },
682 { "DVB-C", DVB_SYS_DVBC_ANNEX_A },
683 { "DVBC/ANNEX_A", DVB_SYS_DVBC_ANNEX_A },
684 { "DVBC_ANNEX_A", DVB_SYS_DVBC_ANNEX_A },
685 { "ATSC-C", DVB_SYS_DVBC_ANNEX_B },
686 { "DVBC/ANNEX_B", DVB_SYS_DVBC_ANNEX_B },
687 { "DVBC_ANNEX_B", DVB_SYS_DVBC_ANNEX_B },
688 { "DVB-C/ANNEX-C",DVB_SYS_DVBC_ANNEX_C },
689 { "DVBC/ANNEX_C", DVB_SYS_DVBC_ANNEX_C },
690 { "DVBC_ANNEX_C", DVB_SYS_DVBC_ANNEX_C },
691 { "DVBC_ANNEX_AC",DVB_SYS_DVBC_ANNEX_A }, /* for compatibility */
692 { "DVB-T", DVB_SYS_DVBT },
693 { "DVBT", DVB_SYS_DVBT },
694 { "DVB-T2", DVB_SYS_DVBT2 },
695 { "DVBT2", DVB_SYS_DVBT2 },
696 { "DVB-S", DVB_SYS_DVBS },
697 { "DVBS", DVB_SYS_DVBS },
698 { "DVB-S2", DVB_SYS_DVBS2 },
699 { "DVBS2", DVB_SYS_DVBS2 },
700 { "DVB-H", DVB_SYS_DVBH },
701 { "DVBH", DVB_SYS_DVBH },
702 { "ISDB-T", DVB_SYS_ISDBT },
703 { "ISDBT", DVB_SYS_ISDBT },
704 { "ISDB-S", DVB_SYS_ISDBS },
705 { "ISDBS", DVB_SYS_ISDBS },
706 { "ISDB-C", DVB_SYS_ISDBC },
707 { "ISDBC", DVB_SYS_ISDBC },
708 { "ATSC-T", DVB_SYS_ATSC },
709 { "ATSC", DVB_SYS_ATSC },
710 { "ATSCM-H", DVB_SYS_ATSCMH },
711 { "ATSCMH", DVB_SYS_ATSCMH },
712 { "DTMB", DVB_SYS_DTMB },
713 { "DMBTH", DVB_SYS_DTMB }, /* for compatibility */
714 { "CMMB", DVB_SYS_CMMB },
715 { "DAB", DVB_SYS_DAB },
716 { "DSS", DVB_SYS_DSS },
717 { "TURBO", DVB_SYS_TURBO }
718 };
719 dvb_str2val(delsys);
720
721 int
dvb_delsys2type(mpegts_network_t * ln,dvb_fe_delivery_system_t delsys)722 dvb_delsys2type ( mpegts_network_t *ln, dvb_fe_delivery_system_t delsys )
723 {
724 switch (delsys) {
725 case DVB_SYS_DVBC_ANNEX_A:
726 case DVB_SYS_DVBC_ANNEX_C:
727 return DVB_TYPE_C;
728 case DVB_SYS_DVBT:
729 case DVB_SYS_DVBT2:
730 case DVB_SYS_TURBO:
731 return DVB_TYPE_T;
732 case DVB_SYS_DVBS:
733 case DVB_SYS_DVBS2:
734 return DVB_TYPE_S;
735 case DVB_SYS_ATSC:
736 case DVB_SYS_ATSCMH:
737 return DVB_TYPE_ATSC_T;
738 case DVB_SYS_DVBC_ANNEX_B:
739 if (ln && idnode_is_instance(&ln->mn_id, &dvb_network_dvbc_class))
740 return DVB_TYPE_C;
741 else
742 return DVB_TYPE_ATSC_C;
743 case DVB_SYS_ISDBT:
744 return DVB_TYPE_ISDB_T;
745 case DVB_SYS_ISDBC:
746 return DVB_TYPE_ISDB_C;
747 case DVB_SYS_ISDBS:
748 return DVB_TYPE_ISDB_S;
749 case DVB_SYS_DAB:
750 return DVB_TYPE_DAB;
751 default:
752 return DVB_TYPE_NONE;
753 }
754 }
755
dvb_fec2str(int p)756 const char *dvb_fec2str(int p)
757 {
758 static __thread char buf[16];
759 const char *res = dvb_common2str(p);
760 if (res)
761 return res;
762 sprintf(buf, "%i/%i", p / 100, p % 100);
763 return buf;
764 }
765
dvb_str2fec(const char * p)766 int dvb_str2fec(const char *p)
767 {
768 static int fec_table[] = {
769 DVB_FEC_1_2,
770 DVB_FEC_1_3,
771 DVB_FEC_1_5,
772 DVB_FEC_2_3,
773 DVB_FEC_2_5,
774 DVB_FEC_2_9,
775 DVB_FEC_3_4,
776 DVB_FEC_3_5,
777 DVB_FEC_4_5,
778 DVB_FEC_4_15,
779 DVB_FEC_5_6,
780 DVB_FEC_5_9,
781 DVB_FEC_6_7,
782 DVB_FEC_7_8,
783 DVB_FEC_7_9,
784 DVB_FEC_7_15,
785 DVB_FEC_8_9,
786 DVB_FEC_8_15,
787 DVB_FEC_9_10,
788 DVB_FEC_9_20,
789 DVB_FEC_11_15,
790 DVB_FEC_11_20,
791 DVB_FEC_11_45,
792 DVB_FEC_13_18,
793 DVB_FEC_13_45,
794 DVB_FEC_14_45,
795 DVB_FEC_23_36,
796 DVB_FEC_25_36,
797 DVB_FEC_26_45,
798 DVB_FEC_28_45,
799 DVB_FEC_29_45,
800 DVB_FEC_31_45,
801 DVB_FEC_32_45,
802 DVB_FEC_77_90,
803 DVB_EOD,
804 };
805 int res = dvb_str2common(p);
806 int hi, lo;
807 if (res != DVB_EOD)
808 return res;
809 hi = lo = 0;
810 sscanf(p, "%i/%i", &hi, &lo);
811 return dvb_verify(hi * 100 + lo, fec_table);
812 }
813
814 static const struct strtab qamtab[] = {
815 { "NONE", DVB_MOD_NONE },
816 { "AUTO", DVB_MOD_AUTO },
817 { "QPSK", DVB_MOD_QPSK },
818 { "QAM4NR", DVB_MOD_QAM_4_NR },
819 { "QAM/AUTO", DVB_MOD_QAM_AUTO },
820 { "QAM-AUTO", DVB_MOD_QAM_AUTO },
821 { "QAM/16", DVB_MOD_QAM_16 },
822 { "QAM16", DVB_MOD_QAM_16 },
823 { "QAM/32", DVB_MOD_QAM_32 },
824 { "QAM32", DVB_MOD_QAM_32 },
825 { "QAM/64", DVB_MOD_QAM_64 },
826 { "QAM64", DVB_MOD_QAM_64 },
827 { "QAM/128", DVB_MOD_QAM_128 },
828 { "QAM128", DVB_MOD_QAM_128 },
829 { "QAM/256", DVB_MOD_QAM_256 },
830 { "QAM256", DVB_MOD_QAM_256 },
831 { "VSB/8", DVB_MOD_VSB_8 },
832 { "8VSB", DVB_MOD_VSB_8 },
833 { "VSB/16", DVB_MOD_VSB_16 },
834 { "16VSB", DVB_MOD_VSB_16 },
835 { "PSK/8", DVB_MOD_PSK_8 },
836 { "8PSK", DVB_MOD_PSK_8 },
837 { "DQPSK", DVB_MOD_DQPSK },
838 { "BPSK", DVB_MOD_BPSK },
839 { "BPSK-S", DVB_MOD_BPSK_S },
840 { "16APSK", DVB_MOD_APSK_16 },
841 { "32APSK", DVB_MOD_APSK_32 },
842 { "64APSK", DVB_MOD_APSK_64 },
843 { "128APSK", DVB_MOD_APSK_128 },
844 { "256APSK", DVB_MOD_APSK_256 },
845 { "8APSK-L", DVB_MOD_APSK_8_L },
846 { "16APSK-L", DVB_MOD_APSK_16_L },
847 { "32APSK-L", DVB_MOD_APSK_32_L },
848 { "64APSK-L", DVB_MOD_APSK_64_L },
849 { "128APSK-L", DVB_MOD_APSK_128_L },
850 { "256APSK-L", DVB_MOD_APSK_256_L },
851 };
852 dvb_str2val(qam);
853
dvb_bw2str(int p)854 const char *dvb_bw2str(int p)
855 {
856 static __thread char buf[17];
857 const char *res = dvb_common2str(p);
858 if (res)
859 return res;
860 if (p % 1000)
861 sprintf(buf, "%i.%iMHz", p / 1000, p % 1000);
862 else
863 sprintf(buf, "%iMHz", p / 1000);
864 return buf;
865 }
866
dvb_str2bw(const char * p)867 int dvb_str2bw(const char *p)
868 {
869 static int bw_table[] = {
870 DVB_BANDWIDTH_1_712_MHZ,
871 DVB_BANDWIDTH_5_MHZ,
872 DVB_BANDWIDTH_6_MHZ,
873 DVB_BANDWIDTH_7_MHZ,
874 DVB_BANDWIDTH_8_MHZ,
875 DVB_BANDWIDTH_10_MHZ,
876 DVB_EOD,
877 };
878 int len, res = dvb_str2common(p);
879 int hi, lo;
880 if (res != DVB_EOD)
881 return res;
882 len = strlen(p);
883 hi = lo = 0;
884 sscanf(p, "%i.%i", &hi, &lo);
885 if (len > 3 && strcmp(&p[len-3], "MHz") == 0)
886 hi = hi * 1000 + lo;
887 return dvb_verify(hi, bw_table);
888 }
889
890 static const struct strtab invertab[] = {
891 { "NONE", DVB_INVERSION_UNDEFINED },
892 { "AUTO", DVB_INVERSION_AUTO },
893 { "ON", DVB_INVERSION_ON },
894 { "OFF", DVB_INVERSION_OFF },
895 };
896 dvb_str2val(inver);
897
898 static const struct strtab modetab[] = {
899 { "NONE", DVB_TRANSMISSION_MODE_NONE },
900 { "AUTO", DVB_TRANSMISSION_MODE_AUTO },
901 { "1k", DVB_TRANSMISSION_MODE_1K },
902 { "2k", DVB_TRANSMISSION_MODE_2K },
903 { "8k", DVB_TRANSMISSION_MODE_8K },
904 { "4k", DVB_TRANSMISSION_MODE_4K },
905 { "16k", DVB_TRANSMISSION_MODE_16K },
906 { "32k", DVB_TRANSMISSION_MODE_32K },
907 { "C1", DVB_TRANSMISSION_MODE_C1 },
908 { "C3780", DVB_TRANSMISSION_MODE_C3780 },
909 };
910 dvb_str2val(mode);
911
912 static const struct strtab guardtab[] = {
913 { "NONE", DVB_GUARD_INTERVAL_NONE },
914 { "AUTO", DVB_GUARD_INTERVAL_AUTO },
915 { "1/4", DVB_GUARD_INTERVAL_1_4 },
916 { "1/8", DVB_GUARD_INTERVAL_1_8 },
917 { "1/32", DVB_GUARD_INTERVAL_1_32 },
918 { "1/16", DVB_GUARD_INTERVAL_1_16 },
919 { "1/128", DVB_GUARD_INTERVAL_1_128 },
920 { "19/128", DVB_GUARD_INTERVAL_19_128 },
921 { "19/256", DVB_GUARD_INTERVAL_19_256 },
922 { "PN420", DVB_GUARD_INTERVAL_PN420 },
923 { "PN595", DVB_GUARD_INTERVAL_PN595 },
924 { "PN945", DVB_GUARD_INTERVAL_PN945 },
925 };
926 dvb_str2val(guard);
927
928 static const struct strtab hiertab[] = {
929 { "NONE", DVB_HIERARCHY_NONE },
930 { "AUTO", DVB_HIERARCHY_AUTO },
931 { "1", DVB_HIERARCHY_1 },
932 { "2", DVB_HIERARCHY_2 },
933 { "4", DVB_HIERARCHY_4 },
934 };
935 dvb_str2val(hier);
936
937 static const struct strtab poltab[] = {
938 { "V", DVB_POLARISATION_VERTICAL },
939 { "H", DVB_POLARISATION_HORIZONTAL },
940 { "L", DVB_POLARISATION_CIRCULAR_LEFT },
941 { "R", DVB_POLARISATION_CIRCULAR_RIGHT },
942 { "O", DVB_POLARISATION_OFF },
943 };
944 dvb_str2val(pol);
945
946 static const struct strtab typetab[] = {
947 {"DVB-T", DVB_TYPE_T},
948 {"DVB-C", DVB_TYPE_C},
949 {"DVB-S", DVB_TYPE_S},
950 {"ATSC-T", DVB_TYPE_ATSC_T},
951 {"ATSC-C", DVB_TYPE_ATSC_C},
952 {"ISDB-T", DVB_TYPE_ISDB_T},
953 {"ISDB-C", DVB_TYPE_ISDB_C},
954 {"ISDB-S", DVB_TYPE_ISDB_S},
955 {"DAB", DVB_TYPE_DAB},
956 {"DVBT", DVB_TYPE_T},
957 {"DVBC", DVB_TYPE_C},
958 {"DVBS", DVB_TYPE_S},
959 {"ATSC", DVB_TYPE_ATSC_T},
960 {"ATSCT", DVB_TYPE_ATSC_T},
961 {"ATSCC", DVB_TYPE_ATSC_C},
962 {"ISDBT", DVB_TYPE_ISDB_T},
963 {"ISDBC", DVB_TYPE_ISDB_C},
964 {"ISDBS", DVB_TYPE_ISDB_S}
965 };
966 dvb_str2val(type);
967
968 static const struct strtab pilottab[] = {
969 {"NONE", DVB_PILOT_NONE},
970 {"AUTO", DVB_PILOT_AUTO},
971 {"ON", DVB_PILOT_ON},
972 {"OFF", DVB_PILOT_OFF}
973 };
974 dvb_str2val(pilot);
975
976 static const struct strtab plsmodetab[] = {
977 {"ROOT", DVB_PLS_ROOT},
978 {"GOLD", DVB_PLS_GOLD},
979 {"COMBO", DVB_PLS_COMBO},
980 };
981 dvb_str2val(plsmode);
982 #undef dvb_str2val
983
984
985 void
dvb_mux_conf_init(mpegts_network_t * ln,dvb_mux_conf_t * dmc,dvb_fe_delivery_system_t delsys)986 dvb_mux_conf_init ( mpegts_network_t *ln,
987 dvb_mux_conf_t *dmc,
988 dvb_fe_delivery_system_t delsys )
989 {
990 memset(dmc, 0, sizeof(*dmc));
991 dmc->dmc_fe_type = dvb_delsys2type(ln, delsys);
992 dmc->dmc_fe_delsys = delsys;
993 dmc->dmc_fe_inversion = DVB_INVERSION_AUTO;
994 dmc->dmc_fe_pilot = DVB_PILOT_AUTO;
995 dmc->dmc_fe_stream_id = DVB_NO_STREAM_ID_FILTER;
996 dmc->dmc_fe_pls_mode = DVB_PLS_GOLD;
997 switch (dmc->dmc_fe_type) {
998 case DVB_TYPE_S:
999 dmc->u.dmc_fe_qpsk.orbital_pos = INT_MAX;
1000 break;
1001 default:
1002 break;
1003 }
1004 }
1005
1006
1007 static int
dvb_mux_conf_str_dvbt(dvb_mux_conf_t * dmc,char * buf,size_t bufsize)1008 dvb_mux_conf_str_dvbt ( dvb_mux_conf_t *dmc, char *buf, size_t bufsize )
1009 {
1010 char hp[16];
1011 snprintf(hp, sizeof(hp), "%s", dvb_fec2str(dmc->u.dmc_fe_ofdm.code_rate_HP));
1012 return
1013 snprintf(buf, bufsize,
1014 "%s freq %d bw %s cons %s hier %s code_rate %s:%s guard %s trans %s plp_id %d",
1015 dvb_delsys2str(dmc->dmc_fe_delsys),
1016 dmc->dmc_fe_freq,
1017 dvb_bw2str(dmc->u.dmc_fe_ofdm.bandwidth),
1018 dvb_qam2str(dmc->dmc_fe_modulation),
1019 dvb_hier2str(dmc->u.dmc_fe_ofdm.hierarchy_information),
1020 hp, dvb_fec2str(dmc->u.dmc_fe_ofdm.code_rate_LP),
1021 dvb_guard2str(dmc->u.dmc_fe_ofdm.guard_interval),
1022 dvb_mode2str(dmc->u.dmc_fe_ofdm.transmission_mode),
1023 dmc->dmc_fe_stream_id);
1024 }
1025
1026 static int
dvb_mux_conf_str_dvbc(dvb_mux_conf_t * dmc,char * buf,size_t bufsize)1027 dvb_mux_conf_str_dvbc ( dvb_mux_conf_t *dmc, char *buf, size_t bufsize )
1028 {
1029 const char *delsys;
1030 if (dmc->dmc_fe_type == DVB_TYPE_C &&
1031 dmc->dmc_fe_delsys == DVB_SYS_DVBC_ANNEX_B)
1032 delsys = "DVB-C/ANNEX_B";
1033 else
1034 delsys = dvb_delsys2str(dmc->dmc_fe_delsys);
1035 return
1036 snprintf(buf, bufsize,
1037 "%s freq %d sym %d mod %s fec %s ds %d plp %d",
1038 delsys,
1039 dmc->dmc_fe_freq,
1040 dmc->u.dmc_fe_qam.symbol_rate,
1041 dvb_qam2str(dmc->dmc_fe_modulation),
1042 dvb_fec2str(dmc->u.dmc_fe_qam.fec_inner),
1043 dmc->dmc_fe_data_slice,
1044 dmc->dmc_fe_stream_id);
1045 }
1046
1047 static int
dvb_mux_conf_str_dvbs(dvb_mux_conf_t * dmc,char * buf,size_t bufsize)1048 dvb_mux_conf_str_dvbs ( dvb_mux_conf_t *dmc, char *buf, size_t bufsize )
1049 {
1050 const char *pol = dvb_pol2str(dmc->u.dmc_fe_qpsk.polarisation);
1051 const int satpos = dmc->u.dmc_fe_qpsk.orbital_pos;
1052 char satbuf[16];
1053 if (satpos != INT_MAX) {
1054 snprintf(satbuf, sizeof(satbuf), "%d.%d%c ", abs(satpos) / 10, abs(satpos) % 10, satpos < 0 ? 'W' : 'E');
1055 } else {
1056 satbuf[0] = '\0';
1057 }
1058 return
1059 snprintf(buf, bufsize,
1060 "%s %sfreq %d %c sym %d fec %s mod %s roff %s is_id %d pls_mode %s pls_code %d",
1061 dvb_delsys2str(dmc->dmc_fe_delsys),
1062 satbuf,
1063 dmc->dmc_fe_freq,
1064 pol ? pol[0] : 'X',
1065 dmc->u.dmc_fe_qpsk.symbol_rate,
1066 dvb_fec2str(dmc->u.dmc_fe_qpsk.fec_inner),
1067 dvb_qam2str(dmc->dmc_fe_modulation),
1068 dvb_rolloff2str(dmc->dmc_fe_rolloff),
1069 dmc->dmc_fe_stream_id,
1070 dvb_plsmode2str(dmc->dmc_fe_pls_mode),
1071 dmc->dmc_fe_pls_code);
1072 }
1073
1074 static int
dvb_mux_conf_str_atsc_t(dvb_mux_conf_t * dmc,char * buf,size_t bufsize)1075 dvb_mux_conf_str_atsc_t ( dvb_mux_conf_t *dmc, char *buf, size_t bufsize )
1076 {
1077 return
1078 snprintf(buf, bufsize,
1079 "%s freq %d mod %s",
1080 dvb_delsys2str(dmc->dmc_fe_delsys),
1081 dmc->dmc_fe_freq,
1082 dvb_qam2str(dmc->dmc_fe_modulation));
1083 }
1084
1085 static int
dvb_mux_conf_str_isdb_t(dvb_mux_conf_t * dmc,char * buf,size_t bufsize)1086 dvb_mux_conf_str_isdb_t ( dvb_mux_conf_t *dmc, char *buf, size_t bufsize )
1087 {
1088 char hp[16];
1089 snprintf(hp, sizeof(hp), "%s", dvb_fec2str(dmc->u.dmc_fe_ofdm.code_rate_HP));
1090 return
1091 snprintf(buf, bufsize,
1092 "%s freq %d bw %s guard %s A (%s,%s,%d,%d) B (%s,%s,%d,%d) C (%s,%s,%d,%d)",
1093 dvb_delsys2str(dmc->dmc_fe_delsys),
1094 dmc->dmc_fe_freq,
1095 dvb_bw2str(dmc->u.dmc_fe_isdbt.bandwidth),
1096 dvb_guard2str(dmc->u.dmc_fe_isdbt.guard_interval),
1097 dvb_fec2str(dmc->u.dmc_fe_isdbt.layers[0].fec),
1098 dvb_qam2str(dmc->u.dmc_fe_isdbt.layers[0].modulation),
1099 dmc->u.dmc_fe_isdbt.layers[0].segment_count,
1100 dmc->u.dmc_fe_isdbt.layers[0].time_interleaving,
1101 dvb_fec2str(dmc->u.dmc_fe_isdbt.layers[1].fec),
1102 dvb_qam2str(dmc->u.dmc_fe_isdbt.layers[1].modulation),
1103 dmc->u.dmc_fe_isdbt.layers[1].segment_count,
1104 dmc->u.dmc_fe_isdbt.layers[1].time_interleaving,
1105 dvb_fec2str(dmc->u.dmc_fe_isdbt.layers[2].fec),
1106 dvb_qam2str(dmc->u.dmc_fe_isdbt.layers[2].modulation),
1107 dmc->u.dmc_fe_isdbt.layers[2].segment_count,
1108 dmc->u.dmc_fe_isdbt.layers[2].time_interleaving);
1109 }
1110
1111 int
dvb_mux_conf_str(dvb_mux_conf_t * dmc,char * buf,size_t bufsize)1112 dvb_mux_conf_str ( dvb_mux_conf_t *dmc, char *buf, size_t bufsize )
1113 {
1114 switch (dmc->dmc_fe_type) {
1115 case DVB_TYPE_NONE:
1116 return
1117 snprintf(buf, bufsize, "NONE %s", dvb_delsys2str(dmc->dmc_fe_delsys));
1118 case DVB_TYPE_T:
1119 return dvb_mux_conf_str_dvbt(dmc, buf, bufsize);
1120 case DVB_TYPE_C:
1121 case DVB_TYPE_ATSC_C:
1122 case DVB_TYPE_ISDB_C:
1123 return dvb_mux_conf_str_dvbc(dmc, buf, bufsize);
1124 case DVB_TYPE_S:
1125 return dvb_mux_conf_str_dvbs(dmc, buf, bufsize);
1126 case DVB_TYPE_ATSC_T:
1127 return dvb_mux_conf_str_atsc_t(dmc, buf, bufsize);
1128 case DVB_TYPE_ISDB_T:
1129 return dvb_mux_conf_str_isdb_t(dmc, buf, bufsize);
1130 default:
1131 return
1132 snprintf(buf, bufsize, "UNKNOWN MUX CONFIG");
1133 }
1134 }
1135
1136 const char *
dvb_sat_position_to_str(int position,char * buf,size_t buflen)1137 dvb_sat_position_to_str(int position, char *buf, size_t buflen)
1138 {
1139 const int dec = position % 10;
1140
1141 if (!buf || !buflen)
1142 return "";
1143 snprintf(buf, buflen, "%d", abs(position / 10));
1144 if (dec)
1145 snprintf(buf + strlen(buf), buflen - strlen(buf), ".%d", abs(dec));
1146 snprintf(buf + strlen(buf), buflen - strlen(buf), "%c", position < 0 ? 'W' : 'E');
1147 return buf;
1148 }
1149
1150 int
dvb_sat_position_from_str(const char * buf)1151 dvb_sat_position_from_str( const char *buf )
1152 {
1153 const char *s = buf;
1154 int min, maj;
1155 char c;
1156
1157 if (!buf)
1158 return INT_MAX;
1159 maj = atoi(s);
1160 while (*s && *s != '.')
1161 s++;
1162 min = *s == '.' ? atoi(s + 1) : 0;
1163 if (*s != '.') s = buf;
1164 do {
1165 c = *s++;
1166 } while (c && c != 'W' && c != 'E');
1167 if (!c)
1168 return INT_MAX;
1169 if (maj > 180 || maj < 0)
1170 return INT_MAX;
1171 if (min > 9 || min < 0)
1172 return INT_MAX;
1173 return (maj * 10 + min) * (c == 'W' ? -1 : 1);
1174 }
1175
1176 uint32_t
dvb_sat_pls(dvb_mux_conf_t * dmc)1177 dvb_sat_pls( dvb_mux_conf_t *dmc )
1178 {
1179 if (dmc->dmc_fe_pls_mode == DVB_PLS_ROOT) {
1180 uint32_t x, g;
1181 const uint32_t root = dmc->dmc_fe_pls_code & 0x3ffff;
1182
1183 for (g = 0, x = 1; g < 0x3ffff; g++) {
1184 if (root == x)
1185 return g;
1186 x = (((x ^ (x >> 7)) & 1) << 17) | (x >> 1);
1187 }
1188 return 0x3ffff;
1189 }
1190 return dmc->dmc_fe_pls_code & 0x3ffff;
1191 }
1192
1193 #endif /* ENABLE_MPEGTS_DVB */
1194
1195 /**
1196 *
1197 */
dvb_init(void)1198 void dvb_init( void )
1199 {
1200 #if ENABLE_MPEGTS_DVB
1201 satellites = hts_settings_load("satellites");
1202 #endif
1203 }
1204
dvb_done(void)1205 void dvb_done( void )
1206 {
1207 #if ENABLE_MPEGTS_DVB
1208 htsmsg_destroy(satellites);
1209 #endif
1210 }
1211