From 043127c40def3b5819dd4742b078e614bce9c1c2 Mon Sep 17 00:00:00 2001 From: Donald Delmar Davis Date: Fri, 26 Apr 2013 16:17:40 -0700 Subject: We are very close to functional. Midi output works, sysex debugging needs to be revisited. --- libmaple/include/libmaple/usb_midi_device.c | 687 ---------------------------- libmaple/include/libmaple/usb_midi_device.h | 28 +- libmaple/usb/stm32f1/usb_midi_device.c | 79 ++++ libmaple/usb_midi_device.h | 199 -------- wirish/usb_midi.cpp | 52 +-- 5 files changed, 105 insertions(+), 940 deletions(-) delete mode 100644 libmaple/include/libmaple/usb_midi_device.c delete mode 100644 libmaple/usb_midi_device.h diff --git a/libmaple/include/libmaple/usb_midi_device.c b/libmaple/include/libmaple/usb_midi_device.c deleted file mode 100644 index 1a13148..0000000 --- a/libmaple/include/libmaple/usb_midi_device.c +++ /dev/null @@ -1,687 +0,0 @@ -/****************************************************************************** - * 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. - */ - -#include -#include - -#include -#include -#include - -/* 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 - -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 uint8* usbGetDeviceDescriptor(uint16 length); -static uint8* usbGetConfigDescriptor(uint16 length); -static uint8* usbGetStringDescriptor(uint16 length); -static void usbSetConfiguration(void); -static void usbSetDeviceAddress(void); - -/* - * Descriptors - */ - -/* FIXME move to Wirish */ -#define LEAFLABS_ID_VENDOR 0x1EAF -#define MAPLE_ID_PRODUCT 0x0014 -/* 0x7D = ED/FREE next two DIGITS MUST BE LESS THAN 0x7f */ -#define LEAFLABS_MMA_VENDOR_1 0x7D -#define LEAFLABS_MMA_VENDOR_2 0x1E -#define LEAFLABS_MMA_VENDOR_3 0x4F - -#define DEFAULT_MIDI_CHANNEL 0x0A -#define DEFAULT_MIDI_DEVICE 0x0A -#define DEFAULT_MIDI_CABLE 0x00 - -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; - -#define MAX_POWER (100 >> 1) -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)} -}; - -/* - * Etc. - */ - -/* 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/ - * - * Mark these weak so they can be overriden to implement other USB - * functionality. - */ - -#define NUM_ENDPTS 0x04 -__weak DEVICE Device_Table = { - .Total_Endpoint = NUM_ENDPTS, - .Total_Configuration = 1 -}; - -#define MAX_PACKET_SIZE 0x40 /* 64B, maximum for USB FS Devices */ -__weak 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 = usbGetDeviceDescriptor, - .GetConfigDescriptor = usbGetConfigDescriptor, - .GetStringDescriptor = usbGetStringDescriptor, - .RxEP_buffer = NULL, - .MaxPacketSize = MAX_PACKET_SIZE -}; - -__weak 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((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; -} - -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; -} - -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); - - lgl_sysex_handler(midiBuferRX,&rx_offset,&n_unread_bytes); - - 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, move to usb_lib */ -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; -} - -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 uint8* usbGetDeviceDescriptor(uint16 length) { - return Standard_GetDescriptorData(length, &Device_Descriptor); -} - -static uint8* usbGetConfigDescriptor(uint16 length) { - return Standard_GetDescriptorData(length, &Config_Descriptor); -} - -static uint8* usbGetStringDescriptor(uint16 length) { - uint8 wValue0 = pInformation->USBwValue0; - - if (wValue0 > N_STRING_DESCRIPTORS) { - return NULL; - } - return Standard_GetDescriptorData(length, &String_Descriptor[wValue0]); -} - -static void usbSetConfiguration(void) { - if (pInformation->Current_Configuration != 0) { - USBLIB->state = USB_CONFIGURED; - } -} - -static void usbSetDeviceAddress(void) { - USBLIB->state = USB_ADDRESSED; -} diff --git a/libmaple/include/libmaple/usb_midi_device.h b/libmaple/include/libmaple/usb_midi_device.h index 63e886d..84374e0 100644 --- a/libmaple/include/libmaple/usb_midi_device.h +++ b/libmaple/include/libmaple/usb_midi_device.h @@ -36,11 +36,9 @@ #define _LIBMAPLE_USB_MIDI_H_ #include -#include -#include #include #include - +#include #ifdef __cplusplus extern "C" { @@ -182,17 +180,19 @@ typedef struct { * 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 uint32* buf, uint32 len); -uint32 usb_midi_rx(uint32* buf, uint32 len); -uint32 usb_midi_peek(uint32* buf, uint32 len); - -uint32 usb_midi_data_available(void); /* in RX buffer */ -uint16 usb_midi_get_pending(void); -uint8 usb_midi_is_transmitting(void); + 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 uint32* buf, uint32 len); + uint32 usb_midi_rx(uint32* buf, uint32 len); + uint32 usb_midi_peek(uint32* buf, uint32 len); + + uint32 usb_midi_data_available(void); /* in RX buffer */ + uint16 usb_midi_get_pending(void); + uint8 usb_midi_is_transmitting(void); + + void sendThroughSysex(char *printbuffer, int bufferlength); #ifdef __cplusplus } diff --git a/libmaple/usb/stm32f1/usb_midi_device.c b/libmaple/usb/stm32f1/usb_midi_device.c index 0c26cb0..df79f05 100644 --- a/libmaple/usb/stm32f1/usb_midi_device.c +++ b/libmaple/usb/stm32f1/usb_midi_device.c @@ -35,6 +35,7 @@ */ #include +#include #include #include @@ -686,3 +687,81 @@ static void usbSetConfiguration(void) { static void usbSetDeviceAddress(void) { USBLIB->state = USB_ADDRESSED; } +// .............THIS IS NOT WORKING YET................ +// send debugging information to +static uint8_t sysexbuffer[80]={CIN_SYSEX,0xF0,0x7D,0x33,CIN_SYSEX,0x33,0x00,0xf7}; // !!!bad hardcoded number foo !!! +uint8_t iSysHexLine(uint8_t rectype, uint16_t address, uint8_t *payload,uint8_t payloadlength, uint8_t *buffer); +void sendThroughSysex(char *printbuffer, int bufferlength) { + int i,n; + n = iSysHexLine(1, 0 , (uint8_t *) printbuffer, (uint8_t) bufferlength , sysexbuffer+6); + usb_midi_tx((uint32*)sysexbuffer,n/4); +} + +#define HIGHBYTE(x) ((uint8_t) (((x) >> 8) & 0x00ff) ) +#define LOWBYTE(x) ((uint8_t) ((x) & 0x00ff) ) +#define HIGHNIBBLE(x) ((((uint8_t)(x)) & 0xF0) >> 4) +#define LOWNIBBLE(x) (((uint8_t)(x)) & 0x0F) +#define HEXCHAR(c) ((c>9)?55+c:48+c) + + +uint8_t iSysHexLine(uint8_t rectype, uint16_t address, uint8_t *payload,uint8_t payloadlength, uint8_t *buffer) { + + int i=0; int j; int thirdone; + uint8_t n=0; + uint16_t checksum=0; + //uint16_t length=0; + + buffer[i++]=':'; + + checksum+=payloadlength; + buffer[i++]=HEXCHAR(HIGHNIBBLE(payloadlength)); + buffer[i++]=HEXCHAR(LOWNIBBLE(payloadlength)); + buffer[i++]=CIN_SYSEX; + + n=HIGHBYTE(address); + checksum+=n; + buffer[i++]=HEXCHAR(HIGHNIBBLE(n)); + buffer[i++]=HEXCHAR(LOWNIBBLE(n)); + + n=LOWBYTE(address); + checksum+=n; + buffer[i++]=HEXCHAR(HIGHNIBBLE(n)); + buffer[i++]=CIN_SYSEX; + buffer[i++]=HEXCHAR(LOWNIBBLE(n)); + + n=rectype; + checksum+=n; + buffer[i++]=HEXCHAR(HIGHNIBBLE(n)); + buffer[i++]=HEXCHAR(LOWNIBBLE(n)); + buffer[i++]=CIN_SYSEX; + thirdone=0; + for (j=0; j -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef union { - uint8 byte[4]; - uint32 data; -} USB_MIDI_Event_Packet; - -/* - * 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 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 - -/* - * 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 - -#ifndef __cplusplus -#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, \ - } -#endif - -/* - * Sysex Stuff. - */ - -#define SYSEX_BUFFER_LENGTH 256 - - - /* - * MIDI interface - */ - -void usb_midi_enable(gpio_dev*, uint8); -void usb_midi_disable(gpio_dev*, uint8); -bogus -void usb_midi_putc(char ch); -uint32 usb_midi_tx(const uint32* buf, uint32 len); -uint32 usb_midi_rx(const uint32* buf, uint32 len); -uint32 usb_midi_peek(const uint32* 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/wirish/usb_midi.cpp b/wirish/usb_midi.cpp index 6926639..f0a797f 100644 --- a/wirish/usb_midi.cpp +++ b/wirish/usb_midi.cpp @@ -25,6 +25,9 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * + * This is a munging of Tymm's arduino Midi Library into the Libusb class. + * I am not sure this is the right way to go especially since its licensed differently. + * * Midi.cpp: Code for MIDI processing library, Arduino version * * (c) 2003-2008 Tymm Twillman @@ -49,7 +52,7 @@ *****************************************************************************/ /** - * @brief USB MIDI device + * @brief USB MIDI device with a class compatible with maplemidi */ #include @@ -108,10 +111,6 @@ void USBMidi::writePacket(uint32 p) { this->writePackets(&p, 1); } -//void USBMidi::write(const char *str) { -// this->write(str, strlen(str)); -//} - void USBMidi::writePackets(const void *buf, uint32 len) { if (!this->isConnected() || !buf) { return; @@ -183,25 +182,7 @@ USBMidi MidiUSB; static const int MODE_PROPRIETARY = 0xff; -// These are midi status message types as sent on the wire -static const int STATUS_EVENT_NOTE_OFF = 0x80; -static const int STATUS_EVENT_NOTE_ON = 0x90; -static const int STATUS_EVENT_VELOCITY_CHANGE = 0xA0; -static const int STATUS_EVENT_CONTROL_CHANGE = 0xB0; -static const int STATUS_EVENT_PROGRAM_CHANGE = 0xC0; -static const int STATUS_AFTER_TOUCH = 0xD0; -static const int STATUS_PITCH_CHANGE = 0xE0; -static const int STATUS_START_PROPRIETARY = 0xF0; -static const int STATUS_SONG_POSITION = 0xF2; -static const int STATUS_SONG_SELECT = 0xF3; -static const int STATUS_TUNE_REQUEST = 0xF6; -static const int STATUS_END_PROPRIETARY = 0xF7; -static const int STATUS_SYNC = 0xF8; -static const int STATUS_START = 0xFA; -static const int STATUS_CONTINUE = 0xFB; -static const int STATUS_STOP = 0xFC; -static const int STATUS_ACTIVE_SENSE = 0xFE; -static const int STATUS_RESET = 0xFF; +// These are midi status message types are defined in MidiSpec.h union EVENT_t { uint32 i; @@ -220,17 +201,16 @@ void USBMidi::dispatchPacket(uint32 p) union EVENT_t e; e.i=p; - // !!!!!!!!!!!!!!!! FIX THIS VERY VERY SHORTLY !!!!!!!!!!!!!! + // !!!!!!!!!!!!!!!! Add a sysex handler FIX THIS VERY VERY SHORTLY !!!!!!!!!!!!!! if (recvMode_ & MODE_PROPRIETARY && CIN_IS_SYSEX(e.p.cin)) { - /* If proprietary handling compiled in, just pass all data received - * after a START_PROPRIETARY event to proprietary_decode - * until get an END_PROPRIETARY event + /* If sysex handling compiled in, just pass all data received + * to the sysex handler */ #ifdef CONFIG_MIDI_PROPRIETARY - proprietaryDecode(byte); +// handleSysex(p); #endif return; @@ -249,6 +229,7 @@ void USBMidi::dispatchPacket(uint32 p) handleSongSelect(e.p.midi1); break; case MIDIv1_MTC_QUARTER_FRAME: + // reference library doesnt handle quarter frame. break; } break; @@ -296,7 +277,7 @@ void USBMidi::dispatchPacket(uint32 p) case MIDIv1_RESET: handleReset(); break; - case STATUS_TUNE_REQUEST: + case MIDIv1_TUNE_REQUEST: handleTuneRequest(); break; @@ -315,7 +296,7 @@ void USBMidi::poll(void) } } -static union EVENT_t outPacket; +static union EVENT_t outPacket; // since we only use one at a time no point in reallocating it // Send Midi NOTE OFF message to a given channel, with note 0-127 and velocity 0-127 void USBMidi::sendNoteOff(unsigned int channel, unsigned int note, unsigned int velocity) @@ -495,14 +476,6 @@ void USBMidi::sendReset(void) } -// Open the serial port and begin processing. -//void Midi::begin(unsigned int channel, unsigned long baud) -//{ -// channelIn_ = channel; -// serial_.begin(baud); -//} - - // Set (package-specific) parameters for the Midi instance void USBMidi::setParam(unsigned int param, unsigned int val) { @@ -530,7 +503,6 @@ unsigned int USBMidi::getParam(unsigned int param) return 0; } - // Placeholders. You should subclass the Midi base class and define these to have your // version called. void USBMidi::handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity) {} -- cgit v1.2.3