Skip to content

Commit 1b9fa48

Browse files
committed
refactor(usb): dynamic endpoint descriptor generation
Replace static endpoint variables with EndpointIN and EndpointOUT functions. Allows flexible endpoint remapping across USB configs. Map CDC, HID, MIDI and MSC USB devices to bidirectional endpoints consistently across different configurations.
1 parent d9d19e8 commit 1b9fa48

8 files changed

Lines changed: 101 additions & 133 deletions

File tree

builder/sizes_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ func TestBinarySize(t *testing.T) {
4242
// This is a small number of very diverse targets that we want to test.
4343
tests := []sizeTest{
4444
// microcontrollers
45-
{"hifive1b", "examples/echo", 3817, 299, 0, 2252},
46-
{"microbit", "examples/serial", 2820, 356, 8, 2248},
47-
{"wioterminal", "examples/pininterrupt", 8036, 1652, 132, 7480},
45+
{"hifive1b", "examples/echo", 3680, 280, 0, 2252},
46+
{"microbit", "examples/serial", 2694, 342, 8, 2248},
47+
{"wioterminal", "examples/pininterrupt", 7074, 1510, 120, 7248},
4848

4949
// TODO: also check wasm. Right now this is difficult, because
5050
// wasm binaries are run through wasm-opt and therefore the

src/machine/usb/descriptor/cdc.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,9 @@ var InterfaceCDCData = InterfaceType{
150150
data: interfaceCDCData[:],
151151
}
152152

153+
// EP1 IN : CDC Call Management
154+
// EP2 OUT: CDC OUT
155+
// EP2 IN : CDC IN
153156
var CDC = Descriptor{
154157
Device: DeviceCDC.Bytes(),
155158
Configuration: Append([][]byte{
@@ -160,9 +163,9 @@ var CDC = Descriptor{
160163
ClassSpecificCDCCallManagement.Bytes(),
161164
ClassSpecificCDCACM.Bytes(),
162165
ClassSpecificCDCUnion.Bytes(),
163-
EndpointEP1IN.Bytes(),
166+
EndpointIN(EndpointEP1, TransferTypeInterrupt, 0x10, 0x10).Bytes(),
164167
InterfaceCDCData.Bytes(),
165-
EndpointEP2OUT.Bytes(),
166-
EndpointEP3IN.Bytes(),
168+
EndpointOUT(EndpointEP2, TransferTypeBulk, 0x40, 0x00).Bytes(),
169+
EndpointIN(EndpointEP2, TransferTypeBulk, 0x40, 0x00).Bytes(),
167170
}),
168171
}

src/machine/usb/descriptor/endpoint.go

Lines changed: 34 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -15,104 +15,44 @@ const (
1515
TransferTypeInterrupt
1616
)
1717

18-
var endpointEP1IN = [endpointTypeLen]byte{
19-
endpointTypeLen,
20-
TypeEndpoint,
21-
0x81, // EndpointAddress
22-
0x03, // Attributes
23-
0x10, // MaxPacketSizeL
24-
0x00, // MaxPacketSizeH
25-
0x10, // Interval
26-
}
27-
28-
var EndpointEP1IN = EndpointType{
29-
data: endpointEP1IN[:],
30-
}
31-
32-
var endpointEP2OUT = [endpointTypeLen]byte{
33-
endpointTypeLen,
34-
TypeEndpoint,
35-
0x02, // EndpointAddress
36-
0x02, // Attributes
37-
0x40, // MaxPacketSizeL
38-
0x00, // MaxPacketSizeH
39-
0x00, // Interval
40-
}
41-
42-
var EndpointEP2OUT = EndpointType{
43-
data: endpointEP2OUT[:],
44-
}
18+
type EndpointNumber uint8
4519

46-
var endpointEP3IN = [endpointTypeLen]byte{
47-
endpointTypeLen,
48-
TypeEndpoint,
49-
0x83, // EndpointAddress
50-
0x02, // Attributes
51-
0x40, // MaxPacketSizeL
52-
0x00, // MaxPacketSizeH
53-
0x00, // Interval
54-
}
55-
56-
var EndpointEP3IN = EndpointType{
57-
data: endpointEP3IN[:],
58-
}
59-
60-
var endpointEP4IN = [endpointTypeLen]byte{
61-
endpointTypeLen,
62-
TypeEndpoint,
63-
0x84, // EndpointAddress
64-
0x03, // Attributes
65-
0x40, // MaxPacketSizeL
66-
0x00, // MaxPacketSizeH
67-
0x01, // Interval
68-
}
69-
70-
var EndpointEP4IN = EndpointType{
71-
data: endpointEP4IN[:],
72-
}
73-
74-
var endpointEP5OUT = [endpointTypeLen]byte{
75-
endpointTypeLen,
76-
TypeEndpoint,
77-
0x05, // EndpointAddress
78-
0x03, // Attributes
79-
0x40, // MaxPacketSizeL
80-
0x00, // MaxPacketSizeH
81-
0x01, // Interval
82-
}
83-
84-
var EndpointEP5OUT = EndpointType{
85-
data: endpointEP5OUT[:],
86-
}
87-
88-
// Mass Storage Class bulk in endpoint
89-
var endpointMSCIN = [endpointTypeLen]byte{
90-
endpointTypeLen,
91-
TypeEndpoint,
92-
0x86, // EndpointAddress
93-
TransferTypeBulk, // Attributes
94-
0x40, // MaxPacketSizeL (64 bytes)
95-
0x00, // MaxPacketSizeH
96-
0x00, // Interval
97-
}
20+
const (
21+
EndpointEP1 EndpointNumber = iota
22+
EndpointEP2
23+
EndpointEP3
24+
EndpointEP4
25+
)
9826

99-
var EndpointMSCIN = EndpointType{
100-
data: endpointMSCIN[:],
101-
}
27+
const (
28+
maxEndpoints = 4
29+
)
10230

103-
// Mass Storage Class bulk out endpoint
104-
var endpointMSCOUT = [endpointTypeLen]byte{
105-
endpointTypeLen,
106-
TypeEndpoint,
107-
0x07, // EndpointAddress
108-
TransferTypeBulk, // Attributes
109-
0x40, // MaxPacketSizeL (64 bytes)
110-
0x00, // MaxPacketSizeH
111-
0x00, // Interval
112-
}
31+
var (
32+
endpointEPIn = [maxEndpoints][endpointTypeLen]byte{}
33+
endpointEPOut = [maxEndpoints][endpointTypeLen]byte{}
34+
)
11335

114-
var EndpointMSCOUT = EndpointType{
115-
data: endpointMSCOUT[:],
36+
func EndpointIN(ep EndpointNumber, transferType uint8, maxPacketSize uint16, interval uint8) EndpointType {
37+
e := EndpointType{data: endpointEPIn[ep][:]}
38+
e.Length(endpointTypeLen)
39+
e.Type(TypeEndpoint)
40+
e.EndpointAddress(uint8(ep+1) | 0x80) // EndpointNumber is 0-based, addresses are 1-based
41+
e.Attributes(transferType)
42+
e.MaxPacketSize(maxPacketSize)
43+
e.Interval(interval)
44+
return e
45+
}
46+
47+
func EndpointOUT(ep EndpointNumber, transferType uint8, maxPacketSize uint16, interval uint8) EndpointType {
48+
e := EndpointType{data: endpointEPOut[ep][:]}
49+
e.Length(endpointTypeLen)
50+
e.Type(TypeEndpoint)
51+
e.EndpointAddress(uint8(ep + 1)) // EndpointNumber is 0-based, addresses are 1-based
52+
e.Attributes(transferType)
53+
e.MaxPacketSize(maxPacketSize)
54+
e.Interval(interval)
55+
return e
11656
}
11757

11858
const (

src/machine/usb/descriptor/hid.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ var ClassHID = ClassHIDType{
111111
data: classHID[:],
112112
}
113113

114+
// EP1 IN : CDC Call Management
115+
// EP2 OUT: CDC OUT
116+
// EP2 IN : CDC IN
117+
// EP3 OUT: HID OUT
118+
// EP3 IN : HID IN
114119
var CDCHID = Descriptor{
115120
Device: DeviceCDC.Bytes(),
116121
Configuration: Append([][]byte{
@@ -121,14 +126,14 @@ var CDCHID = Descriptor{
121126
ClassSpecificCDCACM.Bytes(),
122127
ClassSpecificCDCUnion.Bytes(),
123128
ClassSpecificCDCCallManagement.Bytes(),
124-
EndpointEP1IN.Bytes(),
129+
EndpointIN(EndpointEP1, TransferTypeInterrupt, 0x10, 0x10).Bytes(),
125130
InterfaceCDCData.Bytes(),
126-
EndpointEP2OUT.Bytes(),
127-
EndpointEP3IN.Bytes(),
131+
EndpointOUT(EndpointEP2, TransferTypeBulk, 0x40, 0x00).Bytes(),
132+
EndpointIN(EndpointEP2, TransferTypeBulk, 0x40, 0x00).Bytes(),
128133
InterfaceHID.Bytes(),
129134
ClassHID.Bytes(),
130-
EndpointEP4IN.Bytes(),
131-
EndpointEP5OUT.Bytes(),
135+
EndpointIN(EndpointEP3, TransferTypeInterrupt, 0x40, 0x01).Bytes(),
136+
EndpointOUT(EndpointEP3, TransferTypeInterrupt, 0x40, 0x01).Bytes(),
132137
}),
133138
HID: map[uint16][]byte{
134139
2: Append([][]byte{ // Update ClassLength in classHID whenever the array length is modified!

src/machine/usb/descriptor/joystick.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,11 @@ var JoystickDefaultHIDReport = Append([][]byte{
121121
// CDCJoystick requires that you append the JoystickDescriptor
122122
// to the Configuration before using. This is in order to support
123123
// custom configurations.
124+
// EP1 IN : CDC Call Management
125+
// EP2 OUT: CDC OUT
126+
// EP2 IN : CDC IN
127+
// EP3 OUT: HID OUT
128+
// EP3 IN : HID IN
124129
var CDCJoystick = Descriptor{
125130
Device: DeviceJoystick.Bytes(),
126131
Configuration: Append([][]byte{
@@ -131,14 +136,14 @@ var CDCJoystick = Descriptor{
131136
ClassSpecificCDCACM.Bytes(),
132137
ClassSpecificCDCUnion.Bytes(),
133138
ClassSpecificCDCCallManagement.Bytes(),
134-
EndpointEP1IN.Bytes(),
139+
EndpointIN(EndpointEP1, TransferTypeInterrupt, 0x10, 0x10).Bytes(),
135140
InterfaceCDCData.Bytes(),
136-
EndpointEP2OUT.Bytes(),
137-
EndpointEP3IN.Bytes(),
141+
EndpointOUT(EndpointEP2, TransferTypeBulk, 0x40, 0x00).Bytes(),
142+
EndpointIN(EndpointEP2, TransferTypeBulk, 0x40, 0x00).Bytes(),
138143
InterfaceHIDJoystick.Bytes(),
139144
ClassHIDJoystick.Bytes(),
140-
EndpointEP4IN.Bytes(),
141-
EndpointEP5OUT.Bytes(),
145+
EndpointIN(EndpointEP3, TransferTypeInterrupt, 0x40, 0x01).Bytes(),
146+
EndpointOUT(EndpointEP3, TransferTypeInterrupt, 0x40, 0x01).Bytes(),
142147
}),
143148
HID: map[uint16][]byte{},
144149
}

src/machine/usb/descriptor/midi.go

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,10 @@ var ClassSpecificMIDIInEndpoint = ClassSpecificType{
171171

172172
const endpointMIDITypeLen = 9
173173

174-
var endpointEP6IN = [endpointMIDITypeLen]byte{
174+
var endpointMIDIIN = [endpointMIDITypeLen]byte{
175175
endpointMIDITypeLen,
176176
TypeEndpoint,
177-
0x86, // EndpointAddress
177+
0x83, // EndpointAddress
178178
0x02, // Attributes
179179
0x40, // MaxPacketSizeL
180180
0x00, // MaxPacketSizeH
@@ -183,14 +183,14 @@ var endpointEP6IN = [endpointMIDITypeLen]byte{
183183
0x00, // sync address
184184
}
185185

186-
var EndpointEP6IN = EndpointType{
187-
data: endpointEP6IN[:],
186+
var EndpointMIDIIN = EndpointType{
187+
data: endpointMIDIIN[:],
188188
}
189189

190-
var endpointEP7OUT = [endpointMIDITypeLen]byte{
190+
var endpointMIDIOUT = [endpointMIDITypeLen]byte{
191191
endpointMIDITypeLen,
192192
TypeEndpoint,
193-
0x07, // EndpointAddress
193+
0x03, // EndpointAddress
194194
0x02, // Attributes
195195
0x40, // MaxPacketSizeL
196196
0x00, // MaxPacketSizeH
@@ -199,8 +199,8 @@ var endpointEP7OUT = [endpointMIDITypeLen]byte{
199199
0x00, // sync address
200200
}
201201

202-
var EndpointEP7OUT = EndpointType{
203-
data: endpointEP7OUT[:],
202+
var EndpointMIDIOUT = EndpointType{
203+
data: endpointMIDIOUT[:],
204204
}
205205

206206
var configurationCDCMIDI = [configurationTypeLen]byte{
@@ -218,6 +218,11 @@ var ConfigurationCDCMIDI = ConfigurationType{
218218
data: configurationCDCMIDI[:],
219219
}
220220

221+
// EP1 IN : CDC Call Management
222+
// EP2 OUT: CDC OUT
223+
// EP2 IN : CDC IN
224+
// EP3 OUT: MIDI OUT (custom endpoint descriptor)
225+
// EP3 IN : MIDI IN (custom endpoint descriptor)
221226
var CDCMIDI = Descriptor{
222227
Device: DeviceCDC.Bytes(),
223228
Configuration: Append([][]byte{
@@ -228,10 +233,10 @@ var CDCMIDI = Descriptor{
228233
ClassSpecificCDCACM.Bytes(),
229234
ClassSpecificCDCUnion.Bytes(),
230235
ClassSpecificCDCCallManagement.Bytes(),
231-
EndpointEP1IN.Bytes(),
236+
EndpointIN(EndpointEP1, TransferTypeInterrupt, 0x10, 0x10).Bytes(),
232237
InterfaceCDCData.Bytes(),
233-
EndpointEP2OUT.Bytes(),
234-
EndpointEP3IN.Bytes(),
238+
EndpointOUT(EndpointEP2, TransferTypeBulk, 0x40, 0x00).Bytes(),
239+
EndpointIN(EndpointEP2, TransferTypeBulk, 0x40, 0x00).Bytes(),
235240
InterfaceAssociationMIDI.Bytes(),
236241
InterfaceAudio.Bytes(),
237242
ClassSpecificAudioInterface.Bytes(),
@@ -241,9 +246,9 @@ var CDCMIDI = Descriptor{
241246
ClassSpecificMIDIInJack2.Bytes(),
242247
ClassSpecificMIDIOutJack1.Bytes(),
243248
ClassSpecificMIDIOutJack2.Bytes(),
244-
EndpointEP7OUT.Bytes(),
249+
EndpointMIDIOUT.Bytes(),
245250
ClassSpecificMIDIOutEndpoint.Bytes(),
246-
EndpointEP6IN.Bytes(),
251+
EndpointMIDIIN.Bytes(),
247252
ClassSpecificMIDIInEndpoint.Bytes(),
248253
}),
249254
}

src/machine/usb/descriptor/msc.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,17 @@ var ConfigurationMSC = ConfigurationType{
5252
data: configurationMSC[:],
5353
}
5454

55+
var (
56+
EndpointMSCIN = EndpointIN(EndpointEP3, TransferTypeBulk, 0x40, 0x00)
57+
EndpointMSCOUT = EndpointOUT(EndpointEP3, TransferTypeBulk, 0x40, 0x00)
58+
)
59+
5560
// Mass Storage Class
61+
// EP1 IN : CDC Call Management
62+
// EP2 OUT: CDC OUT
63+
// EP2 IN : CDC IN
64+
// EP3 OUT: MSC OUT
65+
// EP3 IN : MSC IN
5666
var MSC = Descriptor{
5767
Device: DeviceCDC.Bytes(),
5868
Configuration: Append([][]byte{
@@ -63,10 +73,10 @@ var MSC = Descriptor{
6373
ClassSpecificCDCACM.Bytes(),
6474
ClassSpecificCDCUnion.Bytes(),
6575
ClassSpecificCDCCallManagement.Bytes(),
66-
EndpointEP1IN.Bytes(),
76+
EndpointIN(EndpointEP1, TransferTypeInterrupt, 0x10, 0x10).Bytes(),
6777
InterfaceCDCData.Bytes(),
68-
EndpointEP2OUT.Bytes(),
69-
EndpointEP3IN.Bytes(),
78+
EndpointOUT(EndpointEP2, TransferTypeBulk, 0x40, 0x00).Bytes(),
79+
EndpointIN(EndpointEP2, TransferTypeBulk, 0x40, 0x00).Bytes(),
7080
InterfaceAssociationMSC.Bytes(),
7181
InterfaceMSC.Bytes(),
7282
EndpointMSCIN.Bytes(),

src/machine/usb/usb.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,13 @@ const (
7474
CONTROL_ENDPOINT = 0
7575
CDC_ENDPOINT_ACM = 1
7676
CDC_ENDPOINT_OUT = 2
77-
CDC_ENDPOINT_IN = 3
78-
HID_ENDPOINT_IN = 4 // for Interrupt In
79-
HID_ENDPOINT_OUT = 5 // for Interrupt Out
80-
MIDI_ENDPOINT_IN = 6 // for Bulk In
81-
MIDI_ENDPOINT_OUT = 7 // for Bulk Out
82-
MSC_ENDPOINT_IN = 6 // for Bulk In
83-
MSC_ENDPOINT_OUT = 7 // for Bulk Out
77+
CDC_ENDPOINT_IN = 2
78+
HID_ENDPOINT_IN = 3 // for Interrupt In
79+
HID_ENDPOINT_OUT = 3 // for Interrupt Out
80+
MIDI_ENDPOINT_IN = 3 // for Bulk In
81+
MIDI_ENDPOINT_OUT = 3 // for Bulk Out
82+
MSC_ENDPOINT_IN = 3 // for Bulk In
83+
MSC_ENDPOINT_OUT = 3 // for Bulk Out
8484

8585
// bmRequestType
8686
REQUEST_HOSTTODEVICE = 0x00

0 commit comments

Comments
 (0)