if (ff->unit_version == SND_FF_UNIT_VERSION_UCX) { // For Fireface UCX. Always use the maximum number of data // channels in data block of packet. if (rate >= 32000 && rate <= 48000)
flag = 0x92; elseif (rate >= 64000 && rate <= 96000)
flag = 0x8e; elseif (rate >= 128000 && rate <= 192000)
flag = 0x8c; else return -EINVAL;
} else { // For Fireface UFX and 802. Due to bandwidth limitation on // IEEE 1394a (400 Mbps), Analog 1-12 and AES are available // without any ADAT at quadruple speed. if (rate >= 32000 && rate <= 48000)
flag = 0x9e; elseif (rate >= 64000 && rate <= 96000)
flag = 0x96; elseif (rate >= 128000 && rate <= 192000)
flag = 0x8e; else return -EINVAL;
}
if (generation != fw_parent_device(ff->unit)->card->generation) {
err = fw_iso_resources_update(&ff->tx_resources); if (err < 0) return err;
err = fw_iso_resources_update(&ff->rx_resources); if (err < 0) return err;
}
// NOTE: transactions are transferred within 0x00-0x7f in allocated range of // address. This seems to be for check of discontinuity in receiver side. // // Like Fireface 400, drivers can select one of 4 options for lower 4 bytes of // destination address by bit flags in quadlet register (little endian) at // 0x'ffff'0000'0014: // // bit flags: offset of destination address // - 0x00002000: 0x'....'....'0000'0000 // - 0x00004000: 0x'....'....'0000'0080 // - 0x00008000: 0x'....'....'0000'0100 // - 0x00010000: 0x'....'....'0000'0180 // // Drivers can suppress the device to transfer asynchronous transactions by // clear these bit flags. // // Actually, the register is write-only and includes the other settings such as // input attenuation. This driver allocates for the first option // (0x'....'....'0000'0000) and expects userspace application to configure the // register for it. staticvoid latter_handle_midi_msg(struct snd_ff *ff, unsignedint offset, const __le32 *buf,
size_t length, u32 tstamp)
{
u32 data = le32_to_cpu(*buf); unsignedint index = (data & 0x000000f0) >> 4;
u8 byte[3]; struct snd_rawmidi_substream *substream; unsignedint 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;
}
substream = READ_ONCE(ff->tx_midi_substreams[index]); if (substream)
snd_rawmidi_receive(substream, byte, len);
}
/* * When return minus value, given argument is not MIDI status. * When return 0, given argument is a beginning of system exclusive. * When return the others, given argument is MIDI data.
*/ staticinlineint calculate_message_bytes(u8 status)
{ switch (status) { case 0xf6: /* Tune request. */ case 0xf8: /* Timing clock. */ case 0xfa: /* Start. */ case 0xfb: /* Continue. */ case 0xfc: /* Stop. */ case 0xfe: /* Active sensing. */ case 0xff: /* System reset. */ return 1; case 0xf1: /* MIDI time code quarter frame. */ case 0xf3: /* Song select. */ return 2; case 0xf2: /* Song position pointer. */ return 3; case 0xf0: /* Exclusive. */ return 0; case 0xf7: /* End of exclusive. */ break; case 0xf4: /* Undefined. */ case 0xf5: /* Undefined. */ case 0xf9: /* Undefined. */ case 0xfd: /* Undefined. */ break; default: switch (status & 0xf0) { case 0x80: /* Note on. */ case 0x90: /* Note off. */ case 0xa0: /* Polyphonic key pressure. */ case 0xb0: /* Control change and Mode change. */ case 0xe0: /* Pitch bend change. */ return 3; case 0xc0: /* Program change. */ case 0xd0: /* Channel pressure. */ return 2; default: break;
} break;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.