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_atsc_service_location.h>
21 #include <libdvbv5/dvb-fe.h>
22 #include <ctype.h>
23
24 #if __GNUC__ >= 9
25 #pragma GCC diagnostic ignored "-Waddress-of-packed-member"
26 #endif
27
atsc_desc_service_location_init(struct dvb_v5_fe_parms * parms,const uint8_t * buf,struct dvb_desc * desc)28 int atsc_desc_service_location_init(struct dvb_v5_fe_parms *parms,
29 const uint8_t *buf, struct dvb_desc *desc)
30 {
31 struct atsc_desc_service_location *s_loc = (struct atsc_desc_service_location *)desc;
32 struct atsc_desc_service_location_elementary *el;
33 unsigned char *p = (unsigned char *)buf;
34 int i;
35 size_t len, dlen = desc->length;
36
37 // raw data should have one element
38 len = sizeof(u_int16_t) + sizeof(u_int8_t) + sizeof(struct atsc_desc_service_location_elementary);
39 if (dlen < len) {
40 dvb_logwarn("ATSC service location descriptor is too small");
41 return -1;
42 }
43
44 memcpy(&s_loc->bitfield , p, sizeof(u_int16_t));
45 p += sizeof(u_int16_t);
46 dlen -= sizeof(u_int16_t);
47 bswap16(s_loc->bitfield);
48
49 memcpy(&s_loc->number_elements , p, sizeof(u_int8_t));
50 p += sizeof(u_int8_t);
51 dlen -= sizeof(u_int8_t);
52
53 bswap16(s_loc->bitfield);
54
55 len = s_loc->number_elements * sizeof(*s_loc->elementary);
56 if (dlen < len) {
57 dvb_logwarn("ATSC service location descriptor is too small for %d elements",
58 s_loc->number_elements);
59 return -1;
60 }
61 if (dlen > len) {
62 dvb_logwarn("ATSC service location descriptor %zu bytes bigger than expected",
63 dlen - len);
64 return -1;
65 }
66
67 if (s_loc->number_elements) {
68 s_loc->elementary = malloc(len);
69 if (!s_loc->elementary) {
70 dvb_perror("Can't allocate space for ATSC service location elementary data");
71 return -1;
72 }
73
74 el = s_loc->elementary;
75
76 for (i = 0; i < s_loc->number_elements; i++) {
77 memcpy(el, p, sizeof(*el));
78 bswap16(el->bitfield);
79
80 el++;
81 p += sizeof(*el);
82 }
83 } else {
84 s_loc->elementary = NULL;
85 }
86 return 0;
87 }
88
89 #define prt_char(x) (isprint(x) ? x : '.')
90
atsc_desc_service_location_print(struct dvb_v5_fe_parms * parms,const struct dvb_desc * desc)91 void atsc_desc_service_location_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc)
92 {
93 const struct atsc_desc_service_location *s_loc = (const struct atsc_desc_service_location *) desc;
94 struct atsc_desc_service_location_elementary *el = s_loc->elementary;
95 int i;
96
97 dvb_loginfo("| pcr PID %d", s_loc->pcr_pid);
98 dvb_loginfo("|\\ elementary service - %d elementaries", s_loc->number_elements);
99 for (i = 0; i < s_loc->number_elements; i++) {
100 dvb_loginfo("|- elementary %d", i);
101 dvb_loginfo("|- | stream type 0x%02x", el[i].stream_type);
102 dvb_loginfo("|- | PID %d", el[i].elementary_pid);
103 dvb_loginfo("|- | Language %c%c%c (0x%02x 0x%02x 0x%02x)",
104 prt_char(el[i].ISO_639_language_code[0]),
105 prt_char(el[i].ISO_639_language_code[1]),
106 prt_char(el[i].ISO_639_language_code[2]),
107 el[i].ISO_639_language_code[0],
108 el[i].ISO_639_language_code[1],
109 el[i].ISO_639_language_code[2]);
110 }
111 }
112
atsc_desc_service_location_free(struct dvb_desc * desc)113 void atsc_desc_service_location_free(struct dvb_desc *desc)
114 {
115 const struct atsc_desc_service_location *s_loc = (const struct atsc_desc_service_location *) desc;
116
117 if (s_loc->elementary)
118 free(s_loc->elementary);
119 }
120