[alsa-devel] [PATCH 5/6] ALSA: fireface: add protocol-specific operation to fill transaction buffer with MIDI messages
Takashi Sakamoto
o-takashi at sakamocchi.jp
Tue Jan 22 14:17:04 CET 2019
Between former and latter models, content of asynchronous transaction
for MIDI messages from driver to device is different.
This commit is a preparation to support latter models. A protocol-specific
operation is added to encode MIDI messages to the transaction.
Signed-off-by: Takashi Sakamoto <o-takashi at sakamocchi.jp>
---
sound/firewire/fireface/ff-protocol-former.c | 23 +++++++++++++++
sound/firewire/fireface/ff-transaction.c | 31 ++++++++------------
sound/firewire/fireface/ff.h | 3 ++
3 files changed, 38 insertions(+), 19 deletions(-)
diff --git a/sound/firewire/fireface/ff-protocol-former.c b/sound/firewire/fireface/ff-protocol-former.c
index 266e4892a818..e0acf40a02ee 100644
--- a/sound/firewire/fireface/ff-protocol-former.c
+++ b/sound/firewire/fireface/ff-protocol-former.c
@@ -263,6 +263,27 @@ static void former_dump_status(struct snd_ff *ff,
dump_sync_status(ff, buffer);
}
+static int former_fill_midi_msg(struct snd_ff *ff,
+ struct snd_rawmidi_substream *substream,
+ unsigned int port)
+{
+ u8 *buf = (u8 *)ff->msg_buf[port];
+ int len;
+ int i;
+
+ len = snd_rawmidi_transmit_peek(substream, buf,
+ SND_FF_MAXIMIM_MIDI_QUADS);
+ if (len <= 0)
+ return len;
+
+ // One quadlet includes one byte.
+ for (i = len - 1; i >= 0; --i)
+ ff->msg_buf[port][i] = cpu_to_le32(buf[i]);
+ ff->rx_bytes[port] = len;
+
+ return len;
+}
+
#define FF800_STF 0x0000fc88f000
#define FF800_RX_PACKET_FORMAT 0x0000fc88f004
#define FF800_ALLOC_TX_STREAM 0x0000fc88f008
@@ -392,6 +413,7 @@ static void ff800_handle_midi_msg(struct snd_ff *ff, unsigned int offset,
const struct snd_ff_protocol snd_ff_protocol_ff800 = {
.handle_midi_msg = ff800_handle_midi_msg,
+ .fill_midi_msg = former_fill_midi_msg,
.get_clock = former_get_clock,
.switch_fetching_mode = former_switch_fetching_mode,
.begin_session = ff800_begin_session,
@@ -543,6 +565,7 @@ static void ff400_handle_midi_msg(struct snd_ff *ff, unsigned int offset,
const struct snd_ff_protocol snd_ff_protocol_ff400 = {
.handle_midi_msg = ff400_handle_midi_msg,
+ .fill_midi_msg = former_fill_midi_msg,
.get_clock = former_get_clock,
.switch_fetching_mode = former_switch_fetching_mode,
.begin_session = ff400_begin_session,
diff --git a/sound/firewire/fireface/ff-transaction.c b/sound/firewire/fireface/ff-transaction.c
index 92ca76ab7537..d8a8b01b39a1 100644
--- a/sound/firewire/fireface/ff-transaction.c
+++ b/sound/firewire/fireface/ff-transaction.c
@@ -51,23 +51,17 @@ static void finish_transmit_midi1_msg(struct fw_card *card, int rcode,
finish_transmit_midi_msg(ff, 1, rcode);
}
-static inline void fill_midi_buf(struct snd_ff *ff, unsigned int port,
- unsigned int index, u8 byte)
-{
- ff->msg_buf[port][index] = cpu_to_le32(byte);
-}
-
static void transmit_midi_msg(struct snd_ff *ff, unsigned int port)
{
struct snd_rawmidi_substream *substream =
READ_ONCE(ff->rx_midi_substreams[port]);
- u8 *buf = (u8 *)ff->msg_buf[port];
- int i, len;
+ int quad_count;
struct fw_device *fw_dev = fw_parent_device(ff->unit);
unsigned long long addr;
int generation;
fw_transaction_callback_t callback;
+ int tcode;
if (substream == NULL || snd_rawmidi_transmit_empty(substream))
return;
@@ -81,14 +75,10 @@ static void transmit_midi_msg(struct snd_ff *ff, unsigned int port)
return;
}
- len = snd_rawmidi_transmit_peek(substream, buf,
- SND_FF_MAXIMIM_MIDI_QUADS);
- if (len <= 0)
+ quad_count = ff->spec->protocol->fill_midi_msg(ff, substream, port);
+ if (quad_count <= 0)
return;
- for (i = len - 1; i >= 0; i--)
- fill_midi_buf(ff, port, i, buf[i]);
-
if (port == 0) {
addr = ff->spec->midi_rx_addrs[0];
callback = finish_transmit_midi0_msg;
@@ -99,8 +89,12 @@ static void transmit_midi_msg(struct snd_ff *ff, unsigned int port)
/* Set interval to next transaction. */
ff->next_ktime[port] = ktime_add_ns(ktime_get(),
- len * 8 * NSEC_PER_SEC / 31250);
- ff->rx_bytes[port] = len;
+ ff->rx_bytes[port] * 8 * NSEC_PER_SEC / 31250);
+
+ if (quad_count == 1)
+ tcode = TCODE_WRITE_QUADLET_REQUEST;
+ else
+ tcode = TCODE_WRITE_BLOCK_REQUEST;
/*
* In Linux FireWire core, when generation is updated with memory
@@ -112,10 +106,9 @@ static void transmit_midi_msg(struct snd_ff *ff, unsigned int port)
*/
generation = fw_dev->generation;
smp_rmb();
- fw_send_request(fw_dev->card, &ff->transactions[port],
- TCODE_WRITE_BLOCK_REQUEST,
+ fw_send_request(fw_dev->card, &ff->transactions[port], tcode,
fw_dev->node_id, generation, fw_dev->max_speed,
- addr, &ff->msg_buf[port], len * 4,
+ addr, &ff->msg_buf[port], quad_count * 4,
callback, &ff->transactions[port]);
}
diff --git a/sound/firewire/fireface/ff.h b/sound/firewire/fireface/ff.h
index edad75a4b260..e52ad11803e0 100644
--- a/sound/firewire/fireface/ff.h
+++ b/sound/firewire/fireface/ff.h
@@ -107,6 +107,9 @@ enum snd_ff_clock_src {
struct snd_ff_protocol {
void (*handle_midi_msg)(struct snd_ff *ff, unsigned int offset,
__le32 *buf, size_t length);
+ int (*fill_midi_msg)(struct snd_ff *ff,
+ struct snd_rawmidi_substream *substream,
+ unsigned int port);
int (*get_clock)(struct snd_ff *ff, unsigned int *rate,
enum snd_ff_clock_src *src);
int (*switch_fetching_mode)(struct snd_ff *ff, bool enable);
--
2.19.1
More information about the Alsa-devel
mailing list