• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /*
3  * Copyright 2012 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
4  * Author: Konke Radlow <koradlow@gmail.com>
5  */
6 
7 #ifndef __LIBV4L2RDS
8 #define __LIBV4L2RDS
9 
10 
11 #include <stdbool.h>
12 #include <stdint.h>
13 
14 #if defined(__OpenBSD__)
15 #include <sys/videoio.h>
16 #else
17 #include <linux/videodev2.h>
18 #endif
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif /* __cplusplus */
23 
24 #if HAVE_VISIBILITY
25 #define LIBV4L_PUBLIC __attribute__ ((visibility("default")))
26 #else
27 #define LIBV4L_PUBLIC
28 #endif
29 
30 /* used to define the current version (version field) of the v4l2_rds struct */
31 #define V4L2_RDS_VERSION (2)
32 
33 /* Constants used to define the size of arrays used to store RDS information */
34 #define MAX_ODA_CNT 18 	/* there are 16 groups each with type a or b. Of these
35 			 * 32 distinct groups, 18 can be used for ODA purposes */
36 #define MAX_AF_CNT 25	/* AF Method A allows a maximum of 25 AFs to be defined
37 			 * AF Method B does not impose a limit on the number of AFs
38 			 * but it is not fully supported at the moment and will
39 			 * not receive more than 25 AFs */
40 #define MAX_TMC_ADDITIONAL 28	/* 28 is the maximal possible number of fields.
41 			* Additional data is limited to 112 bit, and the smallest
42 			* optional tuple has a size of 4 bit (4 bit identifier +
43 			* 0 bits of data) */
44 #define MAX_TMC_ALT_STATIONS 32 /* defined by ISO 14819-1:2003, 7.5.3.3  */
45 #define MAX_TMC_AF_CNT 4	/* limit for the numbers of AFs stored per alternative TMC
46 			* station. This value is not defined by the standard, but based on observation
47 			* of real-world RDS-TMC streams. The maximum encountered number of AFs per
48 			* station during testing was 2 */
49 #define MAX_EON_CNT 20	/* Maximal number of entries in the EON table (for storing
50 			* information about other radio stations, broadcasted by the current station).
51 			* This value is not defined by the standard, but based on observation
52 			* of real-world RDS-TMC streams. EON doesn't seem to be a widely used feature
53 			* and the maximum number of EON encountered during testing was 8 */
54 
55 /* Define Constants for the possible types of RDS information
56  * used to address the relevant bit in the valid_fields bitmask */
57 #define V4L2_RDS_PI 		0x01	/* Program Identification */
58 #define V4L2_RDS_PTY		0x02	/* Program Type */
59 #define V4L2_RDS_TP		0x04	/* Traffic Program */
60 #define V4L2_RDS_PS		0x08	/* Program Service Name */
61 #define V4L2_RDS_TA		0x10	/* Traffic Announcement */
62 #define V4L2_RDS_DI		0x20	/* Decoder Information */
63 #define V4L2_RDS_MS		0x40	/* Music / Speech flag */
64 #define V4L2_RDS_PTYN		0x80	/* Program Type Name */
65 #define V4L2_RDS_RT		0x100 	/* Radio-Text */
66 #define V4L2_RDS_TIME		0x200	/* Date and Time information */
67 #define V4L2_RDS_TMC		0x400	/* TMC availability */
68 #define V4L2_RDS_AF		0x800	/* AF (alternative freq) available */
69 #define V4L2_RDS_ECC		0x1000	/* Extended County Code */
70 #define V4L2_RDS_LC		0x2000	/* Language Code */
71 #define V4L2_RDS_TMC_SG		0x4000	/* RDS-TMC single group */
72 #define V4L2_RDS_TMC_MG		0x8000	/* RDS-TMC multi group */
73 #define V4L2_RDS_TMC_SYS	0x10000	/* RDS-TMC system information */
74 #define V4L2_RDS_EON		0x20000	/* Enhanced Other Network Info */
75 #define V4L2_RDS_LSF		0x40000	/* Linkage information */
76 #define V4L2_RDS_TMC_TUNING	0x80000	/* RDS-TMC tuning information */
77 
78 /* Define Constants for the state of the RDS decoding process
79  * used to address the relevant bit in the decode_information bitmask */
80 #define V4L2_RDS_GROUP_NEW 	0x01	/* New group received */
81 #define V4L2_RDS_ODA		0x02	/* Open Data Group announced */
82 
83 /* Decoder Information (DI) codes
84  * used to decode the DI information according to the RDS standard */
85 #define V4L2_RDS_FLAG_STEREO 		0x01
86 #define V4L2_RDS_FLAG_ARTIFICIAL_HEAD	0x02
87 #define V4L2_RDS_FLAG_COMPRESSED	0x04
88 #define V4L2_RDS_FLAG_DYNAMIC_PTY	0x08
89 
90 /* TMC related codes
91  * used to extract TMC fields from RDS-TMC groups
92  * see ISO 14819-1:2003, Figure 2 - RDS-TMC single-grp full message structure */
93 #define V4L2_TMC_TUNING_INFO	0x10	/* Bit 4 indicates Tuning Info / User msg */
94 #define V4L2_TMC_SINGLE_GROUP	0x08	/* Bit 3 indicates Single / Multi-group msg */
95 
96 /* struct to encapsulate one complete RDS group */
97 /* This structure is used internally to store data until a complete RDS
98  * group was received and group id dependent decoding can be done.
99  * It is also used to provide external access to uninterpreted RDS groups
100  * when manual decoding is required (e.g. special ODA types) */
101 struct v4l2_rds_group {
102 	uint16_t pi;		/* Program Identification */
103 	char group_version;	/* group version ('A' / 'B') */
104 	uint8_t group_id;	/* group number (0..16) */
105 
106 	/* uninterpreted data blocks for decoding (e.g. ODA) */
107 	uint8_t data_b_lsb;
108 	uint8_t data_c_msb;
109 	uint8_t data_c_lsb;
110 	uint8_t data_d_msb;
111 	uint8_t data_d_lsb;
112 };
113 
114 /* struct to encapsulate some statistical information about the decoding process */
115 struct v4l2_rds_statistics {
116 	uint32_t block_cnt;		/* total amount of received blocks */
117 	uint32_t group_cnt;		/* total amount of successfully
118 					 * decoded groups */
119 	uint32_t block_error_cnt;	/* blocks that were marked as erroneous
120 					 * and had to be dropped */
121 	uint32_t group_error_cnt;	/* group decoding processes that had to be
122 					 * aborted because of erroneous blocks
123 					 * or wrong order of blocks */
124 	uint32_t block_corrected_cnt;	/* blocks that contained 1-bit errors
125 					 * which were corrected */
126 	uint32_t group_type_cnt[16];	/* number of occurrence for each
127 					 * defined RDS group */
128 };
129 
130 /* struct to encapsulate the definition of one ODA (Open Data Application) type */
131 struct v4l2_rds_oda {
132 	uint8_t group_id;	/* RDS group used to broadcast this ODA */
133 	char group_version;	/* group version (A / B) for this ODA */
134 	uint16_t aid;		/* Application Identification for this ODA,
135 				 * AIDs are centrally administered by the
136 				 * RDS Registration Office (rds.org.uk) */
137 };
138 
139 /* struct to encapsulate an array of all defined ODA types for a channel */
140 /* This structure will grow with ODA announcements broadcasted in type 3A
141  * groups, that were verified not to be no duplicates or redefinitions */
142 struct v4l2_rds_oda_set {
143 	uint8_t size;		/* number of ODAs defined by this channel */
144 	struct v4l2_rds_oda oda[MAX_ODA_CNT];
145 };
146 
147 /* struct to encapsulate an array of Alternative Frequencies for a channel */
148 /* Every channel can send out AFs for his program. The number of AFs that
149  * will be broadcasted is announced by the channel */
150 struct v4l2_rds_af_set {
151 	uint8_t size;			/* size of the set (might be smaller
152 					 * than the announced size) */
153 	uint8_t announced_af;		/* number of announced AF */
154 	uint32_t af[MAX_AF_CNT];	/* AFs defined in Hz */
155 };
156 
157 /* struct to encapsulate one entry in the EON table (Enhanced Other Network) */
158 struct v4l2_rds_eon {
159 	uint32_t valid_fields;
160 	uint16_t pi;
161 	uint8_t ps[9];
162 	uint8_t pty;
163 	bool ta;
164 	bool tp;
165 	uint16_t lsf;		/* Linkage Set Number */
166 	struct v4l2_rds_af_set af;
167 };
168 
169 /* struct to encapsulate a table of EON information */
170 struct v4l2_rds_eon_set {
171 	uint8_t size;		/* size of the table */
172 	uint8_t index;		/* current position in the table */
173 	struct v4l2_rds_eon eon[MAX_EON_CNT];	/* Information about other
174 						 * radio channels */
175 };
176 
177 /* struct to encapsulate alternative frequencies (AFs) for RDS-TMC stations.
178  * AFs listed in af[] can be used unconditionally.
179  * AFs listed in mapped_af[n] should only be used if the current
180  * tuner frequency matches the value in mapped_af_tuning[n] */
181 struct v4l2_tmc_alt_freq {
182 	uint8_t af_size;		/* number of known AFs */
183 	uint8_t af_index;
184 	uint8_t mapped_af_size;		/* number of mapped AFs */
185 	uint8_t mapped_af_index;
186 	uint32_t af[MAX_TMC_AF_CNT];		/* AFs defined in Hz */
187 	uint32_t mapped_af[MAX_TMC_AF_CNT];		/* mapped AFs defined in Hz */
188 	uint32_t mapped_af_tuning[MAX_TMC_AF_CNT];	/* mapped AFs defined in Hz */
189 };
190 
191 /* struct to encapsulate information about stations carrying RDS-TMC services */
192 struct v4l2_tmc_station {
193 	uint16_t pi;
194 	uint8_t ltn;	/* database-ID of ON */
195 	uint8_t msg;	/* msg parameters of ON */
196 	uint8_t sid;	/* service-ID of ON */
197 	struct v4l2_tmc_alt_freq afi;
198 };
199 
200 /* struct to encapsulate tuning information for TMC */
201 struct v4l2_tmc_tuning {
202 	uint8_t station_cnt;	/* number of announced alternative stations */
203 	uint8_t index;
204 	struct v4l2_tmc_station station[MAX_TMC_ALT_STATIONS];	/* information
205 							* about other stations carrying the same RDS-TMC service */
206 };
207 
208 /* struct to encapsulate an additional data field in a TMC message */
209 struct v4l2_tmc_additional {
210 	uint8_t label;
211 	uint16_t data;
212 };
213 
214 /* struct to encapsulate an arbitrary number of additional data fields
215  * belonging to one TMC message */
216 struct v4l2_tmc_additional_set {
217 	uint8_t size;
218 	struct v4l2_tmc_additional fields[MAX_TMC_ADDITIONAL];
219 };
220 
221 /* struct to encapsulate a decoded TMC message with optional additional
222  * data field (in case of a multi-group TMC message) */
223 struct v4l2_rds_tmc_msg {
224 	uint8_t length;	/* length of multi-group message (0..4) */
225 	uint8_t sid;		/* service identifier at time of reception */
226 	uint8_t extent;
227 	uint8_t dp;		/* duration and persistence */
228 	uint16_t event;		/* TMC event code */
229 	uint16_t location;	/* TMC event location */
230 	bool follow_diversion;	/* indicates if the driver is adviced to
231 				 * follow the diversion */
232 	bool neg_direction;	/* indicates negative / positive direction */
233 
234 	/* decoded additional information (only available in multi-group
235 	 * messages) */
236 	struct v4l2_tmc_additional_set additional;
237 };
238 
239 /* struct to encapsulate all TMC related information, including TMC System
240  * Information, TMC Tuning information and a buffer for the last decoded
241  * TMC messages */
242 struct v4l2_rds_tmc {
243 	uint8_t ltn;		/* location_table_number */
244 	bool afi;		/* alternative frequency indicator */
245 	bool enhanced_mode;	/* mode of transmission,
246 				 * if false -> basic => gaps between tmc groups
247 				 * gap defines timing behavior
248 				 * if true -> enhanced => t_a, t_w and t_d
249 				 * define timing behavior of tmc groups */
250 	uint8_t mgs;		/* message geographical scope */
251 	uint8_t sid;		/* service identifier (unique ID on national level) */
252 	uint8_t gap;		/* Gap parameters */
253 	uint8_t t_a;		/* activity time (only if mode = enhanced) */
254 	uint8_t t_w;		/* window time (only if mode = enhanced */
255 	uint8_t t_d;		/* delay time (only if mode = enhanced */
256 	uint8_t spn[9];		/* service provider name */
257 	struct v4l2_rds_tmc_msg tmc_msg;
258 
259 	/* tuning information for alternative service providers */
260 	struct v4l2_tmc_tuning tuning;
261 };
262 
263 /* struct to encapsulate state and RDS information for current decoding process */
264 /* This is the structure that will be used by external applications, to
265  * communicate with the library and get access to RDS data */
266 struct v4l2_rds {
267 	/** state information **/
268 	uint32_t decode_information;	/* state of decoding process */
269 	uint32_t valid_fields;		/* currently valid info fields
270 					 * of this structure */
271 
272 	/** RDS info fields **/
273 	bool is_rbds; 		/* use RBDS standard version of LUTs */
274 	uint16_t pi;		/* Program Identification */
275 	uint8_t ps[9];		/* Program Service Name, UTF-8 encoding,
276 				 * '\0' terminated */
277 	uint8_t pty;		/* Program Type */
278 	uint8_t ptyn[9];	/* Program Type Name, UTF-8 encoding,
279 				 * '\0' terminated */
280 	bool ptyn_ab_flag;	/* PTYN A/B flag (toggled), to signal
281 				 * change of PTYN */
282 	uint8_t rt_length;	/* length of RT string */
283 	uint8_t rt[65];		/* Radio-Text string, UTF-8 encoding,
284 				 * '\0' terminated */
285 	bool rt_ab_flag;	/* RT A/B flag (toggled), to signal
286 				 * transmission of new RT */
287 	bool ta;		/* Traffic Announcement */
288 	bool tp;		/* Traffic Program */
289 	bool ms;		/* Music / Speech flag */
290 	uint8_t di;		/* Decoder Information */
291 	uint8_t ecc;		/* Extended Country Code */
292 	uint8_t lc;		/* Language Code */
293 	time_t time;		/* local time and date of transmission */
294 
295 	struct v4l2_rds_statistics rds_statistics;
296 	struct v4l2_rds_oda_set rds_oda;	/* Open Data Services */
297 	struct v4l2_rds_af_set rds_af; 		/* Alternative Frequencies */
298 	struct v4l2_rds_eon_set rds_eon;	/* EON information */
299 	struct v4l2_rds_tmc tmc;		/* TMC information */
300 };
301 
302 /* v4l2_rds_init() - initializes a new decoding process
303  * @is_rbds:	defines which standard is used: true=RBDS, false=RDS
304  *
305  * initialize a new instance of the RDS-decoding struct and return
306  * a handle containing state and RDS information, used to interact
307  * with the library functions */
308 LIBV4L_PUBLIC struct v4l2_rds *v4l2_rds_create(bool is_rbds);
309 
310 /* frees all memory allocated for the RDS-decoding struct */
311 LIBV4L_PUBLIC void v4l2_rds_destroy(struct v4l2_rds *handle);
312 
313 /* resets the RDS information in the handle to initial values
314  * e.g. can be used when radio channel is changed
315  * @reset_statistics:	true = set all statistic values to 0, false = keep them untouched */
316 LIBV4L_PUBLIC void v4l2_rds_reset(struct v4l2_rds *handle, bool reset_statistics);
317 
318 /* adds a raw RDS block to decode it into RDS groups
319  * @return:	bitmask with with updated fields set to 1
320  * @rds_data: 	3 bytes of raw RDS data, obtained by calling read()
321  * 				on RDS capable V4L2 devices */
322 LIBV4L_PUBLIC uint32_t v4l2_rds_add(struct v4l2_rds *handle, struct v4l2_rds_data *rds_data);
323 
324 /*
325  * group of functions to translate numerical RDS data into strings
326  *
327  * return program description string defined in the RDS/RBDS Standard
328  * ! return value depends on selected Standard !*/
329 LIBV4L_PUBLIC const char *v4l2_rds_get_pty_str(const struct v4l2_rds *handle);
330 LIBV4L_PUBLIC const char *v4l2_rds_get_language_str(const struct v4l2_rds *handle);
331 LIBV4L_PUBLIC const char *v4l2_rds_get_country_str(const struct v4l2_rds *handle);
332 LIBV4L_PUBLIC const char *v4l2_rds_get_coverage_str(const struct v4l2_rds *handle);
333 
334 /* returns a pointer to the last decoded RDS group, in order to give raw
335  * access to RDS data if it is required (e.g. ODA decoding) */
336 LIBV4L_PUBLIC const struct v4l2_rds_group *v4l2_rds_get_group
337 	(const struct v4l2_rds *handle);
338 
339 
340 #ifdef __cplusplus
341 }
342 #endif /* __cplusplus */
343 #endif
344