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;
0 commit comments