Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: UsbHostMAX3421E_Hello
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 }
Generated on Tue Jul 12 2022 18:12:05 by
1.7.2