USB Host Shield 2.0
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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  // Get device descriptor
151  rcode = pUsb->getDevDescr( 0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf );
152  vid = udd->idVendor;
153  pid = udd->idProduct;
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  num_of_conf = udd->bNumConfigurations;
190 
191  // Assign epInfo to epinfo pointer
192  rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
193  if (rcode) {
194  USBTRACE("setEpInfoEntry failed");
195  goto FailSetDevTblEntry;
196  }
197 
198  USBTRACE("VID:"), D_PrintHex(vid, 0x80);
199  USBTRACE(" PID:"), D_PrintHex(pid, 0x80);
200  USBTRACE2(" #Conf:", num_of_conf);
201 
202  //Setup for well known vendor/device specific configuration
205 
206  isMidiFound = false;
207  for (uint8_t i=0; i<num_of_conf; i++) {
208  rcode = parseConfigDescr(bAddress, i);
209  if( rcode )
210  goto FailGetConfDescr;
211  if (bNumEP > 1)
212  break;
213  } // for
214 
215  USBTRACE2("\r\nNumEP:", bNumEP);
216 
217  if( bNumEP < 2 ){ //Device not found.
218  rcode = 0xff;
219  goto FailGetConfDescr;
220  }
221 
222  if( !isMidiFound ){ //MIDI Device not found. Try last Bulk transfer device
223  USBTRACE("MIDI not found. Attempts bulk device\r\n");
228  }
229 
230  // Assign epInfo to epinfo pointer
231  rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
232  USBTRACE2("Conf:", bConfNum);
233  USBTRACE2("EPin :", (uint8_t)(epInfo[epDataInIndex].epAddr + 0x80));
234  USBTRACE2("EPout:", epInfo[epDataOutIndex].epAddr);
235 
236  // Set Configuration Value
237  rcode = pUsb->setConf(bAddress, 0, bConfNum);
238  if (rcode) {
239  goto FailSetConfDescr;
240  }
241  bPollEnable = true;
242  USBTRACE("Init done.\r\n");
243  return 0;
244 FailGetDevDescr:
245 FailSetDevTblEntry:
246 FailGetConfDescr:
247 FailSetConfDescr:
248  Release();
249  return rcode;
250 }
251 
252 /* get and parse config descriptor */
253 uint8_t USBH_MIDI::parseConfigDescr( uint8_t addr, uint8_t conf )
254 {
255  uint8_t buf[ DESC_BUFF_SIZE ];
256  uint8_t* buf_ptr = buf;
257  uint8_t rcode;
258  uint8_t descr_length;
259  uint8_t descr_type;
260  uint16_t total_length;
261  USB_ENDPOINT_DESCRIPTOR *epDesc;
262  bool isMidi = false;
263 
264  // get configuration descriptor (get descriptor size only)
265  rcode = pUsb->getConfDescr( addr, 0, 4, conf, buf );
266  if( rcode ){
267  return rcode;
268  }
269  total_length = buf[2] | ((int)buf[3] << 8);
270  if( total_length > DESC_BUFF_SIZE ) { //check if total length is larger than buffer
271  total_length = DESC_BUFF_SIZE;
272  }
273 
274  // get configuration descriptor (all)
275  rcode = pUsb->getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor
276  if( rcode ){
277  return rcode;
278  }
279 
280  //parsing descriptors
281  while( buf_ptr < buf + total_length ) {
282  descr_length = *( buf_ptr );
283  descr_type = *( buf_ptr + 1 );
284  switch( descr_type ) {
286  bConfNum = buf_ptr[5];
287  break;
289  USBTRACE("\r\nConf:"), D_PrintHex(bConfNum, 0x80);
290  USBTRACE(" Int:"), D_PrintHex(buf_ptr[2], 0x80);
291  USBTRACE(" Alt:"), D_PrintHex(buf_ptr[3], 0x80);
292  USBTRACE(" EPs:"), D_PrintHex(buf_ptr[4], 0x80);
293  USBTRACE(" IntCl:"), D_PrintHex(buf_ptr[5], 0x80);
294  USBTRACE(" IntSubCl:"), D_PrintHex(buf_ptr[6], 0x80);
295  USBTRACE("\r\n");
296 
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)
298  isMidiFound = true; //MIDI device found.
299  isMidi = true;
300  USBTRACE("MIDI Device\r\n");
301  }else{
302  isMidi = false;
303  USBTRACE("No MIDI Device\r\n");
304  }
305  break;
307  epDesc = (USB_ENDPOINT_DESCRIPTOR *)buf_ptr;
308  USBTRACE("-EPAddr:"), D_PrintHex(epDesc->bEndpointAddress, 0x80);
309  USBTRACE(" bmAttr:"), D_PrintHex(epDesc->bmAttributes, 0x80);
310  USBTRACE2(" MaxPktSz:", (uint8_t)epDesc->wMaxPacketSize);
311  if ((epDesc->bmAttributes & bTransferTypeMask) == USB_TRANSFER_TYPE_BULK) {//bulk
312  uint8_t index;
313  if( isMidi )
314  index = ((epDesc->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
315  else
316  index = ((epDesc->bEndpointAddress & 0x80) == 0x80) ? epDataInIndexVSP : epDataOutIndexVSP;
317  epInfo[index].epAddr = (epDesc->bEndpointAddress & 0x0F);
318  epInfo[index].maxPktSize = (uint8_t)epDesc->wMaxPacketSize;
319  bNumEP ++;
320 #ifdef DEBUG_USB_HOST
321  PrintEndpointDescriptor(epDesc);
322 #endif
323  }
324  break;
325  default:
326  break;
327  }//switch( descr_type
328  buf_ptr += descr_length; //advance buffer pointer
329  }//while( buf_ptr <=...
330  return 0;
331 }
332 
333 /* Performs a cleanup after failed Init() attempt */
335 {
337  bNumEP = 1; //must have to be reset to 1
338  bAddress = 0;
339  bPollEnable = false;
340  readPtr = 0;
341  return 0;
342 }
343 
344 /* Setup for well known vendor/device specific configuration */
346 {
347  // Novation
348  if( vid == 0x1235 ) {
349  // LaunchPad's endpoint attirbute is interrupt (0x20:S, 0x36:Mini, 0x51:Pro, 0x69:MK2, 0x7b:Launchkey25 MK2)
350  if(pid == 0x20 || pid == 0x36 || pid == 0x51 || pid == 0x69 || pid == 0x7b ) {
351  bTransferTypeMask = 2;
352  }
353  }
354 }
355 
356 /* Receive data from MIDI device */
357 uint8_t USBH_MIDI::RecvData(uint16_t *bytes_rcvd, uint8_t *dataptr)
358 {
359  *bytes_rcvd = (uint16_t)epInfo[epDataInIndex].maxPktSize;
360  uint8_t r = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr);
361 
362  if( *bytes_rcvd < (MIDI_EVENT_PACKET_SIZE-4)){
363  dataptr[*bytes_rcvd] = '\0';
364  dataptr[(*bytes_rcvd)+1] = '\0';
365  }
366  return r;
367 }
368 
369 /* Receive data from MIDI device */
370 uint8_t USBH_MIDI::RecvData(uint8_t *outBuf, bool isRaw)
371 {
372  uint8_t rcode = 0; //return code
373  uint16_t rcvd;
374 
375  if( bPollEnable == false ) return 0;
376 
377  //Checking unprocessed message in buffer.
378  if( readPtr != 0 && readPtr < MIDI_EVENT_PACKET_SIZE ){
379  if(recvBuf[readPtr] == 0 && recvBuf[readPtr+1] == 0) {
380  //no unprocessed message left in the buffer.
381  }else{
382  goto RecvData_return_from_buffer;
383  }
384  }
385 
386  readPtr = 0;
387  rcode = RecvData( &rcvd, recvBuf);
388  if( rcode != 0 ) {
389  return 0;
390  }
391 
392  //if all data is zero, no valid data received.
393  if( recvBuf[0] == 0 && recvBuf[1] == 0 && recvBuf[2] == 0 && recvBuf[3] == 0 ) {
394  return 0;
395  }
396 
397 RecvData_return_from_buffer:
398  uint8_t m;
399  uint8_t cin = recvBuf[readPtr];
400  if( isRaw == true ) {
401  *(outBuf++) = cin;
402  }
403  readPtr++;
404  *(outBuf++) = m = recvBuf[readPtr++];
405  *(outBuf++) = recvBuf[readPtr++];
406  *(outBuf++) = recvBuf[readPtr++];
407  return lookupMsgSize(m, cin);
408 }
409 
410 /* Receive raw data from MIDI device */
411 uint8_t USBH_MIDI::RecvRawData(uint8_t *outBuf)
412 {
413  return RecvData(outBuf, true);
414 }
415 
416 /* Send data to MIDI device */
417 uint8_t USBH_MIDI::SendData(uint8_t *dataptr, uint8_t nCable)
418 {
419  uint8_t buf[4];
420  uint8_t msg;
421 
422  msg = dataptr[0];
423  // SysEx long message ?
424  if( msg == 0xf0 )
425  {
426  return SendSysEx(dataptr, countSysExDataSize(dataptr), nCable);
427  }
428 
429  buf[0] = (nCable << 4) | (msg >> 4);
430  if( msg < 0xf0 ) msg = msg & 0xf0;
431 
432 
433  //Building USB-MIDI Event Packets
434  buf[1] = dataptr[0];
435  buf[2] = dataptr[1];
436  buf[3] = dataptr[2];
437 
438  switch(lookupMsgSize(msg)) {
439  //3 bytes message
440  case 3 :
441  if(msg == 0xf2) {//system common message(SPP)
442  buf[0] = (nCable << 4) | 3;
443  }
444  break;
445 
446  //2 bytes message
447  case 2 :
448  if(msg == 0xf1 || msg == 0xf3) {//system common message(MTC/SongSelect)
449  buf[0] = (nCable << 4) | 2;
450  }
451  buf[3] = 0;
452  break;
453 
454  //1 byte message
455  case 1 :
456  default :
457  buf[2] = 0;
458  buf[3] = 0;
459  break;
460  }
461  return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, 4, buf);
462 }
463 
464 #ifdef DEBUG_USB_HOST
465 void USBH_MIDI::PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr )
466 {
467  USBTRACE("Endpoint descriptor:\r\n");
468  USBTRACE2(" Length:\t", ep_ptr->bLength);
469  USBTRACE2(" Type:\t\t", ep_ptr->bDescriptorType);
470  USBTRACE2(" Address:\t", ep_ptr->bEndpointAddress);
471  USBTRACE2(" Attributes:\t", ep_ptr->bmAttributes);
472  USBTRACE2(" MaxPktSize:\t", ep_ptr->wMaxPacketSize);
473  USBTRACE2(" Poll Intrv:\t", ep_ptr->bInterval);
474 }
475 #endif
476 
477 /* look up a MIDI message size from spec */
478 /*Return */
479 /* 0 : undefined message */
480 /* 0<: Vaild message size(1-3) */
481 uint8_t USBH_MIDI::lookupMsgSize(uint8_t midiMsg, uint8_t cin)
482 {
483  uint8_t msgSize = 0;
484 
485  //SysEx message?
486  cin = cin & 0x0f;
487  if( (cin & 0xc) == 4 ) {
488  if( cin == 4 || cin == 7 ) return 3;
489  if( cin == 6 ) return 2;
490  if( cin == 5 ) return 1;
491  }
492 
493  if( midiMsg < 0xf0 ) midiMsg &= 0xf0;
494  switch(midiMsg) {
495  //3 bytes messages
496  case 0xf2 : //system common message(SPP)
497  case 0x80 : //Note off
498  case 0x90 : //Note on
499  case 0xa0 : //Poly KeyPress
500  case 0xb0 : //Control Change
501  case 0xe0 : //PitchBend Change
502  msgSize = 3;
503  break;
504 
505  //2 bytes messages
506  case 0xf1 : //system common message(MTC)
507  case 0xf3 : //system common message(SongSelect)
508  case 0xc0 : //Program Change
509  case 0xd0 : //Channel Pressure
510  msgSize = 2;
511  break;
512 
513  //1 byte messages
514  case 0xf8 : //system realtime message
515  case 0xf9 : //system realtime message
516  case 0xfa : //system realtime message
517  case 0xfb : //system realtime message
518  case 0xfc : //system realtime message
519  case 0xfe : //system realtime message
520  case 0xff : //system realtime message
521  msgSize = 1;
522  break;
523 
524  //undefine messages
525  default :
526  break;
527  }
528  return msgSize;
529 }
530 
531 /* SysEx data size counter */
532 uint16_t USBH_MIDI::countSysExDataSize(uint8_t *dataptr)
533 {
534  uint16_t c = 1;
535 
536  if( *dataptr != 0xf0 ){ //not SysEx
537  return 0;
538  }
539 
540  //Search terminator(0xf7)
541  while(*dataptr != 0xf7)
542  {
543  dataptr++;
544  c++;
545 
546  //Limiter (default: 256 bytes)
547  if(c > MIDI_MAX_SYSEX_SIZE){
548  c = 0;
549  break;
550  }
551  }
552  return c;
553 }
554 
555 /* Send SysEx message to MIDI device */
556 uint8_t USBH_MIDI::SendSysEx(uint8_t *dataptr, uint16_t datasize, uint8_t nCable)
557 {
558  uint8_t buf[MIDI_EVENT_PACKET_SIZE];
559  uint8_t rc = 0;
560  uint16_t n = datasize;
561  uint16_t pktSize = (n*10/3+7)/10*4; //Calculate total USB MIDI packet size
562  uint8_t wptr = 0;
563  uint8_t maxpkt = epInfo[epDataInIndex].maxPktSize;
564 
565  if( maxpkt > MIDI_EVENT_PACKET_SIZE ) maxpkt = MIDI_EVENT_PACKET_SIZE;
566 
567  USBTRACE("SendSysEx:\r\t");
568  USBTRACE2(" Length:\t", datasize);
569  USBTRACE2(" Total pktSize:\t", pktSize);
570 
571  while(n > 0) {
572  //Byte 0
573  buf[wptr] = (nCable << 4) | 0x4; //x4 SysEx starts or continues
574 
575  switch ( n ) {
576  case 1 :
577  buf[wptr++] = (nCable << 4) | 0x5; //x5 SysEx ends with following single byte.
578  buf[wptr++] = *(dataptr++);
579  buf[wptr++] = 0x00;
580  buf[wptr++] = 0x00;
581  n = n - 1;
582  break;
583  case 2 :
584  buf[wptr++] = (nCable << 4) | 0x6; //x6 SysEx ends with following two bytes.
585  buf[wptr++] = *(dataptr++);
586  buf[wptr++] = *(dataptr++);
587  buf[wptr++] = 0x00;
588  n = n - 2;
589  break;
590  case 3 :
591  buf[wptr] = (nCable << 4) | 0x7; //x7 SysEx ends with following three bytes.
592  default :
593  wptr++;
594  buf[wptr++] = *(dataptr++);
595  buf[wptr++] = *(dataptr++);
596  buf[wptr++] = *(dataptr++);
597  n = n - 3;
598  break;
599  }
600 
601  if( wptr >= maxpkt || n == 0 ){ //Reach a maxPktSize or data end.
602  USBTRACE2(" wptr:\t", wptr);
603  if( (rc = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, wptr, buf)) != 0 ){
604  break;
605  }
606  wptr = 0; //rewind data pointer
607  }
608  }
609  return(rc);
610 }
611 
612 /* Send raw data to MIDI device */
613 uint8_t USBH_MIDI::SendRawData(uint16_t bytes_send, uint8_t *dataptr)
614 {
615  return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes_send, dataptr);
616 
617 }
618 
619 uint8_t USBH_MIDI::extractSysExData(uint8_t *p, uint8_t *buf)
620 {
621  uint8_t rc = 0;
622  uint8_t cin = *(p) & 0x0f;
623 
624  //SysEx message?
625  if( (cin & 0xc) != 4 ) return rc;
626 
627  switch(cin) {
628  case 4:
629  case 7:
630  *buf++ = *(p+1);
631  *buf++ = *(p+2);
632  *buf++ = *(p+3);
633  rc = 3;
634  break;
635  case 6:
636  *buf++ = *(p+1);
637  *buf++ = *(p+2);
638  rc = 2;
639  break;
640  case 5:
641  *buf++ = *(p+1);
642  rc = 1;
643  break;
644  default:
645  break;
646  }
647  return(rc);
648 }
uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t *dataptr)
Definition: Usb.cpp:784
uint8_t bmRcvToggle
Definition: address.h:48
uint8_t SendSysEx(uint8_t *dataptr, uint16_t datasize, uint8_t nCable=0)
Definition: usbh_midi.cpp:556
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:357
uint16_t vid
Definition: usbh_midi.h:54
uint8_t setConf(uint8_t addr, uint8_t ep, uint8_t conf_value)
Definition: Usb.cpp:823
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:71
USB * pUsb
Definition: usbh_midi.h:48
uint8_t SendRawData(uint16_t bytes_send, uint8_t *dataptr)
Definition: usbh_midi.cpp:613
uint16_t countSysExDataSize(uint8_t *dataptr)
Definition: usbh_midi.cpp:532
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:345
#define USBTRACE2(s, r)
Definition: macros.h:84
uint8_t setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr)
Definition: Usb.cpp:814
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:300
virtual uint8_t Release()
Definition: usbh_midi.cpp:334
uint8_t RecvRawData(uint8_t *outBuf)
Definition: usbh_midi.cpp:411
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:481
#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:213
#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:619
uint8_t SendData(uint8_t *dataptr, uint8_t nCable=0)
Definition: usbh_midi.cpp:417
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:253
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:779
#define USB_DESCRIPTOR_INTERFACE
Definition: usb_ch9.h:73