RFC: Completing the V4L2 RDS API ================================ Introduction ------------ There are several drivers that implement RDS support: bttv (through saa6588), radio-si470x and radio-cadet. radio-tea5764 wants to support this in the future as well. The saa6588 is used in different cards, but is currently only enabled in bttv, but I have it working with a saa7134 as well. I expect this to become more important with the increased use of linux and v4l2 in embedded devices. What is holding it back at the moment is the fact that this interface has not been defined properly. It's 90% there, but it is poorly documented and is still not officially part of V4L2. This RFC is intended to fill in the final gaps and make it official. Current API ----------- The V4L2 spec says this about the RDS Interface: 4.11. RDS Interface The Radio Data System transmits supplementary information in binary format, for example the station name or travel information, on a inaudible audio subcarrier of a radio program. This interface aims at devices capable of receiving and decoding RDS information. The V4L API defines its RDS API as follows. >From radio devices supporting it, RDS data can be read with the read() function. The data is packed in groups of three, as follows: First Octet: Least Significant Byte of RDS Block Second Octet: Most Significant Byte of RDS Block Third Octet: Bit 7: Error bit. Indicates that an uncorrectable error occurred during reception of this block. Bit 6: Corrected bit. Indicates that an error was corrected for this data block. Bits 5-3: Received Offset. Indicates the offset received by the sync system. Bits 2-0: Offset Name. Indicates the offset applied to this data. It was argued the RDS API should be extended before integration into V4L2, no new API has been devised yet. Please write to the linux-media mailing list for discussion: http://www.linuxtv.org/lists.php. Meanwhile no V4L2 driver should set the V4L2_CAP_RDS_CAPTURE capability flag. Problems with this API ---------------------- As I said before, it is 90% complete, there are just a few things missing. The Offset Name refers to six possible offsets as defined by the RDS and RBDS standard (that is the US variant of RDS). Possible offsets are: A, B, C, C', D and E (RBDS specific). The mapping of the values 0-7 to offsets is as follows: 0: A 1: B 2: C 3: D 4: C' 5: E (RBDS specific) 6: invalid block E (RDS mode) 7: invalid block This mapping comes from the saa6588 RDS decoder, but it makes sense and I see no reason to change this. As long as we document it and add a public RDS header with this information. The original mapping was from the radio-cadet.c driver. Unfortunately, it was never documented and I cannot find any details on what the mapping between number and offset code looks like. Since the cadet is an ISA card I am not too worried about this and I'm following the newer devices. After a lot of googling I found this ancient radio-cadet posting: http://lkml.indiana.edu/hypermail/linux/kernel/9904.0/0609.html This finally explained what the difference between the Received Offset and the Offset Name is: "Bits 5-3: Received Offset. Indicates the block offset received by the decoder hardware (used to determine the location of the block in a RDS group). Bits 2-0: Offset Name. Indicates the block offset applied by the decoder. (In some cases, the hardware may try to second-guess the received values to try to overcome poor reception conditions)." Currently all other RDS implementations just make a copy of bits 2-0 and the rdsd daemon (http://rdsd.berlios.de/) uses only bits 2-0. I would like to change the definition of these bits, setting bits 5-3 to 0. This way we have three bits available for future enhancements. I see no advantage in having two offsets. Just pick the one the decoder gives you. Another problem is that there is no good method of selecting RDS vs RBDS, or checking which of these two (or both) are available. I propose to use the v4l2_tuner struct for this. It is an obvious match since the ability to read RDS is tuner related (no tuner, no RDS :-) ). The v4l2_tuner capability field needs two additional caps: V4L2_TUNER_CAP_RDS V4L2_TUNER_CAP_RBDS And we can add support to select RDS/RDBS by using one of the reserved fields: __u8 rds_type; __u8 rds_signal; /* RDS signal strength quality, 0-255 */ __u8 rds_reserved[2]; __u32 reserved[3]; And rds_type is: V4L2_TUNER_RDS_TYPE_RDS 0x00 V4L2_TUNER_RDS_TYPE_RBDS 0x01 We can also add new subband flags V4L2_TUNER_SUB_RDS and V4L2_TUNER_SUB_RBSD so we can report if RDS/RBDS is present. I do not think there is any need to introduce an additional V4L2_CAP_RDS_CAPTURE capability, since it is taken care of in v4l2_tuner. Finally I would prefer to have the requirement that the driver will buffer at least 10 seconds worth of data (comes to 1200 bytes). Or perhaps we should add a field that reports the maximum number of buffered packets? E.g. __u16 rds_buf_size. This might be more generic and you can even allow this to be set with VIDIOC_S_TUNER (although drivers can ignore it). With these small changes I think the RDS API is pretty complete and can become an official V4L2 API. Comments? Hans Verkuil -- Hans Verkuil - video4linux developer - sponsored by TANDBERG -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html