1 /*****************************************************************************
2 * desc_57.h: ETSI EN 300 468 Descriptor 0x57: Telephone descriptor
3 *****************************************************************************
4 * Copyright (C) 2011 Unix Solutions Ltd.
5 *
6 * Authors: Georgi Chorbadzhiyski <georgi@unixsol.org>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining
9 * a copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sublicense, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject
14 * to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be
17 * included in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *****************************************************************************/
27
28 /*
29 * Normative references:
30 * - ETSI EN 300 468 V1.11.1 (2010-04) (SI in DVB systems)
31 */
32
33 #ifndef __BITSTREAM_DVB_DESC_57_H__
34 #define __BITSTREAM_DVB_DESC_57_H__
35
36 #include <bitstream/common.h>
37 #include <bitstream/mpeg/psi/descriptors.h>
38
39 #ifdef __cplusplus
40 extern "C"
41 {
42 #endif
43
44 /*****************************************************************************
45 * Descriptor 0x57: Telephone descriptor
46 *****************************************************************************/
47 #define DESC57_HEADER_SIZE (DESC_HEADER_SIZE + 3)
48
desc57_init(uint8_t * p_desc)49 static inline void desc57_init(uint8_t *p_desc)
50 {
51 desc_set_tag(p_desc, 0x57);
52 desc_set_length(p_desc, DESC57_HEADER_SIZE - DESC_HEADER_SIZE);
53 p_desc[2] = 0xc0;
54 p_desc[3] = 0x80;
55 p_desc[4] = 0x80;
56 }
57
desc57_get_foreign_availability(const uint8_t * p_desc)58 static inline bool desc57_get_foreign_availability(const uint8_t *p_desc)
59 {
60 return (p_desc[2] & 0x20) == 0x20;
61 }
62
63
desc57_set_foreign_availability(uint8_t * p_desc,bool b_foreign_availability)64 static inline void desc57_set_foreign_availability(uint8_t *p_desc, bool b_foreign_availability)
65 {
66 p_desc[2] = b_foreign_availability ? (p_desc[2] | 0x20) : (p_desc[2] &~ 0x20);
67 }
68
desc57_get_connection_type(const uint8_t * p_desc)69 static inline uint8_t desc57_get_connection_type(const uint8_t *p_desc)
70 {
71 return p_desc[2] & 0x1f;
72 }
73
desc57_set_connection_type(uint8_t * p_desc,uint8_t i_connection_type)74 static inline void desc57_set_connection_type(uint8_t *p_desc, uint8_t i_connection_type)
75 {
76 p_desc[2] = (p_desc[2] & 0xe0) | (i_connection_type & 0x1f);
77 }
78
79
desc57_get_country_prefix_length(const uint8_t * p_desc)80 static inline uint8_t desc57_get_country_prefix_length(const uint8_t *p_desc)
81 {
82 return (p_desc[3] & 0x60) >> 5; // x11xxxxx
83 }
84
desc57_get_country_prefix(const uint8_t * p_desc,uint8_t * i_length)85 static inline const char *desc57_get_country_prefix(const uint8_t *p_desc, uint8_t *i_length)
86 {
87 *i_length = desc57_get_country_prefix_length(p_desc);
88 if (*i_length == 0) return NULL;
89 return (const char *)p_desc + DESC57_HEADER_SIZE;
90 }
91
desc57_set_country_prefix(uint8_t * p_desc,const char * p_country_prefix,uint8_t i_length)92 static inline void desc57_set_country_prefix(uint8_t *p_desc, const char *p_country_prefix, uint8_t i_length)
93 {
94 p_desc[3] = (p_desc[3] &~ 0x60) | ((i_length & 0x03) << 5); // x11xxxxx
95 memcpy(p_desc + DESC57_HEADER_SIZE, p_country_prefix, i_length);
96 }
97
98
desc57_get_international_area_code_length(const uint8_t * p_desc)99 static inline uint8_t desc57_get_international_area_code_length(const uint8_t *p_desc)
100 {
101 return (p_desc[3] & 0x1c) >> 2; // xxx111xx
102 }
103
desc57_get_international_area_code(const uint8_t * p_desc,uint8_t * i_length)104 static inline const char *desc57_get_international_area_code(const uint8_t *p_desc, uint8_t *i_length)
105 {
106 *i_length = desc57_get_international_area_code_length(p_desc);
107 if (*i_length == 0) return NULL;
108 return (const char *)p_desc + DESC57_HEADER_SIZE
109 + desc57_get_country_prefix_length(p_desc);
110 }
111
desc57_set_international_area_code(uint8_t * p_desc,const char * p_international_area_code,uint8_t i_length)112 static inline void desc57_set_international_area_code(uint8_t *p_desc, const char *p_international_area_code, uint8_t i_length)
113 {
114 p_desc[3] = (p_desc[3] &~ 0x1c) | ((i_length & 0x07) << 2); // xxx111xx
115 memcpy(p_desc + DESC57_HEADER_SIZE
116 + desc57_get_country_prefix_length(p_desc),
117 p_international_area_code, i_length);
118 }
119
120
desc57_get_operator_code_length(const uint8_t * p_desc)121 static inline uint8_t desc57_get_operator_code_length(const uint8_t *p_desc)
122 {
123 return (p_desc[3] & 0x03); // xxxxxx11
124 }
125
desc57_get_operator_code(const uint8_t * p_desc,uint8_t * i_length)126 static inline const char *desc57_get_operator_code(const uint8_t *p_desc, uint8_t *i_length)
127 {
128 *i_length = desc57_get_operator_code_length(p_desc);
129 if (*i_length == 0) return NULL;
130 return (const char *)p_desc + DESC57_HEADER_SIZE
131 + desc57_get_country_prefix_length(p_desc)
132 + desc57_get_international_area_code_length(p_desc);
133 }
134
desc57_set_operator_code(uint8_t * p_desc,const char * p_operator_code,uint8_t i_length)135 static inline void desc57_set_operator_code(uint8_t *p_desc, const char *p_operator_code, uint8_t i_length)
136 {
137 p_desc[3] = (p_desc[3] &~ 0x03) | (i_length & 0x03); // xxxxxx11
138 memcpy(p_desc + DESC57_HEADER_SIZE
139 + desc57_get_country_prefix_length(p_desc)
140 + desc57_get_international_area_code_length(p_desc),
141 p_operator_code, i_length);
142 }
143
144
desc57_get_national_area_code_length(const uint8_t * p_desc)145 static inline uint8_t desc57_get_national_area_code_length(const uint8_t *p_desc)
146 {
147 return (p_desc[4] & 0x70) >> 4; // x111xxxx
148 }
149
desc57_get_national_area_code(const uint8_t * p_desc,uint8_t * i_length)150 static inline const char *desc57_get_national_area_code(const uint8_t *p_desc, uint8_t *i_length)
151 {
152 *i_length = desc57_get_national_area_code_length(p_desc);
153 if (*i_length == 0) return NULL;
154 return (const char *)p_desc + DESC57_HEADER_SIZE
155 + desc57_get_country_prefix_length(p_desc)
156 + desc57_get_international_area_code_length(p_desc)
157 + desc57_get_operator_code_length(p_desc);
158 }
159
desc57_set_national_area_code(uint8_t * p_desc,const char * p_national_area_code,uint8_t i_length)160 static inline void desc57_set_national_area_code(uint8_t *p_desc, const char *p_national_area_code, uint8_t i_length)
161 {
162 p_desc[4] = (p_desc[4] &~ 0x70) | ((i_length & 0x07) << 4); // x111xxxx
163 memcpy(p_desc + DESC57_HEADER_SIZE
164 + desc57_get_country_prefix_length(p_desc)
165 + desc57_get_international_area_code_length(p_desc)
166 + desc57_get_operator_code_length(p_desc),
167 p_national_area_code, i_length);
168 }
169
170
desc57_get_core_number_length(const uint8_t * p_desc)171 static inline uint8_t desc57_get_core_number_length(const uint8_t *p_desc)
172 {
173 return (p_desc[4] & 0x0f); // xxxx1111
174 }
175
desc57_get_core_number(const uint8_t * p_desc,uint8_t * i_length)176 static inline const char *desc57_get_core_number(const uint8_t *p_desc, uint8_t *i_length)
177 {
178 *i_length = desc57_get_core_number_length(p_desc);
179 if (*i_length == 0) return NULL;
180 return (const char *)p_desc + DESC57_HEADER_SIZE
181 + desc57_get_country_prefix_length(p_desc)
182 + desc57_get_international_area_code_length(p_desc)
183 + desc57_get_operator_code_length(p_desc)
184 + desc57_get_national_area_code_length(p_desc);
185 }
186
desc57_set_core_number(uint8_t * p_desc,const char * p_core_number,uint8_t i_length)187 static inline void desc57_set_core_number(uint8_t *p_desc, const char *p_core_number, uint8_t i_length)
188 {
189 p_desc[4] = (p_desc[4] &~ 0x0f) | (i_length & 0x0f);
190 memcpy(p_desc + DESC57_HEADER_SIZE
191 + desc57_get_country_prefix_length(p_desc)
192 + desc57_get_international_area_code_length(p_desc)
193 + desc57_get_operator_code_length(p_desc)
194 + desc57_get_national_area_code_length(p_desc),
195 p_core_number, i_length);
196 }
197
198
desc57_get_phone_length(const uint8_t * p_desc)199 static inline uint8_t desc57_get_phone_length(const uint8_t *p_desc)
200 {
201 return desc_get_length(p_desc) - (DESC57_HEADER_SIZE - DESC_HEADER_SIZE);
202 }
203
desc57_get_phone(const uint8_t * p_desc,uint8_t * i_length)204 static inline const char *desc57_get_phone(const uint8_t *p_desc, uint8_t *i_length)
205 {
206 *i_length = desc57_get_phone_length(p_desc);
207 if (*i_length == 0) return NULL;
208 return (const char *)p_desc + DESC57_HEADER_SIZE;
209 }
210
211
desc57_set_length(uint8_t * p_desc)212 static inline void desc57_set_length(uint8_t *p_desc)
213 {
214 desc_set_length(p_desc, DESC57_HEADER_SIZE - DESC_HEADER_SIZE +
215 + desc57_get_country_prefix_length(p_desc)
216 + desc57_get_international_area_code_length(p_desc)
217 + desc57_get_operator_code_length(p_desc)
218 + desc57_get_national_area_code_length(p_desc)
219 + desc57_get_core_number_length(p_desc));
220 }
221
desc57_validate(const uint8_t * p_desc)222 static inline bool desc57_validate(const uint8_t *p_desc)
223 {
224 return (p_desc + DESC57_HEADER_SIZE
225 + desc57_get_country_prefix_length(p_desc)
226 + desc57_get_international_area_code_length(p_desc)
227 + desc57_get_operator_code_length(p_desc)
228 + desc57_get_national_area_code_length(p_desc)
229 + desc57_get_core_number_length(p_desc))
230 == (p_desc + DESC_HEADER_SIZE + desc_get_length(p_desc));
231 }
232
desc57_print(uint8_t * p_desc,f_print pf_print,void * opaque,print_type_t i_print_type)233 static inline void desc57_print(uint8_t *p_desc, f_print pf_print,
234 void *opaque, print_type_t i_print_type)
235 {
236 uint8_t i_country_prefix_len, i_international_area_code_len, i_operator_code_len;
237 uint8_t i_national_area_code_len, i_core_number_len, i_phone;
238 const char *empty = "";
239 const char *p_country_prefix = desc57_get_country_prefix(p_desc, &i_country_prefix_len);
240 const char *p_international_area_code = desc57_get_international_area_code(p_desc, &i_international_area_code_len);
241 const char *p_operator_code = desc57_get_operator_code(p_desc, &i_operator_code_len);
242 const char *p_national_area_code = desc57_get_national_area_code(p_desc, &i_national_area_code_len);
243 const char *p_core_number = desc57_get_core_number(p_desc, &i_core_number_len);
244 const char *p_phone = desc57_get_phone(p_desc, &i_phone);
245
246 if (!p_country_prefix) p_country_prefix = empty;
247 if (!p_international_area_code) p_international_area_code = empty;
248 if (!p_operator_code) p_operator_code = empty;
249 if (!p_national_area_code) p_national_area_code = empty;
250 if (!p_core_number) p_core_number = empty;
251 if (!p_phone) p_phone = empty;
252
253 switch (i_print_type) {
254 case PRINT_XML:
255 pf_print(opaque,
256 "<TELEPHONE_DESC foreign_availability=\"%u\" connection_type=\"%u\""
257 " country_prefix=\"%.*s\" international_area_code=\"%.*s\""
258 " operator_code=\"%.*s\" national_area_code=\"%.*s\""
259 " core_number=\"%.*s\" full_telephone=\"%.*s\"/>",
260 desc57_get_foreign_availability(p_desc),
261 desc57_get_connection_type(p_desc),
262 i_country_prefix_len, p_country_prefix,
263 i_international_area_code_len, p_international_area_code,
264 i_operator_code_len, p_operator_code,
265 i_national_area_code_len, p_national_area_code,
266 i_core_number_len, p_core_number,
267 i_phone, p_phone
268 );
269 break;
270 default:
271 pf_print(opaque,
272 " - desc 57 telephone foreign_availability=%u connection_type=%u"
273 " country_prefix=%.*s international_area_code=%.*s"
274 " operator_code=%.*s national_area_code=%.*s"
275 " core_number=%.*s phone=%.*s",
276 desc57_get_foreign_availability(p_desc),
277 desc57_get_connection_type(p_desc),
278 i_country_prefix_len, p_country_prefix,
279 i_international_area_code_len, p_international_area_code,
280 i_operator_code_len, p_operator_code,
281 i_national_area_code_len, p_national_area_code,
282 i_core_number_len, p_core_number,
283 i_phone, p_phone
284 );
285 }
286 }
287
288 #ifdef __cplusplus
289 }
290 #endif
291
292 #endif
293