USB Host Shield 2.0
Loading...
Searching...
No Matches
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-2022 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"
28// To enable serial debugging see "settings.h"
29//#define EXTRADEBUG // Uncomment to get even more debugging data
30
32// MIDI MESAGES
33// midi.org/techspecs/
35// STATUS BYTES
36// 0x8n == noteOff
37// 0x9n == noteOn
38// 0xAn == afterTouch
39// 0xBn == controlChange
40// n == Channel(0x0-0xf)
42//DATA BYTE 1
43// note# == (0-127)
44// or
45// control# == (0-119)
47// DATA BYTE 2
48// velocity == (0-127)
49// or
50// controlVal == (0-127)
52// USB-MIDI Event Packets
53// usb.org - Universal Serial Bus Device Class Definition for MIDI Devices 1.0
55//+-------------+-------------+-------------+-------------+
56//| Byte 0 | Byte 1 | Byte 2 | Byte 3 |
57//+------+------+-------------+-------------+-------------+
58//|Cable | Code | | | |
59//|Number|Index | MIDI_0 | MIDI_1 | MIDI_2 |
60//| |Number| | | |
61//|(4bit)|(4bit)| (8bit) | (8bit) | (8bit) |
62//+------+------+-------------+-------------+-------------+
63// CN == 0x0-0xf
64//+-----+-----------+-------------------------------------------------------------------
65//| CIN |MIDI_x size|Description
66//+-----+-----------+-------------------------------------------------------------------
67//| 0x0 | 1, 2 or 3 |Miscellaneous function codes. Reserved for future extensions.
68//| 0x1 | 1, 2 or 3 |Cable events. Reserved for future expansion.
69//| 0x2 | 2 |Two-byte System Common messages like MTC, SongSelect, etc.
70//| 0x3 | 3 |Three-byte System Common messages like SPP, etc.
71//| 0x4 | 3 |SysEx starts or continues
72//| 0x5 | 1 |Single-byte System Common Message or SysEx ends with following single byte.
73//| 0x6 | 2 |SysEx ends with following two bytes.
74//| 0x7 | 3 |SysEx ends with following three bytes.
75//| 0x8 | 3 |Note-off
76//| 0x9 | 3 |Note-on
77//| 0xA | 3 |Poly-KeyPress
78//| 0xB | 3 |Control Change
79//| 0xC | 2 |Program Change
80//| 0xD | 2 |Channel Pressure
81//| 0xE | 3 |PitchBend Change
82//| 0xF | 1 |Single Byte
83//+-----+-----------+-------------------------------------------------------------------
84
86pUsb(p),
87bAddress(0),
88bPollEnable(false),
89readPtr(0) {
90 // initialize endpoint data structures
91 for(uint8_t i=0; i<MIDI_MAX_ENDPOINTS; i++) {
92 epInfo[i].epAddr = 0;
93 epInfo[i].maxPktSize = (i) ? 0 : 8;
95 }
96 // register in USB subsystem
97 if (pUsb) {
99 }
100}
101
102/* Connection initialization of an MIDI Device */
104{
106 USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
108 UsbDevice *p = NULL;
110 uint8_t num_of_conf; // number of configurations
111 uint8_t bConfNum = 0; // configuration number
112 uint8_t bNumEP = 1; // total number of EP in the configuration
113
114 USBTRACE("\rMIDI Init\r\n");
115#ifdef DEBUG_USB_HOST
116 Notify(PSTR("USBH_MIDI version "), 0x80), D_PrintHex((uint8_t) (USBH_MIDI_VERSION / 10000), 0x80), D_PrintHex((uint8_t) (USBH_MIDI_VERSION / 100 % 100), 0x80), D_PrintHex((uint8_t) (USBH_MIDI_VERSION % 100), 0x80), Notify(PSTR("\r\n"), 0x80);
117#endif
118
119 //for reconnect
121 epInfo[i].bmSndToggle = 0;
122 epInfo[i].bmRcvToggle = 0;
123 // If you want to retry if you get a NAK response when sending, enable the following:
124 // epInfo[i].bmNakPower = (i==epDataOutIndex) ? 10 : USB_NAK_NOWAIT;
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)
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
200 if (rcode) {
201 USBTRACE("setEpInfoEntry failed");
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 // STEP1: Check if attached device is a MIDI device and fill endpoint data structure
214 USBTRACE("\r\nSTEP1: MIDI Start\r\n");
215 for(uint8_t i = 0; i < num_of_conf; i++) {
216 MidiDescParser midiDescParser(this, true); // Check for MIDI device
218 if(rcode) // Check error code
219 goto FailGetConfDescr;
220 bNumEP += midiDescParser.getNumEPs();
221 if(bNumEP > 1) {// All endpoints extracted
222 bConfNum = midiDescParser.getConfValue();
223 break;
224 }
225 }
226 USBTRACE2("STEP1: MIDI,NumEP:", bNumEP);
227 //Found the MIDI device?
228 if( bNumEP == 1 ){ //Device not found.
229 USBTRACE("MIDI not found.\r\nSTEP2: Attempts vendor specific bulk device\r\n");
230 // STEP2: Check if attached device is a MIDI device and fill endpoint data structure
231 for(uint8_t i = 0; i < num_of_conf; i++) {
232 MidiDescParser midiDescParser(this, false); // Allow all devices, vendor specific class with Bulk transfer
234 if(rcode) // Check error code
235 goto FailGetConfDescr;
236 bNumEP += midiDescParser.getNumEPs();
237 if(bNumEP > 1) {// All endpoints extracted
238 bConfNum = midiDescParser.getConfValue();
239 break;
240 }
241 }
242 USBTRACE2("\r\nSTEP2: Vendor,NumEP:", bNumEP);
243 }
244
245 if( bNumEP < 2 ){ //Device not found.
246 rcode = 0xff;
247 goto FailGetConfDescr;
248 }
249
250 // Assign epInfo to epinfo pointer
252 USBTRACE2("Conf:", bConfNum);
253 USBTRACE2("EPin :", (uint8_t)(epInfo[epDataInIndex].epAddr + 0x80));
254 USBTRACE2("EPout:", epInfo[epDataOutIndex].epAddr);
255
256 // Set Configuration Value
257 rcode = pUsb->setConf(bAddress, 0, bConfNum);
258 if (rcode)
259 goto FailSetConfDescr;
260
261 bPollEnable = true;
262
263 if(pFuncOnInit)
264 pFuncOnInit(); // Call the user function
265
266 USBTRACE("Init done.\r\n");
267 return 0;
272 Release();
273 return rcode;
274}
275
276/* Performs a cleanup after failed Init() attempt */
278{
279 if(pFuncOnRelease && bPollEnable)
280 pFuncOnRelease(); // Call the user function
281
283 bAddress = 0;
284 bPollEnable = false;
285 readPtr = 0;
286
287 return 0;
288}
289
290/* Setup for well known vendor/device specific configuration */
292{
293 // Novation
294 if( vid == 0x1235 ) {
295 // LaunchPad and LaunchKey endpoint attribute is interrupt
296 // https://github.com/YuuichiAkagawa/USBH_MIDI/wiki/Novation-USB-Product-ID-List
297
298 // LaunchPad: 0x20:S, 0x36:Mini, 0x51:Pro, 0x69:MK2
299 if( pid == 0x20 || pid == 0x36 || pid == 0x51 || pid == 0x69 ) {
301 return;
302 }
303
304 // LaunchKey: 0x30-32, 0x35:Mini, 0x7B-0x7D:MK2, 0x0102,0x113-0x122:MiniMk3, 0x134-0x137:MK3
305 if( (0x30 <= pid && pid <= 0x32) || pid == 0x35 || (0x7B <= pid && pid <= 0x7D)
306 || pid == 0x102 || (0x113 <= pid && pid <= 0x122) || (0x134 <= pid && pid <= 0x137) ) {
308 return;
309 }
310 }
311}
312
313/* Receive data from MIDI device */
315{
316 *bytes_rcvd = (uint16_t)epInfo[epDataInIndex].maxPktSize;
318#ifdef EXTRADEBUG
319 if( r )
320 USBTRACE2("inTransfer():", r);
321#endif
323 dataptr[*bytes_rcvd] = '\0';
324 dataptr[(*bytes_rcvd)+1] = '\0';
325 }
326 return r;
327}
328
329/* Receive data from MIDI device */
331{
332 uint8_t rcode = 0; //return code
334
335 if( bPollEnable == false ) return 0;
336
337 //Checking unprocessed message in buffer.
338 if( readPtr != 0 && readPtr < MIDI_EVENT_PACKET_SIZE ){
339 if(recvBuf[readPtr] == 0 && recvBuf[readPtr+1] == 0) {
340 //no unprocessed message left in the buffer.
341 }else{
343 }
344 }
345
346 readPtr = 0;
348 if( rcode != 0 ) {
349 return 0;
350 }
351
352 //if all data is zero, no valid data received.
353 if( recvBuf[0] == 0 && recvBuf[1] == 0 && recvBuf[2] == 0 && recvBuf[3] == 0 ) {
354 return 0;
355 }
356
358 uint8_t m;
360 if( isRaw == true ) {
361 *(outBuf++) = cin;
362 }
363 readPtr++;
364 *(outBuf++) = m = recvBuf[readPtr++];
365 *(outBuf++) = recvBuf[readPtr++];
366 *(outBuf++) = recvBuf[readPtr++];
367
368 return getMsgSizeFromCin(cin & 0x0f);
369}
370
371/* Send data to MIDI device */
373{
374 uint8_t buf[4];
375 uint8_t status = dataptr[0];
376
377 uint8_t cin = convertStatus2Cin(status);
378 if ( status == 0xf0 ) {
379 // SysEx long message
381 }
382
383 //Building USB-MIDI Event Packets
384 buf[0] = (uint8_t)(nCable << 4) | cin;
385 buf[1] = dataptr[0];
386
388 switch(msglen) {
389 //3 bytes message
390 case 3 :
391 buf[2] = dataptr[1];
392 buf[3] = dataptr[2];
393 break;
394
395 //2 bytes message
396 case 2 :
397 buf[2] = dataptr[1];
398 buf[3] = 0;
399 break;
400
401 //1 byte message
402 case 1 :
403 buf[2] = 0;
404 buf[3] = 0;
405 break;
406 default :
407 break;
408 }
409#ifdef EXTRADEBUG
410 //Dump for raw USB-MIDI event packet
411 Notify(PSTR("SendData():"), 0x80), D_PrintHex((buf[0]), 0x80), D_PrintHex((buf[1]), 0x80), D_PrintHex((buf[2]), 0x80), D_PrintHex((buf[3]), 0x80), Notify(PSTR("\r\n"), 0x80);
412#endif
413 return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, 4, buf);
414}
415
416#ifdef DEBUG_USB_HOST
417void USBH_MIDI::PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr )
418{
419 USBTRACE("Endpoint descriptor:\r\n");
420 USBTRACE2(" Length:\t", ep_ptr->bLength);
421 USBTRACE2(" Type:\t\t", ep_ptr->bDescriptorType);
422 USBTRACE2(" Address:\t", ep_ptr->bEndpointAddress);
423 USBTRACE2(" Attributes:\t", ep_ptr->bmAttributes);
424 USBTRACE2(" MaxPktSize:\t", ep_ptr->wMaxPacketSize);
425 USBTRACE2(" Poll Intrv:\t", ep_ptr->bInterval);
426}
427#endif
428
429/* look up a MIDI message size from spec */
430/*Return */
431/* 0 : undefined message */
432/* 0<: Vaild message size(1-3) */
433//uint8_t USBH_MIDI::lookupMsgSize(uint8_t midiMsg, uint8_t cin)
435{
436 if( cin == 0 ){
437 cin = convertStatus2Cin(status);
438 }
439 return getMsgSizeFromCin(cin);
440}
441
442/* SysEx data size counter */
444{
445 uint16_t c = 1;
446
447 if( *dataptr != 0xf0 ){ //not SysEx
448 return 0;
449 }
450
451 //Search terminator(0xf7)
452 while(*dataptr != 0xf7) {
453 dataptr++;
454 c++;
455 //Limiter (default: 256 bytes)
457 c = 0;
458 break;
459 }
460 }
461 return c;
462}
463
464/* Send SysEx message to MIDI device */
466{
468 uint8_t rc = 0;
470 uint8_t wptr = 0;
472
473 USBTRACE("SendSysEx:\r\t");
474 USBTRACE2(" Length:\t", datasize);
475#ifdef EXTRADEBUG
476 uint16_t pktSize = (n+2)/3; //Calculate total USB MIDI packet size
477 USBTRACE2(" Total pktSize:\t", pktSize);
478#endif
479
480 while(n > 0) {
481 //Byte 0
482 buf[wptr] = (nCable << 4) | 0x4; //x4 SysEx starts or continues
483
484 switch ( n ) {
485 case 1 :
486 buf[wptr++] = (nCable << 4) | 0x5; //x5 SysEx ends with following single byte.
487 buf[wptr++] = *(dataptr++);
488 buf[wptr++] = 0x00;
489 buf[wptr++] = 0x00;
490 n = 0;
491 break;
492 case 2 :
493 buf[wptr++] = (nCable << 4) | 0x6; //x6 SysEx ends with following two bytes.
494 buf[wptr++] = *(dataptr++);
495 buf[wptr++] = *(dataptr++);
496 buf[wptr++] = 0x00;
497 n = 0;
498 break;
499 case 3 :
500 buf[wptr] = (nCable << 4) | 0x7; //x7 SysEx ends with following three bytes.
501 // fall through
502 default :
503 wptr++;
504 buf[wptr++] = *(dataptr++);
505 buf[wptr++] = *(dataptr++);
506 buf[wptr++] = *(dataptr++);
507 n = n - 3;
508 break;
509 }
510
511 if( wptr >= maxpkt || n == 0 ){ //Reach a maxPktSize or data end.
512 USBTRACE2(" wptr:\t", wptr);
514 break;
515 }
516 wptr = 0; //rewind write pointer
517 }
518 }
519 return(rc);
520}
521
523{
524 uint8_t rc = 0;
525 uint8_t cin = *(p) & 0x0f;
526
527 //SysEx message?
528 if( (cin & 0xc) != 4 ) return rc;
529
530 switch(cin) {
531 case 4:
532 case 7:
533 *buf++ = *(p+1);
534 *buf++ = *(p+2);
535 *buf++ = *(p+3);
536 rc = 3;
537 break;
538 case 6:
539 *buf++ = *(p+1);
540 *buf++ = *(p+2);
541 rc = 2;
542 break;
543 case 5:
544 *buf++ = *(p+1);
545 rc = 1;
546 break;
547 default:
548 break;
549 }
550 return(rc);
551}
552
553// Configuration Descriptor Parser
554// Copied from confdescparser.h and modifiy.
556theXtractor(xtractor),
557stateParseDescr(0),
558dscrLen(0),
559dscrType(0),
560nEPs(0),
561isMidiSearch(modeMidi){
562 theBuffer.pValue = varBuffer;
563 valParser.Initialize(&theBuffer);
564 theSkipper.Initialize(&theBuffer);
565}
568 uint8_t *p = (uint8_t*)pbuf;
569
570 while(cntdn)
571 if(!ParseDescriptor(&p, &cntdn))
572 return;
573}
574
575bool MidiDescParser::ParseDescriptor(uint8_t **pp, uint16_t *pcntdn) {
576 USB_CONFIGURATION_DESCRIPTOR* ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR*>(varBuffer);
577 USB_INTERFACE_DESCRIPTOR* uid = reinterpret_cast<USB_INTERFACE_DESCRIPTOR*>(varBuffer);
578 switch(stateParseDescr) {
579 case 0:
580 theBuffer.valueSize = 2;
581 valParser.Initialize(&theBuffer);
582 stateParseDescr = 1;
583 // fall through
584 case 1:
585 if(!valParser.Parse(pp, pcntdn))
586 return false;
587 dscrLen = *((uint8_t*)theBuffer.pValue);
588 dscrType = *((uint8_t*)theBuffer.pValue + 1);
589 stateParseDescr = 2;
590 // fall through
591 case 2:
592 // This is a sort of hack. Assuming that two bytes are all ready in the buffer
593 // the pointer is positioned two bytes ahead in order for the rest of descriptor
594 // to be read right after the size and the type fields.
595 // This should be used carefully. varBuffer should be used directly to handle data
596 // in the buffer.
597 theBuffer.pValue = varBuffer + 2;
598 stateParseDescr = 3;
599 // fall through
600 case 3:
601 switch(dscrType) {
603 isGoodInterface = false;
604 break;
608 break;
609 }
610 theBuffer.valueSize = dscrLen - 2;
611 valParser.Initialize(&theBuffer);
612 stateParseDescr = 4;
613 // fall through
614 case 4:
615 switch(dscrType) {
617 if(!valParser.Parse(pp, pcntdn))
618 return false;
619 confValue = ucd->bConfigurationValue;
620 break;
622 if(!valParser.Parse(pp, pcntdn))
623 return false;
624 USBTRACE("Interface descriptor:\r\n");
625 USBTRACE2(" Inf#:\t\t", uid->bInterfaceNumber);
626 USBTRACE2(" Alt:\t\t", uid->bAlternateSetting);
627 USBTRACE2(" EPs:\t\t", uid->bNumEndpoints);
628 USBTRACE2(" IntCl:\t\t", uid->bInterfaceClass);
629 USBTRACE2(" IntSubcl:\t", uid->bInterfaceSubClass);
630 USBTRACE2(" Protocol:\t", uid->bInterfaceProtocol);
631 // MIDI check mode ?
632 if( isMidiSearch ){ //true: MIDI Streaming, false: ALL
633 if( uid->bInterfaceClass == USB_CLASS_AUDIO && uid->bInterfaceSubClass == USB_SUBCLASS_MIDISTREAMING ) {
634 // MIDI found.
635 USBTRACE("+MIDI found\r\n\r\n");
636 }else{
637 USBTRACE("-MIDI not found\r\n\r\n");
638 break;
639 }
640 }
641 isGoodInterface = true;
642 // Initialize the counter if no two endpoints can be found in one interface.
643 if(nEPs < 2)
644 // reset endpoint counter
645 nEPs = 0;
646 break;
648 if(!valParser.Parse(pp, pcntdn))
649 return false;
650 if(isGoodInterface && nEPs < 2){
651 USBTRACE(">Extracting endpoint\r\n");
652 if( theXtractor->EndpointXtract(confValue, 0, 0, 0, (USB_ENDPOINT_DESCRIPTOR*)varBuffer) )
653 nEPs++;
654 }
655 break;
656
657 default:
658 if(!theSkipper.Skip(pp, pcntdn, dscrLen - 2))
659 return false;
660 }
661 theBuffer.pValue = varBuffer;
662 stateParseDescr = 0;
663 }
664 return true;
665}
666
667/* Extracts endpoint information from config descriptor */
669 uint8_t iface __attribute__((unused)),
670 uint8_t alt __attribute__((unused)),
671 uint8_t proto __attribute__((unused)),
673{
674 uint8_t index;
675
676#ifdef DEBUG_USB_HOST
677 PrintEndpointDescriptor(pep);
678#endif
679 // Is the endpoint transfer type bulk?
680 if((pep->bmAttributes & bTransferTypeMask) == USB_TRANSFER_TYPE_BULK) {
681 USBTRACE("+valid EP found.\r\n");
682 index = (pep->bEndpointAddress & 0x80) == 0x80 ? epDataInIndex : epDataOutIndex;
683 } else {
684 USBTRACE("-No valid EP found.\r\n");
685 return false;
686 }
687
688 // Fill the rest of endpoint data structure
689 epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
690 // The maximum packet size for the USB Host Shield 2.0 library is 64 bytes.
691 if(pep->wMaxPacketSize > MIDI_EVENT_PACKET_SIZE) {
693 } else {
694 epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
695 }
696
697 return true;
698}
#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL
Definition UsbCore.h:103
#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE
Definition UsbCore.h:108
#define USB_CLASS_AUDIO
Definition UsbCore.h:80
#define USB_ERROR_EPINFO_IS_NULL
Definition UsbCore.h:106
#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL
Definition UsbCore.h:105
#define USB_NAK_MAX_POWER
Definition address.h:34
#define USB_NAK_NOWAIT
Definition address.h:36
virtual void FreeAddress(uint8_t addr)=0
virtual UsbDevice * GetUsbDevicePtr(uint8_t addr)=0
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub=false, uint8_t port=0)=0
bool Skip(uint8_t **pp, uint16_t *pcntdn, uint16_t bytes_to_skip)
Definition parsetools.h:77
void Initialize(MultiValueBuffer *pbuf)
Definition parsetools.h:72
void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset)
MidiDescParser(UsbMidiConfigXtracter *xtractor, bool modeMidi)
void Initialize(MultiValueBuffer *const pbuf)
Definition parsetools.h:54
bool Parse(uint8_t **pp, uint16_t *pcntdn)
static const uint8_t epDataInIndex
Definition usbh_midi.h:83
uint8_t convertStatus2Cin(uint8_t status)
Definition usbh_midi.h:100
bool EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep)
uint8_t bTransferTypeMask
Definition usbh_midi.h:91
static const uint8_t epDataOutIndex
Definition usbh_midi.h:84
bool bPollEnable
Definition usbh_midi.h:89
uint8_t SendData(uint8_t *dataptr, uint8_t nCable=0)
USBH_MIDI(USB *p)
Definition usbh_midi.cpp:85
uint8_t lookupMsgSize(uint8_t midiMsg, uint8_t cin=0)
virtual uint8_t Release()
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed)
uint8_t SendSysEx(uint8_t *dataptr, uint16_t datasize, uint8_t nCable=0)
uint16_t vid
Definition usbh_midi.h:90
uint8_t recvBuf[MIDI_EVENT_PACKET_SIZE]
Definition usbh_midi.h:95
void setupDeviceSpecific()
uint8_t readPtr
Definition usbh_midi.h:96
uint16_t pid
Definition usbh_midi.h:90
uint16_t countSysExDataSize(uint8_t *dataptr)
uint8_t extractSysExData(uint8_t *p, uint8_t *buf)
EpInfo epInfo[MIDI_MAX_ENDPOINTS]
Definition usbh_midi.h:93
uint8_t RecvData(uint16_t *bytes_rcvd, uint8_t *dataptr)
uint8_t getMsgSizeFromCin(uint8_t cin)
Definition usbh_midi.h:103
uint8_t bAddress
Definition usbh_midi.h:88
USB * pUsb
Definition usbh_midi.h:87
Definition UsbCore.h:220
AddressPool & GetAddressPool()
Definition UsbCore.h:236
uint8_t getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t *dataptr)
defined(USB_METHODS_INLINE)
Definition Usb.cpp:801
uint8_t setConf(uint8_t addr, uint8_t ep, uint8_t conf_value)
Definition Usb.cpp:850
uint8_t setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr)
Definition Usb.cpp:841
uint8_t RegisterDeviceClass(USBDeviceConfig *pdev)
Definition UsbCore.h:240
uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t *dataptr)
Definition Usb.cpp:806
uint8_t setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo *eprecord_ptr)
Definition Usb.cpp:64
uint8_t inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t *data, uint8_t bInterval=0)
Definition Usb.cpp:209
uint8_t outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t *data)
Definition Usb.cpp:303
virtual bool EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep)
Definition usbh_midi.h:48
#define USBTRACE2(s, r)
Definition macros.h:84
#define USBTRACE(s)
Definition macros.h:82
#define Notify(...)
Definition message.h:51
void D_PrintHex(T val, int lvl)
Definition printhex.h:76
uint8_t bmNakPower
Definition address.h:49
uint8_t bmRcvToggle
Definition address.h:48
uint8_t epAddr
Definition address.h:40
uint8_t maxPktSize
Definition address.h:41
uint8_t bmSndToggle
Definition address.h:47
uint8_t valueSize
Definition parsetools.h:31
#define USB_TRANSFER_TYPE_BULK
Definition usb_ch9.h:92
#define USB_DESCRIPTOR_INTERFACE
Definition usb_ch9.h:73
#define HID_DESCRIPTOR_HID
Definition usb_ch9.h:80
#define USB_DESCRIPTOR_CONFIGURATION
Definition usb_ch9.h:71
#define bmUSB_TRANSFER_TYPE
Definition usb_ch9.h:94
#define USB_DESCRIPTOR_ENDPOINT
Definition usb_ch9.h:74
#define USB_SUBCLASS_MIDISTREAMING
Definition usbh_midi.h:33
#define MIDI_EVENT_PACKET_SIZE
Definition usbh_midi.h:34
#define MIDI_MAX_ENDPOINTS
Definition usbh_midi.h:32
#define MIDI_MAX_SYSEX_SIZE
Definition usbh_midi.h:35
#define USBH_MIDI_VERSION
Definition usbh_midi.h:31
#define PSTR(str)