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_extension.h>
21 #include <libdvbv5/desc_t2_delivery.h>
22 #include <libdvbv5/dvb-fe.h>
23
24 #if __GNUC__ >= 9
25 #pragma GCC diagnostic ignored "-Waddress-of-packed-member"
26 #endif
27
28 const struct dvb_ext_descriptor dvb_ext_descriptors[] = {
29 [0 ...255 ] = {
30 .name = "Unknown descriptor",
31 .init = NULL,
32 .print = NULL,
33 .free = NULL,
34 .size = 0,
35 },
36 [image_icon_descriptor] = {
37 .name = "image_icon_descriptor",
38 .init = NULL,
39 .print = NULL,
40 .free = NULL,
41 .size = 0,
42 },
43 [cpcm_delivery_signalling_descriptor] = {
44 .name = "cpcm_delivery_signalling_descriptor",
45 .init = NULL,
46 .print = NULL,
47 .free = NULL,
48 .size = 0,
49 },
50 [CP_descriptor] = {
51 .name = "CP_descriptor",
52 .init = NULL,
53 .print = NULL,
54 .free = NULL,
55 .size = 0,
56 },
57 [CP_identifier_descriptor] = {
58 .name = "CP_identifier_descriptor",
59 .init = NULL,
60 .print = NULL,
61 .free = NULL,
62 .size = 0,
63 },
64 [T2_delivery_system_descriptor] = {
65 .name = "T2_delivery_system_descriptor",
66 .init = dvb_desc_t2_delivery_init,
67 .print = dvb_desc_t2_delivery_print,
68 .free = dvb_desc_t2_delivery_free,
69 .size = sizeof(struct dvb_desc_t2_delivery),
70 },
71 [SH_delivery_system_descriptor] = {
72 .name = "SH_delivery_system_descriptor",
73 .init = NULL,
74 .print = NULL,
75 .free = NULL,
76 .size = 0,
77 },
78 [supplementary_audio_descriptor] = {
79 .name = "supplementary_audio_descriptor",
80 .init = NULL,
81 .print = NULL,
82 .free = NULL,
83 .size = 0,
84 },
85 [network_change_notify_descriptor] = {
86 .name = "network_change_notify_descriptor",
87 .init = NULL,
88 .print = NULL,
89 .free = NULL,
90 .size = 0,
91 },
92 [message_descriptor] = {
93 .name = "message_descriptor",
94 .init = NULL,
95 .print = NULL,
96 .free = NULL,
97 .size = 0,
98 },
99 [target_region_descriptor] = {
100 .name = "target_region_descriptor",
101 .init = NULL,
102 .print = NULL,
103 .free = NULL,
104 .size = 0,
105 },
106 [target_region_name_descriptor] = {
107 .name = "target_region_name_descriptor",
108 .init = NULL,
109 .print = NULL,
110 .free = NULL,
111 .size = 0,
112 },
113 [service_relocated_descriptor] = {
114 .name = "service_relocated_descriptor",
115 .init = NULL,
116 .print = NULL,
117 .free = NULL,
118 .size = 0,
119 },
120 };
121
dvb_extension_descriptor_init(struct dvb_v5_fe_parms * parms,const uint8_t * buf,struct dvb_desc * desc)122 int dvb_extension_descriptor_init(struct dvb_v5_fe_parms *parms,
123 const uint8_t *buf, struct dvb_desc *desc)
124 {
125 struct dvb_extension_descriptor *ext = (void *)desc;
126 unsigned char *p = (unsigned char *)buf;
127 unsigned desc_type = *p;
128 size_t size = 0;
129 int desc_len = ext->length - 1;
130 dvb_desc_ext_init_func init;
131
132 ext->extension_code = desc_type;
133 p++;
134
135 switch (parms->verbose) {
136 case 0:
137 case 1:
138 break;
139 case 2:
140 if (dvb_ext_descriptors[desc_type].init)
141 break;
142 /* fall through */
143 case 3:
144 dvb_logwarn("%sextension descriptor %s type 0x%02x, size %d",
145 dvb_ext_descriptors[desc_type].init ? "" : "Not handled ",
146 dvb_ext_descriptors[desc_type].name, desc_type, desc_len);
147 dvb_hexdump(parms, "content: ", p, desc_len);
148 }
149
150 init = dvb_ext_descriptors[desc_type].init;
151 if (init)
152 size = dvb_ext_descriptors[desc_type].size;
153 if (!size)
154 size = desc_len;
155
156 ext->descriptor = calloc(1, size);
157
158 if (init) {
159 if (init(parms, p, ext, ext->descriptor) != 0)
160 return -1;
161 }
162 else
163 memcpy(ext->descriptor, p, size);
164 return 0;
165 }
166
dvb_extension_descriptor_free(struct dvb_desc * descriptor)167 void dvb_extension_descriptor_free(struct dvb_desc *descriptor)
168 {
169 struct dvb_extension_descriptor *ext = (void *)descriptor;
170 uint8_t type = ext->extension_code;
171
172 if (!ext->descriptor)
173 return;
174
175 if (dvb_ext_descriptors[type].free)
176 dvb_ext_descriptors[type].free(ext->descriptor);
177
178 free(ext->descriptor);
179 }
180
dvb_extension_descriptor_print(struct dvb_v5_fe_parms * parms,const struct dvb_desc * desc)181 void dvb_extension_descriptor_print(struct dvb_v5_fe_parms *parms,
182 const struct dvb_desc *desc)
183 {
184 struct dvb_extension_descriptor *ext = (void *)desc;
185 uint8_t type = ext->extension_code;
186 dvb_loginfo("| descriptor %s type 0x%02x",
187 dvb_ext_descriptors[type].name, type);
188
189 if (dvb_ext_descriptors[type].print)
190 dvb_ext_descriptors[type].print(parms, ext, ext->descriptor);
191 }
192