Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 35ee99e

Browse files
committed
add stub MIDIUSB library
only a proof of concept for PluggableUSB module
1 parent 98c7569 commit 35ee99e

File tree

2 files changed

+370
-0
lines changed

2 files changed

+370
-0
lines changed

‎libraries/MIDIUSB/MIDIUSB.cpp‎

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
// Copyright (c) 2015, Gary Grewal
2+
/*
3+
** Permission to use, copy, modify, and/or distribute this software for
4+
** any purpose with or without fee is hereby granted, provided that the
5+
** above copyright notice and this permission notice appear in all copies.
6+
**
7+
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
8+
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
9+
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
10+
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
11+
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
12+
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
13+
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
14+
** SOFTWARE.
15+
*/
16+
#include "PluggableUSB.h"
17+
#include "MIDIUSB.h"
18+
19+
#define MIDI_BUFFER_SIZE 128
20+
21+
22+
static u8 MIDI_AC_INTERFACE; // MIDI AC Interface
23+
static u8 MIDI_INTERFACE;
24+
static u8 MIDI_FIRST_ENDPOINT;
25+
static u8 MIDI_ENDPOINT_OUT;
26+
static u8 MIDI_ENDPOINT_IN;
27+
28+
#define MIDI_RX MIDI_ENDPOINT_OUT
29+
#define MIDI_TX MIDI_ENDPOINT_IN
30+
31+
struct ring_bufferMIDI
32+
{
33+
midiEventPacket_t midiEvent[MIDI_BUFFER_SIZE];
34+
volatile uint32_t head;
35+
volatile uint32_t tail;
36+
};
37+
38+
ring_bufferMIDI midi_rx_buffer = {{0,0,0,0 }, 0, 0};
39+
40+
static MIDIDescriptor _midiInterface;
41+
42+
void WEAK setupUSB() {
43+
MidiUSB.begin();
44+
}
45+
46+
int8_t WEAK MIDI_GetInterface(uint8_t* interfaceNum)
47+
{
48+
interfaceNum[0] += 2; // uses 2
49+
return USB_SendControl(0,&_midiInterface,sizeof(_midiInterface));
50+
}
51+
bool WEAK MIDI_Setup(Setup& setup, u8 i)
52+
{
53+
//Support requests here if needed. Typically these are optional
54+
return false;
55+
}
56+
57+
int8_t WEAK MIDI_GetDescriptor(int8_t t)
58+
{
59+
return 0;
60+
}
61+
62+
void MIDI_::accept(void)
63+
{
64+
// static uint32_t mguard = 0;
65+
66+
// // synchronized access to guard
67+
// do {
68+
// if (__LDREXW(&mguard) != 0) {
69+
// __CLREX();
70+
// return; // busy
71+
// }
72+
// } while (__STREXW(1, &mguard) != 0); // retry until write succeed
73+
74+
// ring_bufferMIDI *buffer = &midi_rx_buffer;
75+
// uint32_t i = (uint32_t)(buffer->head+1) % MIDI_BUFFER_SIZE;
76+
77+
// // if we should be storing the received character into the location
78+
// // just before the tail (meaning that the head would advance to the
79+
// // current location of the tail), we're about to overflow the buffer
80+
// // and so we don't write the character or advance the head.
81+
// while (i != buffer->tail) {
82+
// int c;
83+
// midiEventPacket_t event;
84+
// if (!USB_Available(MIDI_RX)) {
85+
// udd_ack_fifocon(MIDI_RX);
86+
// break;
87+
// }
88+
// c = USB_Recv(MIDI_RX, &event, sizeof(event) );
89+
90+
// //MIDI paacket has to be 4 bytes
91+
// if(c < 4)
92+
// return;
93+
// buffer->midiEvent[buffer->head] = event;
94+
// buffer->head = i;
95+
96+
// i = (i + 1) % MIDI_BUFFER_SIZE;
97+
// }
98+
99+
// // release the guard
100+
// mguard = 0;
101+
}
102+
103+
uint32_t MIDI_::available(void)
104+
{
105+
106+
ring_bufferMIDI *buffer = &midi_rx_buffer;
107+
return (uint32_t)(MIDI_BUFFER_SIZE + buffer->head - buffer->tail) % MIDI_BUFFER_SIZE;
108+
}
109+
110+
111+
midiEventPacket_t MIDI_::read(void)
112+
{
113+
ring_bufferMIDI *buffer = &midi_rx_buffer;
114+
midiEventPacket_t c = buffer->midiEvent[buffer->tail];
115+
c.header = 0;
116+
c.byte1 = 0;
117+
c.byte2 = 0;
118+
c.byte3 = 0;
119+
120+
// if the head isn't ahead of the tail, we don't have any characters
121+
if (buffer->head == buffer->tail)
122+
{
123+
return c;
124+
}
125+
else
126+
{
127+
midiEventPacket_t c = buffer->midiEvent[buffer->tail];
128+
buffer->tail = (uint32_t)(buffer->tail + 1) % MIDI_BUFFER_SIZE;
129+
if (USB_Available(MIDI_RX))
130+
accept();
131+
return c;
132+
}
133+
}
134+
135+
void MIDI_::flush(void)
136+
{
137+
USB_Flush(MIDI_TX);
138+
}
139+
140+
size_t MIDI_::write(const uint8_t *buffer, size_t size)
141+
{
142+
/* only try to send bytes if the high-level MIDI connection itself
143+
is open (not just the pipe) - the OS should set lineState when the port
144+
is opened and clear lineState when the port is closed.
145+
bytes sent before the user opens the connection or after
146+
the connection is closed are lost - just like with a UART. */
147+
148+
// TODO - ZE - check behavior on different OSes and test what happens if an
149+
// open connection isn't broken cleanly (cable is yanked out, host dies
150+
// or locks up, or host virtual serial port hangs)
151+
152+
int r = USB_Send(MIDI_TX, buffer, size);
153+
154+
if (r > 0)
155+
{
156+
return r;
157+
} else
158+
{
159+
return 0;
160+
}
161+
return 0;
162+
}
163+
164+
void MIDI_::sendMIDI(midiEventPacket_t event)
165+
{
166+
uint8_t data[4];
167+
data[0] = event.header;
168+
data[1] = event.byte1;
169+
data[2] = event.byte2;
170+
data[3] = event.byte3;
171+
write(data, 4);
172+
}
173+
174+
int8_t MIDI_plug(void)
175+
{
176+
PUSBCallbacks cb;
177+
178+
cb.setup = &MIDI_Setup;
179+
cb.getInterface = &MIDI_GetInterface;
180+
cb.getDescriptor = &MIDI_GetDescriptor;
181+
cb.numEndpoints = 2;
182+
cb.endpointType[0] = EP_TYPE_BULK_OUT_MIDI; // MIDI_ENDPOINT_OUT
183+
cb.endpointType[1] = EP_TYPE_BULK_IN_MIDI; // MIDI_ENDPOINT_IN
184+
185+
MIDI_ENDPOINT_OUT = PUSB_AddFunction(&cb, &MIDI_AC_INTERFACE);
186+
MIDI_ENDPOINT_IN = MIDI_ENDPOINT_OUT + 1;
187+
MIDI_INTERFACE = MIDI_AC_INTERFACE + 1;
188+
189+
_midiInterface =
190+
{
191+
D_IAD(MIDI_AC_INTERFACE, 2, MIDI_AUDIO, MIDI_AUDIO_CONTROL, 0),
192+
D_INTERFACE(MIDI_AC_INTERFACE,0,MIDI_AUDIO,MIDI_AUDIO_CONTROL,0),
193+
D_AC_INTERFACE(0x1, MIDI_INTERFACE),
194+
D_INTERFACE(MIDI_INTERFACE,2, MIDI_AUDIO,MIDI_STREAMING,0),
195+
D_AS_INTERFACE,
196+
D_MIDI_INJACK(MIDI_JACK_EMD, 0x1),
197+
D_MIDI_INJACK(MIDI_JACK_EXT, 0x2),
198+
D_MIDI_OUTJACK(MIDI_JACK_EMD, 0x3, 1, 2, 1),
199+
D_MIDI_OUTJACK(MIDI_JACK_EXT, 0x4, 1, 1, 1),
200+
D_MIDI_JACK_EP(USB_ENDPOINT_OUT(MIDI_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,512),
201+
D_MIDI_AC_JACK_EP(1, 1),
202+
D_MIDI_JACK_EP(USB_ENDPOINT_IN(MIDI_ENDPOINT_IN),USB_ENDPOINT_TYPE_BULK,512),
203+
D_MIDI_AC_JACK_EP (1, 3)
204+
};
205+
206+
return MIDI_ENDPOINT_IN;
207+
}
208+
209+
int8_t MIDI_::begin()
210+
{
211+
return MIDI_plug();
212+
}
213+
214+
215+
MIDI_ MidiUSB;

‎libraries/MIDIUSB/MIDIUSB.h‎

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
//================================================================================
2+
//================================================================================
3+
// MIDI USB class
4+
5+
#ifndef MIDIUSB_h
6+
#define MIDIUSB_h
7+
8+
#include <stdint.h>
9+
#include <Arduino.h>
10+
11+
#if defined(USBCON)
12+
13+
typedef struct
14+
{
15+
uint8_t header;
16+
uint8_t byte1;
17+
uint8_t byte2;
18+
uint8_t byte3;
19+
}midiEventPacket_t;
20+
21+
#define EP_TYPE_BULK_OUT_MIDI EP_TYPE_BULK_OUT
22+
#define EP_TYPE_BULK_IN_MIDI EP_TYPE_BULK_IN
23+
24+
class MIDI_
25+
{
26+
// private:
27+
// RingBuffer *_midi_rx_buffer;
28+
public:
29+
int8_t begin();
30+
31+
virtual uint32_t available(void);
32+
virtual void accept(void);
33+
virtual midiEventPacket_t read(void);
34+
virtual void flush(void);
35+
virtual void sendMIDI(midiEventPacket_t event);
36+
virtual size_t write(const uint8_t *buffer, size_t size);
37+
operator bool();
38+
};
39+
extern MIDI_ MidiUSB;
40+
41+
#define MIDI_AUDIO 0x01
42+
#define MIDI_AUDIO_CONTROL 0x01
43+
#define MIDI_CS_INTERFACE 0x24
44+
#define MIDI_CS_ENDPOINT 0x25
45+
#define MIDI_STREAMING 0x3
46+
#define MIDI_JACK_EMD 0x01
47+
#define MIDI_JACK_EXT 0X02
48+
49+
typedef struct
50+
{
51+
uint8_t len; // 9
52+
uint8_t dtype; // 4
53+
uint8_t dsubType;
54+
uint16_t bcdADc;
55+
uint16_t wTotalLength;
56+
uint8_t bInCollection;
57+
uint8_t interfaceNumbers;
58+
} MIDI_ACInterfaceDescriptor;
59+
60+
typedef struct
61+
{
62+
uint8_t len; // 9
63+
uint8_t dtype; // 4
64+
uint8_t dsubType;
65+
uint8_t jackType;
66+
uint8_t jackID;
67+
uint8_t jackStrIndex;
68+
} MIDIJackinDescriptor;
69+
70+
typedef struct
71+
{
72+
uint8_t len; // 9
73+
uint8_t dtype; // 4
74+
uint8_t dsubType;
75+
uint8_t jackType;
76+
uint8_t jackID;
77+
uint8_t nPins;
78+
uint8_t srcJackID;
79+
uint8_t srcPinID;
80+
uint8_t jackStrIndex;
81+
} MIDIJackOutDescriptor;
82+
83+
typedef struct
84+
{
85+
EndpointDescriptor len; // 9
86+
uint8_t refresh; // 4
87+
uint8_t sync;
88+
} MIDI_EPDescriptor;
89+
90+
typedef struct
91+
{
92+
uint8_t len; // 5
93+
uint8_t dtype; // 0x24
94+
uint8_t subtype;
95+
uint8_t embJacks;
96+
uint8_t jackID;
97+
} MIDI_EP_ACDescriptor;
98+
99+
typedef struct
100+
{
101+
uint8_t len; // 9
102+
uint8_t dtype; // 4
103+
uint8_t dsubType;
104+
uint16_t bcdADc;
105+
uint16_t wTotalLength;
106+
} MIDI_ASInterfaceDescriptor;
107+
108+
typedef struct
109+
{
110+
// IAD
111+
IADDescriptor iad;
112+
// MIDI Audio Control Interface
113+
InterfaceDescriptor Audio_ControlInterface;
114+
MIDI_ACInterfaceDescriptor Audio_ControlInterface_SPC;
115+
116+
// MIDI Audio Streaming Interface
117+
InterfaceDescriptor Audio_StreamInterface;
118+
MIDI_ASInterfaceDescriptor Audio_StreamInterface_SPC;
119+
120+
MIDIJackinDescriptor MIDI_In_Jack_Emb;
121+
MIDIJackinDescriptor MIDI_In_Jack_Ext;
122+
MIDIJackOutDescriptor MIDI_Out_Jack_Emb;
123+
MIDIJackOutDescriptor MIDI_Out_Jack_Ext;
124+
125+
MIDI_EPDescriptor MIDI_In_Jack_Endpoint;
126+
MIDI_EP_ACDescriptor MIDI_In_Jack_Endpoint_SPC;
127+
MIDI_EPDescriptor MIDI_Out_Jack_Endpoint;
128+
MIDI_EP_ACDescriptor MIDI_Out_Jack_Endpoint_SPC;
129+
} MIDIDescriptor;
130+
131+
#define D_AC_INTERFACE(_streamingInterfaces, _MIDIInterface) \
132+
{ 9, MIDI_CS_INTERFACE, 0x1, 0x0100, 0x0009, _streamingInterfaces, _MIDIInterface }
133+
134+
#define D_AS_INTERFACE \
135+
{ 0x7, MIDI_CS_INTERFACE, 0x01,0x0100, 0x0041}
136+
137+
#define D_MIDI_INJACK(jackProp, _jackID) \
138+
{ 0x06, MIDI_CS_INTERFACE, 0x02, jackProp, _jackID, 0 }
139+
140+
#define D_MIDI_OUTJACK(jackProp, _jackID, _nPins, _srcID, _srcPin) \
141+
{ 0x09, MIDI_CS_INTERFACE, 0x3, jackProp, _jackID, _nPins, _srcID, _srcPin, 0 }
142+
143+
#define D_MIDI_JACK_EP(_addr,_attr,_packetSize) \
144+
{ 9, 5, _addr,_attr,_packetSize, 0, 0, 0}
145+
146+
#define D_MIDI_AC_JACK_EP(_nMIDI, _iDMIDI) \
147+
{ 5, MIDI_CS_ENDPOINT, 0x1, _nMIDI, _iDMIDI}
148+
149+
#define D_CDCCS(_subtype,_d0,_d1) { 5, 0x24, _subtype, _d0, _d1 }
150+
#define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 }
151+
152+
#define WEAK __attribute__ ((weak))
153+
154+
#endif
155+
#endif

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /