1 /*
2 * Copyright (c) 2024 Titouan Christophe
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * @file
7 * @brief Sample application for USB MIDI 2.0 device class
8 */
9
10 #include <sample_usbd.h>
11
12 #include <zephyr/device.h>
13 #include <zephyr/drivers/gpio.h>
14 #include <zephyr/input/input.h>
15 #include <zephyr/usb/class/usbd_midi2.h>
16
17 #include <zephyr/logging/log.h>
18 LOG_MODULE_REGISTER(sample_usb_midi, LOG_LEVEL_INF);
19
20 static const struct device *const midi = DEVICE_DT_GET(DT_NODELABEL(usb_midi));
21
22 static struct gpio_dt_spec led = GPIO_DT_SPEC_GET_OR(DT_ALIAS(led0), gpios, {0});
23
key_press(struct input_event * evt,void * user_data)24 static void key_press(struct input_event *evt, void *user_data)
25 {
26 /* Only handle key presses in the 7bit MIDI range */
27 if (evt->type != INPUT_EV_KEY || evt->code > 0x7f) {
28 return;
29 }
30 uint8_t command = evt->value ? UMP_MIDI_NOTE_ON : UMP_MIDI_NOTE_OFF;
31 uint8_t channel = 0;
32 uint8_t note = evt->code;
33 uint8_t velocity = 100;
34
35 struct midi_ump ump = UMP_MIDI1_CHANNEL_VOICE(0, command, channel,
36 note, velocity);
37 usbd_midi_send(midi, ump);
38 }
39 INPUT_CALLBACK_DEFINE(NULL, key_press, NULL);
40
on_midi_packet(const struct device * dev,const struct midi_ump ump)41 static void on_midi_packet(const struct device *dev, const struct midi_ump ump)
42 {
43 LOG_INF("Received MIDI packet (MT=%X)", UMP_MT(ump));
44
45 /* Only send MIDI1 channel voice messages back to the host */
46 if (UMP_MT(ump) == UMP_MT_MIDI1_CHANNEL_VOICE) {
47 LOG_INF("Send back MIDI1 message %02X %02X %02X", UMP_MIDI_STATUS(ump),
48 UMP_MIDI1_P1(ump), UMP_MIDI1_P2(ump));
49 usbd_midi_send(dev, ump);
50 }
51 }
52
on_device_ready(const struct device * dev,const bool ready)53 static void on_device_ready(const struct device *dev, const bool ready)
54 {
55 /* Light up the LED (if any) when USB-MIDI2.0 is enabled */
56 if (led.port) {
57 gpio_pin_set_dt(&led, ready);
58 }
59 }
60
61 static const struct usbd_midi_ops ops = {
62 .rx_packet_cb = on_midi_packet,
63 .ready_cb = on_device_ready,
64 };
65
main(void)66 int main(void)
67 {
68 struct usbd_context *sample_usbd;
69
70 if (!device_is_ready(midi)) {
71 LOG_ERR("MIDI device not ready");
72 return -1;
73 }
74
75 if (led.port) {
76 if (gpio_pin_configure_dt(&led, GPIO_OUTPUT)) {
77 LOG_ERR("Unable to setup LED, not using it");
78 memset(&led, 0, sizeof(led));
79 }
80 }
81
82 usbd_midi_set_ops(midi, &ops);
83
84 sample_usbd = sample_usbd_init_device(NULL);
85 if (sample_usbd == NULL) {
86 LOG_ERR("Failed to initialize USB device");
87 return -1;
88 }
89
90 if (usbd_enable(sample_usbd)) {
91 LOG_ERR("Failed to enable device support");
92 return -1;
93 }
94
95 LOG_INF("USB device support enabled");
96 return 0;
97 }
98