aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README14
-rw-r--r--libmaple/include/libmaple/stm32.h4
-rw-r--r--libmaple/include/libmaple/usb_midi_descr.h150
-rw-r--r--libmaple/include/libmaple/usb_midi_device.h104
-rw-r--r--libmaple/stm32f2/include/series/stm32.h6
-rw-r--r--libmaple/usb/stm32f1/usb_midi_device.c498
-rw-r--r--libmaple/usb/usb_lib/usb_midi_descr.c308
-rw-r--r--support/ld/stm32/mem/sram_112k_flash_768k/mem-jtag.inc5
-rw-r--r--support/ld/stm32/mem/sram_112k_flash_768k/mem-ram.inc5
-rwxr-xr-xsupport/scripts/copy-to-ide24
-rw-r--r--wirish/boards/maple/board.mk12
-rw-r--r--wirish/include/wirish/boards.h8
-rw-r--r--wirish/include/wirish/usb_midi.h70
-rw-r--r--wirish/usb_midi.cpp139
14 files changed, 1330 insertions, 17 deletions
diff --git a/README b/README
index 400e656..33ad1a2 100644
--- a/README
+++ b/README
@@ -7,7 +7,21 @@
|_| by LeafLabs!
leaflabs.com
+/************************************************************************************
+Cloned directory with experimental modifications to Leaflabs main libmaple code
+
+Work in progress include:
+* usb-midi, currently only for stm32f1xxx targets
+* stm32f4 support, i2c is working
+* support for Netduino 2 and Netduino plus 2
+
+All experimental code needs more cleanup and testing, so it is supplied as is :)
+
+Magnus Lundin
+lundin@mlu.mine.nu
+
+*************************************************************************************/
The latest version of this repository can be found here:
https://github.com/leaflabs/libmaple
diff --git a/libmaple/include/libmaple/stm32.h b/libmaple/include/libmaple/stm32.h
index 3845cab..75acc57 100644
--- a/libmaple/include/libmaple/stm32.h
+++ b/libmaple/include/libmaple/stm32.h
@@ -77,11 +77,11 @@ extern "C" {
!defined(STM32_NR_GPIO_PORTS) || \
!defined(STM32_TIMER_MASK) || \
!defined(STM32_DELAY_US_MULT) || \
- !defined(STM32_SRAM_END) || \
+/* !defined(STM32_SRAM_END) || */ \
!defined(STM32_HAVE_DAC) || \
!defined(STM32_HAVE_FSMC) || \
!defined(STM32_HAVE_USB))
-#error "Bad STM32F1 configuration. Check <series/stm32.h> header for your MCU."
+#error "Bad STM32Fx configuration. Check <series/stm32.h> header for your MCU."
#endif
/*
diff --git a/libmaple/include/libmaple/usb_midi_descr.h b/libmaple/include/libmaple/usb_midi_descr.h
new file mode 100644
index 0000000..023b034
--- /dev/null
+++ b/libmaple/include/libmaple/usb_midi_descr.h
@@ -0,0 +1,150 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 LeafLabs LLC.
+ * Copyright (c) 2013 Magnus Lundin.
+ *
+ * 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.
+ *****************************************************************************/
+
+/**
+ * @file libmaple/include/libmaple/usb_midi_descr.h
+ * @brief USB MIDI Descriptor support
+ *
+ * IMPORTANT: this API is unstable, and may change without notice.
+ */
+
+#ifndef _LIBMAPLE_USB_MIDI_DESCR_H_
+#define _LIBMAPLE_USB_MIDI_DESCR_H_
+
+#include <libmaple/libmaple_types.h>
+#include <libmaple/usb.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * USB MIDI Requests
+ */
+
+/*
+ * Descriptors, etc.
+ */
+#define USB_DESCRIPTOR_TYPE_CS_INTERFACE 0x24
+#define USB_DESCRIPTOR_TYPE_CS_ENDPOINT 0x25
+
+
+#define USB_DEVICE_CLASS_UNDEFINED 0x00
+#define USB_DEVICE_CLASS_CDC 0x02
+#define USB_DEVICE_SUBCLASS_UNDEFINED 0x00
+
+#define USB_INTERFACE_CLASS_AUDIO 0x01
+#define USB_INTERFACE_SUBCLASS_UNDEFINED 0x00
+#define USB_INTERFACE_AUDIOCONTROL 0x01
+#define USB_INTERFACE_AUDIOSTREAMING 0x02
+#define USB_INTERFACE_MIDISTREAMING 0x03
+
+/* MIDI Streaming class specific interfaces */
+#define MIDI_IN_JACK 0x02
+#define MIDI_OUT_JACK 0x03
+
+#define MIDI_JACK_EMBEDDED 0x01
+#define MIDI_JACK_EXTERNAL 0x02
+
+
+#define USB_MIDI_DECLARE_DEV_DESC(vid, pid) \
+{ \
+.bLength = sizeof(usb_descriptor_device), \
+.bDescriptorType = USB_DESCRIPTOR_TYPE_DEVICE, \
+.bcdUSB = 0x0110, \
+.bDeviceClass = USB_DEVICE_CLASS_UNDEFINED, \
+.bDeviceSubClass = USB_DEVICE_SUBCLASS_UNDEFINED, \
+.bDeviceProtocol = 0x00, \
+.bMaxPacketSize0 = 0x40, \
+.idVendor = vid, \
+.idProduct = pid, \
+.bcdDevice = 0x0200, \
+.iManufacturer = 0x01, \
+.iProduct = 0x02, \
+.iSerialNumber = 0x00, \
+.bNumConfigurations = 0x01, \
+}
+
+#define AC_CS_INTERFACE_DESCRIPTOR_SIZE(DataSize) (8 + DataSize)
+#define AC_CS_INTERFACE_DESCRIPTOR(DataSize) \
+ struct { \
+ uint8 bLength; \
+ uint8 bDescriptorType; \
+ uint8 SubType; \
+ uint16 bcdADC; \
+ uint16 wTotalLength; \
+ uint8 bInCollection; \
+ uint8 baInterfaceNr[DataSize]; \
+ } __packed
+
+typedef struct {
+ uint8 bLength;
+ uint8 bDescriptorType;
+ uint8 SubType;
+ uint16 bcdADC;
+ uint16 wTotalLength;
+ } __packed MS_CS_INTERFACE_DESCRIPTOR;
+
+typedef struct {
+ uint8 bLength;
+ uint8 bDescriptorType;
+ uint8 SubType;
+ uint8 bJackType;
+ uint8 bJackId;
+ uint8 iJack;
+ } __packed MIDI_IN_JACK_DESCRIPTOR;
+
+#define MIDI_OUT_JACK_DESCRIPTOR_SIZE(DataSize) (7 + 2*DataSize)
+#define MIDI_OUT_JACK_DESCRIPTOR(DataSize) \
+ struct { \
+ uint8 bLength; \
+ uint8 bDescriptorType; \
+ uint8 SubType; \
+ uint8 bJackType; \
+ uint8 bJackId; \
+ uint8 bNrInputPins; \
+ uint8 baSourceId[DataSize]; \
+ uint8 baSourcePin[DataSize]; \
+ uint8 iJack; \
+ } __packed
+
+
+#define MS_CS_BULK_ENDPOINT_DESCRIPTOR_SIZE(DataSize) (4 + DataSize)
+#define MS_CS_BULK_ENDPOINT_DESCRIPTOR(DataSize) \
+ struct { \
+ uint8 bLength; \
+ uint8 bDescriptorType; \
+ uint8 SubType; \
+ uint8 bNumEmbMIDIJack; \
+ uint8 baAssocJackID[DataSize]; \
+ } __packed
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libmaple/include/libmaple/usb_midi_device.h b/libmaple/include/libmaple/usb_midi_device.h
new file mode 100644
index 0000000..3d48bd7
--- /dev/null
+++ b/libmaple/include/libmaple/usb_midi_device.h
@@ -0,0 +1,104 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 LeafLabs LLC.
+ * Copyright (c) 2013 Magnus Lundin.
+ *
+ * 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.
+ *****************************************************************************/
+
+/**
+ * @file libmaple/include/libmaple/usb_midi_device.h
+ * @brief USB MIDI support, device configuration
+ *
+ * IMPORTANT: this API is unstable, and may change without notice.
+ */
+
+#ifndef _LIBMAPLE_USB_MIDI_DEVICE_H_
+#define _LIBMAPLE_USB_MIDI_DEVICE_H_
+
+#include <libmaple/libmaple_types.h>
+#include <libmaple/gpio.h>
+#include <libmaple/usb.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef union {
+ uint8 byte[4];
+ uint32 data;
+} USB_MIDI_Event_Packet;
+
+/*
+ * USB MIDI Requests
+ */
+
+/*
+ * USB Device configuration
+ */
+
+/* FIXME move to Wirish */
+
+#define LEAFLABS_ID_VENDOR 0x1EAF
+#define MAPLE_ID_PRODUCT 0x0014
+
+#define MAX_POWER (100 >> 1)
+
+/*
+ * Endpoint configuration
+ */
+
+#define USB_MIDI_CTRL_ENDP 0
+#define USB_MIDI_CTRL_RX_ADDR 0x40
+#define USB_MIDI_CTRL_TX_ADDR 0x80
+#define USB_MIDI_CTRL_EPSIZE 0x40
+
+#define USB_MIDI_TX_ENDP 1
+#define USB_MIDI_TX_ADDR 0xC0
+#define USB_MIDI_TX_EPSIZE 0x40
+
+#define USB_MIDI_RX_ENDP 2
+#define USB_MIDI_RX_ADDR 0x100
+#define USB_MIDI_RX_EPSIZE 0x40
+
+/*
+ * MIDI interface
+ */
+
+void usb_midi_enable(gpio_dev*, uint8);
+void usb_midi_disable(gpio_dev*, uint8);
+
+void usb_midi_putc(char ch);
+uint32 usb_midi_tx(const uint8* buf, uint32 len);
+uint32 usb_midi_tx_buffered(const uint8* buf, uint32 len);
+uint32 usb_midi_rx(uint8* buf, uint32 len);
+uint32 usb_midi_peek(uint8* buf, uint32 len);
+
+uint32 usb_midi_data_available(void); /* in RX buffer */
+uint16 usb_midi_get_pending(void);
+uint8 usb_midi_is_transmitting(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libmaple/stm32f2/include/series/stm32.h b/libmaple/stm32f2/include/series/stm32.h
index 180ab30..e71e787 100644
--- a/libmaple/stm32f2/include/series/stm32.h
+++ b/libmaple/stm32f2/include/series/stm32.h
@@ -49,7 +49,7 @@ extern "C" {
#endif
#ifndef STM32_DELAY_US_MULT
-#define STM32_DELAY_US_MULT 20 /* FIXME: dummy value. */
+#define STM32_DELAY_US_MULT 40 /* 120MHz flash based program. */
#endif
/*
@@ -62,10 +62,10 @@ extern "C" {
#define STM32_HAVE_USB 1
#define STM32_HAVE_DAC 1
-#if defined(MCU_STM32F207IC) || defined(MCU_STM32F207IG)
+#if defined(MCU_STM32F207IC) || defined(MCU_STM32F207IG) || defined(MCU_STM32F205RF)
# define STM32_NR_GPIO_PORTS 9
# define STM32_TIMER_MASK 0x7FFE /* TIMER1-TIMER14. */
-# define STM32_SRAM_END ((void*)0x20020000)
+/*# define STM32_SRAM_END ((void*)0x20020000) */
#else
#warning "Unsupported or unspecified STM32F2 MCU."
#endif
diff --git a/libmaple/usb/stm32f1/usb_midi_device.c b/libmaple/usb/stm32f1/usb_midi_device.c
new file mode 100644
index 0000000..9d46cc2
--- /dev/null
+++ b/libmaple/usb/stm32f1/usb_midi_device.c
@@ -0,0 +1,498 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 LeafLabs LLC.
+ * Copyright (c) 2013 Magnus Lundin.
+ *
+ * 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.
+ *****************************************************************************/
+
+/**
+ * @file libmaple/usb/stm32f1/usb_midi_device.c
+ * @brief USB MIDI.
+ *
+ * FIXME: this works on the STM32F1 USB peripherals, and probably no
+ * place else. Nonportable bits really need to be factored out, and
+ * the result made cleaner.
+ */
+
+#define USETXBUFFER
+
+#include <libmaple/usb_midi_device.h>
+
+#include <libmaple/usb.h>
+#include <libmaple/nvic.h>
+#include <libmaple/delay.h>
+
+/* Private headers */
+#include "usb_lib_globals.h"
+#include "usb_reg_map.h"
+
+/* usb_lib headers */
+#include "usb_type.h"
+#include "usb_core.h"
+#include "usb_def.h"
+
+/******************************************************************************
+ ******************************************************************************
+ ***
+ *** HACK ALERT! FIXME FIXME FIXME FIXME!
+ ***
+ *** A bunch of LeafLabs-specific configuration lives in here for
+ *** now. This mess REALLY needs to get teased apart, with
+ *** appropriate pieces moved into Wirish.
+ ***
+ ******************************************************************************
+ *****************************************************************************/
+
+#if !(defined(BOARD_maple) || defined(BOARD_maple_RET6) || \
+ defined(BOARD_maple_mini) || defined(BOARD_maple_native))
+#warning USB MIDI relies on LeafLabs board-specific configuration.\
+ You may have problems on non-LeafLabs boards.
+#endif
+
+/* Descriptor handling functions from usb_midi_descr.c */
+extern uint8* usbGetMidiDeviceDescriptor(uint16 length);
+extern uint8* usbGetMidiConfigDescriptor(uint16 length);
+extern uint8* usbGetMidiStringDescriptor(uint16 length);
+
+/* interrupt callbacks */
+static void midiDataTxCb(void);
+static void midiDataRxCb(void);
+
+static void usbInit(void);
+static void usbReset(void);
+static RESULT usbDataSetup(uint8 request);
+static RESULT usbNoDataSetup(uint8 request);
+static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting);
+static void usbSetConfiguration(void);
+static void usbSetDeviceAddress(void);
+
+
+/* I/O state */
+
+/* Received data */
+static volatile uint8 midiBufferRx[USB_MIDI_RX_EPSIZE];
+/* Read index into midiBufferRx */
+static volatile uint32 rx_offset = 0;
+/* Transmit data */
+static volatile uint8 midiBufferTx[USB_MIDI_TX_EPSIZE];
+/* Write index into midiBufferTx */
+static volatile uint32 tx_offset = 0;
+/* Number of bytes left to transmit */
+static volatile uint32 n_unsent_bytes = 0;
+/* Are we currently sending an IN packet? */
+static volatile uint8 transmitting = 0;
+/* Number of unread bytes */
+static volatile uint32 n_unread_bytes = 0;
+
+/*
+ * Endpoint callbacks
+ */
+
+static void (*ep_int_in[7])(void) =
+ {midiDataTxCb,
+ NOP_Process,
+ NOP_Process,
+ NOP_Process,
+ NOP_Process,
+ NOP_Process,
+ NOP_Process};
+
+static void (*ep_int_out[7])(void) =
+ {NOP_Process,
+ midiDataRxCb,
+ NOP_Process,
+ NOP_Process,
+ NOP_Process,
+ NOP_Process,
+ NOP_Process};
+
+/*
+ * Globals required by usb_lib/
+ *
+ * These will override _weak defines in usb_cdcasm.c
+ *
+ */
+
+#if defined(USB_TYPE) && (USB_TYPE==USB_MIDI)
+
+#define NUM_ENDPTS 0x04
+
+DEVICE Device_Table = {
+ .Total_Endpoint = NUM_ENDPTS,
+ .Total_Configuration = 1
+};
+
+#define MAX_PACKET_SIZE 0x40 /* 64B, maximum for USB FS Devices */
+
+DEVICE_PROP Device_Property = {
+ .Init = usbInit,
+ .Reset = usbReset,
+ .Process_Status_IN = NOP_Process,
+ .Process_Status_OUT = NOP_Process,
+ .Class_Data_Setup = usbDataSetup,
+ .Class_NoData_Setup = usbNoDataSetup,
+ .Class_Get_Interface_Setting = usbGetInterfaceSetting,
+ .GetDeviceDescriptor = usbGetMidiDeviceDescriptor,
+ .GetConfigDescriptor = usbGetMidiConfigDescriptor,
+ .GetStringDescriptor = usbGetMidiStringDescriptor,
+ .RxEP_buffer = NULL,
+ .MaxPacketSize = MAX_PACKET_SIZE
+};
+
+USER_STANDARD_REQUESTS User_Standard_Requests = {
+ .User_GetConfiguration = NOP_Process,
+ .User_SetConfiguration = usbSetConfiguration,
+ .User_GetInterface = NOP_Process,
+ .User_SetInterface = NOP_Process,
+ .User_GetStatus = NOP_Process,
+ .User_ClearFeature = NOP_Process,
+ .User_SetEndPointFeature = NOP_Process,
+ .User_SetDeviceFeature = NOP_Process,
+ .User_SetDeviceAddress = usbSetDeviceAddress
+};
+
+/*
+ * MIDI interface
+ */
+
+void usb_midi_enable(gpio_dev *disc_dev, uint8 disc_bit) {
+ /* Present ourselves to the host. Writing 0 to "disc" pin must
+ * pull USB_DP pin up while leaving USB_DM pulled down by the
+ * transceiver. See USB 2.0 spec, section 7.1.7.3. */
+ gpio_set_mode(disc_dev, disc_bit, GPIO_OUTPUT_PP);
+ gpio_write_bit(disc_dev, disc_bit, 0);
+
+ /* Initialize the USB peripheral. */
+ usb_init_usblib(USBLIB, ep_int_in, ep_int_out);
+}
+
+void usb_midi_disable(gpio_dev *disc_dev, uint8 disc_bit) {
+ /* Turn off the interrupt and signal disconnect (see e.g. USB 2.0
+ * spec, section 7.1.7.3). */
+ nvic_irq_disable(NVIC_USB_LP_CAN_RX0);
+ gpio_write_bit(disc_dev, disc_bit, 1);
+}
+
+void usb_midi_putc(char ch) {
+ while (!usb_midi_tx_buffered((uint8*)&ch, 1))
+ ;
+/*
+ while (!usb_midi_tx((uint8*)&ch, 1))
+ ;
+*/
+}
+
+/* This function is non-blocking.
+ *
+ * It copies data from a usercode buffer into the USB peripheral TX
+ * buffer, and returns the number of bytes copied. */
+uint32 usb_midi_tx(const uint8* buf, uint32 len) {
+ /* Last transmission hasn't finished, so abort. */
+ if (usb_midi_is_transmitting()) {
+ /* Copy to TxBuffer */
+
+ return 0; /* return len */
+ }
+
+ /* We can only put USB_MIDI_TX_EPSIZE bytes in the buffer. */
+ if (len > USB_MIDI_TX_EPSIZE) {
+ len = USB_MIDI_TX_EPSIZE;
+ }
+
+ /* Queue bytes for sending. */
+ if (len) {
+ usb_copy_to_pma(buf, len, USB_MIDI_TX_ADDR);
+ }
+ // We still need to wait for the interrupt, even if we're sending
+ // zero bytes. (Sending zero-size packets is useful for flushing
+ // host-side buffers.)
+ usb_set_ep_tx_count(USB_MIDI_TX_ENDP, len);
+ n_unsent_bytes = len;
+ transmitting = 1;
+ usb_set_ep_tx_stat(USB_MIDI_TX_ENDP, USB_EP_STAT_TX_VALID);
+
+ return len;
+}
+
+/*
+ * Theese functions replaces EP double buffering:
+ *
+ * usb_midi_tx_buffered(const uint8* buf, uint32 len)
+ * usb_midi_tx_send_buffer()
+ *
+ * TODO: Use the modules EP double buffering instead
+ *
+ * */
+uint32 usb_midi_tx_buffered(const uint8* buf, uint32 len) {
+ if (usb_midi_is_transmitting()) {
+ uint8 count;
+ /* Copy to TxBuffer */
+ /* Disable USB EP interrupts */
+ USB_BASE->CNTR = USB_ISR_MSK&~USB_CNTR_CTRM;
+ if (len>(USB_MIDI_TX_EPSIZE-tx_offset)) len = USB_MIDI_TX_EPSIZE-tx_offset;
+ for (count=0;count<len;count++)
+ {
+ midiBufferTx[tx_offset+count]=buf[count];
+ }
+ tx_offset += len;
+ /* Reenable USB EP interrupts */
+ USB_BASE->CNTR = USB_ISR_MSK&~USB_CNTR_CTRM;
+ return len; /* return len */
+ }
+
+ /* We can only put USB_MIDI_TX_EPSIZE bytes in the buffer. */
+ if (len > USB_MIDI_TX_EPSIZE) {
+ len = USB_MIDI_TX_EPSIZE;
+ }
+
+ /* Queue bytes for sending. */
+ if (len) {
+ usb_copy_to_pma(buf, len, USB_MIDI_TX_ADDR);
+ }
+ // We still need to wait for the interrupt, even if we're sending
+ // zero bytes. (Sending zero-size packets is useful for flushing
+ // host-side buffers.)
+ usb_set_ep_tx_count(USB_MIDI_TX_ENDP, len);
+ n_unsent_bytes = len;
+ transmitting = 1;
+ usb_set_ep_tx_stat(USB_MIDI_TX_ENDP, USB_EP_STAT_TX_VALID);
+
+ return len;
+}
+
+#ifdef USETXBUFFER
+uint32 usb_midi_tx_send_buffer() {
+ if (usb_midi_is_transmitting()) {
+ return 0;
+ }
+ /* Queue bytes for sending. */
+ if (tx_offset) {
+ usb_copy_to_pma((const uint8 *)midiBufferTx, tx_offset, USB_MIDI_TX_ADDR);
+ }
+ else return 0;
+ // We still need to wait for the interrupt, even if we're sending
+ // zero bytes. (Sending zero-size packets is useful for flushing
+ // host-side buffers.)
+ usb_set_ep_tx_count(USB_MIDI_TX_ENDP, tx_offset);
+ n_unsent_bytes = tx_offset;
+ tx_offset = 0;
+ transmitting = 1;
+ usb_set_ep_tx_stat(USB_MIDI_TX_ENDP, USB_EP_STAT_TX_VALID);
+
+ return n_unsent_bytes;
+}
+#endif
+
+uint32 usb_midi_data_available(void) {
+ return n_unread_bytes;
+}
+
+uint8 usb_midi_is_transmitting(void) {
+ return transmitting;
+}
+
+uint16 usb_midi_get_pending(void) {
+ return n_unsent_bytes;
+}
+
+/* Nonblocking byte receive.
+ *
+ * Copies up to len bytes from our private data buffer (*NOT* the PMA)
+ * into buf and deq's the FIFO. */
+uint32 usb_midi_rx(uint8* buf, uint32 len) {
+ /* Copy bytes to buffer. */
+ uint32 n_copied = usb_midi_peek(buf, len);
+
+ /* Mark bytes as read. */
+ n_unread_bytes -= n_copied;
+ rx_offset += n_copied;
+
+ /* If all bytes have been read, re-enable the RX endpoint, which
+ * was set to NAK when the current batch of bytes was received. */
+ if (n_unread_bytes == 0) {
+ usb_set_ep_rx_count(USB_MIDI_RX_ENDP, USB_MIDI_RX_EPSIZE);
+ usb_set_ep_rx_stat(USB_MIDI_RX_ENDP, USB_EP_STAT_RX_VALID);
+ rx_offset = 0;
+ }
+
+ return n_copied;
+}
+
+/* Nonblocking byte lookahead.
+ *
+ * Looks at unread bytes without marking them as read. */
+uint32 usb_midi_peek(uint8* buf, uint32 len) {
+ int i;
+
+ if (len > n_unread_bytes) {
+ len = n_unread_bytes;
+ }
+
+ for (i = 0; i < len; i++) {
+ buf[i] = midiBufferRx[i + rx_offset];
+ }
+
+ return len;
+}
+
+/*
+ * Callbacks
+ */
+
+static void midiDataTxCb(void) {
+ n_unsent_bytes = 0;
+ transmitting = 0;
+#ifdef USETXBUFFER
+ usb_midi_tx_send_buffer();
+#endif
+}
+
+static void midiDataRxCb(void) {
+ usb_set_ep_rx_stat(USB_MIDI_RX_ENDP, USB_EP_STAT_RX_NAK);
+ n_unread_bytes = usb_get_ep_rx_count(USB_MIDI_RX_ENDP);
+ /* This copy won't overwrite unread bytes, since we've set the RX
+ * endpoint to NAK, and will only set it to VALID when all bytes
+ * have been read. */
+ usb_copy_from_pma((uint8*)midiBufferRx, n_unread_bytes,
+ USB_MIDI_RX_ADDR);
+
+
+ if (n_unread_bytes == 0) {
+ usb_set_ep_rx_count(USB_MIDI_RX_ENDP, USB_MIDI_RX_EPSIZE);
+ usb_set_ep_rx_stat(USB_MIDI_RX_ENDP, USB_EP_STAT_RX_VALID);
+ rx_offset = 0;
+ }
+
+}
+
+/* NOTE: Nothing specific to this device class in this function, but depenedent on the device, move to usb_lib or stm32fxx*/
+static void usbInit(void) {
+ pInformation->Current_Configuration = 0;
+
+ USB_BASE->CNTR = USB_CNTR_FRES;
+
+ USBLIB->irq_mask = 0;
+ USB_BASE->CNTR = USBLIB->irq_mask;
+ USB_BASE->ISTR = 0;
+ USBLIB->irq_mask = USB_CNTR_RESETM | USB_CNTR_SUSPM | USB_CNTR_WKUPM;
+ USB_BASE->CNTR = USBLIB->irq_mask;
+
+ USB_BASE->ISTR = 0;
+ USBLIB->irq_mask = USB_ISR_MSK;
+ USB_BASE->CNTR = USBLIB->irq_mask;
+
+ nvic_irq_enable(NVIC_USB_LP_CAN_RX0);
+ USBLIB->state = USB_UNCONNECTED;
+}
+
+#define BTABLE_ADDRESS 0x00
+static void usbReset(void) {
+ pInformation->Current_Configuration = 0;
+
+ /* current feature is current bmAttributes */
+ pInformation->Current_Feature = (USB_CONFIG_ATTR_BUSPOWERED |
+ USB_CONFIG_ATTR_SELF_POWERED);
+
+ USB_BASE->BTABLE = BTABLE_ADDRESS;
+
+ /* setup control endpoint 0 */
+ usb_set_ep_type(USB_EP0, USB_EP_EP_TYPE_CONTROL);
+ usb_set_ep_tx_stat(USB_EP0, USB_EP_STAT_TX_STALL);
+ usb_set_ep_rx_addr(USB_EP0, USB_MIDI_CTRL_RX_ADDR);
+ usb_set_ep_tx_addr(USB_EP0, USB_MIDI_CTRL_TX_ADDR);
+ usb_clear_status_out(USB_EP0);
+
+ usb_set_ep_rx_count(USB_EP0, pProperty->MaxPacketSize);
+ usb_set_ep_rx_stat(USB_EP0, USB_EP_STAT_RX_VALID);
+
+ /* TODO figure out differences in style between RX/TX EP setup */
+
+ /* set up data endpoint OUT (RX) */
+ usb_set_ep_type(USB_MIDI_RX_ENDP, USB_EP_EP_TYPE_BULK);
+ usb_set_ep_rx_addr(USB_MIDI_RX_ENDP, USB_MIDI_RX_ADDR);
+ usb_set_ep_rx_count(USB_MIDI_RX_ENDP, USB_MIDI_RX_EPSIZE);
+ usb_set_ep_rx_stat(USB_MIDI_RX_ENDP, USB_EP_STAT_RX_VALID);
+
+ /* set up data endpoint IN (TX) */
+ usb_set_ep_type(USB_MIDI_TX_ENDP, USB_EP_EP_TYPE_BULK);
+ usb_set_ep_tx_addr(USB_MIDI_TX_ENDP, USB_MIDI_TX_ADDR);
+ usb_set_ep_tx_stat(USB_MIDI_TX_ENDP, USB_EP_STAT_TX_NAK);
+ usb_set_ep_rx_stat(USB_MIDI_TX_ENDP, USB_EP_STAT_RX_DISABLED);
+
+ USBLIB->state = USB_ATTACHED;
+ SetDeviceAddress(0);
+
+ /* Reset the RX/TX state */
+ n_unread_bytes = 0;
+ n_unsent_bytes = 0;
+ rx_offset = 0;
+ tx_offset = 0;
+ transmitting = 0;
+}
+
+static RESULT usbDataSetup(uint8 request) {
+ uint8* (*CopyRoutine)(uint16) = 0;
+
+ if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) {
+
+ }
+
+ if (CopyRoutine == NULL) {
+ return USB_UNSUPPORT;
+ }
+
+ pInformation->Ctrl_Info.CopyData = CopyRoutine;
+ pInformation->Ctrl_Info.Usb_wOffset = 0;
+ (*CopyRoutine)(0);
+ return USB_SUCCESS;
+}
+
+static RESULT usbNoDataSetup(uint8 request) {
+ RESULT ret = USB_UNSUPPORT;
+
+ if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) {
+ }
+ return ret;
+}
+
+static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting) {
+ if (alt_setting > 0) {
+ return USB_UNSUPPORT;
+ } else if (interface > 1) {
+ return USB_UNSUPPORT;
+ }
+
+ return USB_SUCCESS;
+}
+
+static void usbSetConfiguration(void) {
+ if (pInformation->Current_Configuration != 0) {
+ USBLIB->state = USB_CONFIGURED;
+ }
+}
+
+static void usbSetDeviceAddress(void) {
+ USBLIB->state = USB_ADDRESSED;
+}
+
+#endif
diff --git a/libmaple/usb/usb_lib/usb_midi_descr.c b/libmaple/usb/usb_lib/usb_midi_descr.c
new file mode 100644
index 0000000..d476fd2
--- /dev/null
+++ b/libmaple/usb/usb_lib/usb_midi_descr.c
@@ -0,0 +1,308 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 LeafLabs LLC.
+ * Copyright (c) 2013 Magnus Lundin.
+ *
+ * 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.
+ *****************************************************************************/
+
+/**
+ * @file libmaple/usb/stm32f1/usb_midi_descr.c
+ * @brief USB MIDI Class descriptor.
+ *
+ * This file uses no device specific code
+ *
+ */
+
+#include <libmaple/usb_midi_device.h>
+#include <libmaple/usb_midi_descr.h>
+
+/* Private headers */
+#include "usb_lib_globals.h"
+
+/* usb_lib headers */
+#include "usb_type.h"
+#include "usb_core.h"
+#include "usb_def.h"
+
+/*
+ * Descriptors
+ */
+
+static const usb_descriptor_device usbMIDIDescriptor_Device =
+ USB_MIDI_DECLARE_DEV_DESC(LEAFLABS_ID_VENDOR, MAPLE_ID_PRODUCT);
+
+typedef struct {
+ usb_descriptor_config_header Config_Header;
+ /* Control Interface */
+ usb_descriptor_interface AC_Interface;
+ AC_CS_INTERFACE_DESCRIPTOR(1) AC_CS_Interface;
+ /* Control Interface */
+ usb_descriptor_interface MS_Interface;
+ MS_CS_INTERFACE_DESCRIPTOR MS_CS_Interface;
+ MIDI_IN_JACK_DESCRIPTOR MIDI_IN_JACK_1;
+ MIDI_IN_JACK_DESCRIPTOR MIDI_IN_JACK_2;
+ MIDI_OUT_JACK_DESCRIPTOR(1) MIDI_OUT_JACK_3;
+ MIDI_OUT_JACK_DESCRIPTOR(1) MIDI_OUT_JACK_4;
+ usb_descriptor_endpoint DataOutEndpoint;
+ MS_CS_BULK_ENDPOINT_DESCRIPTOR(1) MS_CS_DataOutEndpoint;
+ usb_descriptor_endpoint DataInEndpoint;
+ MS_CS_BULK_ENDPOINT_DESCRIPTOR(1) MS_CS_DataInEndpoint;
+} __packed usb_descriptor_config;
+
+static const usb_descriptor_config usbMIDIDescriptor_Config = {
+ .Config_Header = {
+ .bLength = sizeof(usb_descriptor_config_header),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_CONFIGURATION,
+ .wTotalLength = sizeof(usb_descriptor_config),
+ .bNumInterfaces = 0x02,
+ .bConfigurationValue = 0x01,
+ .iConfiguration = 0x00,
+ .bmAttributes = (USB_CONFIG_ATTR_BUSPOWERED |
+ USB_CONFIG_ATTR_SELF_POWERED),
+ .bMaxPower = MAX_POWER,
+ },
+
+ .AC_Interface = {
+ .bLength = sizeof(usb_descriptor_interface),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE,
+ .bInterfaceNumber = 0x00,
+ .bAlternateSetting = 0x00,
+ .bNumEndpoints = 0x00,
+ .bInterfaceClass = USB_INTERFACE_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_INTERFACE_AUDIOCONTROL,
+ .bInterfaceProtocol = 0x00,
+ .iInterface = 0x00,
+ },
+
+ .AC_CS_Interface = {
+ .bLength = AC_CS_INTERFACE_DESCRIPTOR_SIZE(1),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_CS_INTERFACE,
+ .SubType = 0x01,
+ .bcdADC = 0x0100,
+ .wTotalLength = AC_CS_INTERFACE_DESCRIPTOR_SIZE(1),
+ .bInCollection = 0x01,
+ .baInterfaceNr = {0x01},
+ },
+
+ .MS_Interface = {
+ .bLength = sizeof(usb_descriptor_interface),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE,
+ .bInterfaceNumber = 0x01,
+ .bAlternateSetting = 0x00,
+ .bNumEndpoints = 0x02,
+ .bInterfaceClass = USB_INTERFACE_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_INTERFACE_MIDISTREAMING,
+ .bInterfaceProtocol = 0x00,
+ .iInterface = 0x04,
+ },
+
+ .MS_CS_Interface = {
+ .bLength = sizeof(MS_CS_INTERFACE_DESCRIPTOR),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_CS_INTERFACE,
+ .SubType = 0x01,
+ .bcdADC = 0x0100,
+ .wTotalLength = sizeof(MS_CS_INTERFACE_DESCRIPTOR)
+ +sizeof(MIDI_IN_JACK_DESCRIPTOR)
+ +sizeof(MIDI_IN_JACK_DESCRIPTOR)
+ +MIDI_OUT_JACK_DESCRIPTOR_SIZE(1)
+ +MIDI_OUT_JACK_DESCRIPTOR_SIZE(1)
+ +sizeof(usb_descriptor_endpoint)
+ +MS_CS_BULK_ENDPOINT_DESCRIPTOR_SIZE(1)
+ +sizeof(usb_descriptor_endpoint)
+ +MS_CS_BULK_ENDPOINT_DESCRIPTOR_SIZE(1)
+ /* 0x41-4 */,
+ },
+
+ .MIDI_IN_JACK_1 = {
+ .bLength = sizeof(MIDI_IN_JACK_DESCRIPTOR),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_CS_INTERFACE,
+ .SubType = MIDI_IN_JACK,
+ .bJackType = MIDI_JACK_EMBEDDED,
+ .bJackId = 0x01,
+ .iJack = 0x05,
+ },
+
+ .MIDI_IN_JACK_2 = {
+ .bLength = sizeof(MIDI_IN_JACK_DESCRIPTOR),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_CS_INTERFACE,
+ .SubType = MIDI_IN_JACK,
+ .bJackType = MIDI_JACK_EXTERNAL,
+ .bJackId = 0x02,
+ .iJack = 0x00,
+ },
+
+ .MIDI_OUT_JACK_3 = {
+ .bLength = MIDI_OUT_JACK_DESCRIPTOR_SIZE(1),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_CS_INTERFACE,
+ .SubType = MIDI_OUT_JACK,
+ .bJackType = MIDI_JACK_EMBEDDED,
+ .bJackId = 0x03,
+ .bNrInputPins = 0x01,
+ .baSourceId = {0x02},
+ .baSourcePin = {0x01},
+ .iJack = 0x00,
+ },
+
+ .MIDI_OUT_JACK_4 = {
+ .bLength = MIDI_OUT_JACK_DESCRIPTOR_SIZE(1),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_CS_INTERFACE,
+ .SubType = MIDI_OUT_JACK,
+ .bJackType = MIDI_JACK_EXTERNAL,
+ .bJackId = 0x04,
+ .bJackId = 0x03,
+ .bNrInputPins = 0x01,
+ .baSourceId = {0x01},
+ .baSourcePin = {0x01},
+ .iJack = 0x00,
+ },
+
+ .DataOutEndpoint = {
+ .bLength = sizeof(usb_descriptor_endpoint),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT,
+ .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_OUT |
+ USB_MIDI_RX_ENDP),
+ .bmAttributes = USB_EP_TYPE_BULK,
+ .wMaxPacketSize = USB_MIDI_RX_EPSIZE,
+ .bInterval = 0x00,
+ },
+
+ .MS_CS_DataOutEndpoint = {
+ .bLength = MS_CS_BULK_ENDPOINT_DESCRIPTOR_SIZE(1),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_CS_ENDPOINT,
+ .SubType = 0x01,
+ .bNumEmbMIDIJack = 0x01,
+ .baAssocJackID = {0x01},
+ },
+
+ .DataInEndpoint = {
+ .bLength = sizeof(usb_descriptor_endpoint),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT,
+ .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_IN | USB_MIDI_TX_ENDP),
+ .bmAttributes = USB_EP_TYPE_BULK,
+ .wMaxPacketSize = USB_MIDI_TX_EPSIZE,
+ .bInterval = 0x00,
+ },
+
+ .MS_CS_DataInEndpoint = {
+ .bLength = MS_CS_BULK_ENDPOINT_DESCRIPTOR_SIZE(1),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_CS_ENDPOINT,
+ .SubType = 0x01,
+ .bNumEmbMIDIJack = 0x01,
+ .baAssocJackID = {0x03},
+ },
+
+};
+
+/*
+ String Descriptors:
+
+ we may choose to specify any or none of the following string
+ identifiers:
+
+ iManufacturer: LeafLabs
+ iProduct: Maple
+ iSerialNumber: NONE
+ iConfiguration: NONE
+ iInterface(CCI): NONE
+ iInterface(DCI): NONE
+
+*/
+
+/* Unicode language identifier: 0x0409 is US English */
+/* FIXME move to Wirish */
+static const usb_descriptor_string usbMIDIDescriptor_LangID = {
+ .bLength = USB_DESCRIPTOR_STRING_LEN(1),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
+ .bString = {0x09, 0x04},
+};
+
+/* FIXME move to Wirish */
+static const usb_descriptor_string usbMIDIDescriptor_iManufacturer = {
+ .bLength = USB_DESCRIPTOR_STRING_LEN(8),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
+ .bString = {'L', 0, 'e', 0, 'a', 0, 'f', 0,
+ 'L', 0, 'a', 0, 'b', 0, 's', 0},
+};
+
+/* FIXME move to Wirish */
+static const usb_descriptor_string usbMIDIDescriptor_iProduct = {
+ .bLength = USB_DESCRIPTOR_STRING_LEN(10),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
+ .bString = {'M', 0, 'a', 0, 'p', 0, 'l', 0, 'e', 0, ' ', 0, 'M', 0, 'I', 0, 'D', 0, 'I', 0},
+};
+
+/* FIXME move to Wirish */
+static const usb_descriptor_string usbMIDIDescriptor_iInterface = {
+ .bLength = USB_DESCRIPTOR_STRING_LEN(4),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
+ .bString = {'M', 0, 'I', 0, 'D', 0, 'I', 0},
+};
+
+/* FIXME move to Wirish */
+static const usb_descriptor_string usbMIDIDescriptor_iJack1 = {
+ .bLength = USB_DESCRIPTOR_STRING_LEN(5),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
+ .bString = {'J', 0, 'a', 0, 'c', 0, 'k', 0, '1', 0},
+};
+
+
+static ONE_DESCRIPTOR Device_Descriptor = {
+ (uint8*)&usbMIDIDescriptor_Device,
+ sizeof(usb_descriptor_device)
+};
+
+static ONE_DESCRIPTOR Config_Descriptor = {
+ (uint8*)&usbMIDIDescriptor_Config,
+ sizeof(usb_descriptor_config)
+};
+
+#define N_STRING_DESCRIPTORS 5
+static ONE_DESCRIPTOR String_Descriptor[N_STRING_DESCRIPTORS] = {
+ {(uint8*)&usbMIDIDescriptor_LangID, USB_DESCRIPTOR_STRING_LEN(1)},
+ {(uint8*)&usbMIDIDescriptor_iManufacturer,USB_DESCRIPTOR_STRING_LEN(8)},
+ {(uint8*)&usbMIDIDescriptor_iProduct, USB_DESCRIPTOR_STRING_LEN(10)},
+ {(uint8*)&usbMIDIDescriptor_iInterface, USB_DESCRIPTOR_STRING_LEN(4)},
+ {(uint8*)&usbMIDIDescriptor_iJack1, USB_DESCRIPTOR_STRING_LEN(5)}
+};
+
+/*
+ * Funtions to access the descriptor structures
+ */
+
+uint8* usbGetMidiDeviceDescriptor(uint16 length) {
+ return Standard_GetDescriptorData(length, &Device_Descriptor);
+}
+
+uint8* usbGetMidiConfigDescriptor(uint16 length) {
+ return Standard_GetDescriptorData(length, &Config_Descriptor);
+}
+
+uint8* usbGetMidiStringDescriptor(uint16 length) {
+ uint8 wValue0 = pInformation->USBwValue0;
+
+ if (wValue0 > N_STRING_DESCRIPTORS) {
+ return NULL;
+ }
+ return Standard_GetDescriptorData(length, &String_Descriptor[wValue0]);
+}
+
diff --git a/support/ld/stm32/mem/sram_112k_flash_768k/mem-jtag.inc b/support/ld/stm32/mem/sram_112k_flash_768k/mem-jtag.inc
new file mode 100644
index 0000000..d62fb7a
--- /dev/null
+++ b/support/ld/stm32/mem/sram_112k_flash_768k/mem-jtag.inc
@@ -0,0 +1,5 @@
+MEMORY
+{
+ ram (rwx) : ORIGIN = 0x20000000, LENGTH = 112K
+ rom (rx) : ORIGIN = 0x08000000, LENGTH = 768K
+}
diff --git a/support/ld/stm32/mem/sram_112k_flash_768k/mem-ram.inc b/support/ld/stm32/mem/sram_112k_flash_768k/mem-ram.inc
new file mode 100644
index 0000000..d21f17c
--- /dev/null
+++ b/support/ld/stm32/mem/sram_112k_flash_768k/mem-ram.inc
@@ -0,0 +1,5 @@
+MEMORY
+{
+ ram (rwx) : ORIGIN = 0x20000000, LENGTH = 112K
+ rom (rx) : ORIGIN = 0x08000000, LENGTH = 0K
+}
diff --git a/support/scripts/copy-to-ide b/support/scripts/copy-to-ide
index e68abca..3f28dfe 100755
--- a/support/scripts/copy-to-ide
+++ b/support/scripts/copy-to-ide
@@ -13,23 +13,24 @@ LMAPLE_SRC="LICENSE
./libmaple/*.h
./libmaple/*.c
./libmaple/*.S
+ ./wirish/*.h
+ ./wirish/main.cxx
+ ./wirish/*.cpp
./libmaple/usb/*.h
./libmaple/usb/*.c
./libmaple/usb/usb_lib/*.h
./libmaple/usb/usb_lib/*.c
- ./wirish/*.h
- ./wirish/main.cxx
- ./wirish/*.cpp
./wirish/comm/*.cpp
./wirish/comm/*.h
- ./wirish/boards/*.h
- ./wirish/boards/*.cpp
- ./support/ld/common.inc
- ./support/ld/maple
- ./support/ld/maple_mini
- ./support/ld/maple_native
- ./support/ld/maple_RET6
- ./support/ld/names.inc"
+ ./wirish/boards
+ ./libmaple/include
+ ./wirish/include
+ ./ld/common.inc
+ ./ld/maple
+ ./ld/maple_mini
+ ./ld/maple_native
+ ./ld/maple_RET6
+ ./ld/names.inc"
echo "First make sure DEST exists: $DEST"
if !(test -d $DEST)
@@ -42,6 +43,7 @@ fi
echo Copying libmaple source
rm -rf $DEST_CORES/*.c $DEST_CORES/*.cpp $DEST_CORES/*.h $DEST_CORES/*.cxx $DEST_CORES/*.S
rm -rf $DEST_CORES/*.inc $DEST_CORES/*.a $DEST_CORES/maple $DEST_CORES/maple_*
+mkdir -p $DEST_CORES
cp -R $LMAPLE_SRC $DEST_CORES
echo Copying over libraries
diff --git a/wirish/boards/maple/board.mk b/wirish/boards/maple/board.mk
new file mode 100644
index 0000000..e31d777
--- /dev/null
+++ b/wirish/boards/maple/board.mk
@@ -0,0 +1,12 @@
+# Board specific make defines for Maple board
+
+CPU = cortex-m3
+ARCH = armv7-m
+MCU_SERIES = stm32f1
+MCU = MCU_STM32F103RB
+MEMORY = sram_20k_flash_128k
+ifeq ($(TARGET),jtag)
+DFUID = 0483:df11
+DFUALT = 0
+endif
+
diff --git a/wirish/include/wirish/boards.h b/wirish/include/wirish/boards.h
index 6676a02..693c739 100644
--- a/wirish/include/wirish/boards.h
+++ b/wirish/include/wirish/boards.h
@@ -167,7 +167,13 @@ bool boardUsesPin(uint8 pin);
/**
* @brief Feature test: nonzero iff the board has SerialUSB.
*/
-#define BOARD_HAVE_SERIALUSB (defined(BOARD_USB_DISC_DEV) && \
+#ifndef BOARD_HAVE_USB
+#define BOARD_HAVE_USB (defined(BOARD_USB_DISC_DEV) && \
defined(BOARD_USB_DISC_BIT))
+#endif
+
+#define BOARD_HAVE_SERIALUSB (BOARD_HAVE_USB && \
+ ((defined(USB_TYPE) && USB_TYPE == USB_SERIAL) || \
+ !defined(USB_TYPE)))
#endif
diff --git a/wirish/include/wirish/usb_midi.h b/wirish/include/wirish/usb_midi.h
new file mode 100644
index 0000000..0e2d4f0
--- /dev/null
+++ b/wirish/include/wirish/usb_midi.h
@@ -0,0 +1,70 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2010 Perry Hung.
+ * Copyright (c) 2013 Magnus Lundin.
+ *
+ * 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.
+ *****************************************************************************/
+
+/**
+ * @brief Wirish USB MIDI port (MidiUSB).
+ */
+
+#ifndef _WIRISH_USB_MIDI_H_
+#define _WIRISH_USB_MIDI_H_
+
+#include <wirish/Print.h>
+#include <wirish/boards.h>
+
+#define BOARD_HAVE_MIDIUSB (BOARD_HAVE_USB && \
+ defined(USB_TYPE) && \
+ (USB_TYPE == USB_MIDI))
+
+/**
+ * @brief Virtual serial terminal.
+ */
+class USBMidi : public Print {
+public:
+ USBMidi(void);
+
+ void begin(void);
+ void end(void);
+
+ uint32 available(void);
+
+ uint32 read(void *buf, uint32 len);
+ uint8 read(void);
+
+ void write(uint8);
+ void write(const char *str);
+ void write(const void*, uint32);
+
+ uint8 isConnected();
+ uint8 pending();
+};
+
+#if BOARD_HAVE_MIDIUSB
+extern USBMidi MidiUSB;
+#endif
+
+#endif
+
diff --git a/wirish/usb_midi.cpp b/wirish/usb_midi.cpp
new file mode 100644
index 0000000..5a48efb
--- /dev/null
+++ b/wirish/usb_midi.cpp
@@ -0,0 +1,139 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2010 Perry Hung.
+ * Copyright (c) 2013 Magnus Lundin.
+ *
+ * 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.
+ *****************************************************************************/
+
+/**
+ * @brief USB MIDI device
+ */
+
+#include <wirish/usb_midi.h>
+
+#include <string.h>
+#include <stdint.h>
+
+#include <libmaple/nvic.h>
+#include <libmaple/usb_midi_device.h>
+#include <libmaple/usb.h>
+
+#include <wirish/wirish.h>
+
+/*
+ * USBMidi interface
+ */
+
+#define USB_TIMEOUT 50
+
+USBMidi::USBMidi(void) {
+#if !BOARD_HAVE_MIDIUSB
+ ASSERT(0);
+#endif
+}
+
+void USBMidi::begin(void) {
+#if BOARD_HAVE_MIDIUSB
+ usb_midi_enable(BOARD_USB_DISC_DEV, BOARD_USB_DISC_BIT);
+#endif
+}
+
+void USBMidi::end(void) {
+#if BOARD_HAVE_MIDIUSB
+ usb_midi_disable(BOARD_USB_DISC_DEV, BOARD_USB_DISC_BIT);
+#endif
+}
+
+void USBMidi::write(uint8 ch) {
+ this->write(&ch, 1);
+}
+
+void USBMidi::write(const char *str) {
+ this->write(str, strlen(str));
+}
+
+void USBMidi::write(const void *buf, uint32 len) {
+ if (!this->isConnected() || !buf) {
+ return;
+ }
+
+ uint32 txed = 0;
+ uint32 old_txed = 0;
+ uint32 start = millis();
+
+ uint32 sent = 0;
+
+ while (txed < len && (millis() - start < USB_TIMEOUT)) {
+// sent = usb_midi_tx_buffered((const uint8*)buf + txed, len - txed);
+ sent = usb_midi_tx((const uint8*)buf + txed, len - txed);
+ txed += sent;
+ if (old_txed != txed) {
+ start = millis();
+ }
+ old_txed = txed;
+ }
+
+
+ if (sent == USB_MIDI_TX_EPSIZE) {
+ while (usb_midi_is_transmitting() != 0) {
+ }
+ /* flush out to avoid having the pc wait for more data */
+ usb_midi_tx(NULL, 0);
+ }
+}
+
+uint32 USBMidi::available(void) {
+ return usb_midi_data_available();
+}
+
+uint32 USBMidi::read(void *buf, uint32 len) {
+ if (!buf) {
+ return 0;
+ }
+
+ uint32 rxed = 0;
+ while (rxed < len) {
+ rxed += usb_midi_rx((uint8*)buf + rxed, len - rxed);
+ }
+
+ return rxed;
+}
+
+/* Blocks forever until 1 byte is received */
+uint8 USBMidi::read(void) {
+ uint8 b;
+ this->read(&b, 1);
+ return b;
+}
+
+uint8 USBMidi::pending(void) {
+ return usb_midi_get_pending();
+}
+
+uint8 USBMidi::isConnected(void) {
+ return usb_is_connected(USBLIB) && usb_is_configured(USBLIB);
+}
+
+#if BOARD_HAVE_MIDIUSB
+USBMidi MidiUSB;
+#endif