Zoltan Hudak / UsbHostMAX3421E

Dependents:   UsbHostMAX3421E_Hello

Committer:
hudakz
Date:
Sun Jul 12 20:39:26 2020 +0000
Revision:
0:84353c479782
Child:
1:2263e77400e9
MAX3421E-based USB Host Shield Library

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hudakz 0:84353c479782 1 /*
hudakz 0:84353c479782 2 *******************************************************************************
hudakz 0:84353c479782 3 * USB-MIDI class driver for USB Host Shield 2.0 Library
hudakz 0:84353c479782 4 * Copyright (c) 2012-2018 Yuuichi Akagawa
hudakz 0:84353c479782 5 *
hudakz 0:84353c479782 6 * Idea from LPK25 USB-MIDI to Serial MIDI converter
hudakz 0:84353c479782 7 * by Collin Cunningham - makezine.com, narbotic.com
hudakz 0:84353c479782 8 *
hudakz 0:84353c479782 9 * for use with USB Host Shield 2.0 from Circuitsathome.com
hudakz 0:84353c479782 10 * https://github.com/felis/USB_Host_Shield_2.0
hudakz 0:84353c479782 11 *******************************************************************************
hudakz 0:84353c479782 12 * This program is free software; you can redistribute it and/or modify
hudakz 0:84353c479782 13 * it under the terms of the GNU General Public License as published by
hudakz 0:84353c479782 14 * the Free Software Foundation; either version 2 of the License, or
hudakz 0:84353c479782 15 * (at your option) any later version.
hudakz 0:84353c479782 16 *
hudakz 0:84353c479782 17 * This program is distributed in the hope that it will be useful,
hudakz 0:84353c479782 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
hudakz 0:84353c479782 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
hudakz 0:84353c479782 20 * GNU General Public License for more details.
hudakz 0:84353c479782 21 *
hudakz 0:84353c479782 22 * You should have received a copy of the GNU General Public License
hudakz 0:84353c479782 23 * along with this program. If not, see <http://www.gnu.org/licenses/>
hudakz 0:84353c479782 24 *******************************************************************************
hudakz 0:84353c479782 25 */
hudakz 0:84353c479782 26
hudakz 0:84353c479782 27 #include "usbh_midi.h"
hudakz 0:84353c479782 28 //////////////////////////
hudakz 0:84353c479782 29 // MIDI MESAGES
hudakz 0:84353c479782 30 // midi.org/techspecs/
hudakz 0:84353c479782 31 //////////////////////////
hudakz 0:84353c479782 32 // STATUS BYTES
hudakz 0:84353c479782 33 // 0x8n == noteOff
hudakz 0:84353c479782 34 // 0x9n == noteOn
hudakz 0:84353c479782 35 // 0xAn == afterTouch
hudakz 0:84353c479782 36 // 0xBn == controlChange
hudakz 0:84353c479782 37 // n == Channel(0x0-0xf)
hudakz 0:84353c479782 38 //////////////////////////
hudakz 0:84353c479782 39 //DATA BYTE 1
hudakz 0:84353c479782 40 // note# == (0-127)
hudakz 0:84353c479782 41 // or
hudakz 0:84353c479782 42 // control# == (0-119)
hudakz 0:84353c479782 43 //////////////////////////
hudakz 0:84353c479782 44 // DATA BYTE 2
hudakz 0:84353c479782 45 // velocity == (0-127)
hudakz 0:84353c479782 46 // or
hudakz 0:84353c479782 47 // controlVal == (0-127)
hudakz 0:84353c479782 48 ///////////////////////////////////////////////////////////////////////////////
hudakz 0:84353c479782 49 // USB-MIDI Event Packets
hudakz 0:84353c479782 50 // usb.org - Universal Serial Bus Device Class Definition for MIDI Devices 1.0
hudakz 0:84353c479782 51 ///////////////////////////////////////////////////////////////////////////////
hudakz 0:84353c479782 52 //+-------------+-------------+-------------+-------------+
hudakz 0:84353c479782 53 //| Byte 0 | Byte 1 | Byte 2 | Byte 3 |
hudakz 0:84353c479782 54 //+------+------+-------------+-------------+-------------+
hudakz 0:84353c479782 55 //|Cable | Code | | | |
hudakz 0:84353c479782 56 //|Number|Index | MIDI_0 | MIDI_1 | MIDI_2 |
hudakz 0:84353c479782 57 //| |Number| | | |
hudakz 0:84353c479782 58 //|(4bit)|(4bit)| (8bit) | (8bit) | (8bit) |
hudakz 0:84353c479782 59 //+------+------+-------------+-------------+-------------+
hudakz 0:84353c479782 60 // CN == 0x0-0xf
hudakz 0:84353c479782 61 //+-----+-----------+-------------------------------------------------------------------
hudakz 0:84353c479782 62 //| CIN |MIDI_x size|Description
hudakz 0:84353c479782 63 //+-----+-----------+-------------------------------------------------------------------
hudakz 0:84353c479782 64 //| 0x0 | 1, 2 or 3 |Miscellaneous function codes. Reserved for future extensions.
hudakz 0:84353c479782 65 //| 0x1 | 1, 2 or 3 |Cable events. Reserved for future expansion.
hudakz 0:84353c479782 66 //| 0x2 | 2 |Two-byte System Common messages like MTC, SongSelect, etc.
hudakz 0:84353c479782 67 //| 0x3 | 3 |Three-byte System Common messages like SPP, etc.
hudakz 0:84353c479782 68 //| 0x4 | 3 |SysEx starts or continues
hudakz 0:84353c479782 69 //| 0x5 | 1 |Single-byte System Common Message or SysEx ends with following single byte.
hudakz 0:84353c479782 70 //| 0x6 | 2 |SysEx ends with following two bytes.
hudakz 0:84353c479782 71 //| 0x7 | 3 |SysEx ends with following three bytes.
hudakz 0:84353c479782 72 //| 0x8 | 3 |Note-off
hudakz 0:84353c479782 73 //| 0x9 | 3 |Note-on
hudakz 0:84353c479782 74 //| 0xA | 3 |Poly-KeyPress
hudakz 0:84353c479782 75 //| 0xB | 3 |Control Change
hudakz 0:84353c479782 76 //| 0xC | 2 |Program Change
hudakz 0:84353c479782 77 //| 0xD | 2 |Channel Pressure
hudakz 0:84353c479782 78 //| 0xE | 3 |PitchBend Change
hudakz 0:84353c479782 79 //| 0xF | 1 |Single Byte
hudakz 0:84353c479782 80 //+-----+-----------+-------------------------------------------------------------------
hudakz 0:84353c479782 81
hudakz 0:84353c479782 82 const uint8_t USBH_MIDI::epDataInIndex = 1;
hudakz 0:84353c479782 83 const uint8_t USBH_MIDI::epDataOutIndex = 2;
hudakz 0:84353c479782 84 const uint8_t USBH_MIDI::epDataInIndexVSP = 3;
hudakz 0:84353c479782 85 const uint8_t USBH_MIDI::epDataOutIndexVSP = 4;
hudakz 0:84353c479782 86
hudakz 0:84353c479782 87 USBH_MIDI::USBH_MIDI(USB *p) :
hudakz 0:84353c479782 88 pUsb(p),
hudakz 0:84353c479782 89 bAddress(0),
hudakz 0:84353c479782 90 bNumEP(1),
hudakz 0:84353c479782 91 bPollEnable(false),
hudakz 0:84353c479782 92 isMidiFound(false),
hudakz 0:84353c479782 93 readPtr(0) {
hudakz 0:84353c479782 94 // initialize endpoint data structures
hudakz 0:84353c479782 95 for(uint8_t i=0; i<MIDI_MAX_ENDPOINTS; i++) {
hudakz 0:84353c479782 96 epInfo[i].epAddr = 0;
hudakz 0:84353c479782 97 epInfo[i].maxPktSize = (i) ? 0 : 8;
hudakz 0:84353c479782 98 epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
hudakz 0:84353c479782 99
hudakz 0:84353c479782 100 }
hudakz 0:84353c479782 101 // register in USB subsystem
hudakz 0:84353c479782 102 if (pUsb) {
hudakz 0:84353c479782 103 pUsb->RegisterDeviceClass(this);
hudakz 0:84353c479782 104 }
hudakz 0:84353c479782 105 }
hudakz 0:84353c479782 106
hudakz 0:84353c479782 107 /* Connection initialization of an MIDI Device */
hudakz 0:84353c479782 108 uint8_t USBH_MIDI::Init(uint8_t parent, uint8_t port, bool lowspeed)
hudakz 0:84353c479782 109 {
hudakz 0:84353c479782 110 uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
hudakz 0:84353c479782 111 USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
hudakz 0:84353c479782 112 uint8_t rcode;
hudakz 0:84353c479782 113 UsbDevice *p = NULL;
hudakz 0:84353c479782 114 EpInfo *oldep_ptr = NULL;
hudakz 0:84353c479782 115 uint8_t num_of_conf; // number of configurations
hudakz 0:84353c479782 116
hudakz 0:84353c479782 117 USBTRACE("\rMIDI Init\r\n");
hudakz 0:84353c479782 118
hudakz 0:84353c479782 119 //for reconnect
hudakz 0:84353c479782 120 for(uint8_t i=epDataInIndex; i<=epDataOutIndex; i++) {
hudakz 0:84353c479782 121 epInfo[i].epAddr = (i==epDataInIndex) ? 0x81 : 0x01;
hudakz 0:84353c479782 122 epInfo[i].maxPktSize = 0;
hudakz 0:84353c479782 123 epInfo[i].bmSndToggle = 0;
hudakz 0:84353c479782 124 epInfo[i].bmRcvToggle = 0;
hudakz 0:84353c479782 125 }
hudakz 0:84353c479782 126
hudakz 0:84353c479782 127 // get memory address of USB device address pool
hudakz 0:84353c479782 128 AddressPool &addrPool = pUsb->GetAddressPool();
hudakz 0:84353c479782 129
hudakz 0:84353c479782 130 // check if address has already been assigned to an instance
hudakz 0:84353c479782 131 if (bAddress) {
hudakz 0:84353c479782 132 return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
hudakz 0:84353c479782 133 }
hudakz 0:84353c479782 134 // Get pointer to pseudo device with address 0 assigned
hudakz 0:84353c479782 135 p = addrPool.GetUsbDevicePtr(bAddress);
hudakz 0:84353c479782 136 if (!p) {
hudakz 0:84353c479782 137 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
hudakz 0:84353c479782 138 }
hudakz 0:84353c479782 139 if (!p->epinfo) {
hudakz 0:84353c479782 140 return USB_ERROR_EPINFO_IS_NULL;
hudakz 0:84353c479782 141 }
hudakz 0:84353c479782 142
hudakz 0:84353c479782 143 // Save old pointer to EP_RECORD of address 0
hudakz 0:84353c479782 144 oldep_ptr = p->epinfo;
hudakz 0:84353c479782 145
hudakz 0:84353c479782 146 // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
hudakz 0:84353c479782 147 p->epinfo = epInfo;
hudakz 0:84353c479782 148 p->lowspeed = lowspeed;
hudakz 0:84353c479782 149
hudakz 0:84353c479782 150 // Get device descriptor
hudakz 0:84353c479782 151 rcode = pUsb->getDevDescr( 0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf );
hudakz 0:84353c479782 152 vid = udd->idVendor;
hudakz 0:84353c479782 153 pid = udd->idProduct;
hudakz 0:84353c479782 154 // Restore p->epinfo
hudakz 0:84353c479782 155 p->epinfo = oldep_ptr;
hudakz 0:84353c479782 156
hudakz 0:84353c479782 157 if( rcode ){
hudakz 0:84353c479782 158 goto FailGetDevDescr;
hudakz 0:84353c479782 159 }
hudakz 0:84353c479782 160
hudakz 0:84353c479782 161 // Allocate new address according to device class
hudakz 0:84353c479782 162 bAddress = addrPool.AllocAddress(parent, false, port);
hudakz 0:84353c479782 163 if (!bAddress) {
hudakz 0:84353c479782 164 return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
hudakz 0:84353c479782 165 }
hudakz 0:84353c479782 166
hudakz 0:84353c479782 167 // Extract Max Packet Size from device descriptor
hudakz 0:84353c479782 168 epInfo[0].maxPktSize = udd->bMaxPacketSize0;
hudakz 0:84353c479782 169
hudakz 0:84353c479782 170 // Assign new address to the device
hudakz 0:84353c479782 171 rcode = pUsb->setAddr( 0, 0, bAddress );
hudakz 0:84353c479782 172 if (rcode) {
hudakz 0:84353c479782 173 p->lowspeed = false;
hudakz 0:84353c479782 174 addrPool.FreeAddress(bAddress);
hudakz 0:84353c479782 175 bAddress = 0;
hudakz 0:84353c479782 176 return rcode;
hudakz 0:84353c479782 177 }//if (rcode...
hudakz 0:84353c479782 178 USBTRACE2("Addr:", bAddress);
hudakz 0:84353c479782 179
hudakz 0:84353c479782 180 p->lowspeed = false;
hudakz 0:84353c479782 181
hudakz 0:84353c479782 182 //get pointer to assigned address record
hudakz 0:84353c479782 183 p = addrPool.GetUsbDevicePtr(bAddress);
hudakz 0:84353c479782 184 if (!p) {
hudakz 0:84353c479782 185 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
hudakz 0:84353c479782 186 }
hudakz 0:84353c479782 187 p->lowspeed = lowspeed;
hudakz 0:84353c479782 188
hudakz 0:84353c479782 189 num_of_conf = udd->bNumConfigurations;
hudakz 0:84353c479782 190
hudakz 0:84353c479782 191 // Assign epInfo to epinfo pointer
hudakz 0:84353c479782 192 rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
hudakz 0:84353c479782 193 if (rcode) {
hudakz 0:84353c479782 194 USBTRACE("setEpInfoEntry failed");
hudakz 0:84353c479782 195 goto FailSetDevTblEntry;
hudakz 0:84353c479782 196 }
hudakz 0:84353c479782 197
hudakz 0:84353c479782 198 USBTRACE("VID:"), D_PrintHex(vid, 0x80);
hudakz 0:84353c479782 199 USBTRACE(" PID:"), D_PrintHex(pid, 0x80);
hudakz 0:84353c479782 200 USBTRACE2(" #Conf:", num_of_conf);
hudakz 0:84353c479782 201
hudakz 0:84353c479782 202 //Setup for well known vendor/device specific configuration
hudakz 0:84353c479782 203 bTransferTypeMask = bmUSB_TRANSFER_TYPE;
hudakz 0:84353c479782 204 setupDeviceSpecific();
hudakz 0:84353c479782 205
hudakz 0:84353c479782 206 isMidiFound = false;
hudakz 0:84353c479782 207 for (uint8_t i=0; i<num_of_conf; i++) {
hudakz 0:84353c479782 208 rcode = parseConfigDescr(bAddress, i);
hudakz 0:84353c479782 209 if( rcode )
hudakz 0:84353c479782 210 goto FailGetConfDescr;
hudakz 0:84353c479782 211 if (bNumEP > 1)
hudakz 0:84353c479782 212 break;
hudakz 0:84353c479782 213 } // for
hudakz 0:84353c479782 214
hudakz 0:84353c479782 215 USBTRACE2("\r\nNumEP:", bNumEP);
hudakz 0:84353c479782 216
hudakz 0:84353c479782 217 if( bNumEP < 2 ){ //Device not found.
hudakz 0:84353c479782 218 rcode = 0xff;
hudakz 0:84353c479782 219 goto FailGetConfDescr;
hudakz 0:84353c479782 220 }
hudakz 0:84353c479782 221
hudakz 0:84353c479782 222 if( !isMidiFound ){ //MIDI Device not found. Try last Bulk transfer device
hudakz 0:84353c479782 223 USBTRACE("MIDI not found. Attempts bulk device\r\n");
hudakz 0:84353c479782 224 epInfo[epDataInIndex].epAddr = epInfo[epDataInIndexVSP].epAddr;
hudakz 0:84353c479782 225 epInfo[epDataInIndex].maxPktSize = epInfo[epDataInIndexVSP].maxPktSize;
hudakz 0:84353c479782 226 epInfo[epDataOutIndex].epAddr = epInfo[epDataOutIndexVSP].epAddr;
hudakz 0:84353c479782 227 epInfo[epDataOutIndex].maxPktSize = epInfo[epDataOutIndexVSP].maxPktSize;
hudakz 0:84353c479782 228 }
hudakz 0:84353c479782 229
hudakz 0:84353c479782 230 // Assign epInfo to epinfo pointer
hudakz 0:84353c479782 231 rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
hudakz 0:84353c479782 232 USBTRACE2("Conf:", bConfNum);
hudakz 0:84353c479782 233 USBTRACE2("EPin :", (uint8_t)(epInfo[epDataInIndex].epAddr + 0x80));
hudakz 0:84353c479782 234 USBTRACE2("EPout:", epInfo[epDataOutIndex].epAddr);
hudakz 0:84353c479782 235
hudakz 0:84353c479782 236 // Set Configuration Value
hudakz 0:84353c479782 237 rcode = pUsb->setConf(bAddress, 0, bConfNum);
hudakz 0:84353c479782 238 if (rcode) {
hudakz 0:84353c479782 239 goto FailSetConfDescr;
hudakz 0:84353c479782 240 }
hudakz 0:84353c479782 241 bPollEnable = true;
hudakz 0:84353c479782 242 USBTRACE("Init done.\r\n");
hudakz 0:84353c479782 243 return 0;
hudakz 0:84353c479782 244 FailGetDevDescr:
hudakz 0:84353c479782 245 FailSetDevTblEntry:
hudakz 0:84353c479782 246 FailGetConfDescr:
hudakz 0:84353c479782 247 FailSetConfDescr:
hudakz 0:84353c479782 248 Release();
hudakz 0:84353c479782 249 return rcode;
hudakz 0:84353c479782 250 }
hudakz 0:84353c479782 251
hudakz 0:84353c479782 252 /* get and parse config descriptor */
hudakz 0:84353c479782 253 uint8_t USBH_MIDI::parseConfigDescr( uint8_t addr, uint8_t conf )
hudakz 0:84353c479782 254 {
hudakz 0:84353c479782 255 uint8_t buf[ DESC_BUFF_SIZE ];
hudakz 0:84353c479782 256 uint8_t* buf_ptr = buf;
hudakz 0:84353c479782 257 uint8_t rcode;
hudakz 0:84353c479782 258 uint8_t descr_length;
hudakz 0:84353c479782 259 uint8_t descr_type;
hudakz 0:84353c479782 260 uint16_t total_length;
hudakz 0:84353c479782 261 USB_ENDPOINT_DESCRIPTOR *epDesc;
hudakz 0:84353c479782 262 bool isMidi = false;
hudakz 0:84353c479782 263
hudakz 0:84353c479782 264 // get configuration descriptor (get descriptor size only)
hudakz 0:84353c479782 265 rcode = pUsb->getConfDescr( addr, 0, 4, conf, buf );
hudakz 0:84353c479782 266 if( rcode ){
hudakz 0:84353c479782 267 return rcode;
hudakz 0:84353c479782 268 }
hudakz 0:84353c479782 269 total_length = buf[2] | ((int)buf[3] << 8);
hudakz 0:84353c479782 270 if( total_length > DESC_BUFF_SIZE ) { //check if total length is larger than buffer
hudakz 0:84353c479782 271 total_length = DESC_BUFF_SIZE;
hudakz 0:84353c479782 272 }
hudakz 0:84353c479782 273
hudakz 0:84353c479782 274 // get configuration descriptor (all)
hudakz 0:84353c479782 275 rcode = pUsb->getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor
hudakz 0:84353c479782 276 if( rcode ){
hudakz 0:84353c479782 277 return rcode;
hudakz 0:84353c479782 278 }
hudakz 0:84353c479782 279
hudakz 0:84353c479782 280 //parsing descriptors
hudakz 0:84353c479782 281 while( buf_ptr < buf + total_length ) {
hudakz 0:84353c479782 282 descr_length = *( buf_ptr );
hudakz 0:84353c479782 283 descr_type = *( buf_ptr + 1 );
hudakz 0:84353c479782 284 switch( descr_type ) {
hudakz 0:84353c479782 285 case USB_DESCRIPTOR_CONFIGURATION :
hudakz 0:84353c479782 286 bConfNum = buf_ptr[5];
hudakz 0:84353c479782 287 break;
hudakz 0:84353c479782 288 case USB_DESCRIPTOR_INTERFACE :
hudakz 0:84353c479782 289 USBTRACE("\r\nConf:"), D_PrintHex(bConfNum, 0x80);
hudakz 0:84353c479782 290 USBTRACE(" Int:"), D_PrintHex(buf_ptr[2], 0x80);
hudakz 0:84353c479782 291 USBTRACE(" Alt:"), D_PrintHex(buf_ptr[3], 0x80);
hudakz 0:84353c479782 292 USBTRACE(" EPs:"), D_PrintHex(buf_ptr[4], 0x80);
hudakz 0:84353c479782 293 USBTRACE(" IntCl:"), D_PrintHex(buf_ptr[5], 0x80);
hudakz 0:84353c479782 294 USBTRACE(" IntSubCl:"), D_PrintHex(buf_ptr[6], 0x80);
hudakz 0:84353c479782 295 USBTRACE("\r\n");
hudakz 0:84353c479782 296
hudakz 0:84353c479782 297 if( buf_ptr[5] == USB_CLASS_AUDIO && buf_ptr[6] == USB_SUBCLASS_MIDISTREAMING ) { //p[5]; bInterfaceClass = 1(Audio), p[6]; bInterfaceSubClass = 3(MIDI Streaming)
hudakz 0:84353c479782 298 isMidiFound = true; //MIDI device found.
hudakz 0:84353c479782 299 isMidi = true;
hudakz 0:84353c479782 300 USBTRACE("MIDI Device\r\n");
hudakz 0:84353c479782 301 }else{
hudakz 0:84353c479782 302 isMidi = false;
hudakz 0:84353c479782 303 USBTRACE("No MIDI Device\r\n");
hudakz 0:84353c479782 304 }
hudakz 0:84353c479782 305 break;
hudakz 0:84353c479782 306 case USB_DESCRIPTOR_ENDPOINT :
hudakz 0:84353c479782 307 epDesc = (USB_ENDPOINT_DESCRIPTOR *)buf_ptr;
hudakz 0:84353c479782 308 USBTRACE("-EPAddr:"), D_PrintHex(epDesc->bEndpointAddress, 0x80);
hudakz 0:84353c479782 309 USBTRACE(" bmAttr:"), D_PrintHex(epDesc->bmAttributes, 0x80);
hudakz 0:84353c479782 310 USBTRACE2(" MaxPktSz:", (uint8_t)epDesc->wMaxPacketSize);
hudakz 0:84353c479782 311 if ((epDesc->bmAttributes & bTransferTypeMask) == USB_TRANSFER_TYPE_BULK) {//bulk
hudakz 0:84353c479782 312 uint8_t index;
hudakz 0:84353c479782 313 if( isMidi )
hudakz 0:84353c479782 314 index = ((epDesc->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
hudakz 0:84353c479782 315 else
hudakz 0:84353c479782 316 index = ((epDesc->bEndpointAddress & 0x80) == 0x80) ? epDataInIndexVSP : epDataOutIndexVSP;
hudakz 0:84353c479782 317 epInfo[index].epAddr = (epDesc->bEndpointAddress & 0x0F);
hudakz 0:84353c479782 318 epInfo[index].maxPktSize = (uint8_t)epDesc->wMaxPacketSize;
hudakz 0:84353c479782 319 bNumEP ++;
hudakz 0:84353c479782 320 #ifdef DEBUG_USB_HOST
hudakz 0:84353c479782 321 PrintEndpointDescriptor(epDesc);
hudakz 0:84353c479782 322 #endif
hudakz 0:84353c479782 323 }
hudakz 0:84353c479782 324 break;
hudakz 0:84353c479782 325 default:
hudakz 0:84353c479782 326 break;
hudakz 0:84353c479782 327 }//switch( descr_type
hudakz 0:84353c479782 328 buf_ptr += descr_length; //advance buffer pointer
hudakz 0:84353c479782 329 }//while( buf_ptr <=...
hudakz 0:84353c479782 330 return 0;
hudakz 0:84353c479782 331 }
hudakz 0:84353c479782 332
hudakz 0:84353c479782 333 /* Performs a cleanup after failed Init() attempt */
hudakz 0:84353c479782 334 uint8_t USBH_MIDI::Release()
hudakz 0:84353c479782 335 {
hudakz 0:84353c479782 336 pUsb->GetAddressPool().FreeAddress(bAddress);
hudakz 0:84353c479782 337 bNumEP = 1; //must have to be reset to 1
hudakz 0:84353c479782 338 bAddress = 0;
hudakz 0:84353c479782 339 bPollEnable = false;
hudakz 0:84353c479782 340 readPtr = 0;
hudakz 0:84353c479782 341 return 0;
hudakz 0:84353c479782 342 }
hudakz 0:84353c479782 343
hudakz 0:84353c479782 344 /* Setup for well known vendor/device specific configuration */
hudakz 0:84353c479782 345 void USBH_MIDI::setupDeviceSpecific()
hudakz 0:84353c479782 346 {
hudakz 0:84353c479782 347 // Novation
hudakz 0:84353c479782 348 if( vid == 0x1235 ) {
hudakz 0:84353c479782 349 // LaunchPad's endpoint attirbute is interrupt (0x20:S, 0x36:Mini, 0x51:Pro, 0x69:MK2, 0x7b:Launchkey25 MK2)
hudakz 0:84353c479782 350 if(pid == 0x20 || pid == 0x36 || pid == 0x51 || pid == 0x69 || pid == 0x7b ) {
hudakz 0:84353c479782 351 bTransferTypeMask = 2;
hudakz 0:84353c479782 352 }
hudakz 0:84353c479782 353 }
hudakz 0:84353c479782 354 }
hudakz 0:84353c479782 355
hudakz 0:84353c479782 356 /* Receive data from MIDI device */
hudakz 0:84353c479782 357 uint8_t USBH_MIDI::RecvData(uint16_t *bytes_rcvd, uint8_t *dataptr)
hudakz 0:84353c479782 358 {
hudakz 0:84353c479782 359 *bytes_rcvd = (uint16_t)epInfo[epDataInIndex].maxPktSize;
hudakz 0:84353c479782 360 uint8_t r = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr);
hudakz 0:84353c479782 361
hudakz 0:84353c479782 362 if( *bytes_rcvd < (MIDI_EVENT_PACKET_SIZE-4)){
hudakz 0:84353c479782 363 dataptr[*bytes_rcvd] = '\0';
hudakz 0:84353c479782 364 dataptr[(*bytes_rcvd)+1] = '\0';
hudakz 0:84353c479782 365 }
hudakz 0:84353c479782 366 return r;
hudakz 0:84353c479782 367 }
hudakz 0:84353c479782 368
hudakz 0:84353c479782 369 /* Receive data from MIDI device */
hudakz 0:84353c479782 370 uint8_t USBH_MIDI::RecvData(uint8_t *outBuf, bool isRaw)
hudakz 0:84353c479782 371 {
hudakz 0:84353c479782 372 uint8_t rcode = 0; //return code
hudakz 0:84353c479782 373 uint16_t rcvd;
hudakz 0:84353c479782 374
hudakz 0:84353c479782 375 if( bPollEnable == false ) return 0;
hudakz 0:84353c479782 376
hudakz 0:84353c479782 377 //Checking unprocessed message in buffer.
hudakz 0:84353c479782 378 if( readPtr != 0 && readPtr < MIDI_EVENT_PACKET_SIZE ){
hudakz 0:84353c479782 379 if(recvBuf[readPtr] == 0 && recvBuf[readPtr+1] == 0) {
hudakz 0:84353c479782 380 //no unprocessed message left in the buffer.
hudakz 0:84353c479782 381 }else{
hudakz 0:84353c479782 382 goto RecvData_return_from_buffer;
hudakz 0:84353c479782 383 }
hudakz 0:84353c479782 384 }
hudakz 0:84353c479782 385
hudakz 0:84353c479782 386 readPtr = 0;
hudakz 0:84353c479782 387 rcode = RecvData( &rcvd, recvBuf);
hudakz 0:84353c479782 388 if( rcode != 0 ) {
hudakz 0:84353c479782 389 return 0;
hudakz 0:84353c479782 390 }
hudakz 0:84353c479782 391
hudakz 0:84353c479782 392 //if all data is zero, no valid data received.
hudakz 0:84353c479782 393 if( recvBuf[0] == 0 && recvBuf[1] == 0 && recvBuf[2] == 0 && recvBuf[3] == 0 ) {
hudakz 0:84353c479782 394 return 0;
hudakz 0:84353c479782 395 }
hudakz 0:84353c479782 396
hudakz 0:84353c479782 397 RecvData_return_from_buffer:
hudakz 0:84353c479782 398 uint8_t m;
hudakz 0:84353c479782 399 uint8_t cin = recvBuf[readPtr];
hudakz 0:84353c479782 400 if( isRaw == true ) {
hudakz 0:84353c479782 401 *(outBuf++) = cin;
hudakz 0:84353c479782 402 }
hudakz 0:84353c479782 403 readPtr++;
hudakz 0:84353c479782 404 *(outBuf++) = m = recvBuf[readPtr++];
hudakz 0:84353c479782 405 *(outBuf++) = recvBuf[readPtr++];
hudakz 0:84353c479782 406 *(outBuf++) = recvBuf[readPtr++];
hudakz 0:84353c479782 407 return lookupMsgSize(m, cin);
hudakz 0:84353c479782 408 }
hudakz 0:84353c479782 409
hudakz 0:84353c479782 410 /* Receive raw data from MIDI device */
hudakz 0:84353c479782 411 uint8_t USBH_MIDI::RecvRawData(uint8_t *outBuf)
hudakz 0:84353c479782 412 {
hudakz 0:84353c479782 413 return RecvData(outBuf, true);
hudakz 0:84353c479782 414 }
hudakz 0:84353c479782 415
hudakz 0:84353c479782 416 /* Send data to MIDI device */
hudakz 0:84353c479782 417 uint8_t USBH_MIDI::SendData(uint8_t *dataptr, uint8_t nCable)
hudakz 0:84353c479782 418 {
hudakz 0:84353c479782 419 uint8_t buf[4];
hudakz 0:84353c479782 420 uint8_t msg;
hudakz 0:84353c479782 421
hudakz 0:84353c479782 422 msg = dataptr[0];
hudakz 0:84353c479782 423 // SysEx long message ?
hudakz 0:84353c479782 424 if( msg == 0xf0 )
hudakz 0:84353c479782 425 {
hudakz 0:84353c479782 426 return SendSysEx(dataptr, countSysExDataSize(dataptr), nCable);
hudakz 0:84353c479782 427 }
hudakz 0:84353c479782 428
hudakz 0:84353c479782 429 buf[0] = (nCable << 4) | (msg >> 4);
hudakz 0:84353c479782 430 if( msg < 0xf0 ) msg = msg & 0xf0;
hudakz 0:84353c479782 431
hudakz 0:84353c479782 432
hudakz 0:84353c479782 433 //Building USB-MIDI Event Packets
hudakz 0:84353c479782 434 buf[1] = dataptr[0];
hudakz 0:84353c479782 435 buf[2] = dataptr[1];
hudakz 0:84353c479782 436 buf[3] = dataptr[2];
hudakz 0:84353c479782 437
hudakz 0:84353c479782 438 switch(lookupMsgSize(msg)) {
hudakz 0:84353c479782 439 //3 bytes message
hudakz 0:84353c479782 440 case 3 :
hudakz 0:84353c479782 441 if(msg == 0xf2) {//system common message(SPP)
hudakz 0:84353c479782 442 buf[0] = (nCable << 4) | 3;
hudakz 0:84353c479782 443 }
hudakz 0:84353c479782 444 break;
hudakz 0:84353c479782 445
hudakz 0:84353c479782 446 //2 bytes message
hudakz 0:84353c479782 447 case 2 :
hudakz 0:84353c479782 448 if(msg == 0xf1 || msg == 0xf3) {//system common message(MTC/SongSelect)
hudakz 0:84353c479782 449 buf[0] = (nCable << 4) | 2;
hudakz 0:84353c479782 450 }
hudakz 0:84353c479782 451 buf[3] = 0;
hudakz 0:84353c479782 452 break;
hudakz 0:84353c479782 453
hudakz 0:84353c479782 454 //1 byte message
hudakz 0:84353c479782 455 case 1 :
hudakz 0:84353c479782 456 default :
hudakz 0:84353c479782 457 buf[2] = 0;
hudakz 0:84353c479782 458 buf[3] = 0;
hudakz 0:84353c479782 459 break;
hudakz 0:84353c479782 460 }
hudakz 0:84353c479782 461 return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, 4, buf);
hudakz 0:84353c479782 462 }
hudakz 0:84353c479782 463
hudakz 0:84353c479782 464 #ifdef DEBUG_USB_HOST
hudakz 0:84353c479782 465 void USBH_MIDI::PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr )
hudakz 0:84353c479782 466 {
hudakz 0:84353c479782 467 USBTRACE("Endpoint descriptor:\r\n");
hudakz 0:84353c479782 468 USBTRACE2(" Length:\t", ep_ptr->bLength);
hudakz 0:84353c479782 469 USBTRACE2(" Type:\t\t", ep_ptr->bDescriptorType);
hudakz 0:84353c479782 470 USBTRACE2(" Address:\t", ep_ptr->bEndpointAddress);
hudakz 0:84353c479782 471 USBTRACE2(" Attributes:\t", ep_ptr->bmAttributes);
hudakz 0:84353c479782 472 USBTRACE2(" MaxPktSize:\t", ep_ptr->wMaxPacketSize);
hudakz 0:84353c479782 473 USBTRACE2(" Poll Intrv:\t", ep_ptr->bInterval);
hudakz 0:84353c479782 474 }
hudakz 0:84353c479782 475 #endif
hudakz 0:84353c479782 476
hudakz 0:84353c479782 477 /* look up a MIDI message size from spec */
hudakz 0:84353c479782 478 /*Return */
hudakz 0:84353c479782 479 /* 0 : undefined message */
hudakz 0:84353c479782 480 /* 0<: Vaild message size(1-3) */
hudakz 0:84353c479782 481 uint8_t USBH_MIDI::lookupMsgSize(uint8_t midiMsg, uint8_t cin)
hudakz 0:84353c479782 482 {
hudakz 0:84353c479782 483 uint8_t msgSize = 0;
hudakz 0:84353c479782 484
hudakz 0:84353c479782 485 //SysEx message?
hudakz 0:84353c479782 486 cin = cin & 0x0f;
hudakz 0:84353c479782 487 if( (cin & 0xc) == 4 ) {
hudakz 0:84353c479782 488 if( cin == 4 || cin == 7 ) return 3;
hudakz 0:84353c479782 489 if( cin == 6 ) return 2;
hudakz 0:84353c479782 490 if( cin == 5 ) return 1;
hudakz 0:84353c479782 491 }
hudakz 0:84353c479782 492
hudakz 0:84353c479782 493 if( midiMsg < 0xf0 ) midiMsg &= 0xf0;
hudakz 0:84353c479782 494 switch(midiMsg) {
hudakz 0:84353c479782 495 //3 bytes messages
hudakz 0:84353c479782 496 case 0xf2 : //system common message(SPP)
hudakz 0:84353c479782 497 case 0x80 : //Note off
hudakz 0:84353c479782 498 case 0x90 : //Note on
hudakz 0:84353c479782 499 case 0xa0 : //Poly KeyPress
hudakz 0:84353c479782 500 case 0xb0 : //Control Change
hudakz 0:84353c479782 501 case 0xe0 : //PitchBend Change
hudakz 0:84353c479782 502 msgSize = 3;
hudakz 0:84353c479782 503 break;
hudakz 0:84353c479782 504
hudakz 0:84353c479782 505 //2 bytes messages
hudakz 0:84353c479782 506 case 0xf1 : //system common message(MTC)
hudakz 0:84353c479782 507 case 0xf3 : //system common message(SongSelect)
hudakz 0:84353c479782 508 case 0xc0 : //Program Change
hudakz 0:84353c479782 509 case 0xd0 : //Channel Pressure
hudakz 0:84353c479782 510 msgSize = 2;
hudakz 0:84353c479782 511 break;
hudakz 0:84353c479782 512
hudakz 0:84353c479782 513 //1 byte messages
hudakz 0:84353c479782 514 case 0xf8 : //system realtime message
hudakz 0:84353c479782 515 case 0xf9 : //system realtime message
hudakz 0:84353c479782 516 case 0xfa : //system realtime message
hudakz 0:84353c479782 517 case 0xfb : //system realtime message
hudakz 0:84353c479782 518 case 0xfc : //system realtime message
hudakz 0:84353c479782 519 case 0xfe : //system realtime message
hudakz 0:84353c479782 520 case 0xff : //system realtime message
hudakz 0:84353c479782 521 msgSize = 1;
hudakz 0:84353c479782 522 break;
hudakz 0:84353c479782 523
hudakz 0:84353c479782 524 //undefine messages
hudakz 0:84353c479782 525 default :
hudakz 0:84353c479782 526 break;
hudakz 0:84353c479782 527 }
hudakz 0:84353c479782 528 return msgSize;
hudakz 0:84353c479782 529 }
hudakz 0:84353c479782 530
hudakz 0:84353c479782 531 /* SysEx data size counter */
hudakz 0:84353c479782 532 uint16_t USBH_MIDI::countSysExDataSize(uint8_t *dataptr)
hudakz 0:84353c479782 533 {
hudakz 0:84353c479782 534 uint16_t c = 1;
hudakz 0:84353c479782 535
hudakz 0:84353c479782 536 if( *dataptr != 0xf0 ){ //not SysEx
hudakz 0:84353c479782 537 return 0;
hudakz 0:84353c479782 538 }
hudakz 0:84353c479782 539
hudakz 0:84353c479782 540 //Search terminator(0xf7)
hudakz 0:84353c479782 541 while(*dataptr != 0xf7)
hudakz 0:84353c479782 542 {
hudakz 0:84353c479782 543 dataptr++;
hudakz 0:84353c479782 544 c++;
hudakz 0:84353c479782 545
hudakz 0:84353c479782 546 //Limiter (default: 256 bytes)
hudakz 0:84353c479782 547 if(c > MIDI_MAX_SYSEX_SIZE){
hudakz 0:84353c479782 548 c = 0;
hudakz 0:84353c479782 549 break;
hudakz 0:84353c479782 550 }
hudakz 0:84353c479782 551 }
hudakz 0:84353c479782 552 return c;
hudakz 0:84353c479782 553 }
hudakz 0:84353c479782 554
hudakz 0:84353c479782 555 /* Send SysEx message to MIDI device */
hudakz 0:84353c479782 556 uint8_t USBH_MIDI::SendSysEx(uint8_t *dataptr, uint16_t datasize, uint8_t nCable)
hudakz 0:84353c479782 557 {
hudakz 0:84353c479782 558 uint8_t buf[MIDI_EVENT_PACKET_SIZE];
hudakz 0:84353c479782 559 uint8_t rc = 0;
hudakz 0:84353c479782 560 uint16_t n = datasize;
hudakz 0:84353c479782 561 uint16_t pktSize = (n*10/3+7)/10*4; //Calculate total USB MIDI packet size
hudakz 0:84353c479782 562 uint8_t wptr = 0;
hudakz 0:84353c479782 563 uint8_t maxpkt = epInfo[epDataInIndex].maxPktSize;
hudakz 0:84353c479782 564
hudakz 0:84353c479782 565 if( maxpkt > MIDI_EVENT_PACKET_SIZE ) maxpkt = MIDI_EVENT_PACKET_SIZE;
hudakz 0:84353c479782 566
hudakz 0:84353c479782 567 USBTRACE("SendSysEx:\r\t");
hudakz 0:84353c479782 568 USBTRACE2(" Length:\t", datasize);
hudakz 0:84353c479782 569 USBTRACE2(" Total pktSize:\t", pktSize);
hudakz 0:84353c479782 570
hudakz 0:84353c479782 571 while(n > 0) {
hudakz 0:84353c479782 572 //Byte 0
hudakz 0:84353c479782 573 buf[wptr] = (nCable << 4) | 0x4; //x4 SysEx starts or continues
hudakz 0:84353c479782 574
hudakz 0:84353c479782 575 switch ( n ) {
hudakz 0:84353c479782 576 case 1 :
hudakz 0:84353c479782 577 buf[wptr++] = (nCable << 4) | 0x5; //x5 SysEx ends with following single byte.
hudakz 0:84353c479782 578 buf[wptr++] = *(dataptr++);
hudakz 0:84353c479782 579 buf[wptr++] = 0x00;
hudakz 0:84353c479782 580 buf[wptr++] = 0x00;
hudakz 0:84353c479782 581 n = n - 1;
hudakz 0:84353c479782 582 break;
hudakz 0:84353c479782 583 case 2 :
hudakz 0:84353c479782 584 buf[wptr++] = (nCable << 4) | 0x6; //x6 SysEx ends with following two bytes.
hudakz 0:84353c479782 585 buf[wptr++] = *(dataptr++);
hudakz 0:84353c479782 586 buf[wptr++] = *(dataptr++);
hudakz 0:84353c479782 587 buf[wptr++] = 0x00;
hudakz 0:84353c479782 588 n = n - 2;
hudakz 0:84353c479782 589 break;
hudakz 0:84353c479782 590 case 3 :
hudakz 0:84353c479782 591 buf[wptr] = (nCable << 4) | 0x7; //x7 SysEx ends with following three bytes.
hudakz 0:84353c479782 592 default :
hudakz 0:84353c479782 593 wptr++;
hudakz 0:84353c479782 594 buf[wptr++] = *(dataptr++);
hudakz 0:84353c479782 595 buf[wptr++] = *(dataptr++);
hudakz 0:84353c479782 596 buf[wptr++] = *(dataptr++);
hudakz 0:84353c479782 597 n = n - 3;
hudakz 0:84353c479782 598 break;
hudakz 0:84353c479782 599 }
hudakz 0:84353c479782 600
hudakz 0:84353c479782 601 if( wptr >= maxpkt || n == 0 ){ //Reach a maxPktSize or data end.
hudakz 0:84353c479782 602 USBTRACE2(" wptr:\t", wptr);
hudakz 0:84353c479782 603 if( (rc = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, wptr, buf)) != 0 ){
hudakz 0:84353c479782 604 break;
hudakz 0:84353c479782 605 }
hudakz 0:84353c479782 606 wptr = 0; //rewind data pointer
hudakz 0:84353c479782 607 }
hudakz 0:84353c479782 608 }
hudakz 0:84353c479782 609 return(rc);
hudakz 0:84353c479782 610 }
hudakz 0:84353c479782 611
hudakz 0:84353c479782 612 /* Send raw data to MIDI device */
hudakz 0:84353c479782 613 uint8_t USBH_MIDI::SendRawData(uint16_t bytes_send, uint8_t *dataptr)
hudakz 0:84353c479782 614 {
hudakz 0:84353c479782 615 return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes_send, dataptr);
hudakz 0:84353c479782 616
hudakz 0:84353c479782 617 }
hudakz 0:84353c479782 618
hudakz 0:84353c479782 619 uint8_t USBH_MIDI::extractSysExData(uint8_t *p, uint8_t *buf)
hudakz 0:84353c479782 620 {
hudakz 0:84353c479782 621 uint8_t rc = 0;
hudakz 0:84353c479782 622 uint8_t cin = *(p) & 0x0f;
hudakz 0:84353c479782 623
hudakz 0:84353c479782 624 //SysEx message?
hudakz 0:84353c479782 625 if( (cin & 0xc) != 4 ) return rc;
hudakz 0:84353c479782 626
hudakz 0:84353c479782 627 switch(cin) {
hudakz 0:84353c479782 628 case 4:
hudakz 0:84353c479782 629 case 7:
hudakz 0:84353c479782 630 *buf++ = *(p+1);
hudakz 0:84353c479782 631 *buf++ = *(p+2);
hudakz 0:84353c479782 632 *buf++ = *(p+3);
hudakz 0:84353c479782 633 rc = 3;
hudakz 0:84353c479782 634 break;
hudakz 0:84353c479782 635 case 6:
hudakz 0:84353c479782 636 *buf++ = *(p+1);
hudakz 0:84353c479782 637 *buf++ = *(p+2);
hudakz 0:84353c479782 638 rc = 2;
hudakz 0:84353c479782 639 break;
hudakz 0:84353c479782 640 case 5:
hudakz 0:84353c479782 641 *buf++ = *(p+1);
hudakz 0:84353c479782 642 rc = 1;
hudakz 0:84353c479782 643 break;
hudakz 0:84353c479782 644 default:
hudakz 0:84353c479782 645 break;
hudakz 0:84353c479782 646 }
hudakz 0:84353c479782 647 return(rc);
hudakz 0:84353c479782 648 }