|
| 1 | +/* |
| 2 | + * Copyright (c) 2024 Titouan Christophe |
| 3 | + * |
| 4 | + * SPDX-License-Identifier: Apache-2.0 |
| 5 | + */ |
| 6 | + |
| 7 | +#ifndef ZEPHYR_INCLUDE_USB_CLASS_USB_MIDI_H_ |
| 8 | +#define ZEPHYR_INCLUDE_USB_CLASS_USB_MIDI_H_ |
| 9 | + |
| 10 | +/** |
| 11 | + * @brief USB-MIDI 2.0 class device API |
| 12 | + * @defgroup usb_midi USB MIDI 2.0 Class device API |
| 13 | + * @ingroup usb |
| 14 | + * @since 4.1 |
| 15 | + * @version 0.1.0 |
| 16 | + * @see ump112: "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" |
| 17 | + * Document version 1.1.2 |
| 18 | + * @{ |
| 19 | + */ |
| 20 | + |
| 21 | +#include <zephyr/device.h> |
| 22 | + |
| 23 | +/** |
| 24 | + * @defgroup usb_midi_mt Universal MIDI Packet message types |
| 25 | + * @ingroup usb_midi |
| 26 | + * @see ump112: 2.1.4 Message Type (MT) Allocation |
| 27 | + * @{ |
| 28 | + */ |
| 29 | + |
| 30 | +#define MT_UTILITY 0x00 |
| 31 | +#define MT_SYS_RT_COMMON 0x01 |
| 32 | +#define MT_MIDI1_CHANNEL_VOICE 0x02 |
| 33 | +#define MT_DATA 0x03 |
| 34 | +#define MT_MIDI2_CHANNEL_VOICE 0x04 |
| 35 | +#define MT_FLEX_DATA 0x0d |
| 36 | +#define MT_UMP_STREAM 0x0f |
| 37 | + |
| 38 | +/** |
| 39 | + * @} |
| 40 | + * |
| 41 | + * @brief Size of a Universal MIDI Packet, in 32bit words |
| 42 | + * @param[in] mt The packet Message Type |
| 43 | + * @see ump112: 2.1.4 Message Type (MT) Allocation |
| 44 | + */ |
| 45 | +static inline size_t ump_words(uint8_t mt) |
| 46 | +{ |
| 47 | + return ((uint8_t[16]) {1, 1, 1, 2, 2, 4, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4})[mt & 0x0f]; |
| 48 | +} |
| 49 | + |
| 50 | + |
| 51 | +/** |
| 52 | + * @brief MIDI1 channel voice message in Universal MIDI Packet format |
| 53 | + * @see ump112: 7.3 MIDI 1.0 Channel Voice Messages |
| 54 | + */ |
| 55 | +struct ump_midi1 { |
| 56 | +#ifdef CONFIG_LITTLE_ENDIAN |
| 57 | + /** @brief The 2nd MIDI1 parameter */ |
| 58 | + uint8_t p2; |
| 59 | + /** @brief The 1st MIDI1 parameter */ |
| 60 | + uint8_t p1; |
| 61 | + /** @brief The MIDI1 channel number */ |
| 62 | + unsigned channel: 4; |
| 63 | + /** @brief The MIDI1 status nibble (command) */ |
| 64 | + unsigned status: 4; |
| 65 | + /** @brief The UMP group to which this message belongs */ |
| 66 | + unsigned group: 4; |
| 67 | + /** @brief The UMP message type (MT_MIDI1_CHANNEL_VOICE) */ |
| 68 | + unsigned mt: 4; |
| 69 | +#else |
| 70 | + /** @brief The UMP message type (MT_MIDI1_CHANNEL_VOICE) */ |
| 71 | + unsigned mt: 4; |
| 72 | + /** @brief The UMP group to which this message belongs */ |
| 73 | + unsigned group: 4; |
| 74 | + /** @brief The MIDI1 status nibble (command) */ |
| 75 | + unsigned status: 4; |
| 76 | + /** @brief The MIDI1 channel number */ |
| 77 | + unsigned channel: 4; |
| 78 | + /** @brief The 1st MIDI1 parameter */ |
| 79 | + uint8_t p1; |
| 80 | + /** @brief The 2nd MIDI1 parameter */ |
| 81 | + uint8_t p2; |
| 82 | +#endif |
| 83 | +} __packed; |
| 84 | + |
| 85 | +/** |
| 86 | + * @brief The Universal MIDI Packet |
| 87 | + * @see ump112: 2. Universal MIDI Packet (UMP) Format |
| 88 | + */ |
| 89 | +union ump { |
| 90 | + uint32_t words[4]; |
| 91 | + struct { |
| 92 | +#ifdef CONFIG_LITTLE_ENDIAN |
| 93 | + unsigned _reserved: 24; |
| 94 | + /** @brief The UMP group to which this message belongs */ |
| 95 | + unsigned group: 4; |
| 96 | + /** @brief The UMP message type */ |
| 97 | + unsigned mt: 4; |
| 98 | +#else |
| 99 | + /** @brief The UMP message type */ |
| 100 | + unsigned mt: 4; |
| 101 | + /** @brief The UMP group to which this message belongs */ |
| 102 | + unsigned group: 4; |
| 103 | +#endif |
| 104 | + } __packed; |
| 105 | + struct ump_midi1 midi1; |
| 106 | +} __packed; |
| 107 | + |
| 108 | +/** |
| 109 | + * @brief Initialize a MIDI1 Universal Midi Packet |
| 110 | + * @param _group The UMP group |
| 111 | + * @param _status The MIDI1 status nibble (command) |
| 112 | + * @param _channel The MIDI1 channel number |
| 113 | + * @param _p1 The 1st MIDI1 parameter |
| 114 | + * @param _p2 The 2nd MIDI1 parameter |
| 115 | + */ |
| 116 | +#define UMP_MIDI1(_group, _status, _channel, _p1, _p2) \ |
| 117 | + ((union ump){.midi1 = {.mt = MT_MIDI1_CHANNEL_VOICE, \ |
| 118 | + .group = _group, \ |
| 119 | + .status = _status, \ |
| 120 | + .channel = _channel, \ |
| 121 | + .p1 = _p1, \ |
| 122 | + .p2 = _p2}}) |
| 123 | + |
| 124 | +/** |
| 125 | + * @defgroup usb_midi_status MIDI status nibble (command) |
| 126 | + * @ingroup usb_midi |
| 127 | + * @see ump112: 7.3 MIDI 1.0 Channel Voice Messages |
| 128 | + * @{ |
| 129 | + */ |
| 130 | +#define MIDI_NOTE_OFF 0x8 |
| 131 | +#define MIDI_NOTE_ON 0x9 |
| 132 | +#define MIDI_AFTERTOUCH 0xa |
| 133 | +#define MIDI_CONTROL_CHANGE 0xb |
| 134 | +#define MIDI_PROGRAM_CHANGE 0xc |
| 135 | +#define MIDI_CHAN_AFTERTOUCH 0xd |
| 136 | +#define MIDI_PITCH_BEND 0xe |
| 137 | + |
| 138 | +/** |
| 139 | + * @} |
| 140 | + * |
| 141 | + * @brief Send a Universal MIDI Packet to the host |
| 142 | + * @param[in] dev The USB-MIDI interface |
| 143 | + * @param[in] pkt The Universal MIDI packet to send |
| 144 | + * @return 0 on success |
| 145 | + * -EIO if MIDI2.0 is not enabled by the host |
| 146 | + * -EAGAIN if there isn't room in the transmission buffer |
| 147 | + * |
| 148 | + */ |
| 149 | +int usb_midi_send(const struct device *dev, const union ump *pkt); |
| 150 | + |
| 151 | +/** |
| 152 | + * @brief Callback type for incoming Universal MIDI Packets from host |
| 153 | + * @param[in] dev The USB-MIDI interface receiving the packet |
| 154 | + * @param[in] pkt The received packet |
| 155 | + */ |
| 156 | +typedef void (*usb_midi_callback)(const struct device *dev, const union ump *pkt); |
| 157 | + |
| 158 | +/** |
| 159 | + * @brief Callback for incoming Universal MIDI Packets from host |
| 160 | + * Set the function to call when a Universal MIDI Packet is received from the |
| 161 | + * host on that interface |
| 162 | + * @param[in] dev The USB-MIDI interface |
| 163 | + * @param[in] cb The function to call |
| 164 | + */ |
| 165 | +void usb_midi_set_callback(const struct device *dev, usb_midi_callback cb); |
| 166 | + |
| 167 | +/** |
| 168 | + * @} |
| 169 | + */ |
| 170 | + |
| 171 | +#endif |
0 commit comments