1 /*****************************************************************************
2 * desc_4a.h: ETSI EN 300 468 Descriptor 0x4a: Linkage descriptor
3 *****************************************************************************
4 * Copyright (C) 2009-2010 VideoLAN
5 *
6 * Authors: Christophe Massiot <massiot@via.ecp.fr>
7 * Georgi Chorbadzhiyski <georgi@unixsol.org>
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining
10 * a copy of this software and associated documentation files (the
11 * "Software"), to deal in the Software without restriction, including
12 * without limitation the rights to use, copy, modify, merge, publish,
13 * distribute, sublicense, and/or sell copies of the Software, and to
14 * permit persons to whom the Software is furnished to do so, subject
15 * to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be
18 * included in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 *****************************************************************************/
28
29 /*
30 * Normative references:
31 * - ETSI EN 300 468 V1.11.1 (2010-04) (SI in DVB systems)
32 */
33
34 #ifndef __BITSTREAM_DVB_DESC_4A_H__
35 #define __BITSTREAM_DVB_DESC_4A_H__
36
37 #include <bitstream/common.h>
38 #include <bitstream/mpeg/psi/descriptors.h>
39
40 #ifdef __cplusplus
41 extern "C"
42 {
43 #endif
44
45 /*****************************************************************************
46 * Descriptor 0x4a: Linkage descriptor
47 *****************************************************************************/
48 #define DESC4A_HEADER_SIZE (DESC_HEADER_SIZE + 7)
49
50 #define DESC4A_LINKAGE_MOBILE 0x08
51 #define DESC4A_LINKAGE_EVENT 0x0d
52 #define DESC4A_LINKAGE_EXT_EVENT 0x0e
53
desc4a_init(uint8_t * p_desc)54 static inline void desc4a_init(uint8_t *p_desc)
55 {
56 desc_set_tag(p_desc, 0x4a);
57 desc_set_length(p_desc, DESC4A_HEADER_SIZE - DESC_HEADER_SIZE);
58 }
59
desc4a_get_tsid(const uint8_t * p_desc)60 static inline uint16_t desc4a_get_tsid(const uint8_t *p_desc)
61 {
62 return (p_desc[2] << 8) | p_desc[3];
63 }
64
desc4a_set_tsid(uint8_t * p_desc,uint16_t i_tsid)65 static inline void desc4a_set_tsid(uint8_t *p_desc, uint16_t i_tsid)
66 {
67 p_desc[2] = (i_tsid >> 8) & 0xff;
68 p_desc[3] = i_tsid & 0xff;
69 }
70
desc4a_get_onid(const uint8_t * p_desc)71 static inline uint16_t desc4a_get_onid(const uint8_t *p_desc)
72 {
73 return (p_desc[4] << 8) | p_desc[5];
74 }
75
desc4a_set_onid(uint8_t * p_desc,uint16_t i_onid)76 static inline void desc4a_set_onid(uint8_t *p_desc, uint16_t i_onid)
77 {
78 p_desc[4] = (i_onid >> 8) & 0xff;
79 p_desc[5] = i_onid & 0xff;
80 }
81
desc4a_get_sid(const uint8_t * p_desc)82 static inline uint16_t desc4a_get_sid(const uint8_t *p_desc)
83 {
84 return (p_desc[6] << 8) | p_desc[7];
85 }
86
desc4a_set_sid(uint8_t * p_desc,uint16_t i_sid)87 static inline void desc4a_set_sid(uint8_t *p_desc, uint16_t i_sid)
88 {
89 p_desc[6] = (i_sid >> 8) & 0xff;
90 p_desc[7] = i_sid & 0xff;
91 }
92
desc4a_get_linkage(const uint8_t * p_desc)93 static inline uint8_t desc4a_get_linkage(const uint8_t *p_desc)
94 {
95 return p_desc[8];
96 }
97
desc4a_set_linkage(uint8_t * p_desc,uint8_t i_linkage)98 static inline void desc4a_set_linkage(uint8_t *p_desc, uint8_t i_linkage)
99 {
100 p_desc[8] = i_linkage;
101 }
102
desc4a_get_linkage_txt(uint8_t i_linkage)103 static inline const char *desc4a_get_linkage_txt(uint8_t i_linkage)
104 {
105 return i_linkage == 0x00 ? "reserved" :
106 i_linkage == 0x01 ? "information service" :
107 i_linkage == 0x02 ? "EPG service" :
108 i_linkage == 0x03 ? "CA replacement service" :
109 i_linkage == 0x04 ? "TS containing complete Network/Bouquet SI" :
110 i_linkage == 0x05 ? "service replacement service" :
111 i_linkage == 0x06 ? "data broadcast service" :
112 i_linkage == 0x07 ? "RCS Map" :
113 i_linkage == 0x08 ? "mobile hand-over" :
114 i_linkage == 0x09 ? "System Software Update Service (TS 102 006 [11])" :
115 i_linkage == 0x0a ? "TS containing SSU BAT or NIT (TS 102 006 [11])" :
116 i_linkage == 0x0b ? "IP/MAC Notification Service (EN 301 192 [4])" :
117 i_linkage == 0x0c ? "TS containing INT BAT or NIT (EN 301 192 [4])" :
118 i_linkage == 0x0d ? "event linkage" :
119 i_linkage == 0x0e ? "extended event linkage" :
120 i_linkage >= 0x0f && i_linkage <= 0x7f ? "reserved" :
121 i_linkage >= 0x80 && i_linkage <= 0xfe ? "user defined" : "reserved";
122 }
123
124 /* MOBILE HANDOVER linkage == 0x08 (DESC4A_LINKAGE_MOBILE) */
125
desc4a_get_mobile_handover_type(const uint8_t * p_desc)126 static inline uint8_t desc4a_get_mobile_handover_type(const uint8_t *p_desc)
127 {
128 return (p_desc[9] & 0xf0) >> 4;
129 }
130
desc4a_set_mobile_handover_type(uint8_t * p_desc,uint8_t i_handover_type)131 static inline void desc4a_set_mobile_handover_type(uint8_t *p_desc, uint8_t i_handover_type)
132 {
133 p_desc[9] = ((i_handover_type & 0x0f) << 4) | 0x0e | (p_desc[9] & 0x01);
134 }
135
desc4a_get_mobile_origin_type(const uint8_t * p_desc)136 static inline bool desc4a_get_mobile_origin_type(const uint8_t *p_desc)
137 {
138 return (p_desc[9] & 0x01) == 0x01;
139 }
140
desc4a_set_mobile_origin_type(uint8_t * p_desc,bool b_origin_type)141 static inline void desc4a_set_mobile_origin_type(uint8_t *p_desc, bool b_origin_type)
142 {
143 p_desc[9] = b_origin_type ? (p_desc[9] | 0x01) : (p_desc[9] &~ 0x01);
144 }
145
desc4a_have_mobile_nid(const uint8_t * p_desc)146 static inline bool desc4a_have_mobile_nid(const uint8_t *p_desc)
147 {
148 uint8_t i_handover_type = desc4a_get_mobile_handover_type(p_desc);
149 return (i_handover_type >= 0x01 && i_handover_type <= 0x03);
150 }
151
desc4a_get_mobile_nid(const uint8_t * p_desc)152 static inline uint16_t desc4a_get_mobile_nid(const uint8_t *p_desc)
153 {
154 if (desc4a_have_mobile_nid(p_desc))
155 return (p_desc[10] << 8) | p_desc[11];
156 else
157 return 0;
158 }
159
desc4a_set_mobile_nid(uint8_t * p_desc,uint16_t i_nid)160 static inline void desc4a_set_mobile_nid(uint8_t *p_desc, uint16_t i_nid)
161 {
162 if (desc4a_have_mobile_nid(p_desc)) {
163 p_desc[10] = (i_nid >> 8) & 0xff;
164 p_desc[11] = i_nid & 0xff;
165 }
166 }
167
desc4a_get_mobile_initial_sid(const uint8_t * p_desc)168 static inline uint16_t desc4a_get_mobile_initial_sid(const uint8_t *p_desc)
169 {
170 if (!desc4a_get_mobile_origin_type(p_desc)) {
171 uint8_t ofs = 10;
172 if (desc4a_have_mobile_nid(p_desc))
173 ofs += 2;
174 return (p_desc[ofs + 0] << 8) | p_desc[ofs + 1];
175 }
176 return 0;
177 }
178
desc4a_set_mobile_initial_sid(uint8_t * p_desc,uint16_t i_initial_sid)179 static inline void desc4a_set_mobile_initial_sid(uint8_t *p_desc, uint16_t i_initial_sid)
180 {
181 if (!desc4a_get_mobile_origin_type(p_desc)) {
182 uint8_t ofs = 10;
183 if (desc4a_have_mobile_nid(p_desc))
184 ofs += 2;
185 p_desc[ofs + 0] = (i_initial_sid >> 8) & 0xff;
186 p_desc[ofs + 1] = i_initial_sid & 0xff;
187 }
188 }
189
desc4a_get_mobile_handover_length(const uint8_t * p_desc)190 static inline uint8_t desc4a_get_mobile_handover_length(const uint8_t *p_desc)
191 {
192 uint8_t i_length = 0;
193 if (desc4a_get_linkage(p_desc) == DESC4A_LINKAGE_MOBILE)
194 {
195 i_length += 1;
196 if (desc4a_have_mobile_nid(p_desc))
197 i_length += 2;
198 if (!desc4a_get_mobile_origin_type(p_desc))
199 i_length += 2;
200 }
201 return i_length;
202 }
203
204 /* EVENT LINKAGE == 0x0d (DESC4A_LINKAGE_EVENT) */
205
desc4a_get_event_target_event_id(const uint8_t * p_desc)206 static inline uint16_t desc4a_get_event_target_event_id(const uint8_t *p_desc)
207 {
208 return (p_desc[9] << 8) | p_desc[10];
209 }
210
desc4a_set_event_target_event_id(uint8_t * p_desc,uint16_t i_target_event_id)211 static inline void desc4a_set_event_target_event_id(uint8_t *p_desc, uint16_t i_target_event_id)
212 {
213 p_desc[ 9] = (i_target_event_id >> 8) & 0xff;
214 p_desc[10] = i_target_event_id & 0xff;
215 }
216
desc4a_get_event_target_listed(const uint8_t * p_desc)217 static inline bool desc4a_get_event_target_listed(const uint8_t *p_desc)
218 {
219 return (p_desc[11] & 0x80) == 0x80;
220 }
221
desc4a_set_event_target_listed(uint8_t * p_desc,bool b_target_listed)222 static inline void desc4a_set_event_target_listed(uint8_t *p_desc, bool b_target_listed)
223 {
224 p_desc[11] |= 0x3f;
225 p_desc[11] = b_target_listed ? (p_desc[11] | 0x80) : (p_desc[11] &~ 0x80);
226 }
227
desc4a_get_event_simulcast(const uint8_t * p_desc)228 static inline bool desc4a_get_event_simulcast(const uint8_t *p_desc)
229 {
230 return (p_desc[11] & 0x40) == 0x40;
231 }
232
desc4a_set_event_simulcast(uint8_t * p_desc,bool b_event_simulcast)233 static inline void desc4a_set_event_simulcast(uint8_t *p_desc, bool b_event_simulcast)
234 {
235 p_desc[11] |= 0x3f;
236 p_desc[11] = b_event_simulcast ? (p_desc[11] | 0x40) : (p_desc[11] &~ 0x40);
237 }
238
desc4a_get_event_length(const uint8_t * p_desc)239 static inline uint8_t desc4a_get_event_length(const uint8_t *p_desc)
240 {
241 if (desc4a_get_linkage(p_desc) == DESC4A_LINKAGE_EVENT)
242 return 3;
243 return 0;
244 }
245
246 /* EXTENDED EVENT LINKAGE == 0x0e (DESC4A_LINKAGE_EXT_EVENT) */
247
desc4an_get_ext_event_target_event_id(const uint8_t * p_desc_n)248 static inline uint16_t desc4an_get_ext_event_target_event_id(const uint8_t *p_desc_n)
249 {
250 return (p_desc_n[0] << 8) | p_desc_n[1];
251 }
252
desc4an_set_ext_event_target_event_id(uint8_t * p_desc_n,uint16_t i_target_event_id)253 static inline void desc4an_set_ext_event_target_event_id(uint8_t *p_desc_n, uint16_t i_target_event_id)
254 {
255 p_desc_n[0] = (i_target_event_id >> 8) & 0xff;
256 p_desc_n[1] = i_target_event_id & 0xff;
257 }
258
desc4an_get_ext_event_target_listed(const uint8_t * p_desc_n)259 static inline bool desc4an_get_ext_event_target_listed(const uint8_t *p_desc_n)
260 {
261 return (p_desc_n[2] & 0x80) == 0x80;
262 }
263
desc4an_set_ext_event_target_listed(uint8_t * p_desc_n,bool b_target_listed)264 static inline void desc4an_set_ext_event_target_listed(uint8_t *p_desc_n, bool b_target_listed)
265 {
266 p_desc_n[2] = b_target_listed ? (p_desc_n[2] | 0x80) : (p_desc_n[2] &~ 0x80);
267 }
268
desc4an_get_ext_event_simulcast(const uint8_t * p_desc_n)269 static inline bool desc4an_get_ext_event_simulcast(const uint8_t *p_desc_n)
270 {
271 return (p_desc_n[2] & 0x40) == 0x40;
272 }
273
desc4an_set_ext_event_simulcast(uint8_t * p_desc_n,bool b_event_simulcast)274 static inline void desc4an_set_ext_event_simulcast(uint8_t *p_desc_n, bool b_event_simulcast)
275 {
276 p_desc_n[2] = b_event_simulcast ? (p_desc_n[2] | 0x40) : (p_desc_n[2] &~ 0x40);
277 }
278
desc4an_get_ext_event_link_type(const uint8_t * p_desc_n)279 static inline uint8_t desc4an_get_ext_event_link_type(const uint8_t *p_desc_n)
280 {
281 return (p_desc_n[2] & 0x30) >> 4;
282 }
283
desc4an_set_ext_event_link_type(uint8_t * p_desc_n,uint8_t i_link_type)284 static inline void desc4an_set_ext_event_link_type(uint8_t *p_desc_n, uint8_t i_link_type)
285 {
286 p_desc_n[2] = (p_desc_n[2] & 0xcf) | ((i_link_type & 0x03) << 4);
287 }
288
desc4a_get_ext_event_link_type_txt(uint8_t i_link_type)289 static inline const char *desc4a_get_ext_event_link_type_txt(uint8_t i_link_type)
290 {
291 return i_link_type == 0 ? "SD" :
292 i_link_type == 1 ? "HD" :
293 i_link_type == 2 ? "3D" : "reserved";
294 }
295
desc4an_get_ext_event_target_id_type(const uint8_t * p_desc_n)296 static inline uint8_t desc4an_get_ext_event_target_id_type(const uint8_t *p_desc_n)
297 {
298 return (p_desc_n[2] & 0x0c) >> 2;
299 }
300
desc4an_set_ext_event_target_id_type(uint8_t * p_desc_n,uint8_t i_target_id_type)301 static inline void desc4an_set_ext_event_target_id_type(uint8_t *p_desc_n, uint8_t i_target_id_type)
302 {
303 p_desc_n[2] = (p_desc_n[2] & 0xf3) | ((i_target_id_type & 0x03) << 2);
304 }
305
desc4a_get_ext_event_target_id_type_txt(uint8_t i_target_id_type)306 static inline const char *desc4a_get_ext_event_target_id_type_txt(uint8_t i_target_id_type)
307 {
308 return i_target_id_type == 0 ? "use tsid" :
309 i_target_id_type == 1 ? "use target_tsid" :
310 i_target_id_type == 2 ? "match any tsid" : "use user_defined_id";
311 }
312
desc4an_get_ext_event_onid_id_flag(const uint8_t * p_desc_n)313 static inline bool desc4an_get_ext_event_onid_id_flag(const uint8_t *p_desc_n)
314 {
315 return (p_desc_n[2] & 0x02) == 0x02;
316 }
317
desc4an_set_ext_event_onid_id_flag(uint8_t * p_desc_n,bool b_event_onid_id_flag)318 static inline void desc4an_set_ext_event_onid_id_flag(uint8_t *p_desc_n, bool b_event_onid_id_flag)
319 {
320 p_desc_n[2] = b_event_onid_id_flag ? (p_desc_n[2] | 0x02) : (p_desc_n[2] &~ 0x02);
321 }
322
desc4an_get_ext_event_service_id_flag(const uint8_t * p_desc_n)323 static inline bool desc4an_get_ext_event_service_id_flag(const uint8_t *p_desc_n)
324 {
325 return (p_desc_n[2] & 0x01) == 0x01;
326 }
327
desc4an_set_ext_event_service_id_flag(uint8_t * p_desc_n,bool b_event_service_id_flag)328 static inline void desc4an_set_ext_event_service_id_flag(uint8_t *p_desc_n, bool b_event_service_id_flag)
329 {
330 p_desc_n[2] = b_event_service_id_flag ? (p_desc_n[2] | 0x01) : (p_desc_n[2] &~ 0x01);
331 }
332
333
desc4an_ext_event_have_user_defined_id(const uint8_t * p_desc_n)334 static inline bool desc4an_ext_event_have_user_defined_id(const uint8_t *p_desc_n)
335 {
336 return desc4an_get_ext_event_target_id_type(p_desc_n) == 3;
337 }
338
desc4an_ext_event_have_target_tsid(const uint8_t * p_desc_n)339 static inline bool desc4an_ext_event_have_target_tsid(const uint8_t *p_desc_n)
340 {
341 return desc4an_get_ext_event_target_id_type(p_desc_n) == 1;
342 }
343
344
desc4an_get_ext_event_user_defined_id(const uint8_t * p_desc_n)345 static inline uint16_t desc4an_get_ext_event_user_defined_id(const uint8_t *p_desc_n)
346 {
347 if (desc4an_ext_event_have_user_defined_id(p_desc_n))
348 return (p_desc_n[3] << 8) | p_desc_n[4];
349 else
350 return 0;
351 }
352
desc4an_set_ext_event_user_defined_id(uint8_t * p_desc_n,uint16_t i_user_defined_id)353 static inline void desc4an_set_ext_event_user_defined_id(uint8_t *p_desc_n, uint16_t i_user_defined_id)
354 {
355 if (desc4an_ext_event_have_user_defined_id(p_desc_n)) {
356 p_desc_n[3] = (i_user_defined_id >> 8) & 0xff;
357 p_desc_n[4] = i_user_defined_id & 0xff;
358 }
359 }
360
desc4an_get_ext_event_target_tsid(const uint8_t * p_desc_n)361 static inline uint16_t desc4an_get_ext_event_target_tsid(const uint8_t *p_desc_n)
362 {
363 if (desc4an_ext_event_have_target_tsid(p_desc_n))
364 return (p_desc_n[3] << 8) | p_desc_n[4];
365 else
366 return 0;
367 }
368
desc4an_set_ext_event_target_tsid(uint8_t * p_desc_n,uint16_t i_target_tsid)369 static inline void desc4an_set_ext_event_target_tsid(uint8_t *p_desc_n, uint16_t i_target_tsid)
370 {
371 if (desc4an_ext_event_have_target_tsid(p_desc_n)) {
372 p_desc_n[3] = (i_target_tsid >> 8) & 0xff;
373 p_desc_n[4] = i_target_tsid & 0xff;
374 }
375 }
376
desc4an_get_ext_event_target_onid(const uint8_t * p_desc_n)377 static inline uint16_t desc4an_get_ext_event_target_onid(const uint8_t *p_desc_n)
378 {
379 if (desc4an_ext_event_have_user_defined_id(p_desc_n))
380 return 0;
381 uint8_t ofs = desc4an_ext_event_have_target_tsid(p_desc_n) ? 5 : 3;
382 if (desc4an_get_ext_event_onid_id_flag(p_desc_n))
383 return (p_desc_n[ofs + 0] << 8) | p_desc_n[ofs + 1];
384 else
385 return 0;
386 }
387
desc4an_set_ext_event_target_onid(uint8_t * p_desc_n,uint16_t i_target_onid)388 static inline void desc4an_set_ext_event_target_onid(uint8_t *p_desc_n, uint16_t i_target_onid)
389 {
390 if (desc4an_ext_event_have_user_defined_id(p_desc_n))
391 return;
392 uint8_t ofs = desc4an_ext_event_have_target_tsid(p_desc_n) ? 5 : 3;
393 if (desc4an_get_ext_event_onid_id_flag(p_desc_n)) {
394 p_desc_n[ofs + 0] = (i_target_onid >> 8) & 0xff;
395 p_desc_n[ofs + 1] = i_target_onid & 0xff;
396 }
397 }
398
desc4an_get_ext_event_service_id(const uint8_t * p_desc_n)399 static inline uint16_t desc4an_get_ext_event_service_id(const uint8_t *p_desc_n)
400 {
401 if (desc4an_ext_event_have_user_defined_id(p_desc_n))
402 return 0;
403 uint8_t ofs = desc4an_ext_event_have_target_tsid(p_desc_n) ? 5 : 3;
404 if (desc4an_get_ext_event_onid_id_flag(p_desc_n))
405 ofs += 2;
406 if (desc4an_get_ext_event_service_id_flag(p_desc_n))
407 return (p_desc_n[ofs + 0] << 8) | p_desc_n[ofs + 1];
408 else
409 return 0;
410 }
411
desc4an_set_ext_event_service_id(uint8_t * p_desc_n,uint16_t i_service_id)412 static inline void desc4an_set_ext_event_service_id(uint8_t *p_desc_n, uint16_t i_service_id)
413 {
414 if (desc4an_ext_event_have_user_defined_id(p_desc_n))
415 return;
416 uint8_t ofs = desc4an_ext_event_have_target_tsid(p_desc_n) ? 5 : 3;
417 if (desc4an_get_ext_event_onid_id_flag(p_desc_n))
418 ofs += 2;
419 if (desc4an_get_ext_event_service_id_flag(p_desc_n)) {
420 p_desc_n[ofs + 0] = (i_service_id >> 8) & 0xff;
421 p_desc_n[ofs + 1] = i_service_id & 0xff;
422 }
423 }
424
desc4an_get_ext_event_length(const uint8_t * p_desc_n)425 static inline uint8_t desc4an_get_ext_event_length(const uint8_t *p_desc_n)
426 {
427 uint8_t i_len = 3;
428 if (desc4an_ext_event_have_user_defined_id(p_desc_n))
429 return i_len + 2;
430 if (desc4an_ext_event_have_target_tsid(p_desc_n))
431 i_len += 2;
432 if (desc4an_get_ext_event_onid_id_flag(p_desc_n))
433 i_len += 2;
434 if (desc4an_get_ext_event_service_id_flag(p_desc_n))
435 i_len += 2;
436 return i_len;
437 }
438
desc4a_get_ext_event(const uint8_t * p_desc,uint8_t n)439 static inline uint8_t *desc4a_get_ext_event(const uint8_t *p_desc, uint8_t n)
440 {
441 uint8_t *p = (uint8_t *)p_desc + DESC4A_HEADER_SIZE;
442 uint8_t *p_end = (uint8_t *)p_desc + DESC_HEADER_SIZE + desc_get_length(p_desc);
443
444 if (p == p_end)
445 return NULL;
446
447 if (n == 0)
448 return p;
449
450 while (p < p_end && n) {
451 p += desc4an_get_ext_event_length(p);
452 if (--n == 0 && p < p_end )
453 return p;
454 }
455
456 return NULL;
457 }
458
459 /* Generic desc4a continued... */
460
desc4a_set_length(uint8_t * p_desc)461 static inline void desc4a_set_length(uint8_t *p_desc)
462 {
463 uint8_t i_length = DESC4A_HEADER_SIZE - DESC_HEADER_SIZE;
464 i_length += desc4a_get_mobile_handover_length(p_desc);
465 i_length += desc4a_get_event_length(p_desc);
466 desc_set_length(p_desc, i_length);
467 }
468
desc4a_validate(const uint8_t * p_desc)469 static inline bool desc4a_validate(const uint8_t *p_desc)
470 {
471 uint8_t i_length = DESC4A_HEADER_SIZE - DESC_HEADER_SIZE;
472 i_length += desc4a_get_mobile_handover_length(p_desc);
473 i_length += desc4a_get_event_length(p_desc);
474 return desc_get_length(p_desc) >= i_length;
475 }
476
desc4a_print(const uint8_t * p_desc,f_print pf_print,void * opaque,print_type_t i_print_type)477 static inline void desc4a_print(const uint8_t *p_desc, f_print pf_print,
478 void *opaque, print_type_t i_print_type)
479 {
480 uint8_t j;
481 uint8_t *p_desc_n;
482 uint8_t i_linkage = desc4a_get_linkage(p_desc);
483
484 switch (i_print_type) {
485 case PRINT_XML:
486 pf_print(opaque,
487 "<LINKAGE_DESC tsid=\"%hu\" onid=\"%hu\" sid=\"%hu\" linkage=\"0x%02x\" linkage_txt=\"%s\">",
488 desc4a_get_tsid(p_desc), desc4a_get_onid(p_desc),
489 desc4a_get_sid(p_desc), i_linkage,
490 desc4a_get_linkage_txt(i_linkage)
491 );
492 if (i_linkage == DESC4A_LINKAGE_MOBILE) {
493 pf_print(opaque,
494 "<MOBILE_HANDOVER_INFO handover_type=\"%u\" origin_type=\"%u\" nid=\"%u\" initial_sid=\"%u\"/>",
495 desc4a_get_mobile_handover_type(p_desc),
496 desc4a_get_mobile_origin_type(p_desc),
497 desc4a_get_mobile_nid(p_desc),
498 desc4a_get_mobile_initial_sid(p_desc)
499 );
500 }
501 if (i_linkage == DESC4A_LINKAGE_EVENT) { // event linkage
502 pf_print(opaque,
503 "<EVENT_LINKAGE target_event_id=\"%u\" target_listed=\"%u\" event_simulcast=\"%u\"/>",
504 desc4a_get_event_target_event_id(p_desc),
505 desc4a_get_event_target_listed(p_desc),
506 desc4a_get_event_simulcast(p_desc)
507 );
508 }
509 if (i_linkage == DESC4A_LINKAGE_EXT_EVENT) {
510 j = 0;
511 while ((p_desc_n = desc4a_get_ext_event(p_desc, j++)) != NULL) {
512 pf_print(opaque,
513 "<EXTENDED_EVENT_LINKAGE target_event_id=\"%u\" target_listed=\"%u\" event_simulcast=\"%u\""
514 " link_type=\"%u\" link_type_txt=\"%s\""
515 " target_id_type=\"%u\" target_id_type_txt=\"%s\""
516 " onid_id_flag=\"%u\" service_id_flag=\"%u\""
517 " user_defined_id=\"%u\" target_tsid=\"%u\" target_onid=\"%u\" target_service_id=\"%u\"/>",
518 desc4an_get_ext_event_target_event_id(p_desc_n),
519 desc4an_get_ext_event_target_listed(p_desc_n),
520 desc4an_get_ext_event_simulcast(p_desc_n),
521 desc4an_get_ext_event_link_type(p_desc_n),
522 desc4a_get_ext_event_link_type_txt(desc4an_get_ext_event_link_type(p_desc_n)),
523 desc4an_get_ext_event_target_id_type(p_desc_n),
524 desc4a_get_ext_event_target_id_type_txt(desc4an_get_ext_event_target_id_type(p_desc_n)),
525 desc4an_get_ext_event_onid_id_flag(p_desc_n),
526 desc4an_get_ext_event_service_id_flag(p_desc_n),
527 desc4an_get_ext_event_user_defined_id(p_desc_n),
528 desc4an_get_ext_event_target_tsid(p_desc_n),
529 desc4an_get_ext_event_target_onid(p_desc_n),
530 desc4an_get_ext_event_service_id(p_desc_n)
531 );
532 }
533 }
534 pf_print(opaque,
535 "</LINKAGE_DESC>");
536 break;
537 default:
538 pf_print(opaque,
539 " - desc 4a linkage tsid=%hu onid=%hu sid=%hu linkage=0x%02x linkage_txt=\"%s\"",
540 desc4a_get_tsid(p_desc), desc4a_get_onid(p_desc),
541 desc4a_get_sid(p_desc), i_linkage,
542 desc4a_get_linkage_txt(i_linkage)
543 );
544 if (i_linkage == DESC4A_LINKAGE_MOBILE) {
545 pf_print(opaque,
546 " - mobile_handover handover_type=%u origin_type=%u nid=%u initial_sid=%u",
547 desc4a_get_mobile_handover_type(p_desc),
548 desc4a_get_mobile_origin_type(p_desc),
549 desc4a_get_mobile_nid(p_desc),
550 desc4a_get_mobile_initial_sid(p_desc)
551 );
552 }
553 if (i_linkage == DESC4A_LINKAGE_EVENT) {
554 pf_print(opaque,
555 " - event_linkage target_event_id=%u target_listed=%u event_simulcast=%u",
556 desc4a_get_event_target_event_id(p_desc),
557 desc4a_get_event_target_listed(p_desc),
558 desc4a_get_event_simulcast(p_desc)
559 );
560 }
561 if (i_linkage == DESC4A_LINKAGE_EXT_EVENT) {
562 j = 0;
563 while ((p_desc_n = desc4a_get_ext_event(p_desc, j++)) != NULL) {
564 pf_print(opaque,
565 " - extended_event_linkage target_event_id=%u target_listed=%u event_simulcast=%u"
566 " link_type=%u link_type_txt=\"%s\""
567 " target_id_type=%u target_id_type_txt=\"%s\""
568 " onid_id_flag=%u service_id_flag=%u"
569 " user_defined_id=%u target_tsid=%u target_onid=%u target_service_id=%u",
570 desc4an_get_ext_event_target_event_id(p_desc_n),
571 desc4an_get_ext_event_target_listed(p_desc_n),
572 desc4an_get_ext_event_simulcast(p_desc_n),
573 desc4an_get_ext_event_link_type(p_desc_n),
574 desc4a_get_ext_event_link_type_txt(desc4an_get_ext_event_link_type(p_desc_n)),
575 desc4an_get_ext_event_target_id_type(p_desc_n),
576 desc4a_get_ext_event_target_id_type_txt(desc4an_get_ext_event_target_id_type(p_desc_n)),
577 desc4an_get_ext_event_onid_id_flag(p_desc_n),
578 desc4an_get_ext_event_service_id_flag(p_desc_n),
579 desc4an_get_ext_event_user_defined_id(p_desc_n),
580 desc4an_get_ext_event_target_tsid(p_desc_n),
581 desc4an_get_ext_event_target_onid(p_desc_n),
582 desc4an_get_ext_event_service_id(p_desc_n)
583 );
584 }
585 }
586 }
587 }
588
589 #ifdef __cplusplus
590 }
591 #endif
592
593 #endif
594