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