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,
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)
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);
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)
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);
.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[] = {