USBHost+USB MIDI

Dependencies:   FATFileSystem mbed-rtos

Dependents:   USBHostMIDI_example MIDISynthwithSpecAnalyzer

Fork of USBHost by mbed official

USBHost with USB MIDI support

(work in progress...)

Tested functions

Receiving

  • note on
  • note off
  • program change
  • control change
  • pitch bend

Tranmitting

  • not tested yet.
Committer:
kshoji
Date:
Fri Dec 06 03:22:34 2013 +0000
Revision:
20:bd4759650fc0
Parent:
19:bf09452b8f26
method for sending MIDI messages

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kshoji 19:bf09452b8f26 1 /* mbed USBHost Library
kshoji 19:bf09452b8f26 2 * Copyright (c) 2006-2013 ARM Limited
kshoji 19:bf09452b8f26 3 *
kshoji 19:bf09452b8f26 4 * Licensed under the Apache License, Version 2.0 (the "License");
kshoji 19:bf09452b8f26 5 * you may not use this file except in compliance with the License.
kshoji 19:bf09452b8f26 6 * You may obtain a copy of the License at
kshoji 19:bf09452b8f26 7 *
kshoji 19:bf09452b8f26 8 * http://www.apache.org/licenses/LICENSE-2.0
kshoji 19:bf09452b8f26 9 *
kshoji 19:bf09452b8f26 10 * Unless required by applicable law or agreed to in writing, software
kshoji 19:bf09452b8f26 11 * distributed under the License is distributed on an "AS IS" BASIS,
kshoji 19:bf09452b8f26 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kshoji 19:bf09452b8f26 13 * See the License for the specific language governing permissions and
kshoji 19:bf09452b8f26 14 * limitations under the License.
kshoji 19:bf09452b8f26 15 */
kshoji 19:bf09452b8f26 16
kshoji 19:bf09452b8f26 17 #include "USBHostMIDI.h"
kshoji 19:bf09452b8f26 18
kshoji 19:bf09452b8f26 19 #if USBHOST_MIDI
kshoji 19:bf09452b8f26 20
kshoji 19:bf09452b8f26 21 #include "dbg.h"
kshoji 19:bf09452b8f26 22
kshoji 19:bf09452b8f26 23 #define SET_LINE_CODING 0x20
kshoji 19:bf09452b8f26 24
kshoji 19:bf09452b8f26 25 USBHostMIDI::USBHostMIDI(): circ_buf() {
kshoji 19:bf09452b8f26 26 host = USBHost::getHostInst();
kshoji 19:bf09452b8f26 27 size_bulk_in = 0;
kshoji 19:bf09452b8f26 28 size_bulk_out = 0;
kshoji 19:bf09452b8f26 29 init();
kshoji 19:bf09452b8f26 30 }
kshoji 19:bf09452b8f26 31
kshoji 19:bf09452b8f26 32 void USBHostMIDI::init() {
kshoji 19:bf09452b8f26 33 dev = NULL;
kshoji 19:bf09452b8f26 34 bulk_in = NULL;
kshoji 19:bf09452b8f26 35 bulk_out = NULL;
kshoji 19:bf09452b8f26 36 dev_connected = false;
kshoji 19:bf09452b8f26 37 midi_intf = -1;
kshoji 19:bf09452b8f26 38 midi_device_found = false;
kshoji 19:bf09452b8f26 39 circ_buf.flush();
kshoji 19:bf09452b8f26 40 }
kshoji 19:bf09452b8f26 41
kshoji 19:bf09452b8f26 42 bool USBHostMIDI::connected()
kshoji 19:bf09452b8f26 43 {
kshoji 19:bf09452b8f26 44 return dev_connected;
kshoji 19:bf09452b8f26 45 }
kshoji 19:bf09452b8f26 46
kshoji 19:bf09452b8f26 47 bool USBHostMIDI::connect() {
kshoji 19:bf09452b8f26 48
kshoji 19:bf09452b8f26 49 if (dev_connected) {
kshoji 19:bf09452b8f26 50 return true;
kshoji 19:bf09452b8f26 51 }
kshoji 19:bf09452b8f26 52 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
kshoji 19:bf09452b8f26 53 if ((dev = host->getDevice(i)) != NULL) {
kshoji 19:bf09452b8f26 54
kshoji 19:bf09452b8f26 55 USB_DBG("Trying to connect MIDI device\r\n");
kshoji 19:bf09452b8f26 56
kshoji 19:bf09452b8f26 57 if(host->enumerate(dev, this))
kshoji 19:bf09452b8f26 58 break;
kshoji 19:bf09452b8f26 59
kshoji 19:bf09452b8f26 60 if (midi_device_found) {
kshoji 19:bf09452b8f26 61 bulk_in = dev->getEndpoint(midi_intf, BULK_ENDPOINT, IN);
kshoji 19:bf09452b8f26 62 bulk_out = dev->getEndpoint(midi_intf, BULK_ENDPOINT, OUT);
kshoji 19:bf09452b8f26 63
kshoji 19:bf09452b8f26 64 if (!bulk_in || !bulk_out)
kshoji 19:bf09452b8f26 65 break;
kshoji 19:bf09452b8f26 66
kshoji 19:bf09452b8f26 67 USB_INFO("New MIDI device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, midi_intf);
kshoji 19:bf09452b8f26 68 dev->setName("MIDI", midi_intf);
kshoji 19:bf09452b8f26 69 host->registerDriver(dev, midi_intf, this, &USBHostMIDI::init);
kshoji 19:bf09452b8f26 70
kshoji 19:bf09452b8f26 71 size_bulk_in = bulk_in->getSize();
kshoji 19:bf09452b8f26 72 size_bulk_out = bulk_out->getSize();
kshoji 19:bf09452b8f26 73
kshoji 19:bf09452b8f26 74 bulk_in->attach(this, &USBHostMIDI::rxHandler);
kshoji 19:bf09452b8f26 75
kshoji 19:bf09452b8f26 76 host->bulkRead(dev, bulk_in, buf, size_bulk_in, false);
kshoji 19:bf09452b8f26 77 dev_connected = true;
kshoji 19:bf09452b8f26 78 return true;
kshoji 19:bf09452b8f26 79 }
kshoji 19:bf09452b8f26 80 }
kshoji 19:bf09452b8f26 81 }
kshoji 19:bf09452b8f26 82 init();
kshoji 19:bf09452b8f26 83 return false;
kshoji 19:bf09452b8f26 84 }
kshoji 19:bf09452b8f26 85
kshoji 19:bf09452b8f26 86 void USBHostMIDI::rxHandler() {
kshoji 19:bf09452b8f26 87 uint8_t pos = 0;
kshoji 19:bf09452b8f26 88 uint8_t midi[4];
kshoji 19:bf09452b8f26 89 if (bulk_in) {
kshoji 19:bf09452b8f26 90 int len = bulk_in->getLengthTransferred();
kshoji 19:bf09452b8f26 91 if (bulk_in->getState() == USB_TYPE_IDLE) {
kshoji 19:bf09452b8f26 92 for (int i = 0; i < len; i++) {
kshoji 19:bf09452b8f26 93 circ_buf.queue(buf[i]);
kshoji 19:bf09452b8f26 94 }
kshoji 19:bf09452b8f26 95
kshoji 19:bf09452b8f26 96 // MIDI event handling
kshoji 19:bf09452b8f26 97 while (!circ_buf.isEmpty()) {
kshoji 19:bf09452b8f26 98 // read each four bytes
kshoji 19:bf09452b8f26 99 circ_buf.dequeue(&midi[pos++]);
kshoji 19:bf09452b8f26 100 if (pos == 4) {
kshoji 19:bf09452b8f26 101 pos = 0;
kshoji 19:bf09452b8f26 102
kshoji 19:bf09452b8f26 103 // process MIDI message
kshoji 19:bf09452b8f26 104 // switch by code index number
kshoji 19:bf09452b8f26 105 switch (midi[0] & 0xf) {
kshoji 19:bf09452b8f26 106 case 8:
kshoji 19:bf09452b8f26 107 noteOff(midi[1] & 0xf, midi[2], midi[3]);
kshoji 19:bf09452b8f26 108 break;
kshoji 19:bf09452b8f26 109 case 9:
kshoji 19:bf09452b8f26 110 if (midi[3]) {
kshoji 19:bf09452b8f26 111 noteOn(midi[1] & 0xf, midi[2], midi[3]);
kshoji 19:bf09452b8f26 112 } else {
kshoji 19:bf09452b8f26 113 noteOff(midi[1] & 0xf, midi[2], midi[3]);
kshoji 19:bf09452b8f26 114 }
kshoji 19:bf09452b8f26 115 break;
kshoji 19:bf09452b8f26 116 case 11:
kshoji 19:bf09452b8f26 117 controlChange(midi[1] & 0xf, midi[2], midi[3]);
kshoji 19:bf09452b8f26 118 break;
kshoji 19:bf09452b8f26 119 case 12:
kshoji 19:bf09452b8f26 120 programChange(midi[1] & 0xf, midi[2]);
kshoji 19:bf09452b8f26 121 break;
kshoji 19:bf09452b8f26 122 case 14:
kshoji 19:bf09452b8f26 123 pitchBend(midi[1] & 0xf, midi[2] | (midi[3] << 7));
kshoji 19:bf09452b8f26 124 break;
kshoji 19:bf09452b8f26 125 default:
kshoji 19:bf09452b8f26 126 break;
kshoji 19:bf09452b8f26 127 }
kshoji 19:bf09452b8f26 128 }
kshoji 19:bf09452b8f26 129 }
kshoji 19:bf09452b8f26 130
kshoji 19:bf09452b8f26 131 host->bulkRead(dev, bulk_in, buf, size_bulk_in, false);
kshoji 19:bf09452b8f26 132 }
kshoji 19:bf09452b8f26 133 }
kshoji 19:bf09452b8f26 134 }
kshoji 19:bf09452b8f26 135
kshoji 19:bf09452b8f26 136 int USBHostMIDI::sendNoteOn(unsigned char channel, unsigned char note, unsigned char velocity) {
kshoji 19:bf09452b8f26 137 uint8_t midi[4];
kshoji 19:bf09452b8f26 138
kshoji 19:bf09452b8f26 139 if (bulk_out) {
kshoji 19:bf09452b8f26 140 midi[0] = 9;
kshoji 19:bf09452b8f26 141 midi[1] = channel & 0xf;
kshoji 19:bf09452b8f26 142 midi[2] = note & 0x7f;
kshoji 19:bf09452b8f26 143 midi[3] = velocity & 0x7f;
kshoji 19:bf09452b8f26 144 if (host->bulkWrite(dev, bulk_out, (uint8_t *)midi, 4) == USB_TYPE_OK) {
kshoji 19:bf09452b8f26 145 return 1;
kshoji 19:bf09452b8f26 146 }
kshoji 19:bf09452b8f26 147 }
kshoji 19:bf09452b8f26 148 return -1;
kshoji 19:bf09452b8f26 149 }
kshoji 19:bf09452b8f26 150
kshoji 19:bf09452b8f26 151 int USBHostMIDI::sendNoteOff(unsigned char channel, unsigned char note, unsigned char velocity) {
kshoji 19:bf09452b8f26 152 uint8_t midi[4];
kshoji 19:bf09452b8f26 153
kshoji 19:bf09452b8f26 154 if (bulk_out) {
kshoji 19:bf09452b8f26 155 midi[0] = 8;
kshoji 19:bf09452b8f26 156 midi[1] = channel & 0xf;
kshoji 19:bf09452b8f26 157 midi[2] = note & 0x7f;
kshoji 19:bf09452b8f26 158 midi[3] = velocity & 0x7f;
kshoji 19:bf09452b8f26 159 if (host->bulkWrite(dev, bulk_out, (uint8_t *)midi, 4) == USB_TYPE_OK) {
kshoji 19:bf09452b8f26 160 return 1;
kshoji 19:bf09452b8f26 161 }
kshoji 19:bf09452b8f26 162 }
kshoji 19:bf09452b8f26 163 return -1;
kshoji 19:bf09452b8f26 164 }
kshoji 19:bf09452b8f26 165
kshoji 19:bf09452b8f26 166 int USBHostMIDI::sendControlChange(unsigned char channel, unsigned char key, unsigned char value) {
kshoji 19:bf09452b8f26 167 uint8_t midi[4];
kshoji 19:bf09452b8f26 168
kshoji 19:bf09452b8f26 169 if (bulk_out) {
kshoji 19:bf09452b8f26 170 midi[0] = 11;
kshoji 19:bf09452b8f26 171 midi[1] = channel & 0xf;
kshoji 19:bf09452b8f26 172 midi[2] = key & 0x7f;
kshoji 19:bf09452b8f26 173 midi[3] = value & 0x7f;
kshoji 19:bf09452b8f26 174 if (host->bulkWrite(dev, bulk_out, (uint8_t *)midi, 4) == USB_TYPE_OK) {
kshoji 19:bf09452b8f26 175 return 1;
kshoji 19:bf09452b8f26 176 }
kshoji 19:bf09452b8f26 177 }
kshoji 19:bf09452b8f26 178 return -1;
kshoji 19:bf09452b8f26 179 }
kshoji 19:bf09452b8f26 180
kshoji 19:bf09452b8f26 181 int USBHostMIDI::sendProgramChange(unsigned char channel, unsigned char program) {
kshoji 19:bf09452b8f26 182 uint8_t midi[4];
kshoji 19:bf09452b8f26 183
kshoji 19:bf09452b8f26 184 if (bulk_out) {
kshoji 19:bf09452b8f26 185 midi[0] = 12;
kshoji 19:bf09452b8f26 186 midi[1] = channel & 0xf;
kshoji 19:bf09452b8f26 187 midi[2] = program & 0x7f;
kshoji 19:bf09452b8f26 188 midi[3] = 0;
kshoji 19:bf09452b8f26 189 if (host->bulkWrite(dev, bulk_out, (uint8_t *)midi, 4) == USB_TYPE_OK) {
kshoji 19:bf09452b8f26 190 return 1;
kshoji 19:bf09452b8f26 191 }
kshoji 19:bf09452b8f26 192 }
kshoji 19:bf09452b8f26 193 return -1;
kshoji 19:bf09452b8f26 194 }
kshoji 19:bf09452b8f26 195
kshoji 19:bf09452b8f26 196 int USBHostMIDI::sendPitchBend(unsigned char channel, unsigned int value) {
kshoji 19:bf09452b8f26 197 uint8_t midi[4];
kshoji 19:bf09452b8f26 198
kshoji 19:bf09452b8f26 199 if (bulk_out) {
kshoji 19:bf09452b8f26 200 midi[0] = 14;
kshoji 19:bf09452b8f26 201 midi[1] = channel & 0xf;
kshoji 19:bf09452b8f26 202 midi[2] = value & 0x7f;
kshoji 19:bf09452b8f26 203 midi[3] = (value >> 7) & 0x7f;
kshoji 19:bf09452b8f26 204 if (host->bulkWrite(dev, bulk_out, (uint8_t *)midi, 4) == USB_TYPE_OK) {
kshoji 19:bf09452b8f26 205 return 1;
kshoji 19:bf09452b8f26 206 }
kshoji 19:bf09452b8f26 207 }
kshoji 19:bf09452b8f26 208 return -1;
kshoji 19:bf09452b8f26 209 }
kshoji 19:bf09452b8f26 210
kshoji 19:bf09452b8f26 211 /*virtual*/ void USBHostMIDI::setVidPid(uint16_t vid, uint16_t pid)
kshoji 19:bf09452b8f26 212 {
kshoji 19:bf09452b8f26 213 // we don't check VID/PID for this driver
kshoji 19:bf09452b8f26 214 }
kshoji 19:bf09452b8f26 215
kshoji 19:bf09452b8f26 216 /*virtual*/ bool USBHostMIDI::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed
kshoji 19:bf09452b8f26 217 {
kshoji 19:bf09452b8f26 218 // USB MIDI class/subclass
kshoji 19:bf09452b8f26 219 if ((midi_intf == -1) &&
kshoji 19:bf09452b8f26 220 (intf_class == AUDIO_CLASS) &&
kshoji 19:bf09452b8f26 221 (intf_subclass == 0x03)) {
kshoji 19:bf09452b8f26 222 midi_intf = intf_nb;
kshoji 19:bf09452b8f26 223 return true;
kshoji 19:bf09452b8f26 224 }
kshoji 19:bf09452b8f26 225
kshoji 19:bf09452b8f26 226 // vendor specific device
kshoji 19:bf09452b8f26 227 if ((midi_intf == -1) &&
kshoji 19:bf09452b8f26 228 (intf_class == 0xff) &&
kshoji 19:bf09452b8f26 229 (intf_subclass == 0x03)) {
kshoji 19:bf09452b8f26 230 midi_intf = intf_nb;
kshoji 19:bf09452b8f26 231 return true;
kshoji 19:bf09452b8f26 232 }
kshoji 19:bf09452b8f26 233
kshoji 19:bf09452b8f26 234 return false;
kshoji 19:bf09452b8f26 235 }
kshoji 19:bf09452b8f26 236
kshoji 19:bf09452b8f26 237 /*virtual*/ bool USBHostMIDI::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
kshoji 19:bf09452b8f26 238 {
kshoji 19:bf09452b8f26 239 if (intf_nb == midi_intf) {
kshoji 19:bf09452b8f26 240 if (type == BULK_ENDPOINT) {
kshoji 19:bf09452b8f26 241 midi_device_found = true;
kshoji 19:bf09452b8f26 242 return true;
kshoji 19:bf09452b8f26 243 }
kshoji 19:bf09452b8f26 244 }
kshoji 19:bf09452b8f26 245 return false;
kshoji 19:bf09452b8f26 246 }
kshoji 19:bf09452b8f26 247
kshoji 19:bf09452b8f26 248 #endif