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[] = {