diff mbox

[42/44] bebob/firewire-lib: Add a quirk of wrong dbc in empty packet for M-Audio special Firewire series

Message ID 1395400229-22957-43-git-send-email-o-takashi@sakamocchi.jp (mailing list archive)
State Superseded
Headers show

Commit Message

Takashi Sakamoto March 21, 2014, 11:10 a.m. UTC
M-Audio Firewire 1814 has a quirk, ProjectMix I/O also has. They transmit
empty packet with wrong value of dbc incremented by 8 at high sampling rate.
According to IEC 61883-1, this value should be the same as the one in
previous packet.

This commit adds a flag named as CIP_EMPTY_HAS_WRONG_DBC. With flag, the value
of dbc in empty packet is overwittern by the one in expected value.

This is an example of this quirk:
CIP Header 0	CIP Header 1	Payload size
010D0000	9004F759	210
010D0010	90040B59	210
010D0020	90042359	210
01020028	9004FFFF	2  <-
010D0030	90043759	210
010D0040	90044B59	210
010D0050	90046359	210
01020058	9004FFFF	2  <-
010D0060	90047759	210
010D0070	90048B59	210
010D0080	9004A359	210
01020088	9004FFFF	2  <-
010D0090	9004B759	210
010D00A0	9004CB59	210
010D00B0	9004E359	210
010200B8	9004FFFF	2  <-
010D00C0	9004F759	210
010D00D0	90040B59	210
010D00E0	90042359	210

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 sound/firewire/amdtp.c              | 2 ++
 sound/firewire/amdtp.h              | 3 +++
 sound/firewire/bebob/bebob_stream.c | 7 +++++++
 3 files changed, 12 insertions(+)

Comments

Takashi Sakamoto March 23, 2014, 2:16 a.m. UTC | #1
I realize this patch includes a bug to cause wrong detection of packet 
discontinuity.

