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