Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
USBHostMIDI.cpp
00001 /* Copyright (c) 2014 mbed.org, MIT License 00002 * 00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00004 * and associated documentation files (the "Software"), to deal in the Software without 00005 * restriction, including without limitation the rights to use, copy, modify, merge, publish, 00006 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 00007 * Software is furnished to do so, subject to the following conditions: 00008 * 00009 * The above copyright notice and this permission notice shall be included in all copies or 00010 * substantial portions of the Software. 00011 * 00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00017 */ 00018 00019 #include "USBHostMIDI.h" 00020 00021 #if USBHOST_MIDI 00022 00023 #include "dbg.h" 00024 00025 #define SET_LINE_CODING 0x20 00026 00027 USBHostMIDI::USBHostMIDI() : 00028 miscellaneousFunctionCode(NULL), 00029 cableEvent(NULL), 00030 systemCommonTwoBytes(NULL), 00031 systemCommonThreeBytes(NULL), 00032 systemExclusive(NULL), 00033 noteOff(NULL), 00034 noteOn(NULL), 00035 polyKeyPress(NULL), 00036 controlChange(NULL), 00037 programChange(NULL), 00038 channelPressure(NULL), 00039 pitchBend(NULL), 00040 singleByte(NULL) { 00041 host = USBHost::getHostInst(); 00042 size_bulk_in = 0; 00043 size_bulk_out = 0; 00044 init(); 00045 } 00046 00047 void USBHostMIDI::init() { 00048 dev = NULL; 00049 bulk_in = NULL; 00050 bulk_out = NULL; 00051 dev_connected = false; 00052 midi_intf = -1; 00053 midi_device_found = false; 00054 sysExBufferPos = 0; 00055 } 00056 00057 bool USBHostMIDI::connected() { 00058 return dev_connected; 00059 } 00060 00061 bool USBHostMIDI::connect() { 00062 if (dev_connected) { 00063 return true; 00064 } 00065 00066 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { 00067 if ((dev = host->getDevice(i)) != NULL) { 00068 00069 USB_DBG("Trying to connect MIDI device\r\n"); 00070 00071 if (host->enumerate(dev, this)) { 00072 break; 00073 } 00074 00075 if (midi_device_found) { 00076 bulk_in = dev->getEndpoint(midi_intf, BULK_ENDPOINT, IN); 00077 bulk_out = dev->getEndpoint(midi_intf, BULK_ENDPOINT, OUT); 00078 00079 if (!bulk_in || !bulk_out) { 00080 break; 00081 } 00082 00083 USB_INFO("New MIDI device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, midi_intf); 00084 dev->setName("MIDI", midi_intf); 00085 host->registerDriver(dev, midi_intf, this, &USBHostMIDI::init); 00086 00087 size_bulk_in = bulk_in->getSize(); 00088 size_bulk_out = bulk_out->getSize(); 00089 00090 bulk_in->attach(this, &USBHostMIDI::rxHandler); 00091 00092 host->bulkRead(dev, bulk_in, buf, size_bulk_in, false); 00093 dev_connected = true; 00094 return true; 00095 } 00096 } 00097 } 00098 00099 init(); 00100 return false; 00101 } 00102 00103 void USBHostMIDI::rxHandler() { 00104 uint8_t *midi; 00105 if (bulk_in) { 00106 int length = bulk_in->getLengthTransferred(); 00107 if (bulk_in->getState() == USB_TYPE_IDLE || bulk_in->getState() == USB_TYPE_FREE) { 00108 // MIDI event handling 00109 for (int i = 0; i < length; i += 4) { 00110 if (i + 4 > length) { 00111 // length shortage, ignored. 00112 break; 00113 } 00114 00115 // read each four bytes 00116 midi = &buf[i]; 00117 // process MIDI message 00118 // switch by code index number 00119 switch (midi[0] & 0xf) { 00120 case 0: // miscellaneous function codes 00121 if (miscellaneousFunctionCode) { 00122 miscellaneousFunctionCode(midi[1], midi[2], midi[3]); 00123 } 00124 break; 00125 case 1: // cable events 00126 if (cableEvent) { 00127 cableEvent(midi[1], midi[2], midi[3]); 00128 } 00129 break; 00130 case 2: // two bytes system common messages 00131 if (systemCommonTwoBytes) { 00132 systemCommonTwoBytes(midi[1], midi[2]); 00133 } 00134 break; 00135 case 3: // three bytes system common messages 00136 if (systemCommonThreeBytes) { 00137 systemCommonThreeBytes(midi[1], midi[2], midi[3]); 00138 } 00139 break; 00140 case 4: // SysEx starts or continues 00141 sysExBuffer[sysExBufferPos++] = midi[1]; 00142 if (sysExBufferPos >= 64) { 00143 if (systemExclusive) { 00144 systemExclusive(sysExBuffer, sysExBufferPos, true); 00145 } 00146 sysExBufferPos = 0; 00147 } 00148 sysExBuffer[sysExBufferPos++] = midi[2]; 00149 if (sysExBufferPos >= 64) { 00150 if (systemExclusive) { 00151 systemExclusive(sysExBuffer, sysExBufferPos, true); 00152 } 00153 sysExBufferPos = 0; 00154 } 00155 sysExBuffer[sysExBufferPos++] = midi[3]; 00156 // SysEx continues. don't send 00157 break; 00158 case 5: // SysEx ends with single byte 00159 sysExBuffer[sysExBufferPos++] = midi[1]; 00160 if (systemExclusive) { 00161 systemExclusive(sysExBuffer, sysExBufferPos, false); 00162 } 00163 sysExBufferPos = 0; 00164 break; 00165 case 6: // SysEx ends with two bytes 00166 sysExBuffer[sysExBufferPos++] = midi[1]; 00167 if (sysExBufferPos >= 64) { 00168 if (systemExclusive) { 00169 systemExclusive(sysExBuffer, sysExBufferPos, true); 00170 } 00171 sysExBufferPos = 0; 00172 } 00173 sysExBuffer[sysExBufferPos++] = midi[2]; 00174 00175 if (systemExclusive) { 00176 systemExclusive(sysExBuffer, sysExBufferPos, false); 00177 } 00178 sysExBufferPos = 0; 00179 break; 00180 case 7: // SysEx ends with three bytes 00181 sysExBuffer[sysExBufferPos++] = midi[1]; 00182 if (sysExBufferPos >= 64) { 00183 if (systemExclusive) { 00184 systemExclusive(sysExBuffer, sysExBufferPos, true); 00185 } 00186 sysExBufferPos = 0; 00187 } 00188 sysExBuffer[sysExBufferPos++] = midi[2]; 00189 if (sysExBufferPos >= 64) { 00190 if (systemExclusive) { 00191 systemExclusive(sysExBuffer, sysExBufferPos, true); 00192 } 00193 sysExBufferPos = 0; 00194 } 00195 sysExBuffer[sysExBufferPos++] = midi[3]; 00196 00197 if (systemExclusive) { 00198 systemExclusive(sysExBuffer, sysExBufferPos, false); 00199 } 00200 sysExBufferPos = 0; 00201 break; 00202 case 8: 00203 if (noteOff) { 00204 noteOff(midi[1] & 0xf, midi[2], midi[3]); 00205 } 00206 break; 00207 case 9: 00208 if (midi[3]) { 00209 if (noteOn) { 00210 noteOn(midi[1] & 0xf, midi[2], midi[3]); 00211 } 00212 } else { 00213 if (noteOff) { 00214 noteOff(midi[1] & 0xf, midi[2], midi[3]); 00215 } 00216 } 00217 break; 00218 case 10: 00219 if (polyKeyPress) { 00220 polyKeyPress(midi[1] & 0xf, midi[2], midi[3]); 00221 } 00222 break; 00223 case 11: 00224 if (controlChange) { 00225 controlChange(midi[1] & 0xf, midi[2], midi[3]); 00226 } 00227 break; 00228 case 12: 00229 if (programChange) { 00230 programChange(midi[1] & 0xf, midi[2]); 00231 } 00232 break; 00233 case 13: 00234 if (channelPressure) { 00235 channelPressure(midi[1] & 0xf, midi[2]); 00236 } 00237 break; 00238 case 14: 00239 if (pitchBend) { 00240 pitchBend(midi[1] & 0xf, midi[2] | (midi[3] << 7)); 00241 } 00242 break; 00243 case 15: 00244 if (singleByte) { 00245 singleByte(midi[1]); 00246 } 00247 break; 00248 } 00249 } 00250 00251 // read another message 00252 host->bulkRead(dev, bulk_in, buf, size_bulk_in, false); 00253 } 00254 } 00255 } 00256 00257 bool USBHostMIDI::sendMidiBuffer(uint8_t data0, uint8_t data1, uint8_t data2, uint8_t data3) { 00258 if (bulk_out) { 00259 uint8_t midi[4]; 00260 00261 midi[0] = data0; 00262 midi[1] = data1; 00263 midi[2] = data2; 00264 midi[3] = data3; 00265 if (host->bulkWrite(dev, bulk_out, (uint8_t *)midi, 4) == USB_TYPE_OK) { 00266 return true; 00267 } 00268 } 00269 return false; 00270 } 00271 00272 bool USBHostMIDI::sendMiscellaneousFunctionCode(uint8_t data1, uint8_t data2, uint8_t data3) { 00273 return sendMidiBuffer(0, data1, data2, data3); 00274 } 00275 00276 bool USBHostMIDI::sendCableEvent(uint8_t data1, uint8_t data2, uint8_t data3) { 00277 return sendMidiBuffer(1, data1, data2, data3); 00278 } 00279 00280 bool USBHostMIDI::sendSystemCommmonTwoBytes(uint8_t data1, uint8_t data2) { 00281 return sendMidiBuffer(2, data1, data2, 0); 00282 } 00283 00284 bool USBHostMIDI::sendSystemCommmonThreeBytes(uint8_t data1, uint8_t data2, uint8_t data3) { 00285 return sendMidiBuffer(3, data1, data2, 0); 00286 } 00287 00288 bool USBHostMIDI::sendSystemExclusive(uint8_t *buffer, int length) { 00289 uint8_t midi[64]; 00290 int midiLength; 00291 int midiPos; 00292 if (bulk_out) { 00293 for (int i = 0; i < length; i += 48) { 00294 if (i + 48 >= length) { 00295 // contains last data 00296 midiLength = (((length - i) + 2) / 3) * 4; 00297 for (int pos = i; pos < length; pos += 3) { 00298 midiPos = (pos + 2) / 3 * 4; 00299 if (pos + 3 >= length) { 00300 // last data 00301 switch (pos % 3) { 00302 case 0: 00303 midi[midiPos ] = 7; 00304 midi[midiPos + 1] = buffer[pos ]; 00305 midi[midiPos + 2] = buffer[pos + 1]; 00306 midi[midiPos + 3] = buffer[pos + 2]; 00307 break; 00308 case 1: 00309 midi[midiPos ] = 5; 00310 midi[midiPos + 1] = buffer[pos ]; 00311 midi[midiPos + 2] = 0; 00312 midi[midiPos + 3] = 0; 00313 break; 00314 case 2: 00315 midi[midiPos ] = 6; 00316 midi[midiPos + 1] = buffer[pos ]; 00317 midi[midiPos + 2] = buffer[pos + 1]; 00318 midi[midiPos + 3] = 0; 00319 break; 00320 } 00321 } else { 00322 // has more data 00323 midi[midiPos ] = 4; 00324 midi[midiPos + 1] = buffer[pos ]; 00325 midi[midiPos + 2] = buffer[pos + 1]; 00326 midi[midiPos + 3] = buffer[pos + 2]; 00327 } 00328 } 00329 } else { 00330 // has more data 00331 midiLength = 64; 00332 for (int pos = i; pos < length; pos += 3) { 00333 midiPos = (pos + 2) / 3 * 4; 00334 midi[midiPos ] = 4; 00335 midi[midiPos + 1] = buffer[pos ]; 00336 midi[midiPos + 2] = buffer[pos + 1]; 00337 midi[midiPos + 3] = buffer[pos + 2]; 00338 } 00339 } 00340 00341 if (host->bulkWrite(dev, bulk_out, (uint8_t *)midi, midiLength) != USB_TYPE_OK) { 00342 return false; 00343 } 00344 } 00345 return true; 00346 } 00347 return false; 00348 } 00349 00350 bool USBHostMIDI::sendNoteOff(uint8_t channel, uint8_t note, uint8_t velocity) { 00351 return sendMidiBuffer(8, channel & 0xf | 0x80, note & 0x7f, velocity & 0x7f); 00352 } 00353 00354 bool USBHostMIDI::sendNoteOn(uint8_t channel, uint8_t note, uint8_t velocity) { 00355 return sendMidiBuffer(9, channel & 0xf | 0x90, note & 0x7f, velocity & 0x7f); 00356 } 00357 00358 bool USBHostMIDI::sendPolyKeyPress(uint8_t channel, uint8_t note, uint8_t pressure) { 00359 return sendMidiBuffer(10, channel & 0xf | 0xa0, note & 0x7f, pressure & 0x7f); 00360 } 00361 00362 bool USBHostMIDI::sendControlChange(uint8_t channel, uint8_t key, uint8_t value) { 00363 return sendMidiBuffer(11, channel & 0xf | 0xb0, key & 0x7f, value & 0x7f); 00364 } 00365 00366 bool USBHostMIDI::sendProgramChange(uint8_t channel, uint8_t program) { 00367 return sendMidiBuffer(12, channel & 0xf | 0xc0, program & 0x7f, 0); 00368 } 00369 00370 bool USBHostMIDI::sendChannelPressure(uint8_t channel, uint8_t pressure) { 00371 return sendMidiBuffer(13, channel & 0xf | 0xd0, pressure & 0x7f, 0); 00372 } 00373 00374 bool USBHostMIDI::sendPitchBend(uint8_t channel, uint16_t value) { 00375 return sendMidiBuffer(14, channel & 0xf | 0xe0, value & 0x7f, (value >> 7) & 0x7f); 00376 } 00377 00378 bool USBHostMIDI::sendSingleByte(uint8_t data) { 00379 return sendMidiBuffer(15, data, 0, 0); 00380 } 00381 00382 /*virtual*/ void USBHostMIDI::setVidPid(uint16_t vid, uint16_t pid) 00383 { 00384 // we don't check VID/PID for this driver 00385 } 00386 00387 /*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 00388 { 00389 // USB MIDI class/subclass 00390 if ((midi_intf == -1) && 00391 (intf_class == AUDIO_CLASS) && 00392 (intf_subclass == 0x03)) { 00393 midi_intf = intf_nb; 00394 return true; 00395 } 00396 00397 // vendor specific device 00398 if ((midi_intf == -1) && 00399 (intf_class == 0xff) && 00400 (intf_subclass == 0x03)) { 00401 midi_intf = intf_nb; 00402 return true; 00403 } 00404 00405 return false; 00406 } 00407 00408 /*virtual*/ bool USBHostMIDI::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used 00409 { 00410 if (intf_nb == midi_intf) { 00411 if (type == BULK_ENDPOINT) { 00412 midi_device_found = true; 00413 return true; 00414 } 00415 } 00416 return false; 00417 } 00418 00419 #endif
Generated on Thu Jul 14 2022 01:07:34 by
1.7.2