> @@ -745,6 +745,8 @@ static void handle_in_packet(struct amdtp_stream *s,
>
>   	/* Check data block counter continuity */
>   	data_block_counter = cip_header[0] & AMDTP_DBC_MASK;
> +	if (data_blocks == 0 && (s->flags & CIP_EMPTY_HAS_WRONG_DBC))
> +		data_block_counter = s->data_block_counter;
>   	if (!(s->flags & CIP_DBC_IS_END_EVENT)) {
>   		lost = data_block_counter != s->data_block_counter;
>   	} else {

These lines should be:

 > +	if (data_blocks == 0 && (s->flags & CIP_EMPTY_HAS_WRONG_DBC) &&
 > +         s->data_block_counter != UINT_MAX)
 > +		data_block_counter = s->data_block_counter;


When CIP_SKIP_INIT_DBC_CHECK is enabled, initial value of 
s->data_block_counter is set to UINT_MAX. An intention of this is to 
skip detecting discontinuity for a first packet [31/44].

This initial value has a bad effect when CIP_EMPTY_HAS_WRONG_DBC is enabled.

A first packet is an empty packet. When this packet is handled, 
data_block_counter is set to initial value of s->data_block_counter 
(UINT_MAX). Later, s->data_block_counter is set to 0xff with bitmask in 
below lines.

         if (s->flags & CIP_DBC_IS_END_EVENT)
                 s->data_block_counter = data_block_counter;
         else
                 s->data_block_counter =
                                 (data_block_counter + data_blocks) & 0xff;

When a packet with data blocks is handled later, s->data_block_counter 
is 0xff, not UINT_MAX. This causes discontinuity detection because this 
packet has 0x00 in itx dbc in below lines.

         if (lost && s->data_block_counter != UINT_MAX) {
                 dev_info(&s->unit->device,
                          "Detect discontinuity of CIP: %02X %02X\n",
                          s->data_block_counter, data_block_counter);

See this log:
[ 2933.102892] 01020000 9002FFFF 02
[ 2933.102894] 01020000 9002FFFF 02
[ 2933.102896] 01020000 9002FFFF 02
[ 2933.102899] 01020000 9002FFFF 02
[ 2933.102901] 01020000 9002FFFF 02
[ 2933.102903] 01020000 9002FFFF 02
[ 2933.104871] 01110000 900258B5 8A
[ 2933.104877] snd-bebob fw1.0: Detect discontinuity of CIP: FF 00

I'm sorry to post a patch including a bug.


Regards

Takashi Sakamoto
o-takashi@sakamocchi.jp
Takashi Sakamoto March 24, 2014, 2:52 a.m. UTC | #2
Hi Euan,

Thanks for your testing.

(Mar 24 2014 10:41), Euan de Kock wrote:
> Thanks for the update. This bit me last night, and I just commented out
> the check to keep working.
>
> I'll try and retest it tonight with this version. (On a Echo Audiofire
> Pre8 with firmware < 5)
>
> Regards,
>
> Euan deKock.

When reading this message, I wondered why this bug affects driving on 
Echo AudioFirePre8.
As describing the title, this affects a part of BeBoB based devices.

Did you test with M-Audio Firewire 1814 or M-Audio ProjectMix I/O?

If not, it may be a bug for Fireworks driver. Then please send me output 
from:
/proc/asound/cardX/firewire/*. (The 'cardX' should be for your device.)


Thanks

Takashi Sakamoto
o-takashi@sakamocchi.jp
diff mbox

Patch

diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c
index 820d790..c443a3a 100644
--- a/sound/firewire/amdtp.c
+++ b/sound/firewire/amdtp.c
@@ -745,6 +745,8 @@  static void handle_in_packet(struct amdtp_stream *s,
 
 	/* Check data block counter continuity */
 	data_block_counter = cip_header[0] & AMDTP_DBC_MASK;
+	if (data_blocks == 0 && (s->flags & CIP_EMPTY_HAS_WRONG_DBC))
+		data_block_counter = s->data_block_counter;
 	if (!(s->flags & CIP_DBC_IS_END_EVENT)) {
 		lost = data_block_counter != s->data_block_counter;
 	} else {
diff --git a/sound/firewire/amdtp.h b/sound/firewire/amdtp.h
index e3ee739..7981f4d 100644
--- a/sound/firewire/amdtp.h
+++ b/sound/firewire/amdtp.h
@@ -29,6 +29,8 @@ 
  *	The value of data_block_quadlets is used instead of reported value.
  * @CIP_SKIP_INIT_DBC_CHECK: Only for in-stream. The value of dbc in first
  *	packet is not continuous from an initial value.
+ * @CIP_EMPTY_HAS_WRONG_DBC: Only for in-stream. The value of dbc in empty
+ *	packet is wrong but the others are correct.
  */
 enum cip_flags {
 	CIP_NONBLOCKING		= 0x00,
@@ -39,6 +41,7 @@  enum cip_flags {
 	CIP_DBC_IS_END_EVENT	= 0x10,
 	CIP_WRONG_DBS		= 0x20,
 	CIP_SKIP_INIT_DBC_CHECK	= 0x40,
+	CIP_EMPTY_HAS_WRONG_DBC	= 0x80,
 };
 
 /**
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c
index 95d82f4..5be82f1 100644
--- a/sound/firewire/bebob/bebob_stream.c
+++ b/sound/firewire/bebob/bebob_stream.c
@@ -436,6 +436,13 @@  int snd_bebob_stream_init_duplex(struct snd_bebob *bebob)
 	}
 	/* See comments in next function */
 	bebob->tx_stream.flags |= CIP_SKIP_INIT_DBC_CHECK;
+	/*
+	 * At high sampling rate, M-Audio special firmware transmits empty
+	 * packet with the value of dbc incremented by 8 but the others are
+	 * valid to IEC 61883-1.
+	 */
+	if (bebob->maudio_special_quirk)
+		bebob->tx_stream.flags |= CIP_EMPTY_HAS_WRONG_DBC;
 
 	err = amdtp_stream_init(&bebob->rx_stream, bebob->unit,
 				AMDTP_OUT_STREAM, CIP_BLOCKING);