summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/firewire/fireface/ff-protocol-latter.c43
-rw-r--r--sound/firewire/fireface/ff.c25
2 files changed, 54 insertions, 14 deletions
diff --git a/sound/firewire/fireface/ff-protocol-latter.c b/sound/firewire/fireface/ff-protocol-latter.c
index 64767ba439db..a812ab6feb58 100644
--- a/sound/firewire/fireface/ff-protocol-latter.c
+++ b/sound/firewire/fireface/ff-protocol-latter.c
@@ -264,7 +264,50 @@ static void latter_dump_status(struct snd_ff *ff, struct snd_info_buffer *buffer
snd_iprintf(buffer, "Referred clock: %s %d\n", label, rate);
}
+// NOTE: transactions are transferred within 0x00-0x7f in allocated range of
+// address. This seems to be for check of discontinuity in receiver side.
+static void latter_handle_midi_msg(struct snd_ff *ff, unsigned int offset,
+ __le32 *buf, size_t length)
+{
+ u32 data = le32_to_cpu(*buf);
+ unsigned int index = (data & 0x000000f0) >> 4;
+ u8 byte[3];
+ struct snd_rawmidi_substream *substream;
+ unsigned int len;
+
+ if (index > ff->spec->midi_in_ports)
+ return;
+
+ switch (data & 0x0000000f) {
+ case 0x00000008:
+ case 0x00000009:
+ case 0x0000000a:
+ case 0x0000000b:
+ case 0x0000000e:
+ len = 3;
+ break;
+ case 0x0000000c:
+ case 0x0000000d:
+ len = 2;
+ break;
+ default:
+ len = data & 0x00000003;
+ if (len == 0)
+ len = 3;
+ break;
+ }
+
+ byte[0] = (data & 0x0000ff00) >> 8;
+ byte[1] = (data & 0x00ff0000) >> 16;
+ byte[2] = (data & 0xff000000) >> 24;
+
+ substream = READ_ONCE(ff->tx_midi_substreams[index]);
+ if (substream)
+ snd_rawmidi_receive(substream, byte, len);
+}
+
const struct snd_ff_protocol snd_ff_protocol_latter = {
+ .handle_midi_msg = latter_handle_midi_msg,
.get_clock = latter_get_clock,
.switch_fetching_mode = latter_switch_fetching_mode,
.begin_session = latter_begin_session,
diff --git a/sound/firewire/fireface/ff.c b/sound/firewire/fireface/ff.c
index c09a4875aa86..a2a9fd82f27d 100644
--- a/sound/firewire/fireface/ff.c
+++ b/sound/firewire/fireface/ff.c
@@ -32,8 +32,7 @@ static void ff_card_free(struct snd_card *card)
struct snd_ff *ff = card->private_data;
snd_ff_stream_destroy_duplex(ff);
- if (ff->spec->midi_high_addr > 0)
- snd_ff_transaction_unregister(ff);
+ snd_ff_transaction_unregister(ff);
}
static void do_registration(struct work_struct *work)
@@ -51,11 +50,9 @@ static void do_registration(struct work_struct *work)
ff->card->private_free = ff_card_free;
ff->card->private_data = ff;
- if (ff->spec->midi_high_addr > 0) {
- err = snd_ff_transaction_register(ff);
- if (err < 0)
- goto error;
- }
+ err = snd_ff_transaction_register(ff);
+ if (err < 0)
+ goto error;
name_card(ff);
@@ -65,11 +62,9 @@ static void do_registration(struct work_struct *work)
snd_ff_proc_init(ff);
- if (ff->spec->midi_in_ports > 0 || ff->spec->midi_out_ports > 0) {
- err = snd_ff_create_midi_devices(ff);
- if (err < 0)
- goto error;
- }
+ err = snd_ff_create_midi_devices(ff);
+ if (err < 0)
+ goto error;
err = snd_ff_create_pcm_devices(ff);
if (err < 0)
@@ -124,8 +119,7 @@ static void snd_ff_update(struct fw_unit *unit)
if (!ff->registered)
snd_fw_schedule_registration(unit, &ff->dwork);
- if (ff->spec->midi_high_addr > 0)
- snd_ff_transaction_reregister(ff);
+ snd_ff_transaction_reregister(ff);
if (ff->registered)
snd_ff_stream_update_duplex(ff);
@@ -177,7 +171,10 @@ static const struct snd_ff_spec spec_ucx = {
.name = "FirefaceUCX",
.pcm_capture_channels = {18, 14, 12},
.pcm_playback_channels = {18, 14, 12},
+ .midi_in_ports = 2,
.protocol = &snd_ff_protocol_latter,
+ .midi_high_addr = 0xffff00000034ull,
+ .midi_addr_range = 0x80,
};
static const struct ieee1394_device_id snd_ff_id_table[] = {