X-TOUCH to djay bridge

Dependencies:   mbed mbed-rtos FATFileSystem

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     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