Re: RFC: Finalizing the V4L2 RDS interface

2009-02-14 Thread Hans Verkuil
On Saturday 14 February 2009 01:42:31 Trent Piepho wrote:
 On Fri, 13 Feb 2009, Hans Verkuil wrote:
  On Friday 13 February 2009 22:15:45 Mauro Carvalho Chehab wrote:
   On Fri, 13 Feb 2009 09:55:19 +0100
  
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.

 What device file does one read from, the radio device or is there another
 one for RDS data?

The radio device.

 If the radio device, then maybe it should handle (S|G|TRY)_FMT ioctls, so
 that one can select the format.  Since the drivers probably already use
 v4l2_ioctl, this should be easy enough to do.

 Some hardware might produce at a higher or lower level in the decoding
 stack that just doesn't fit this format.

 For instance, the common cx88 chip has some sort of RDS decoding ability.
 I think it returns 36 kHz 16 bit I/Q data from the RDS carrier that
 something like gnuradio would need to demodulate.  That's a completely
 different format that this one.  Though I think it might make more sense
 to use ALSA to get data in this format.

Hmm, basically raw RDS data. Interesting.

I'll look into this. It certainly makes it a lot more future-proof by using 
the FMT ioctls.

And we can add support to select RDS/RDBS by using one of the
reserved fields:
   
__u8rds_type;
__u8rds_signal; /* RDS signal strength quality, 0-255 */
__u8rds_reserved[2];
__u32   reserved[3];

 Do any devices support returning signal strength or quality?  If so, can
 we get real units from them?

The saa6588 support has a register containing the signal quality, but there 
are no units attached to that. Just a value 0-15.

And rds_type is:
   
V4L2_TUNER_RDS_TYPE_RDS   0x00
V4L2_TUNER_RDS_TYPE_RBDS  0x01

 Is it necessary to make a distinction between RDS and RBDS?

I need to do a bit more research, but I'm fairly confident that the answer 
is yes. The saa6588 requires you to set it, the si470x seems to handle only 
the RDS subset of RBDS (no support for block E as far as I could see).

Note that I modified the types to:

V4L2_TUNER_RDS_TYPE_NONE  0x00
V4L2_TUNER_RDS_TYPE_RDS   0x01
V4L2_TUNER_RDS_TYPE_RBDS  0x02

This field is currently always 0, so that should indicate no RDS. In 
addition, it might be useful to have the option to turn off RDS decoding to 
save resources if you do not need it.

Finally I would prefer to have the requirement that the driver will
buffer at least 10 seconds worth of data (comes to 1200 bytes).
  
   Why? IMO, this seems to be something that should be a requirement at
   user side, not at kernel side: After changing from one station to
   another, and start receiving RDS/RBDS, wait for some time before
   output the data.
  
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).
  
   Why to spend 16 bits for it? It seems easier to check for for the
   amount of received packets on userspace. I think we should avoid to
   waste those reserved bytes.
 
  Hmm, I'm too creative here, I agree. Let's keep it simple.

 It would nice if there was a way to flush the buffer.  When changing
 channels, I imaging software would like to be sure that it does not
 receive stale data from the previous channel.  Maybe just define that
 changing frequencies empties the buffer?  Keep in mind, there could be
 data sitting in an on card buffer waiting for DMA, or DMAed data waiting
 for the IRQ handler to processes it.  So just calling read() could easily
 not give you all data received prior to calling read().

Good point. Changing frequencies or input should flush any internal buffers. 
I think that it is overkill to add an option to explicitly flush buffers. 
It can always be added later if needed.

Regards,

Hans

-- 
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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RFC: Finalizing the V4L2 RDS interface

2009-02-13 Thread Hans Verkuil
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:

__u8rds_type;
__u8rds_signal; /* RDS signal strength quality, 0-255 */
__u8rds_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 

Re: RFC: Finalizing the V4L2 RDS interface

2009-02-13 Thread Mauro Carvalho Chehab
On Fri, 13 Feb 2009 09:55:19 +0100
Hans Verkuil hverk...@xs4all.nl wrote:

 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.

This would be an userspace API breakage. I can't see any gain on doing this.
Are you needing those bytes for some usage?


