summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Halbert <halbert@halwitz.org>2019-01-10 19:49:33 -0500
committerGitHub <noreply@github.com>2019-01-10 19:49:33 -0500
commit516d7da64173055422230e46173f7d19273a5107 (patch)
treeb1d339121108c551c34376bb26e1322e03ce841e
parent16b4fa7ea76563266ab309070a96f20b8e2e7faa (diff)
parent3dd59c3d5fa59f5bea3acc8e55c4d4a5091e66eb (diff)
Merge pull request #1449 from tannewt/midi
Add USB MIDI support for SAMD and nRF.
-rwxr-xr-x.travis.yml2
m---------lib/tinyusb0
-rw-r--r--ports/atmel-samd/Makefile9
-rw-r--r--ports/atmel-samd/mpconfigport.h3
-rwxr-xr-xports/nrf/Makefile2
-rw-r--r--ports/nrf/mpconfigport.h2
-rw-r--r--shared-bindings/usb_midi/PortIn.c128
-rw-r--r--shared-bindings/usb_midi/PortIn.h44
-rw-r--r--shared-bindings/usb_midi/PortOut.c110
-rw-r--r--shared-bindings/usb_midi/PortOut.h44
-rw-r--r--shared-bindings/usb_midi/__init__.c78
-rw-r--r--shared-bindings/usb_midi/__init__.h34
-rw-r--r--shared-module/usb_midi/PortIn.c40
-rw-r--r--shared-module/usb_midi/PortIn.h39
-rw-r--r--shared-module/usb_midi/PortOut.c40
-rw-r--r--shared-module/usb_midi/PortOut.h39
-rw-r--r--shared-module/usb_midi/__init__.c63
-rw-r--r--shared-module/usb_midi/__init__.h32
-rwxr-xr-xsupervisor/memory.h9
-rw-r--r--supervisor/shared/usb/tusb_config.h1
-rw-r--r--supervisor/shared/usb/usb.c5
-rw-r--r--supervisor/supervisor.mk7
-rw-r--r--tools/gen_usb_descriptor.py74
m---------tools/usb_descriptor0
24 files changed, 763 insertions, 42 deletions
diff --git a/.travis.yml b/.travis.yml
index aa0282172..2fc44116c 100755
--- a/.travis.yml
+++ b/.travis.yml
@@ -21,7 +21,7 @@ git:
# that SDK is shortest and add it there. In the case of major re-organizations,
# just try to make the builds "about equal in run time"
env:
- - TRAVIS_TESTS="unix docs translations website" TRAVIS_BOARDS="feather_huzzah circuitplayground_express mini_sam_m4 grandcentral_m4_express pca10056 pca10059 feather_nrf52832 feather_nrf52840_express makerdiary_nrf52840_mdk particle_boron particle_argon particle_xenon sparkfun_nrf52840_mini" TRAVIS_SDK=arm:nrf:esp8266
+ - TRAVIS_TESTS="unix docs translations website" TRAVIS_BOARDS="feather_huzzah circuitplayground_express mini_sam_m4 grandcentral_m4_express pca10056 pca10059 feather_nrf52840_express makerdiary_nrf52840_mdk particle_boron particle_argon particle_xenon sparkfun_nrf52840_mini" TRAVIS_SDK=arm:nrf:esp8266
- TRAVIS_BOARDS="metro_m0_express metro_m4_express pirkey_m0 trellis_m4_express trinket_m0" TRAVIS_SDK=arm
- TRAVIS_BOARDS="feather_radiofruit_zigbee gemma_m0 hallowing_m0_express itsybitsy_m0_express itsybitsy_m4_express meowmeow" TRAVIS_SDK=arm
- TRAVIS_BOARDS="feather_m0_express_crickit feather_m0_rfm69 feather_m0_rfm9x feather_m4_express arduino_zero arduino_mkr1300 arduino_mkrzero" TRAVIS_SDK=arm
diff --git a/lib/tinyusb b/lib/tinyusb
-Subproject 3bb53273cd3770328f55ba317af3df0cce4333c
+Subproject 5804e56e3c2ab4480bf72d94d997f769a645af4
diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile
index 9a31eb42a..4ac579441 100644
--- a/ports/atmel-samd/Makefile
+++ b/ports/atmel-samd/Makefile
@@ -89,13 +89,13 @@ BASE_CFLAGS = \
ifeq ($(CHIP_FAMILY), samd21)
CFLAGS += -Os -DNDEBUG
# TinyUSB defines
-CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAMD21 -DCFG_TUD_CDC_RX_BUFSIZE=128 -DCFG_TUD_CDC_TX_BUFSIZE=128 -DCFG_TUD_MSC_BUFSIZE=512
+CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAMD21 -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_CDC_RX_BUFSIZE=128 -DCFG_TUD_MIDI_TX_BUFSIZE=128 -DCFG_TUD_CDC_TX_BUFSIZE=128 -DCFG_TUD_MSC_BUFSIZE=512
endif
ifeq ($(CHIP_FAMILY), samd51)
CFLAGS += -Os -DNDEBUG
# TinyUSB defines
-CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAMD51 -DCFG_TUD_CDC_RX_BUFSIZE=256 -DCFG_TUD_CDC_TX_BUFSIZE=256 -DCFG_TUD_MSC_BUFSIZE=1024
+CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAMD51 -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_CDC_RX_BUFSIZE=256 -DCFG_TUD_MIDI_TX_BUFSIZE=128 -DCFG_TUD_CDC_TX_BUFSIZE=256 -DCFG_TUD_MSC_BUFSIZE=1024
endif
#Debugging/Optimization
@@ -103,9 +103,9 @@ ifeq ($(DEBUG), 1)
# Turn on Python modules useful for debugging (e.g. uheap, ustack).
CFLAGS += -ggdb
# You may want to disable -flto if it interferes with debugging.
- CFLAGS += -flto
+ # CFLAGS += -flto
# You may want to enable these flags to make setting breakpoints easier.
- # CFLAGS += -fno-inline -fno-ipa-sra
+ CFLAGS += -fno-inline -fno-ipa-sra
ifeq ($(CHIP_FAMILY), samd21)
CFLAGS += -DENABLE_MICRO_TRACE_BUFFER
endif
@@ -266,7 +266,6 @@ SRC_C = \
lib/oofatfs/option/ccsbcs.c \
lib/timeutils/timeutils.c \
lib/tinyusb/src/portable/microchip/$(CHIP_FAMILY)/dcd_$(CHIP_FAMILY).c \
- lib/tinyusb/src/portable/microchip/$(CHIP_FAMILY)/hal_$(CHIP_FAMILY).c \
lib/utils/buffer_helper.c \
lib/utils/context_manager_helpers.c \
lib/utils/interrupt_char.c \
diff --git a/ports/atmel-samd/mpconfigport.h b/ports/atmel-samd/mpconfigport.h
index d0ebbfa39..65b8c94c5 100644
--- a/ports/atmel-samd/mpconfigport.h
+++ b/ports/atmel-samd/mpconfigport.h
@@ -237,6 +237,7 @@ extern const struct _mp_obj_module_t gamepad_module;
extern const struct _mp_obj_module_t stage_module;
extern const struct _mp_obj_module_t touchio_module;
extern const struct _mp_obj_module_t usb_hid_module;
+extern const struct _mp_obj_module_t usb_midi_module;
extern const struct _mp_obj_module_t network_module;
extern const struct _mp_obj_module_t socket_module;
extern const struct _mp_obj_module_t wiznet_module;
@@ -382,6 +383,7 @@ extern const struct _mp_obj_module_t wiznet_module;
{ MP_OBJ_NEW_QSTR(MP_QSTR_math), (mp_obj_t)&math_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR__time), (mp_obj_t)&time_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_usb_hid),(mp_obj_t)&usb_hid_module }, \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_usb_midi),(mp_obj_t)&usb_midi_module }, \
TOUCHIO_MODULE \
EXTRA_BUILTIN_MODULES
@@ -410,6 +412,7 @@ extern const struct _mp_obj_module_t wiznet_module;
{ MP_OBJ_NEW_QSTR(MP_QSTR_math), (mp_obj_t)&math_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_usb_hid),(mp_obj_t)&usb_hid_module }, \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_usb_midi),(mp_obj_t)&usb_midi_module }, \
TOUCHIO_MODULE \
EXTRA_BUILTIN_MODULES
#endif
diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile
index ca9583df7..4beddb491 100755
--- a/ports/nrf/Makefile
+++ b/ports/nrf/Makefile
@@ -75,7 +75,7 @@ LDFLAGS += -mthumb -mabi=aapcs -T $(LD_FILE) -L boards/
LDFLAGS += -Wl,--gc-sections
# TinyUSB defines
-CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_NRF5X -DCFG_TUD_CDC_RX_BUFSIZE=1024 -DCFG_TUD_CDC_TX_BUFSIZE=1024 -DCFG_TUD_MSC_BUFSIZE=4096
+CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_NRF5X -DCFG_TUD_CDC_RX_BUFSIZE=1024 -DCFG_TUD_CDC_TX_BUFSIZE=1024 -DCFG_TUD_MSC_BUFSIZE=4096 -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_MIDI_TX_BUFSIZE=128
#Debugging/Optimization
ifeq ($(DEBUG), 1)
diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h
index 25710cea2..d38b14578 100644
--- a/ports/nrf/mpconfigport.h
+++ b/ports/nrf/mpconfigport.h
@@ -175,6 +175,7 @@ extern const struct _mp_obj_module_t supervisor_module;
extern const struct _mp_obj_module_t gamepad_module;
extern const struct _mp_obj_module_t neopixel_write_module;
extern const struct _mp_obj_module_t usb_hid_module;
+extern const struct _mp_obj_module_t usb_midi_module;
extern const struct _mp_obj_module_t bleio_module;
#if MICROPY_PY_BLEIO
@@ -207,6 +208,7 @@ extern const struct _mp_obj_module_t bleio_module;
{ MP_OBJ_NEW_QSTR (MP_QSTR_time ), (mp_obj_t)&time_module }, \
{ MP_OBJ_NEW_QSTR (MP_QSTR_json ), (mp_obj_t)&mp_module_ujson }, \
USBHID_MODULE \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_usb_midi),(mp_obj_t)&usb_midi_module }, \
BLEIO_MODULE
// extra built in names to add to the global namespace
diff --git a/shared-bindings/usb_midi/PortIn.c b/shared-bindings/usb_midi/PortIn.c
new file mode 100644
index 000000000..3c4d4f73f
--- /dev/null
+++ b/shared-bindings/usb_midi/PortIn.c
@@ -0,0 +1,128 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+
+#include "shared-bindings/usb_midi/PortIn.h"
+#include "shared-bindings/util.h"
+
+#include "py/ioctl.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "py/stream.h"
+#include "supervisor/shared/translate.h"
+
+
+//| .. currentmodule:: usb_midi
+//|
+//| :class:`PortIn` -- receives midi commands over USB
+//| ===================================================
+//|
+//| .. class:: PortIn()
+//|
+//| Not currently dynamically supported.
+//|
+//| PortIn objects are constructed for every corresponding entry in the USB descriptor and added
+//| to the `usb_midi.ports` tuple.
+//|
+
+STATIC mp_obj_t usb_midi_portin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) {
+ return mp_const_none;
+}
+
+// These are standard stream methods. Code is in py/stream.c.
+//
+//| .. method:: read(nbytes=None)
+//|
+//| Read characters. If ``nbytes`` is specified then read at most that many
+//| bytes. Otherwise, read everything that arrives until the connection
+//| times out. Providing the number of bytes expected is highly recommended
+//| because it will be faster.
+//|
+//| :return: Data read
+//| :rtype: bytes or None
+//|
+//| .. method:: readinto(buf, nbytes=None)
+//|
+//| Read bytes into the ``buf``. If ``nbytes`` is specified then read at most
+//| that many bytes. Otherwise, read at most ``len(buf)`` bytes.
+//|
+//| :return: number of bytes read and stored into ``buf``
+//| :rtype: bytes or None
+//|
+
+// These three methods are used by the shared stream methods.
+STATIC mp_uint_t usb_midi_portin_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
+ usb_midi_portin_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ byte *buf = buf_in;
+
+ // make sure we want at least 1 char
+ if (size == 0) {
+ return 0;
+ }
+
+ return common_hal_usb_midi_portin_read(self, buf, size, errcode);
+}
+
+STATIC mp_uint_t usb_midi_portin_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
+ usb_midi_portin_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_uint_t ret;
+ if (request == MP_IOCTL_POLL) {
+ mp_uint_t flags = arg;
+ ret = 0;
+ if ((flags & MP_IOCTL_POLL_RD) && common_hal_usb_midi_portin_bytes_available(self) > 0) {
+ ret |= MP_IOCTL_POLL_RD;
+ }
+ } else {
+ *errcode = MP_EINVAL;
+ ret = MP_STREAM_ERROR;
+ }
+ return ret;
+}
+
+STATIC const mp_rom_map_elem_t usb_midi_portin_locals_dict_table[] = {
+ // Standard stream methods.
+ { MP_OBJ_NEW_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(usb_midi_portin_locals_dict, usb_midi_portin_locals_dict_table);
+
+STATIC const mp_stream_p_t usb_midi_portin_stream_p = {
+ .read = usb_midi_portin_read,
+ .write = NULL,
+ .ioctl = usb_midi_portin_ioctl,
+ .is_text = false,
+};
+
+const mp_obj_type_t usb_midi_portin_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_PortIn,
+ .make_new = usb_midi_portin_make_new,
+ .getiter = mp_identity_getiter,
+ .iternext = mp_stream_unbuffered_iter,
+ .protocol = &usb_midi_portin_stream_p,
+ .locals_dict = (mp_obj_dict_t*)&usb_midi_portin_locals_dict,
+};
diff --git a/shared-bindings/usb_midi/PortIn.h b/shared-bindings/usb_midi/PortIn.h
new file mode 100644
index 000000000..89bb59b71
--- /dev/null
+++ b/shared-bindings/usb_midi/PortIn.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_USB_MIDI_PORTIN_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_USB_MIDI_PORTIN_H
+
+#include "shared-module/usb_midi/PortIn.h"
+
+extern const mp_obj_type_t usb_midi_portin_type;
+
+// Construct an underlying UART object.
+extern void common_hal_usb_midi_portin_construct(usb_midi_portin_obj_t *self,
+ uint8_t receiver_buffer_size);
+// Read characters.
+extern size_t common_hal_usb_midi_portin_read(usb_midi_portin_obj_t *self,
+ uint8_t *data, size_t len, int *errcode);
+
+extern uint32_t common_hal_usb_midi_portin_bytes_available(usb_midi_portin_obj_t *self);
+extern void common_hal_usb_midi_portin_clear_buffer(usb_midi_portin_obj_t *self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_USB_MIDI_PORTIN_H
diff --git a/shared-bindings/usb_midi/PortOut.c b/shared-bindings/usb_midi/PortOut.c
new file mode 100644
index 000000000..8b26b8ffc
--- /dev/null
+++ b/shared-bindings/usb_midi/PortOut.c
@@ -0,0 +1,110 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+
+#include "shared-bindings/usb_midi/PortOut.h"
+#include "shared-bindings/util.h"
+
+#include "py/ioctl.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "py/stream.h"
+#include "supervisor/shared/translate.h"
+
+
+//| .. currentmodule:: usb_midi
+//|
+//| :class:`PortOut` -- sends midi messages to a computer over USB
+//| ==============================================================
+//|
+//| .. class:: PortOut()
+//|
+//| Not currently dynamically supported.
+//|
+//| PortOut objects are constructed for every corresponding entry in the USB descriptor and added
+//| to the `usb_midi.ports` tuple.
+//|
+
+STATIC mp_obj_t usb_midi_portout_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) {
+ return mp_const_none;
+}
+
+// These are standard stream methods. Code is in py/stream.c.
+//
+//| .. method:: write(buf)
+//|
+//| Write the buffer of bytes to the bus.
+//|
+//| :return: the number of bytes written
+//| :rtype: int or None
+//|
+
+STATIC mp_uint_t usb_midi_portout_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
+ usb_midi_portout_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ const byte *buf = buf_in;
+
+ return common_hal_usb_midi_portout_write(self, buf, size, errcode);
+}
+
+STATIC mp_uint_t usb_midi_portout_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
+ usb_midi_portout_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_uint_t ret;
+ if (request == MP_IOCTL_POLL) {
+ mp_uint_t flags = arg;
+ ret = 0;
+ if ((flags & MP_IOCTL_POLL_WR) && common_hal_usb_midi_portout_ready_to_tx(self)) {
+ ret |= MP_IOCTL_POLL_WR;
+ }
+ } else {
+ *errcode = MP_EINVAL;
+ ret = MP_STREAM_ERROR;
+ }
+ return ret;
+}
+
+STATIC const mp_rom_map_elem_t usb_midi_portout_locals_dict_table[] = {
+ // Standard stream methods.
+ { MP_OBJ_NEW_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(usb_midi_portout_locals_dict, usb_midi_portout_locals_dict_table);
+
+STATIC const mp_stream_p_t usb_midi_portout_stream_p = {
+ .read = NULL,
+ .write = usb_midi_portout_write,
+ .ioctl = usb_midi_portout_ioctl,
+ .is_text = false,
+};
+
+const mp_obj_type_t usb_midi_portout_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_PortOut,
+ .make_new = usb_midi_portout_make_new,
+ .getiter = mp_identity_getiter,
+ .iternext = mp_stream_unbuffered_iter,
+ .protocol = &usb_midi_portout_stream_p,
+ .locals_dict = (mp_obj_dict_t*)&usb_midi_portout_locals_dict,
+};
diff --git a/shared-bindings/usb_midi/PortOut.h b/shared-bindings/usb_midi/PortOut.h
new file mode 100644
index 000000000..dd42d7cdb
--- /dev/null
+++ b/shared-bindings/usb_midi/PortOut.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_USB_MIDI_PORTOUT_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_USB_MIDI_PORTOUT_H
+
+#include "shared-module/usb_midi/PortOut.h"
+
+extern const mp_obj_type_t usb_midi_portout_type;
+
+// Construct an underlying UART object.
+extern void common_hal_usb_midi_portout_construct(usb_midi_portout_obj_t *self,
+ uint8_t receiver_buffer_size);
+
+// Write characters. len is in characters NOT bytes!
+extern size_t common_hal_usb_midi_portout_write(usb_midi_portout_obj_t *self,
+ const uint8_t *data, size_t len, int *errcode);
+
+extern bool common_hal_usb_midi_portout_ready_to_tx(usb_midi_portout_obj_t *self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_USB_MIDI_PORTOUT_H
diff --git a/shared-bindings/usb_midi/__init__.c b/shared-bindings/usb_midi/__init__.c
new file mode 100644
index 000000000..f57d3631b
--- /dev/null
+++ b/shared-bindings/usb_midi/__init__.c
@@ -0,0 +1,78 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+
+#include "py/obj.h"
+#include "py/runtime.h"
+
+#include "shared-bindings/usb_midi/__init__.h"
+#include "shared-bindings/usb_midi/PortIn.h"
+#include "shared-bindings/usb_midi/PortOut.h"
+
+#include "py/runtime.h"
+
+//| :mod:`usb_midi` --- MIDI over USB
+//| =================================================
+//|
+//| .. module:: usb_midi
+//| :synopsis: MIDI over USB
+//|
+//| The `usb_midi` module contains classes to transmit and receive MIDI messages over USB
+//|
+//| Libraries
+//|
+//| .. toctree::
+//| :maxdepth: 3
+//|
+//| PortIn
+//| PortOut
+//|
+//|
+mp_map_elem_t usb_midi_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usb_midi) },
+ { MP_ROM_QSTR(MP_QSTR_ports), mp_const_empty_tuple },
+ { MP_ROM_QSTR(MP_QSTR_PortIn), MP_OBJ_FROM_PTR(&usb_midi_portin_type) },
+ { MP_ROM_QSTR(MP_QSTR_PortOut), MP_OBJ_FROM_PTR(&usb_midi_portout_type) },
+};
+
+// This isn't const so we can set ports dynamically.
+mp_obj_dict_t usb_midi_module_globals = {
+ .base = {&mp_type_dict},
+ .map = {
+ .all_keys_are_qstrs = 1,
+ .is_fixed = 1,
+ .is_ordered = 1,
+ .used = MP_ARRAY_SIZE(usb_midi_module_globals_table),
+ .alloc = MP_ARRAY_SIZE(usb_midi_module_globals_table),
+ .table = usb_midi_module_globals_table,
+ },
+};
+
+const mp_obj_module_t usb_midi_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&usb_midi_module_globals,
+};
diff --git a/shared-bindings/usb_midi/__init__.h b/shared-bindings/usb_midi/__init__.h
new file mode 100644
index 000000000..e81818e04
--- /dev/null
+++ b/shared-bindings/usb_midi/__init__.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_USB_MIDI___INIT___H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_USB_MIDI___INIT___H
+
+#include "py/obj.h"
+
+extern mp_obj_dict_t usb_midi_module_globals;
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_USB_MIDI___INIT___H
diff --git a/shared-module/usb_midi/PortIn.c b/shared-module/usb_midi/PortIn.c
new file mode 100644
index 000000000..b256c5937
--- /dev/null
+++ b/shared-module/usb_midi/PortIn.c
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-module/usb_midi/PortIn.h"
+#include "supervisor/shared/translate.h"
+#include "tusb.h"
+
+void common_hal_usb_midi_portin_construct(usb_midi_portin_obj_t *self, uint8_t receiver_buffer_size) {
+}
+
+size_t common_hal_usb_midi_portin_read(usb_midi_portin_obj_t *self, uint8_t *data, size_t len, int *errcode) {
+ return tud_midi_read(data, len);
+}
+
+uint32_t common_hal_usb_midi_portin_bytes_available(usb_midi_portin_obj_t *self) {
+ return tud_midi_available();
+}
diff --git a/shared-module/usb_midi/PortIn.h b/shared-module/usb_midi/PortIn.h
new file mode 100644
index 000000000..2f72aa4c2
--- /dev/null
+++ b/shared-module/usb_midi/PortIn.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef SHARED_MODULE_USB_MIDI_PORTIN_H
+#define SHARED_MODULE_USB_MIDI_PORTIN_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+} usb_midi_portin_obj_t;
+
+#endif /* SHARED_MODULE_USB_MIDI_PORTIN_H */
diff --git a/shared-module/usb_midi/PortOut.c b/shared-module/usb_midi/PortOut.c
new file mode 100644
index 000000000..3b9998c73
--- /dev/null
+++ b/shared-module/usb_midi/PortOut.c
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-module/usb_midi/PortOut.h"
+#include "supervisor/shared/translate.h"
+#include "tusb.h"
+
+void common_hal_usb_midi_portout_construct(usb_midi_portout_obj_t *self) {
+}
+
+size_t common_hal_usb_midi_portout_write(usb_midi_portout_obj_t *self, const uint8_t *data, size_t len, int *errcode) {
+ return tud_midi_write(0, data, len);
+}
+
+bool common_hal_usb_midi_portout_ready_to_tx(usb_midi_portout_obj_t *self) {
+ return tud_midi_connected();
+}
diff --git a/shared-module/usb_midi/PortOut.h b/shared-module/usb_midi/PortOut.h
new file mode 100644
index 000000000..6b1b88464
--- /dev/null
+++ b/shared-module/usb_midi/PortOut.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef SHARED_MODULE_USB_MIDI_PORTOUT_H
+#define SHARED_MODULE_USB_MIDI_PORTOUT_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+} usb_midi_portout_obj_t;
+
+#endif /* SHARED_MODULE_USB_MIDI_PORTOUT_H */
diff --git a/shared-module/usb_midi/__init__.c b/shared-module/usb_midi/__init__.c
new file mode 100644
index 000000000..73a314b99
--- /dev/null
+++ b/shared-module/usb_midi/__init__.c
@@ -0,0 +1,63 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 hathach for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-bindings/usb_midi/__init__.h"
+
+#include "genhdr/autogen_usb_descriptor.h"
+#include "py/obj.h"
+#include "py/mphal.h"
+#include "py/runtime.h"
+#include "py/objtuple.h"
+#include "shared-bindings/usb_midi/PortIn.h"
+#include "shared-bindings/usb_midi/PortOut.h"
+#include "supervisor/memory.h"
+#include "tusb.h"
+
+supervisor_allocation* usb_midi_allocation;
+
+void usb_midi_init(void) {
+ // TODO(tannewt): Make this dynamic.
+ uint16_t tuple_size = align32_size(sizeof(mp_obj_tuple_t) + sizeof(mp_obj_t*) * 2);
+ uint16_t portin_size = align32_size(sizeof(usb_midi_portin_obj_t));
+ uint16_t portout_size = align32_size(sizeof(usb_midi_portout_obj_t));
+
+ // For each embedded MIDI Jack in the descriptor we create a Port
+ usb_midi_allocation = allocate_memory(tuple_size + portin_size + portout_size, false);
+
+ mp_obj_tuple_t *ports = (mp_obj_tuple_t *) usb_midi_allocation->ptr;
+ ports->base.type = &mp_type_tuple;
+ ports->len = 2;
+
+ usb_midi_portin_obj_t* in = (usb_midi_portin_obj_t *) (usb_midi_allocation->ptr + tuple_size / 4);
+ in->base.type = &usb_midi_portin_type;
+ ports->items[0] = MP_OBJ_FROM_PTR(in);
+
+ usb_midi_portout_obj_t* out = (usb_midi_portout_obj_t *) (usb_midi_allocation->ptr + tuple_size / 4 + portin_size / 4);
+ out->base.type = &usb_midi_portout_type;
+ ports->items[1] = MP_OBJ_FROM_PTR(out);
+
+ mp_map_lookup(&usb_midi_module_globals.map, MP_ROM_QSTR(MP_QSTR_ports), MP_MAP_LOOKUP)->value = MP_OBJ_FROM_PTR(ports);
+}
diff --git a/shared-module/usb_midi/__init__.h b/shared-module/usb_midi/__init__.h
new file mode 100644
index 000000000..e1ad1fbaf
--- /dev/null
+++ b/shared-module/usb_midi/__init__.h
@@ -0,0 +1,32 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef SHARED_MODULE_USB_MIDI___INIT___H
+#define SHARED_MODULE_USB_MIDI___INIT___H
+
+void usb_midi_init(void);
+
+#endif /* SHARED_MODULE_USB_MIDI___INIT___H */
diff --git a/supervisor/memory.h b/supervisor/memory.h
index 4f8317a2d..c89f14bd9 100755
--- a/supervisor/memory.h
+++ b/supervisor/memory.h
@@ -39,6 +39,8 @@ typedef struct {
uint32_t length; // in bytes
} supervisor_allocation;
+
+
void memory_init(void);
void free_memory(supervisor_allocation* allocation);
supervisor_allocation* allocate_remaining_memory(void);
@@ -48,4 +50,11 @@ supervisor_allocation* allocate_remaining_memory(void);
// statically allocated memory.
supervisor_allocation* allocate_memory(uint32_t length, bool high_address);
+static inline uint16_t align32_size(uint16_t size) {
+ if (size % 4 != 0) {
+ return (size & 0xfffc) + 0x4;
+ }
+ return size;
+}
+
#endif // MICROPY_INCLUDED_SUPERVISOR_MEMORY_H
diff --git a/supervisor/shared/usb/tusb_config.h b/supervisor/shared/usb/tusb_config.h
index 649c390ac..301805275 100644
--- a/supervisor/shared/usb/tusb_config.h
+++ b/supervisor/shared/usb/tusb_config.h
@@ -75,6 +75,7 @@
#define CFG_TUD_CDC 1
#define CFG_TUD_MSC 1
#define CFG_TUD_HID 1
+#define CFG_TUD_MIDI 1
#define CFG_TUD_CUSTOM_CLASS 0
/*------------------------------------------------------------------*/
diff --git a/supervisor/shared/usb/usb.c b/supervisor/shared/usb/usb.c
index 1aa34e9e6..5898323e8 100644
--- a/supervisor/shared/usb/usb.c
+++ b/supervisor/shared/usb/usb.c
@@ -26,6 +26,7 @@
#include "tick.h"
#include "shared-bindings/microcontroller/Processor.h"
+#include "shared-module/usb_midi/__init__.h"
#include "supervisor/port.h"
#include "supervisor/usb.h"
#include "lib/utils/interrupt_char.h"
@@ -71,11 +72,13 @@ void usb_init(void) {
// This callback always got invoked regardless of mp_interrupt_char value since we only set it once here
tud_cdc_set_wanted_char(CHAR_CTRL_C);
#endif
+
+ usb_midi_init();
}
void usb_background(void) {
if (usb_enabled()) {
- tusb_task();
+ tud_task();
tud_cdc_write_flush();
}
}
diff --git a/supervisor/supervisor.mk b/supervisor/supervisor.mk
index 56ad8a3ba..191af7b25 100644
--- a/supervisor/supervisor.mk
+++ b/supervisor/supervisor.mk
@@ -49,6 +49,7 @@ else
lib/tinyusb/src/class/msc/msc_device.c \
lib/tinyusb/src/class/cdc/cdc_device.c \
lib/tinyusb/src/class/hid/hid_device.c \
+ lib/tinyusb/src/class/midi/midi_device.c \
lib/tinyusb/src/tusb.c \
supervisor/shared/serial.c \
supervisor/usb.c \
@@ -57,8 +58,14 @@ else
supervisor/shared/usb/usb_msc_flash.c \
shared-bindings/usb_hid/__init__.c \
shared-bindings/usb_hid/Device.c \
+ shared-bindings/usb_midi/__init__.c \
+ shared-bindings/usb_midi/PortIn.c \
+ shared-bindings/usb_midi/PortOut.c \
shared-module/usb_hid/__init__.c \
shared-module/usb_hid/Device.c \
+ shared-module/usb_midi/__init__.c \
+ shared-module/usb_midi/PortIn.c \
+ shared-module/usb_midi/PortOut.c \
$(BUILD)/autogen_usb_descriptor.c
CFLAGS += -DUSB_AVAILABLE
endif
diff --git a/tools/gen_usb_descriptor.py b/tools/gen_usb_descriptor.py
index 2cb06ec2f..10bbf5066 100644
--- a/tools/gen_usb_descriptor.py
+++ b/tools/gen_usb_descriptor.py
@@ -176,16 +176,33 @@ hid_interfaces = [
]
# Audio!
-midi_in_jack = midi.InJackDescriptor(
- description="MIDI PC <- CircuitPython internals",
+# In and out here are relative to CircuitPython
+
+# USB OUT -> midi_in_jack_emb -> midi_out_jack_ext -> CircuitPython
+midi_in_jack_emb = midi.InJackDescriptor(
+ description="MIDI PC -> CircuitPython",
bJackType=midi.JACK_TYPE_EMBEDDED,
- iJack=0)
-midi_out_jack = midi.OutJackDescriptor(
- description="MIDI PC -> CircuitPython internals",
+ iJack=StringIndex.index("CircuitPython usb_midi.ports[0]"))
+midi_out_jack_ext = midi.OutJackDescriptor(
+ description="MIDI data out to user code.",
+ bJackType=midi.JACK_TYPE_EXTERNAL,
+ input_pins=[(midi_in_jack_emb, 1)],
+ iJack=0)
+
+# USB IN <- midi_out_jack_emb <- midi_in_jack_ext <- CircuitPython
+midi_in_jack_ext = midi.InJackDescriptor(
+ description="MIDI data in from user code.",
+ bJackType=midi.JACK_TYPE_EXTERNAL,
+ iJack=0)
+midi_out_jack_emb = midi.OutJackDescriptor(
+ description="MIDI PC <- CircuitPython",
bJackType=midi.JACK_TYPE_EMBEDDED,
- iJack=0)
+ input_pins=[(midi_in_jack_ext, 1)],
+ iJack=StringIndex.index("CircuitPython usb_midi.ports[1]"))
+
+
audio_midi_interface = standard.InterfaceDescriptor(
- description="All the audio",
+ description="Midi goodness",
bInterfaceClass=audio.AUDIO_CLASS_DEVICE,
bInterfaceSubClass=audio.AUDIO_SUBCLASS_MIDI_STREAMING,
bInterfaceProtocol=audio.AUDIO_PROTOCOL_V1,
@@ -193,26 +210,23 @@ audio_midi_interface = standard.InterfaceDescriptor(
subdescriptors=[
midi.Header(
jacks_and_elements=[
- midi_in_jack,
- midi.InJackDescriptor(
- description="MIDI data in from user code.",
- bJackType=midi.JACK_TYPE_EXTERNAL, iJack=0),
- midi_out_jack,
- midi.OutJackDescriptor(
- description="MIDI data out to user code.",
- bJackType=midi.JACK_TYPE_EXTERNAL, iJack=0),
- ]
+ midi_in_jack_emb,
+ midi_in_jack_ext,
+ midi_out_jack_emb,
+ midi_out_jack_ext
+ ],
),
standard.EndpointDescriptor(
- description="MIDI data out",
+ description="MIDI data out to CircuitPython",
bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_OUT,
bmAttributes=standard.EndpointDescriptor.TYPE_BULK),
- midi.DataEndpointDescriptor(baAssocJack=[midi_out_jack]),
+ midi.DataEndpointDescriptor(baAssocJack=[midi_in_jack_emb]),
standard.EndpointDescriptor(
- description="MIDI data in",
+ description="MIDI data in from CircuitPython",
bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN,
- bmAttributes=standard.EndpointDescriptor.TYPE_BULK),
- midi.DataEndpointDescriptor(baAssocJack=[midi_in_jack]),
+ bmAttributes=standard.EndpointDescriptor.TYPE_BULK,
+ bInterval = 0x0),
+ midi.DataEndpointDescriptor(baAssocJack=[midi_out_jack_emb]),
])
cs_ac_interface = audio10.AudioControlInterface(
@@ -234,12 +248,12 @@ audio_control_interface = standard.InterfaceDescriptor(
])
# Audio streaming interfaces must occur before MIDI ones.
-# audio_interfaces = [audio_control_interface] + cs_ac_interface.audio_streaming_interfaces + cs_ac_interface.midi_streaming_interfaces
+audio_interfaces = [audio_control_interface] + cs_ac_interface.audio_streaming_interfaces + cs_ac_interface.midi_streaming_interfaces
# This will renumber the endpoints to make them unique across descriptors,
# and renumber the interfaces in order. But we still need to fix up certain
# interface cross-references.
-interfaces = util.join_interfaces(cdc_interfaces, msc_interfaces, hid_interfaces)
+interfaces = util.join_interfaces(cdc_interfaces, msc_interfaces, hid_interfaces, audio_interfaces)
# Now adjust the CDC interface cross-references.
@@ -256,21 +270,13 @@ cdc_iad = standard.InterfaceAssociationDescriptor(
bFunctionSubClass=cdc.CDC_SUBCLASS_ACM, # Abstract control model
bFunctionProtocol=cdc.CDC_PROTOCOL_NONE)
-# audio_iad = standard.InterfaceAssociationDescriptor(
-# description="Audio IAD",
-# bFirstInterface=audio_control_interface.bInterfaceNumber,
-# bInterfaceCount=len(audio_interfaces),
-# bFunctionClass=audio.AUDIO_CLASS_DEVICE,
-# bFunctionSubClass=audio.AUDIO_SUBCLASS_UNKNOWN,
-# bFunctionProtocol=audio.AUDIO_PROTOCOL_V1)
-
-
descriptor_list = []
descriptor_list.append(cdc_iad)
-# descriptor_list.append(audio_iad)
descriptor_list.extend(cdc_interfaces)
descriptor_list.extend(msc_interfaces)
-# descriptor_list.append(audio_control_interface)
+# Only add the control interface because other audio interfaces are managed by it to ensure the
+# correct ordering.
+descriptor_list.append(audio_control_interface)
# Put the CDC IAD just before the CDC interfaces.
# There appears to be a bug in the Windows composite USB driver that requests the
# HID report descriptor with the wrong interface number if the HID interface is not given
diff --git a/tools/usb_descriptor b/tools/usb_descriptor
-Subproject 57bf602dac9cba8c4226f764c286cbc60103d67
+Subproject e2e79566a807b7230dddbc53a103c19b2f65e2c