USBHost library. NOTE: This library is only officially supported on the LPC1768 platform. For more information, please see the handbook page.
Dependencies: FATFileSystem mbed-rtos
Dependents: BTstack WallbotWii SD to Flash Data Transfer USBHost-MSD_HelloWorld ... more
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 host = USBHost::getHostInst(); 00029 size_bulk_in = 0; 00030 size_bulk_out = 0; 00031 init(); 00032 } 00033 00034 void USBHostMIDI::init() { 00035 dev = NULL; 00036 bulk_in = NULL; 00037 bulk_out = NULL; 00038 dev_connected = false; 00039 midi_intf = -1; 00040 midi_device_found = false; 00041 sysExBufferPos = 0; 00042 } 00043 00044 bool USBHostMIDI::connected() { 00045 return dev_connected; 00046 } 00047 00048 bool USBHostMIDI::connect() { 00049 if (dev_connected) { 00050 return true; 00051 } 00052 00053 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { 00054 if ((dev = host->getDevice(i)) != NULL) { 00055 00056 USB_DBG("Trying to connect MIDI device\r\n"); 00057 00058 if (host->enumerate(dev, this)) { 00059 break; 00060 } 00061 00062 if (midi_device_found) { 00063 bulk_in = dev->getEndpoint(midi_intf, BULK_ENDPOINT, IN); 00064 bulk_out = dev->getEndpoint(midi_intf, BULK_ENDPOINT, OUT); 00065 00066 if (!bulk_in || !bulk_out) { 00067 break; 00068 } 00069 00070 USB_INFO("New MIDI device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, midi_intf); 00071 dev->setName("MIDI", midi_intf); 00072 host->registerDriver(dev, midi_intf, this, &USBHostMIDI::init); 00073 00074 size_bulk_in = bulk_in->getSize(); 00075 size_bulk_out = bulk_out->getSize(); 00076 00077 bulk_in->attach(this, &USBHostMIDI::rxHandler); 00078 00079 host->bulkRead(dev, bulk_in, buf, size_bulk_in, false); 00080 dev_connected = true; 00081 return true; 00082 } 00083 } 00084 } 00085 00086 init(); 00087 return false; 00088 } 00089 00090 void USBHostMIDI::rxHandler() { 00091 uint8_t *midi; 00092 if (bulk_in) { 00093 int length = bulk_in->getLengthTransferred(); 00094 if (bulk_in->getState() == USB_TYPE_IDLE || bulk_in->getState() == USB_TYPE_FREE) { 00095 // MIDI event handling 00096 for (int i = 0; i < length; i += 4) { 00097 if (i + 4 > length) { 00098 // length shortage, ignored. 00099 break; 00100 } 00101 00102 // read each four bytes 00103 midi = &buf[i]; 00104 // process MIDI message 00105 // switch by code index number 00106 switch (midi[0] & 0xf) { 00107 case 0: // miscellaneous function codes 00108 miscellaneousFunctionCode(midi[1], midi[2], midi[3]); 00109 break; 00110 case 1: // cable events 00111 cableEvent(midi[1], midi[2], midi[3]); 00112 break; 00113 case 2: // two bytes system common messages 00114 systemCommonTwoBytes(midi[1], midi[2]); 00115 break; 00116 case 3: // three bytes system common messages 00117 systemCommonThreeBytes(midi[1], midi[2], midi[3]); 00118 break; 00119 case 4: // SysEx starts or continues 00120 sysExBuffer[sysExBufferPos++] = midi[1]; 00121 if (sysExBufferPos >= 64) { 00122 systemExclusive(sysExBuffer, sysExBufferPos, true); 00123 sysExBufferPos = 0; 00124 } 00125 sysExBuffer[sysExBufferPos++] = midi[2]; 00126 if (sysExBufferPos >= 64) { 00127 systemExclusive(sysExBuffer, sysExBufferPos, true); 00128 sysExBufferPos = 0; 00129 } 00130 sysExBuffer[sysExBufferPos++] = midi[3]; 00131 // SysEx continues. don't send 00132 break; 00133 case 5: // SysEx ends with single byte 00134 sysExBuffer[sysExBufferPos++] = midi[1]; 00135 systemExclusive(sysExBuffer, sysExBufferPos, false); 00136 sysExBufferPos = 0; 00137 break; 00138 case 6: // SysEx ends with two bytes 00139 sysExBuffer[sysExBufferPos++] = midi[1]; 00140 if (sysExBufferPos >= 64) { 00141 systemExclusive(sysExBuffer, sysExBufferPos, true); 00142 sysExBufferPos = 0; 00143 } 00144 sysExBuffer[sysExBufferPos++] = midi[2]; 00145 systemExclusive(sysExBuffer, sysExBufferPos, false); 00146 sysExBufferPos = 0; 00147 break; 00148 case 7: // SysEx ends with three bytes 00149 sysExBuffer[sysExBufferPos++] = midi[1]; 00150 if (sysExBufferPos >= 64) { 00151 systemExclusive(sysExBuffer, sysExBufferPos, true); 00152 sysExBufferPos = 0; 00153 } 00154 sysExBuffer[sysExBufferPos++] = midi[2]; 00155 if (sysExBufferPos >= 64) { 00156 systemExclusive(sysExBuffer, sysExBufferPos, true); 00157 sysExBufferPos = 0; 00158 } 00159 sysExBuffer[sysExBufferPos++] = midi[3]; 00160 systemExclusive(sysExBuffer, sysExBufferPos, false); 00161 sysExBufferPos = 0; 00162 break; 00163 case 8: 00164 noteOff(midi[1] & 0xf, midi[2], midi[3]); 00165 break; 00166 case 9: 00167 if (midi[3]) { 00168 noteOn(midi[1] & 0xf, midi[2], midi[3]); 00169 } else { 00170 noteOff(midi[1] & 0xf, midi[2], midi[3]); 00171 } 00172 break; 00173 case 10: 00174 polyKeyPress(midi[1] & 0xf, midi[2], midi[3]); 00175 break; 00176 case 11: 00177 controlChange(midi[1] & 0xf, midi[2], midi[3]); 00178 break; 00179 case 12: 00180 programChange(midi[1] & 0xf, midi[2]); 00181 break; 00182 case 13: 00183 channelPressure(midi[1] & 0xf, midi[2]); 00184 break; 00185 case 14: 00186 pitchBend(midi[1] & 0xf, midi[2] | (midi[3] << 7)); 00187 break; 00188 case 15: 00189 singleByte(midi[1]); 00190 break; 00191 } 00192 } 00193 00194 // read another message 00195 host->bulkRead(dev, bulk_in, buf, size_bulk_in, false); 00196 } 00197 } 00198 } 00199 00200 bool USBHostMIDI::sendMidiBuffer(uint8_t data0, uint8_t data1, uint8_t data2, uint8_t data3) { 00201 if (bulk_out) { 00202 uint8_t midi[4]; 00203 00204 midi[0] = data0; 00205 midi[1] = data1; 00206 midi[2] = data2; 00207 midi[3] = data3; 00208 if (host->bulkWrite(dev, bulk_out, (uint8_t *)midi, 4) == USB_TYPE_OK) { 00209 return true; 00210 } 00211 } 00212 return false; 00213 } 00214 00215 bool USBHostMIDI::sendMiscellaneousFunctionCode(uint8_t data1, uint8_t data2, uint8_t data3) { 00216 return sendMidiBuffer(0, data1, data2, data3); 00217 } 00218 00219 bool USBHostMIDI::sendCableEvent(uint8_t data1, uint8_t data2, uint8_t data3) { 00220 return sendMidiBuffer(1, data1, data2, data3); 00221 } 00222 00223 bool USBHostMIDI::sendSystemCommmonTwoBytes(uint8_t data1, uint8_t data2) { 00224 return sendMidiBuffer(2, data1, data2, 0); 00225 } 00226 00227 bool USBHostMIDI::sendSystemCommmonThreeBytes(uint8_t data1, uint8_t data2, uint8_t data3) { 00228 return sendMidiBuffer(3, data1, data2, 0); 00229 } 00230 00231 bool USBHostMIDI::sendSystemExclusive(uint8_t *buffer, int length) { 00232 uint8_t midi[64]; 00233 int midiLength; 00234 int midiPos; 00235 if (bulk_out) { 00236 for (int i = 0; i < length; i += 48) { 00237 if (i + 48 >= length) { 00238 // contains last data 00239 midiLength = (((length - i) + 2) / 3) * 4; 00240 for (int pos = i; pos < length; pos += 3) { 00241 midiPos = (pos + 2) / 3 * 4; 00242 if (pos + 3 >= length) { 00243 // last data 00244 switch (pos % 3) { 00245 case 0: 00246 midi[midiPos ] = 7; 00247 midi[midiPos + 1] = buffer[pos ]; 00248 midi[midiPos + 2] = buffer[pos + 1]; 00249 midi[midiPos + 3] = buffer[pos + 2]; 00250 break; 00251 case 1: 00252 midi[midiPos ] = 5; 00253 midi[midiPos + 1] = buffer[pos ]; 00254 midi[midiPos + 2] = 0; 00255 midi[midiPos + 3] = 0; 00256 break; 00257 case 2: 00258 midi[midiPos ] = 6; 00259 midi[midiPos + 1] = buffer[pos ]; 00260 midi[midiPos + 2] = buffer[pos + 1]; 00261 midi[midiPos + 3] = 0; 00262 break; 00263 } 00264 } else { 00265 // has more data 00266 midi[midiPos ] = 4; 00267 midi[midiPos + 1] = buffer[pos ]; 00268 midi[midiPos + 2] = buffer[pos + 1]; 00269 midi[midiPos + 3] = buffer[pos + 2]; 00270 } 00271 } 00272 } else { 00273 // has more data 00274 midiLength = 64; 00275 for (int pos = i; pos < length; pos += 3) { 00276 midiPos = (pos + 2) / 3 * 4; 00277 midi[midiPos ] = 4; 00278 midi[midiPos + 1] = buffer[pos ]; 00279 midi[midiPos + 2] = buffer[pos + 1]; 00280 midi[midiPos + 3] = buffer[pos + 2]; 00281 } 00282 } 00283 00284 if (host->bulkWrite(dev, bulk_out, (uint8_t *)midi, midiLength) != USB_TYPE_OK) { 00285 return false; 00286 } 00287 } 00288 return true; 00289 } 00290 return false; 00291 } 00292 00293 bool USBHostMIDI::sendNoteOff(uint8_t channel, uint8_t note, uint8_t velocity) { 00294 return sendMidiBuffer(8, channel & 0xf | 0x80, note & 0x7f, velocity & 0x7f); 00295 } 00296 00297 bool USBHostMIDI::sendNoteOn(uint8_t channel, uint8_t note, uint8_t velocity) { 00298 return sendMidiBuffer(9, channel & 0xf | 0x90, note & 0x7f, velocity & 0x7f); 00299 } 00300 00301 bool USBHostMIDI::sendPolyKeyPress(uint8_t channel, uint8_t note, uint8_t pressure) { 00302 return sendMidiBuffer(10, channel & 0xf | 0xa0, note & 0x7f, pressure & 0x7f); 00303 } 00304 00305 bool USBHostMIDI::sendControlChange(uint8_t channel, uint8_t key, uint8_t value) { 00306 return sendMidiBuffer(11, channel & 0xf | 0xb0, key & 0x7f, value & 0x7f); 00307 } 00308 00309 bool USBHostMIDI::sendProgramChange(uint8_t channel, uint8_t program) { 00310 return sendMidiBuffer(12, channel & 0xf | 0xc0, program & 0x7f, 0); 00311 } 00312 00313 bool USBHostMIDI::sendChannelPressure(uint8_t channel, uint8_t pressure) { 00314 return sendMidiBuffer(13, channel & 0xf | 0xd0, pressure & 0x7f, 0); 00315 } 00316 00317 bool USBHostMIDI::sendPitchBend(uint8_t channel, uint16_t value) { 00318 return sendMidiBuffer(14, channel & 0xf | 0xe0, value & 0x7f, (value >> 7) & 0x7f); 00319 } 00320 00321 bool USBHostMIDI::sendSingleByte(uint8_t data) { 00322 return sendMidiBuffer(15, data, 0, 0); 00323 } 00324 00325 /*virtual*/ void USBHostMIDI::setVidPid(uint16_t vid, uint16_t pid) 00326 { 00327 // we don't check VID/PID for this driver 00328 } 00329 00330 /*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 00331 { 00332 // USB MIDI class/subclass 00333 if ((midi_intf == -1) && 00334 (intf_class == AUDIO_CLASS) && 00335 (intf_subclass == 0x03)) { 00336 midi_intf = intf_nb; 00337 return true; 00338 } 00339 00340 // vendor specific device 00341 if ((midi_intf == -1) && 00342 (intf_class == 0xff) && 00343 (intf_subclass == 0x03)) { 00344 midi_intf = intf_nb; 00345 return true; 00346 } 00347 00348 return false; 00349 } 00350 00351 /*virtual*/ bool USBHostMIDI::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used 00352 { 00353 if (intf_nb == midi_intf) { 00354 if (type == BULK_ENDPOINT) { 00355 midi_device_found = true; 00356 return true; 00357 } 00358 } 00359 return false; 00360 } 00361 00362 #endif
Generated on Tue Jul 12 2022 13:32:26 by 1.7.2