IMO, I would describe those bits at the API, marking it with a flag stating
that this its usage is deprecated, recommending to not use. Let's see if
someone will complain. We can keep this as-is until we need, but, in this case,
we need to properly document that it will be removed in some future.

 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 

Re: RFC: Finalizing the V4L2 RDS interface

2009-02-13 Thread Hans Verkuil
On Friday 13 February 2009 22:15:45 Mauro Carvalho Chehab wrote:
 On Fri, 13 Feb 2009 09:55:19 +0100

 Hans Verkuil hverk...@xs4all.nl wrote:
  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.

 This would be an userspace API breakage. I can't see any gain on doing
 this. Are you needing those bytes for some usage?


 IMO, I would describe those bits at the API, marking it with a flag
 stating that this its usage is deprecated, recommending to not use. Let's
 see if someone will complain. We can keep this as-is until we need, but,
 in this case, we need to properly document that it will be removed in
 some future.

I can live with that.

  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 

Re: RFC: Finalizing the V4L2 RDS interface

2009-02-13 Thread Mauro Carvalho Chehab
On Fri, 13 Feb 2009 22:59:07 +0100
Hans Verkuil hverk...@xs4all.nl wrote:

   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).
 
  Why to spend 16 bits for it? It seems easier to check for for the amount
  of received packets on userspace. I think we should avoid to waste those
  reserved bytes.
 
 Hmm, I'm too creative here, I agree. Let's keep it simple.

Ok.

 I realized that we also need to make a note that no RDS *encoder* interface 
 has yet been designed, and that anyone interested should contact 
 linux-media. Any encoder interface would probably be very similar, except 
 using write() instead of read().

There are some interests on RDS encoder also. Someone contacted me about that
sometime ago. I suspect that a few more is needed than just write().

 BTW, do you think that drivers that can do RDS should set 
 V4L2_CAP_RDS_CAPTURE in addition to the v4l2_tuner caps? I'm leaning 
 towards a 'yes' here. It's already defined, so there might be some apps 
 that already use this define, and it might be a useful high-level 
 capability anyway.

I think so.

Cheers,
Mauro
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: RFC: Finalizing the V4L2 RDS interface

2009-02-13 Thread Trent Piepho
On Fri, 13 Feb 2009, Hans Verkuil wrote:
 On Friday 13 February 2009 22:15:45 Mauro Carvalho Chehab wrote:
  On Fri, 13 Feb 2009 09:55:19 +0100
   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.

What device file does one read from, the radio device or is there another
one for RDS data?

If the radio device, then maybe it should handle (S|G|TRY)_FMT ioctls, so
that one can select the format.  Since the drivers probably already use
v4l2_ioctl, this should be easy enough to do.

Some hardware might produce at a higher or lower level in the decoding
stack that just doesn't fit this format.

For instance, the common cx88 chip has some sort of RDS decoding ability.
I think it returns 36 kHz 16 bit I/Q data from the RDS carrier that
something like gnuradio would need to demodulate.  That's a completely
different format that this one.  Though I think it might make more sense to
use ALSA to get data in this format.

   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];

Do any devices support returning signal strength or quality?  If so, can we
get real units from them?

   And rds_type is:
  
   V4L2_TUNER_RDS_TYPE_RDS   0x00
   V4L2_TUNER_RDS_TYPE_RBDS  0x01

Is it necessary to make a distinction between RDS and RBDS?

   Finally I would prefer to have the requirement that the driver will
   buffer at least 10 seconds worth of data (comes to 1200 bytes).
 
  Why? IMO, this seems to be something that should be a requirement at user
  side, not at kernel side: After changing from one station to another, and
  start receiving RDS/RBDS, wait for some time before output the data.
 
   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).
 
  Why to spend 16 bits for it? It seems easier to check for for the amount
  of received packets on userspace. I think we should avoid to waste those
  reserved bytes.

 Hmm, I'm too creative here, I agree. Let's keep it simple.

It would nice if there was a way to flush the buffer.  When changing
channels, I imaging software would like to be sure that it does not receive
stale data from the previous channel.  Maybe just define that changing
frequencies empties the buffer?  Keep in mind, there could be data sitting
in an on card buffer waiting for DMA, or DMAed data waiting for the IRQ
handler to processes it.  So just calling read() could easily not give you
all data received prior to calling read().
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html