mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 09:19:51 +00:00
ALSA: firewire-lib: split helper function to check incoming CIP header
A parser for CIP header in incoming packet is enough large. This commit splits it into a helper function to better looks of packet handler. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
8a400b9996
commit
e335425b65
1 changed files with 60 additions and 40 deletions
|
@ -549,29 +549,19 @@ static int handle_out_packet_without_header(struct amdtp_stream *s,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle,
|
||||
const __be32 *ctx_header, __be32 *buffer,
|
||||
unsigned int index)
|
||||
static int check_cip_header(struct amdtp_stream *s, const __be32 *buf,
|
||||
unsigned int payload_length,
|
||||
unsigned int *data_blocks, unsigned int *syt)
|
||||
{
|
||||
unsigned int payload_length;
|
||||
u32 cip_header[2];
|
||||
unsigned int sph, fmt, fdf, syt;
|
||||
unsigned int data_block_quadlets, data_block_counter, dbc_interval;
|
||||
unsigned int data_blocks;
|
||||
struct snd_pcm_substream *pcm;
|
||||
unsigned int pcm_frames;
|
||||
unsigned int sph;
|
||||
unsigned int fmt;
|
||||
unsigned int fdf;
|
||||
unsigned int data_block_counter;
|
||||
bool lost;
|
||||
|
||||
payload_length = be32_to_cpu(ctx_header[0]) >> ISO_DATA_LENGTH_SHIFT;
|
||||
if (payload_length > s->ctx_data.tx.max_payload_length) {
|
||||
dev_err(&s->unit->device,
|
||||
"Detect jumbo payload: %04x %04x\n",
|
||||
payload_length, s->ctx_data.tx.max_payload_length);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
cip_header[0] = be32_to_cpu(buffer[0]);
|
||||
cip_header[1] = be32_to_cpu(buffer[1]);
|
||||
cip_header[0] = be32_to_cpu(buf[0]);
|
||||
cip_header[1] = be32_to_cpu(buf[1]);
|
||||
|
||||
/*
|
||||
* This module supports 'Two-quadlet CIP header with SYT field'.
|
||||
|
@ -583,9 +573,7 @@ static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle,
|
|||
dev_info_ratelimited(&s->unit->device,
|
||||
"Invalid CIP header for AMDTP: %08X:%08X\n",
|
||||
cip_header[0], cip_header[1]);
|
||||
data_blocks = 0;
|
||||
pcm_frames = 0;
|
||||
goto end;
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
/* Check valid protocol or not. */
|
||||
|
@ -595,19 +583,17 @@ static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle,
|
|||
dev_info_ratelimited(&s->unit->device,
|
||||
"Detect unexpected protocol: %08x %08x\n",
|
||||
cip_header[0], cip_header[1]);
|
||||
data_blocks = 0;
|
||||
pcm_frames = 0;
|
||||
goto end;
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
/* Calculate data blocks */
|
||||
fdf = (cip_header[1] & CIP_FDF_MASK) >> CIP_FDF_SHIFT;
|
||||
if (payload_length < 12 ||
|
||||
if (payload_length < sizeof(__be32) * 2 ||
|
||||
(fmt == CIP_FMT_AM && fdf == AMDTP_FDF_NO_DATA)) {
|
||||
data_blocks = 0;
|
||||
*data_blocks = 0;
|
||||
} else {
|
||||
data_block_quadlets =
|
||||
(cip_header[0] & CIP_DBS_MASK) >> CIP_DBS_SHIFT;
|
||||
unsigned int data_block_quadlets =
|
||||
(cip_header[0] & CIP_DBS_MASK) >> CIP_DBS_SHIFT;
|
||||
/* avoid division by zero */
|
||||
if (data_block_quadlets == 0) {
|
||||
dev_err(&s->unit->device,
|
||||
|
@ -618,13 +604,13 @@ static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle,
|
|||
if (s->flags & CIP_WRONG_DBS)
|
||||
data_block_quadlets = s->data_block_quadlets;
|
||||
|
||||
data_blocks = (payload_length / 4 - 2) /
|
||||
*data_blocks = (payload_length / sizeof(__be32) - 2) /
|
||||
data_block_quadlets;
|
||||
}
|
||||
|
||||
/* Check data block counter continuity */
|
||||
data_block_counter = cip_header[0] & CIP_DBC_MASK;
|
||||
if (data_blocks == 0 && (s->flags & CIP_EMPTY_HAS_WRONG_DBC) &&
|
||||
if (*data_blocks == 0 && (s->flags & CIP_EMPTY_HAS_WRONG_DBC) &&
|
||||
s->data_block_counter != UINT_MAX)
|
||||
data_block_counter = s->data_block_counter;
|
||||
|
||||
|
@ -635,10 +621,12 @@ static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle,
|
|||
} else if (!(s->flags & CIP_DBC_IS_END_EVENT)) {
|
||||
lost = data_block_counter != s->data_block_counter;
|
||||
} else {
|
||||
if (data_blocks > 0 && s->ctx_data.tx.dbc_interval > 0)
|
||||
unsigned int dbc_interval;
|
||||
|
||||
if (*data_blocks > 0 && s->ctx_data.tx.dbc_interval > 0)
|
||||
dbc_interval = s->ctx_data.tx.dbc_interval;
|
||||
else
|
||||
dbc_interval = data_blocks;
|
||||
dbc_interval = *data_blocks;
|
||||
|
||||
lost = data_block_counter !=
|
||||
((s->data_block_counter + dbc_interval) & 0xff);
|
||||
|
@ -651,16 +639,48 @@ static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle,
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
*syt = cip_header[1] & CIP_SYT_MASK;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_in_packet(struct amdtp_stream *s, unsigned int cycle,
|
||||
const __be32 *ctx_header, __be32 *buffer,
|
||||
unsigned int index)
|
||||
{
|
||||
unsigned int payload_length;
|
||||
unsigned int syt;
|
||||
unsigned int data_blocks;
|
||||
struct snd_pcm_substream *pcm;
|
||||
unsigned int pcm_frames;
|
||||
int err;
|
||||
|
||||
payload_length = be32_to_cpu(ctx_header[0]) >> ISO_DATA_LENGTH_SHIFT;
|
||||
if (payload_length > s->ctx_data.tx.max_payload_length) {
|
||||
dev_err(&s->unit->device,
|
||||
"Detect jumbo payload: %04x %04x\n",
|
||||
payload_length, s->ctx_data.tx.max_payload_length);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
err = check_cip_header(s, buffer, payload_length, &data_blocks, &syt);
|
||||
if (err < 0) {
|
||||
if (err != -EAGAIN)
|
||||
return err;
|
||||
pcm_frames = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
trace_amdtp_packet(s, cycle, buffer, payload_length, data_blocks, index);
|
||||
|
||||
syt = be32_to_cpu(buffer[1]) & CIP_SYT_MASK;
|
||||
pcm_frames = s->process_data_blocks(s, buffer + 2, data_blocks, &syt);
|
||||
|
||||
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;
|
||||
end:
|
||||
if (queue_in_packet(s) < 0)
|
||||
return -EIO;
|
||||
|
|
Loading…
Reference in a new issue