1 /*
2 * Copyright (c) 2013 - Mauro Carvalho Chehab <mchehab@kernel.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation version 2.1 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
17 *
18 */
19
20 #include <libdvbv5/desc_isdbt_delivery.h>
21 #include <libdvbv5/dvb-fe.h>
22 #include <inttypes.h>
23
24 #if __GNUC__ >= 9
25 #pragma GCC diagnostic ignored "-Waddress-of-packed-member"
26 #endif
27
isdbt_desc_delivery_init(struct dvb_v5_fe_parms * parms,const uint8_t * buf,struct dvb_desc * desc)28 int isdbt_desc_delivery_init(struct dvb_v5_fe_parms *parms,
29 const uint8_t *buf, struct dvb_desc *desc)
30 {
31 struct isdbt_desc_terrestrial_delivery_system *d = (void *)desc;
32 unsigned char *p = (unsigned char *) buf;
33 int i;
34 size_t len;
35 uint16_t frq;
36
37 len = sizeof(*d) - offsetof(struct isdbt_desc_terrestrial_delivery_system, bitfield);
38 memcpy(&d->bitfield, p, len);
39 p += len;
40
41 bswap16(d->bitfield);
42
43 if (d->length < len) {
44 dvb_perror("Truncated isdbt_desc_terrestrial_delivery_system_descriptor");
45 d->num_freqs = 0;
46 } else {
47 d->num_freqs = (d->length - len)/ sizeof(uint16_t);
48 }
49 if (!d->num_freqs)
50 return 0;
51 d->frequency = malloc(d->num_freqs * sizeof(*d->frequency));
52 if (!d->frequency) {
53 dvb_perror("Can't allocate space for ISDB-T frequencies");
54 return -2;
55 }
56
57 for (i = 0; i < d->num_freqs; i++) {
58 frq = *(uint16_t *)p;
59 p += sizeof(uint16_t);
60
61 bswap16(frq);
62
63 d->frequency[i] = (uint32_t)((((uint64_t)frq) * 1000000ul) / 7);
64 }
65 return 0;
66 }
67
68 static const char *interval_name[] = {
69 [0] = "1/4",
70 [1] = "1/8",
71 [2] = "1/16",
72 [3] = "1/32",
73 };
74
75 static const char *tm_name[] = {
76 [0] = "2K",
77 [1] = "4K",
78 [2] = "8K",
79 [3] = "AUTO",
80 };
81
82 const uint32_t isdbt_interval[] = {
83 [0] = GUARD_INTERVAL_1_32,
84 [1] = GUARD_INTERVAL_1_16,
85 [2] = GUARD_INTERVAL_1_8,
86 [3] = GUARD_INTERVAL_1_4,
87 };
88
89 const uint32_t isdbt_mode[] = {
90 [0] = TRANSMISSION_MODE_2K, /* Mode 1 */
91 [1] = TRANSMISSION_MODE_4K, /* Mode 2 */
92 [2] = TRANSMISSION_MODE_8K, /* Mode 3 */
93 [3] = TRANSMISSION_MODE_AUTO /* Reserved */
94 };
95
isdbt_desc_delivery_print(struct dvb_v5_fe_parms * parms,const struct dvb_desc * desc)96 void isdbt_desc_delivery_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc)
97 {
98 const struct isdbt_desc_terrestrial_delivery_system *d = (const void *) desc;
99 int i;
100
101 dvb_loginfo("| transmission mode %s (%d)",
102 tm_name[d->transmission_mode], d->transmission_mode);
103 dvb_loginfo("| guard interval %s (%d)",
104 interval_name[d->guard_interval], d->guard_interval);
105 dvb_loginfo("| area code %d", d->area_code);
106
107 for (i = 0; i < d->num_freqs; i++) {
108 dvb_loginfo("| frequency[%d] %.4f MHz", i, d->frequency[i]/1000000.);
109 }
110 }
111
isdbt_desc_delivery_free(struct dvb_desc * desc)112 void isdbt_desc_delivery_free(struct dvb_desc *desc)
113 {
114 const struct isdbt_desc_terrestrial_delivery_system *d = (const void *) desc;
115
116 free(d->frequency);
117 }
118