kaz saita / USBHOST
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHostMIDI.cpp Source File

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