A library to send and receive MIDI messages over USB using the default USB-MIDI drivers on Win/Mac

Dependents:   USBMIDI_HelloWorld USBMIDI_DrumExample USBMIDI_MonoSynth MIDI_Interface_ver_1 ... more

Committer:
simon
Date:
Sun Feb 20 13:10:05 2011 +0000
Revision:
1:ff74eabe02cd
Child:
2:10d694d6ccdc
First version, supporting most USB MIDI functionality

Who changed what in which revision?

UserRevisionLine numberNew contents of line
simon 1:ff74eabe02cd 1 /** @license The MIT License
simon 1:ff74eabe02cd 2 * Copyright (c) 2011 mux, simon
simon 1:ff74eabe02cd 3 *
simon 1:ff74eabe02cd 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
simon 1:ff74eabe02cd 5 * of this software and associated documentation files (the "Software"), to deal
simon 1:ff74eabe02cd 6 * in the Software without restriction, including without limitation the rights
simon 1:ff74eabe02cd 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
simon 1:ff74eabe02cd 8 * copies of the Software, and to permit persons to whom the Software is
simon 1:ff74eabe02cd 9 * furnished to do so, subject to the following conditions:
simon 1:ff74eabe02cd 10 *
simon 1:ff74eabe02cd 11 * The above copyright notice and this permission notice shall be included in
simon 1:ff74eabe02cd 12 * all copies or substantial portions of the Software.
simon 1:ff74eabe02cd 13 *
simon 1:ff74eabe02cd 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
simon 1:ff74eabe02cd 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
simon 1:ff74eabe02cd 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
simon 1:ff74eabe02cd 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
simon 1:ff74eabe02cd 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
simon 1:ff74eabe02cd 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
simon 1:ff74eabe02cd 20 * THE SOFTWARE.
simon 1:ff74eabe02cd 21 */
simon 1:ff74eabe02cd 22
simon 1:ff74eabe02cd 23 #include "usbcore.h"
simon 1:ff74eabe02cd 24 #include "mbed.h"
simon 1:ff74eabe02cd 25
simon 1:ff74eabe02cd 26 #define STANDARD_DEVICE_REQUEST (0x00)
simon 1:ff74eabe02cd 27 #define STANDARD_INTERFACE_REQUEST (0x01)
simon 1:ff74eabe02cd 28 #define STANDARD_ENDPOINT_REQUEST (0x02)
simon 1:ff74eabe02cd 29 #define CLASS_DEVICE_REQUEST (0x20)
simon 1:ff74eabe02cd 30 #define CLASS_INTERFACE_REQUEST (0x21)
simon 1:ff74eabe02cd 31 #define CLASS_ENDPOINT_REQUEST (0x22)
simon 1:ff74eabe02cd 32 #define VENDOR_DEVICE_REQUEST (0x40)
simon 1:ff74eabe02cd 33 #define VENDOR_INTERFACE_REQUEST (0x41)
simon 1:ff74eabe02cd 34 #define VENDOR_ENDPOINT_REQUEST (0x42)
simon 1:ff74eabe02cd 35 #define GET_STATUS (0x00)
simon 1:ff74eabe02cd 36 #define CLEAR_FEATURE (0x01)
simon 1:ff74eabe02cd 37 #define SET_FEATURE (0x03)
simon 1:ff74eabe02cd 38 #define SET_ADDRESS (0x05)
simon 1:ff74eabe02cd 39 #define GET_DESCRIPTOR (0x06)
simon 1:ff74eabe02cd 40 #define SET_DESCRIPTOR (0x07)
simon 1:ff74eabe02cd 41 #define GET_CONFIGURATION (0x08)
simon 1:ff74eabe02cd 42 #define SET_CONFIGURATION (0x09)
simon 1:ff74eabe02cd 43 #define DEVICE_DESCRIPTOR (0x01)
simon 1:ff74eabe02cd 44 #define CONFIG_DESCRIPTOR (0x02)
simon 1:ff74eabe02cd 45 #define STRING_DESCRIPTOR (0x03)
simon 1:ff74eabe02cd 46 #define INTERFACE_DESCRIPTOR (0x04)
simon 1:ff74eabe02cd 47 #define ENDPOINT_DESCRIPTOR (0x05)
simon 1:ff74eabe02cd 48 #define QUALIFIER_DESCRIPTOR (0x06)
simon 1:ff74eabe02cd 49 #define unpack(x) (x & 0xFF),((x >> 8) & 0xFF)
simon 1:ff74eabe02cd 50
simon 1:ff74eabe02cd 51 // setup packet
simon 1:ff74eabe02cd 52 struct {
simon 1:ff74eabe02cd 53 uint8_t bmRequestType;
simon 1:ff74eabe02cd 54 uint8_t bRequest;
simon 1:ff74eabe02cd 55 uint16_t wValue;
simon 1:ff74eabe02cd 56 uint16_t wIndex;
simon 1:ff74eabe02cd 57 uint16_t wLength;
simon 1:ff74eabe02cd 58 } __attribute__((packed)) setup = {0};
simon 1:ff74eabe02cd 59
simon 1:ff74eabe02cd 60 // data packet
simon 1:ff74eabe02cd 61 struct {
simon 1:ff74eabe02cd 62 uint8_t *data;
simon 1:ff74eabe02cd 63 uint8_t size;
simon 1:ff74eabe02cd 64 uint8_t sent;
simon 1:ff74eabe02cd 65 } transfer = {0};
simon 1:ff74eabe02cd 66
simon 1:ff74eabe02cd 67 uint8_t device_descriptor[] = {
simon 1:ff74eabe02cd 68 0x12, // Descriptor size in bytes (12h)
simon 1:ff74eabe02cd 69 DEVICE_DESCRIPTOR, // The constant DEVICE (01h)
simon 1:ff74eabe02cd 70 unpack(0x0200), // US2B specification release number (BCD)
simon 1:ff74eabe02cd 71 0x00, // Class code
simon 1:ff74eabe02cd 72 0x00, // Subclass code
simon 1:ff74eabe02cd 73 0x00, // Protocol Code
simon 1:ff74eabe02cd 74 MAX_EP0_PSIZE, // Maximum packet size for endpoint zero
simon 1:ff74eabe02cd 75 unpack(0x0763), // Vendor ID
simon 1:ff74eabe02cd 76 unpack(0x0198), // Product ID
simon 1:ff74eabe02cd 77 unpack(0x0001), // Device release number (BCD)
simon 1:ff74eabe02cd 78 0x00, // Index of string descriptor for the manufacturer
simon 1:ff74eabe02cd 79 0x00, // Index of string descriptor for the product
simon 1:ff74eabe02cd 80 0x00, // Index of string descriptor for the serial number
simon 1:ff74eabe02cd 81 0x01, // Number of possible configurations
simon 1:ff74eabe02cd 82 };
simon 1:ff74eabe02cd 83
simon 1:ff74eabe02cd 84 uint8_t config_descriptor[]={
simon 1:ff74eabe02cd 85 0x09, 0x02, 0x65, 0x00, 0x02, 0x01, 0x00, 0xc0, 0x50, // configuration descriptor
simon 1:ff74eabe02cd 86 // The Audio Interface Collection
simon 1:ff74eabe02cd 87 0x09, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, // Standard AC Interface Descriptor
simon 1:ff74eabe02cd 88 0x09, 0x24, 0x01, 0x00, 0x01, 0x09, 0x00, 0x01, 0x01, // Class-specific AC Interface Descriptor
simon 1:ff74eabe02cd 89 0x09, 0x04, 0x01, 0x00, 0x02, 0x01, 0x03, 0x00, 0x00, // MIDIStreaming Interface Descriptors
simon 1:ff74eabe02cd 90 0x07, 0x24, 0x01, 0x00, 0x01, 0x41, 0x00, // Class-Specific MS Interface Header Descriptor
simon 1:ff74eabe02cd 91
simon 1:ff74eabe02cd 92 // MIDI IN JACKS
simon 1:ff74eabe02cd 93 0x06, 0x24, 0x02, 0x01, 0x01, 0x00,
simon 1:ff74eabe02cd 94 0x06, 0x24, 0x02, 0x02, 0x02, 0x00,
simon 1:ff74eabe02cd 95
simon 1:ff74eabe02cd 96 // MIDI OUT JACKS
simon 1:ff74eabe02cd 97 0x09, 0x24, 0x03, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00,
simon 1:ff74eabe02cd 98 0x09, 0x24, 0x03, 0x02, 0x06, 0x01, 0x01, 0x01, 0x00,
simon 1:ff74eabe02cd 99
simon 1:ff74eabe02cd 100 // OUT endpoint descriptor
simon 1:ff74eabe02cd 101 0x09, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
simon 1:ff74eabe02cd 102 0x05, 0x25, 0x01, 0x01, 0x01,
simon 1:ff74eabe02cd 103
simon 1:ff74eabe02cd 104 // IN endpoint descriptor
simon 1:ff74eabe02cd 105 0x09, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
simon 1:ff74eabe02cd 106 0x05, 0x25, 0x01, 0x01, 0x03,
simon 1:ff74eabe02cd 107 };
simon 1:ff74eabe02cd 108
simon 1:ff74eabe02cd 109 void ep0_in();
simon 1:ff74eabe02cd 110
simon 1:ff74eabe02cd 111 void data_in_stage(uint8_t *desc, uint8_t length) {
simon 1:ff74eabe02cd 112 transfer.sent = 0;
simon 1:ff74eabe02cd 113 transfer.data = desc;
simon 1:ff74eabe02cd 114 transfer.size = length;
simon 1:ff74eabe02cd 115 ep0_in();
simon 1:ff74eabe02cd 116 }
simon 1:ff74eabe02cd 117
simon 1:ff74eabe02cd 118 void status_in_stage() {
simon 1:ff74eabe02cd 119 ep_write(EP1, 0, 0); // ZLEP for status stage
simon 1:ff74eabe02cd 120 }
simon 1:ff74eabe02cd 121
simon 1:ff74eabe02cd 122 void ep0_setup() {
simon 1:ff74eabe02cd 123 ep_read(EP0,(uint8_t*) &setup);
simon 1:ff74eabe02cd 124
simon 1:ff74eabe02cd 125 switch (setup.bmRequestType & 0x7f) { // mask direction
simon 1:ff74eabe02cd 126 case STANDARD_DEVICE_REQUEST:
simon 1:ff74eabe02cd 127 switch (setup.bRequest) {
simon 1:ff74eabe02cd 128 case GET_DESCRIPTOR:
simon 1:ff74eabe02cd 129 switch ((setup.wValue>>8)) {
simon 1:ff74eabe02cd 130 case DEVICE_DESCRIPTOR: // device descriptor request
simon 1:ff74eabe02cd 131 case QUALIFIER_DESCRIPTOR: // device qualifier descriptor
simon 1:ff74eabe02cd 132 data_in_stage(device_descriptor, sizeof(device_descriptor));
simon 1:ff74eabe02cd 133 break;
simon 1:ff74eabe02cd 134 case CONFIG_DESCRIPTOR: // configuration descriptor
simon 1:ff74eabe02cd 135 data_in_stage(config_descriptor, setup.wLength);
simon 1:ff74eabe02cd 136 break;
simon 1:ff74eabe02cd 137 case STRING_DESCRIPTOR:
simon 1:ff74eabe02cd 138 break;
simon 1:ff74eabe02cd 139 default:
simon 1:ff74eabe02cd 140 break;
simon 1:ff74eabe02cd 141 }
simon 1:ff74eabe02cd 142 break;
simon 1:ff74eabe02cd 143 case SET_ADDRESS:
simon 1:ff74eabe02cd 144 usb_set_address((uint8_t) (setup.wValue & 0xFF));
simon 1:ff74eabe02cd 145 status_in_stage();
simon 1:ff74eabe02cd 146 break;
simon 1:ff74eabe02cd 147 case SET_CONFIGURATION:
simon 1:ff74eabe02cd 148 if (!setup.wValue) {
simon 1:ff74eabe02cd 149 break;
simon 1:ff74eabe02cd 150 }
simon 1:ff74eabe02cd 151 ep_realize(EP4, MAX_EPn_PSIZE);
simon 1:ff74eabe02cd 152 ep_realize(EP5, MAX_EPn_PSIZE);
simon 1:ff74eabe02cd 153 status_in_stage();
simon 1:ff74eabe02cd 154 usb_configure(1);
simon 1:ff74eabe02cd 155 break;
simon 1:ff74eabe02cd 156 default:
simon 1:ff74eabe02cd 157 break;
simon 1:ff74eabe02cd 158 }
simon 1:ff74eabe02cd 159 break;
simon 1:ff74eabe02cd 160 default:
simon 1:ff74eabe02cd 161 break;
simon 1:ff74eabe02cd 162 }
simon 1:ff74eabe02cd 163 }
simon 1:ff74eabe02cd 164
simon 1:ff74eabe02cd 165 void ep0_in() {
simon 1:ff74eabe02cd 166 if ((setup.bmRequestType & 0x80) && transfer.size) { // device to host
simon 1:ff74eabe02cd 167 if (transfer.size > MAX_EP0_PSIZE) {
simon 1:ff74eabe02cd 168 transfer.sent = MAX_EP0_PSIZE;
simon 1:ff74eabe02cd 169 } else {
simon 1:ff74eabe02cd 170 transfer.sent = transfer.size;
simon 1:ff74eabe02cd 171 }
simon 1:ff74eabe02cd 172 ep_write(EP1, transfer.data, transfer.sent);
simon 1:ff74eabe02cd 173 transfer.data += transfer.sent;
simon 1:ff74eabe02cd 174 transfer.size -= transfer.sent;
simon 1:ff74eabe02cd 175 }
simon 1:ff74eabe02cd 176 }
simon 1:ff74eabe02cd 177
simon 1:ff74eabe02cd 178 void ep0_out() {
simon 1:ff74eabe02cd 179 uint8_t buf[64];
simon 1:ff74eabe02cd 180 ep_read(EP0, buf);
simon 1:ff74eabe02cd 181 }