Zoltan Hudak / UsbHostMAX3421E

Dependents:   UsbHostMAX3421E_Hello

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers usbh_midi.cpp Source File

usbh_midi.cpp

00001 /*
00002  *******************************************************************************
00003  * USB-MIDI class driver for USB Host Shield 2.0 Library
00004  * Copyright (c) 2012-2018 Yuuichi Akagawa
00005  *
00006  * Idea from LPK25 USB-MIDI to Serial MIDI converter
00007  *   by Collin Cunningham - makezine.com, narbotic.com
00008  *
00009  * for use with USB Host Shield 2.0 from Circuitsathome.com
00010  * https://github.com/felis/USB_Host_Shield_2.0
00011  *******************************************************************************
00012  * This program is free software; you can redistribute it and/or modify
00013  * it under the terms of the GNU General Public License as published by
00014  * the Free Software Foundation; either version 2 of the License, or
00015  * (at your option) any later version.
00016  *
00017  * This program is distributed in the hope that it will be useful,
00018  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  * GNU General Public License for more details.
00021  *
00022  * You should have received a copy of the GNU General Public License
00023  * along with this program.  If not, see <http://www.gnu.org/licenses/>
00024  *******************************************************************************
00025  */
00026 
00027 #include "usbh_midi.h"
00028 //////////////////////////
00029 // MIDI MESAGES
00030 // midi.org/techspecs/
00031 //////////////////////////
00032 // STATUS BYTES
00033 // 0x8n == noteOff
00034 // 0x9n == noteOn
00035 // 0xAn == afterTouch
00036 // 0xBn == controlChange
00037 //    n == Channel(0x0-0xf)
00038 //////////////////////////
00039 //DATA BYTE 1
00040 // note# == (0-127)
00041 // or
00042 // control# == (0-119)
00043 //////////////////////////
00044 // DATA BYTE 2
00045 // velocity == (0-127)
00046 // or
00047 // controlVal == (0-127)
00048 ///////////////////////////////////////////////////////////////////////////////
00049 // USB-MIDI Event Packets
00050 // usb.org - Universal Serial Bus Device Class Definition for MIDI Devices 1.0
00051 ///////////////////////////////////////////////////////////////////////////////
00052 //+-------------+-------------+-------------+-------------+
00053 //|   Byte 0    |   Byte 1    |   Byte 2    |   Byte 3    |
00054 //+------+------+-------------+-------------+-------------+
00055 //|Cable | Code |             |             |             |
00056 //|Number|Index |   MIDI_0    |   MIDI_1    |   MIDI_2    |
00057 //|      |Number|             |             |             |
00058 //|(4bit)|(4bit)|   (8bit)    |   (8bit)    |   (8bit)    |
00059 //+------+------+-------------+-------------+-------------+
00060 // CN == 0x0-0xf
00061 //+-----+-----------+-------------------------------------------------------------------
00062 //| CIN |MIDI_x size|Description
00063 //+-----+-----------+-------------------------------------------------------------------
00064 //| 0x0 | 1, 2 or 3 |Miscellaneous function codes. Reserved for future extensions.
00065 //| 0x1 | 1, 2 or 3 |Cable events. Reserved for future expansion.
00066 //| 0x2 |     2     |Two-byte System Common messages like MTC, SongSelect, etc.
00067 //| 0x3 |     3     |Three-byte System Common messages like SPP, etc.
00068 //| 0x4 |     3     |SysEx starts or continues
00069 //| 0x5 |     1     |Single-byte System Common Message or SysEx ends with following single byte.
00070 //| 0x6 |     2     |SysEx ends with following two bytes.
00071 //| 0x7 |     3     |SysEx ends with following three bytes.
00072 //| 0x8 |     3     |Note-off
00073 //| 0x9 |     3     |Note-on
00074 //| 0xA |     3     |Poly-KeyPress
00075 //| 0xB |     3     |Control Change
00076 //| 0xC |     2     |Program Change
00077 //| 0xD |     2     |Channel Pressure
00078 //| 0xE |     3     |PitchBend Change
00079 //| 0xF |     1     |Single Byte
00080 //+-----+-----------+-------------------------------------------------------------------
00081 
00082 const uint8_t USBH_MIDI::epDataInIndex  = 1;
00083 const uint8_t USBH_MIDI::epDataOutIndex = 2;
00084 const uint8_t USBH_MIDI::epDataInIndexVSP  = 3;
00085 const uint8_t USBH_MIDI::epDataOutIndexVSP = 4;
00086 
00087 USBH_MIDI::USBH_MIDI(Usb *p) :
00088 pUsb(p),
00089 bAddress(0),
00090 bNumEP(1),
00091 bPollEnable(false),
00092 isMidiFound(false),
00093 readPtr(0) {
00094         // initialize endpoint data structures
00095         for(uint8_t i=0; i<MIDI_MAX_ENDPOINTS; i++) {
00096                 epInfo[i].epAddr      = 0;
00097                 epInfo[i].maxPktSize  = (i) ? 0 : 8;
00098                 epInfo[i].bmNakPower  = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
00099 
00100         }
00101         // register in USB subsystem
00102         if (pUsb) {
00103                 pUsb->RegisterDeviceClass(this);
00104         }
00105 }
00106 
00107 /* Connection initialization of an MIDI Device */
00108 uint8_t USBH_MIDI::Init(uint8_t parent, uint8_t port, bool lowspeed)
00109 {
00110         uint8_t    buf[sizeof (USB_DEVICE_DESCRIPTOR)];
00111         USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
00112         uint8_t    rcode;
00113         UsbDevice  *p = NULL;
00114         EpInfo     *oldep_ptr = NULL;
00115         uint8_t    num_of_conf;  // number of configurations
00116 
00117         USBTRACE("\rMIDI Init\r\n");
00118 
00119         //for reconnect
00120         for(uint8_t i=epDataInIndex; i<=epDataOutIndex; i++) {
00121                 epInfo[i].epAddr      = (i==epDataInIndex) ? 0x81 : 0x01;
00122                 epInfo[i].maxPktSize  = 0;
00123                 epInfo[i].bmSndToggle = 0;
00124                 epInfo[i].bmRcvToggle = 0;
00125         }
00126 
00127         // get memory address of USB device address pool
00128         AddressPool &addrPool = pUsb->GetAddressPool();
00129 
00130         // check if address has already been assigned to an instance
00131         if (bAddress) {
00132                 return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
00133         }
00134         // Get pointer to pseudo device with address 0 assigned
00135         p = addrPool.GetUsbDevicePtr(bAddress);
00136         if (!p) {
00137                 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
00138         }
00139         if (!p->epinfo) {
00140                 return USB_ERROR_EPINFO_IS_NULL;
00141         }
00142 
00143         // Save old pointer to EP_RECORD of address 0
00144         oldep_ptr = p->epinfo;
00145 
00146         // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
00147         p->epinfo = epInfo;
00148         p->lowspeed = lowspeed;
00149 
00150         // Get device descriptor
00151         rcode = pUsb->getDevDescr( 0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf );
00152         vid = udd->idVendor;
00153         pid = udd->idProduct;
00154         // Restore p->epinfo
00155         p->epinfo = oldep_ptr;
00156 
00157         if( rcode ){
00158                 goto FailGetDevDescr;
00159         }
00160 
00161         // Allocate new address according to device class
00162         bAddress = addrPool.AllocAddress(parent, false, port);
00163         if (!bAddress) {
00164                 return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
00165         }
00166 
00167         // Extract Max Packet Size from device descriptor
00168         epInfo[0].maxPktSize = udd->bMaxPacketSize0;
00169 
00170         // Assign new address to the device
00171         rcode = pUsb->setAddr( 0, 0, bAddress );
00172         if (rcode) {
00173                 p->lowspeed = false;
00174                 addrPool.FreeAddress(bAddress);
00175                 bAddress = 0;
00176                 return rcode;
00177         }//if (rcode...
00178         USBTRACE2("Addr:", bAddress);
00179 
00180         p->lowspeed = false;
00181 
00182         //get pointer to assigned address record
00183         p = addrPool.GetUsbDevicePtr(bAddress);
00184         if (!p) {
00185                 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
00186         }
00187         p->lowspeed = lowspeed;
00188 
00189         num_of_conf = udd->bNumConfigurations;
00190 
00191         // Assign epInfo to epinfo pointer
00192         rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
00193         if (rcode) {
00194                 USBTRACE("setEpInfoEntry failed");
00195                 goto FailSetDevTblEntry;
00196         }
00197 
00198         USBTRACE("VID:"), D_PrintHex(vid, 0x80);
00199         USBTRACE(" PID:"), D_PrintHex(pid, 0x80);
00200         USBTRACE2(" #Conf:", num_of_conf);
00201 
00202         //Setup for well known vendor/device specific configuration
00203         bTransferTypeMask = bmUSB_TRANSFER_TYPE;
00204         setupDeviceSpecific();
00205 
00206         isMidiFound  = false;
00207         for (uint8_t i=0; i<num_of_conf; i++) {
00208                 rcode = parseConfigDescr(bAddress, i);
00209                 if( rcode )
00210                         goto FailGetConfDescr;
00211                 if (bNumEP > 1)
00212                         break;
00213         } // for
00214 
00215         USBTRACE2("\r\nNumEP:", bNumEP);
00216 
00217         if( bNumEP < 2 ){  //Device not found.
00218                 rcode = 0xff;
00219                 goto FailGetConfDescr;
00220         }
00221 
00222         if( !isMidiFound ){ //MIDI Device not found. Try last Bulk transfer device
00223                 USBTRACE("MIDI not found. Attempts bulk device\r\n");
00224                 epInfo[epDataInIndex].epAddr      = epInfo[epDataInIndexVSP].epAddr;
00225                 epInfo[epDataInIndex].maxPktSize  = epInfo[epDataInIndexVSP].maxPktSize;
00226                 epInfo[epDataOutIndex].epAddr     = epInfo[epDataOutIndexVSP].epAddr;
00227                 epInfo[epDataOutIndex].maxPktSize = epInfo[epDataOutIndexVSP].maxPktSize;
00228         }
00229 
00230         // Assign epInfo to epinfo pointer
00231         rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
00232         USBTRACE2("Conf:", bConfNum);
00233         USBTRACE2("EPin :", (uint8_t)(epInfo[epDataInIndex].epAddr + 0x80));
00234         USBTRACE2("EPout:", epInfo[epDataOutIndex].epAddr);
00235 
00236         // Set Configuration Value
00237         rcode = pUsb->setConf(bAddress, 0, bConfNum);
00238         if (rcode) {
00239                 goto FailSetConfDescr;
00240         }
00241         bPollEnable = true;
00242         USBTRACE("Init done.\r\n");
00243         return 0;
00244 FailGetDevDescr:
00245 FailSetDevTblEntry:
00246 FailGetConfDescr:
00247 FailSetConfDescr:
00248         Release();
00249         return rcode;
00250 }
00251 
00252 /* get and parse config descriptor */
00253 uint8_t USBH_MIDI::parseConfigDescr( uint8_t addr, uint8_t conf )
00254 {
00255         uint8_t buf[ DESC_BUFF_SIZE ];
00256         uint8_t* buf_ptr = buf;
00257         uint8_t rcode;
00258         uint8_t descr_length;
00259         uint8_t descr_type;
00260         uint16_t total_length;
00261         USB_ENDPOINT_DESCRIPTOR *epDesc;
00262         bool isMidi = false;
00263 
00264         // get configuration descriptor (get descriptor size only)
00265         rcode = pUsb->getConfDescr( addr, 0, 4, conf, buf );
00266         if( rcode ){
00267                 return rcode;
00268         }
00269         total_length = buf[2] | ((int)buf[3] << 8);
00270         if( total_length > DESC_BUFF_SIZE ) {    //check if total length is larger than buffer
00271                 total_length = DESC_BUFF_SIZE;
00272         }
00273 
00274         // get configuration descriptor (all)
00275         rcode = pUsb->getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor
00276         if( rcode ){
00277                 return rcode;
00278         }
00279 
00280         //parsing descriptors
00281         while( buf_ptr < buf + total_length ) {
00282                 descr_length = *( buf_ptr );
00283                 descr_type   = *( buf_ptr + 1 );
00284                 switch( descr_type ) {
00285                   case USB_DESCRIPTOR_CONFIGURATION :
00286                         bConfNum = buf_ptr[5];
00287                         break;
00288                   case  USB_DESCRIPTOR_INTERFACE :
00289                         USBTRACE("\r\nConf:"), D_PrintHex(bConfNum, 0x80);
00290                         USBTRACE(" Int:"), D_PrintHex(buf_ptr[2], 0x80);
00291                         USBTRACE(" Alt:"), D_PrintHex(buf_ptr[3], 0x80);
00292                         USBTRACE(" EPs:"), D_PrintHex(buf_ptr[4], 0x80);
00293                         USBTRACE(" IntCl:"), D_PrintHex(buf_ptr[5], 0x80);
00294                         USBTRACE(" IntSubCl:"), D_PrintHex(buf_ptr[6], 0x80);
00295                         USBTRACE("\r\n");
00296 
00297                         if( buf_ptr[5] == USB_CLASS_AUDIO && buf_ptr[6] == USB_SUBCLASS_MIDISTREAMING ) {  //p[5]; bInterfaceClass = 1(Audio), p[6]; bInterfaceSubClass = 3(MIDI Streaming)
00298                                 isMidiFound = true; //MIDI device found.
00299                                 isMidi      = true;
00300                                 USBTRACE("MIDI Device\r\n");
00301                         }else{
00302                                 isMidi = false;
00303                                 USBTRACE("No MIDI Device\r\n");
00304                         }
00305                         break;
00306                   case USB_DESCRIPTOR_ENDPOINT :
00307                         epDesc = (USB_ENDPOINT_DESCRIPTOR *)buf_ptr;
00308                         USBTRACE("-EPAddr:"), D_PrintHex(epDesc->bEndpointAddress, 0x80);
00309                         USBTRACE(" bmAttr:"), D_PrintHex(epDesc->bmAttributes, 0x80);
00310                         USBTRACE2(" MaxPktSz:", (uint8_t)epDesc->wMaxPacketSize);
00311                         if ((epDesc->bmAttributes & bTransferTypeMask) == USB_TRANSFER_TYPE_BULK) {//bulk
00312                                 uint8_t index;
00313                                 if( isMidi )
00314                                         index = ((epDesc->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
00315                                 else
00316                                         index = ((epDesc->bEndpointAddress & 0x80) == 0x80) ? epDataInIndexVSP : epDataOutIndexVSP;
00317                                 epInfo[index].epAddr     = (epDesc->bEndpointAddress & 0x0F);
00318                                 epInfo[index].maxPktSize = (uint8_t)epDesc->wMaxPacketSize;
00319                                 bNumEP ++;
00320 #ifdef DEBUG_USB_HOST
00321                                 PrintEndpointDescriptor(epDesc);
00322 #endif
00323                         }
00324                         break;
00325                   default:
00326                         break;
00327                 }//switch( descr_type
00328                 buf_ptr += descr_length;    //advance buffer pointer
00329         }//while( buf_ptr <=...
00330         return 0;
00331 }
00332 
00333 /* Performs a cleanup after failed Init() attempt */
00334 uint8_t USBH_MIDI::Release()
00335 {
00336         pUsb->GetAddressPool().FreeAddress(bAddress);
00337         bNumEP       = 1;               //must have to be reset to 1
00338         bAddress     = 0;
00339         bPollEnable  = false;
00340         readPtr      = 0;
00341         return 0;
00342 }
00343 
00344 /* Setup for well known vendor/device specific configuration */
00345 void USBH_MIDI::setupDeviceSpecific()
00346 {
00347         // Novation
00348         if( vid == 0x1235 ) {
00349                 // LaunchPad's endpoint attirbute is interrupt (0x20:S, 0x36:Mini, 0x51:Pro, 0x69:MK2, 0x7b:Launchkey25 MK2)
00350                 if(pid == 0x20 || pid == 0x36 || pid == 0x51 || pid == 0x69 || pid == 0x7b ) {
00351                         bTransferTypeMask = 2;
00352                 }
00353         }
00354 }
00355 
00356 /* Receive data from MIDI device */
00357 uint8_t USBH_MIDI::RecvData(uint16_t *bytes_rcvd, uint8_t *dataptr)
00358 {
00359         *bytes_rcvd = (uint16_t)epInfo[epDataInIndex].maxPktSize;
00360         uint8_t  r = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr);
00361 
00362         if( *bytes_rcvd < (MIDI_EVENT_PACKET_SIZE-4)){
00363                 dataptr[*bytes_rcvd]     = '\0';
00364                 dataptr[(*bytes_rcvd)+1] = '\0';
00365         }
00366         return r;
00367 }
00368 
00369 /* Receive data from MIDI device */
00370 uint8_t USBH_MIDI::RecvData(uint8_t *outBuf, bool isRaw)
00371 {
00372         uint8_t rcode = 0;     //return code
00373         uint16_t  rcvd;
00374 
00375         if( bPollEnable == false ) return 0;
00376 
00377         //Checking unprocessed message in buffer.
00378         if( readPtr != 0 && readPtr < MIDI_EVENT_PACKET_SIZE ){
00379                 if(recvBuf[readPtr] == 0 && recvBuf[readPtr+1] == 0) {
00380                         //no unprocessed message left in the buffer.
00381                 }else{
00382                         goto RecvData_return_from_buffer;
00383                 }
00384         }
00385 
00386         readPtr = 0;
00387         rcode = RecvData( &rcvd, recvBuf);
00388         if( rcode != 0 ) {
00389                 return 0;
00390         }
00391 
00392         //if all data is zero, no valid data received.
00393         if( recvBuf[0] == 0 && recvBuf[1] == 0 && recvBuf[2] == 0 && recvBuf[3] == 0 ) {
00394                 return 0;
00395         }
00396 
00397 RecvData_return_from_buffer:
00398         uint8_t m;
00399         uint8_t cin = recvBuf[readPtr];
00400         if( isRaw == true ) {
00401                 *(outBuf++) = cin;
00402         }
00403         readPtr++;
00404         *(outBuf++) = m = recvBuf[readPtr++];
00405         *(outBuf++) =     recvBuf[readPtr++];
00406         *(outBuf++) =     recvBuf[readPtr++];
00407         return lookupMsgSize(m, cin);
00408 }
00409 
00410 /* Receive raw data from MIDI device */
00411 uint8_t USBH_MIDI::RecvRawData(uint8_t *outBuf)
00412 {
00413         return RecvData(outBuf, true);
00414 }
00415 
00416 /* Send data to MIDI device */
00417 uint8_t USBH_MIDI::SendData(uint8_t *dataptr, uint8_t nCable)
00418 {
00419         uint8_t buf[4];
00420         uint8_t msg;
00421 
00422         msg = dataptr[0];
00423         // SysEx long message ?
00424         if( msg == 0xf0 )
00425         {
00426                 return SendSysEx(dataptr, countSysExDataSize(dataptr), nCable);
00427         }
00428 
00429         buf[0] = (nCable << 4) | (msg >> 4);
00430         if( msg < 0xf0 ) msg = msg & 0xf0;
00431 
00432 
00433         //Building USB-MIDI Event Packets
00434         buf[1] = dataptr[0];
00435         buf[2] = dataptr[1];
00436         buf[3] = dataptr[2];
00437 
00438         switch(lookupMsgSize(msg)) {
00439           //3 bytes message
00440           case 3 :
00441                 if(msg == 0xf2) {//system common message(SPP)
00442                         buf[0] = (nCable << 4) | 3;
00443                 }
00444                 break;
00445 
00446           //2 bytes message
00447           case 2 :
00448                 if(msg == 0xf1 || msg == 0xf3) {//system common message(MTC/SongSelect)
00449                         buf[0] = (nCable << 4) | 2;
00450                 }
00451                 buf[3] = 0;
00452                 break;
00453 
00454           //1 byte message
00455           case 1 :
00456           default :
00457                 buf[2] = 0;
00458                 buf[3] = 0;
00459                 break;
00460         }
00461         return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, 4, buf);
00462 }
00463 
00464 #ifdef DEBUG_USB_HOST
00465 void USBH_MIDI::PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr )
00466 {
00467         USBTRACE("Endpoint descriptor:\r\n");
00468         USBTRACE2(" Length:\t", ep_ptr->bLength);
00469         USBTRACE2(" Type:\t\t", ep_ptr->bDescriptorType);
00470         USBTRACE2(" Address:\t", ep_ptr->bEndpointAddress);
00471         USBTRACE2(" Attributes:\t", ep_ptr->bmAttributes);
00472         USBTRACE2(" MaxPktSize:\t", ep_ptr->wMaxPacketSize);
00473         USBTRACE2(" Poll Intrv:\t", ep_ptr->bInterval);
00474 }
00475 #endif
00476 
00477 /* look up a MIDI message size from spec */
00478 /*Return                                 */
00479 /*  0 : undefined message                */
00480 /*  0<: Vaild message size(1-3)          */
00481 uint8_t USBH_MIDI::lookupMsgSize(uint8_t midiMsg, uint8_t cin)
00482 {
00483         uint8_t msgSize = 0;
00484 
00485         //SysEx message?
00486         cin = cin & 0x0f;
00487         if( (cin & 0xc) == 4 ) {
00488                 if( cin == 4 || cin == 7 ) return 3;
00489                 if( cin == 6 )             return 2;
00490                 if( cin == 5 )             return 1;
00491         }
00492 
00493         if( midiMsg < 0xf0 ) midiMsg &= 0xf0;
00494         switch(midiMsg) {
00495           //3 bytes messages
00496           case 0xf2 : //system common message(SPP)
00497           case 0x80 : //Note off
00498           case 0x90 : //Note on
00499           case 0xa0 : //Poly KeyPress
00500           case 0xb0 : //Control Change
00501           case 0xe0 : //PitchBend Change
00502                 msgSize = 3;
00503                 break;
00504 
00505           //2 bytes messages
00506           case 0xf1 : //system common message(MTC)
00507           case 0xf3 : //system common message(SongSelect)
00508           case 0xc0 : //Program Change
00509           case 0xd0 : //Channel Pressure
00510                 msgSize = 2;
00511                 break;
00512 
00513           //1 byte messages
00514           case 0xf8 : //system realtime message
00515           case 0xf9 : //system realtime message
00516           case 0xfa : //system realtime message
00517           case 0xfb : //system realtime message
00518           case 0xfc : //system realtime message
00519           case 0xfe : //system realtime message
00520           case 0xff : //system realtime message
00521                 msgSize = 1;
00522                 break;
00523 
00524           //undefine messages
00525           default :
00526                 break;
00527         }
00528         return msgSize;
00529 }
00530 
00531 /* SysEx data size counter */
00532 uint16_t USBH_MIDI::countSysExDataSize(uint8_t *dataptr)
00533 {
00534         uint16_t c = 1;
00535 
00536         if( *dataptr != 0xf0 ){ //not SysEx
00537                 return 0;
00538         }
00539 
00540         //Search terminator(0xf7)
00541         while(*dataptr != 0xf7)
00542         {
00543                 dataptr++;
00544                 c++;
00545 
00546                 //Limiter (default: 256 bytes)
00547                 if(c > MIDI_MAX_SYSEX_SIZE){
00548                         c = 0;
00549                         break;
00550                 }
00551         }
00552         return c;
00553 }
00554 
00555 /* Send SysEx message to MIDI device */
00556 uint8_t USBH_MIDI::SendSysEx(uint8_t *dataptr, uint16_t datasize, uint8_t nCable)
00557 {
00558         uint8_t buf[MIDI_EVENT_PACKET_SIZE];
00559         uint8_t rc = 0;
00560         uint16_t n = datasize;
00561         uint16_t pktSize = (n*10/3+7)/10*4;   //Calculate total USB MIDI packet size
00562         uint8_t wptr = 0;
00563         uint8_t maxpkt = epInfo[epDataInIndex].maxPktSize;
00564 
00565         if( maxpkt > MIDI_EVENT_PACKET_SIZE ) maxpkt = MIDI_EVENT_PACKET_SIZE;
00566 
00567         USBTRACE("SendSysEx:\r\t");
00568         USBTRACE2(" Length:\t", datasize);
00569         USBTRACE2(" Total pktSize:\t", pktSize);
00570 
00571         while(n > 0) {
00572                 //Byte 0
00573                 buf[wptr] = (nCable << 4) | 0x4;             //x4 SysEx starts or continues
00574 
00575                 switch ( n ) {
00576                     case 1 :
00577                         buf[wptr++] = (nCable << 4) | 0x5;   //x5 SysEx ends with following single byte.
00578                         buf[wptr++] = *(dataptr++);
00579                         buf[wptr++] = 0x00;
00580                         buf[wptr++] = 0x00;
00581                         n = n - 1;
00582                         break;
00583                     case 2 :
00584                         buf[wptr++] = (nCable << 4) | 0x6;   //x6 SysEx ends with following two bytes.
00585                         buf[wptr++] = *(dataptr++);
00586                         buf[wptr++] = *(dataptr++);
00587                         buf[wptr++] = 0x00;
00588                         n = n - 2;
00589                         break;
00590                     case 3 :
00591                         buf[wptr]   = (nCable << 4) | 0x7;   //x7 SysEx ends with following three bytes.
00592                     default :
00593                         wptr++;
00594                         buf[wptr++] = *(dataptr++);
00595                         buf[wptr++] = *(dataptr++);
00596                         buf[wptr++] = *(dataptr++);
00597                         n = n - 3;
00598                         break;
00599                 }
00600 
00601                 if( wptr >= maxpkt || n == 0 ){ //Reach a maxPktSize or data end.
00602                         USBTRACE2(" wptr:\t", wptr);
00603                         if( (rc = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, wptr, buf)) != 0 ){
00604                                 break;
00605                         }
00606                         wptr = 0;  //rewind data pointer
00607                 }
00608         }
00609         return(rc);
00610 }
00611 
00612 /* Send raw data to MIDI device */
00613 uint8_t USBH_MIDI::SendRawData(uint16_t bytes_send, uint8_t *dataptr)
00614 {
00615         return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes_send, dataptr);
00616 
00617 }
00618 
00619 uint8_t USBH_MIDI::extractSysExData(uint8_t *p, uint8_t *buf)
00620 {
00621         uint8_t rc = 0;
00622         uint8_t cin = *(p) & 0x0f;
00623 
00624         //SysEx message?
00625         if( (cin & 0xc) != 4 ) return rc;
00626 
00627         switch(cin) {
00628             case 4:
00629             case 7:
00630                 *buf++ = *(p+1);
00631                 *buf++ = *(p+2);
00632                 *buf++ = *(p+3);
00633                 rc = 3;
00634                 break;
00635             case 6:
00636                 *buf++ = *(p+1);
00637                 *buf++ = *(p+2);
00638                 rc = 2;
00639                 break;
00640             case 5:
00641                 *buf++ = *(p+1);
00642                 rc = 1;
00643                 break;
00644             default:
00645                 break;
00646         }
00647         return(rc);
00648 }