Skip to content

Commit a8ff3d9

Browse files
authored
Merge pull request #20 from twam/feature/rework-uac2
Rework USB Audio Class stuff
2 parents 9fecaac + ad2e7e7 commit a8ff3d9

File tree

11 files changed

+2105
-636
lines changed

11 files changed

+2105
-636
lines changed

usb_protocol/emitters/descriptors/standard.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,8 @@ def InterfaceDescriptor(self):
129129

130130
def _pre_emit(self):
131131

132-
# Count our interfaces.
133-
self.bNumInterfaces = self._type_counts[StandardDescriptorNumbers.INTERFACE]
132+
# Count our interfaces. Alternate settings of the same interface do not count multiple times.
133+
self.bNumInterfaces = len(set([subordinate[2] for subordinate in self._subordinates if (subordinate[1] == StandardDescriptorNumbers.INTERFACE)]))
134134

135135
# Figure out our total length.
136136
subordinate_length = sum(len(sub) for sub in self._subordinates)

usb_protocol/emitters/descriptors/uac.py

Lines changed: 0 additions & 67 deletions
This file was deleted.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#
2+
# This file is part of usb_protocol.
3+
#
4+
""" Convenience emitters for USB Audio Class 1 descriptors. """
5+
6+
from contextlib import contextmanager
7+
8+
from ...types.descriptors.uac1 import *
9+
10+
AudioControlInterruptEndpointDescriptorEmitter = emitter_for_format(AudioControlInterruptEndpointDescriptor)

usb_protocol/emitters/descriptors/uac2.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,9 @@
66
from contextlib import contextmanager
77

88
from .. import emitter_for_format
9-
from ...types.descriptors.uac import *
109
from ...types.descriptors.uac2 import *
1110
from ...emitters.descriptor import ComplexDescriptorEmitter
1211

13-
###################### Audio #########################
14-
1512
# Create our emitters.
1613
InterfaceAssociationDescriptorEmitter = emitter_for_format(InterfaceAssociationDescriptor)
1714
StandardAudioControlInterfaceDescriptorEmitter = emitter_for_format(StandardAudioControlInterfaceDescriptor)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#
2+
# This file is part of usb_protocol.
3+
#
4+
""" Convenience emitters for USB Audio Class 3 descriptors. """
5+
6+
from .. import emitter_for_format
7+
from ...types.descriptors.uac3 import *
8+
9+
InputTerminalDescriptorEmitter = emitter_for_format(InputTerminalDescriptor)
10+
OutputTerminalDescriptorEmitter = emitter_for_format(OutputTerminalDescriptor)
11+
AudioStreamingInterfaceDescriptorEmitter = emitter_for_format(AudioStreamingInterfaceDescriptor)
12+
ClassSpecificAudioStreamingInterfaceDescriptorEmitter = emitter_for_format(ClassSpecificAudioStreamingInterfaceDescriptor)
13+
AudioControlInterruptEndpointDescriptorEmitter = emitter_for_format(AudioControlInterruptEndpointDescriptor)
14+
AudioStreamingIsochronousEndpointDescriptorEmitter = emitter_for_format(AudioStreamingIsochronousEndpointDescriptor)
15+
AudioStreamingIsochronousFeedbackEndpointDescriptorEmitter = emitter_for_format(AudioStreamingIsochronousFeedbackEndpointDescriptor)
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#
2+
# This file is part of usb-protocol.
3+
#
4+
"""
5+
Descriptors for USB MIDI Class Devices
6+
7+
[Midi10] refers to "Universal Serial Bus Device Class Definition for MIDI Devices", Release 1.0, November 1, 1999
8+
"""
9+
10+
from enum import IntEnum
11+
12+
from .standard import StandardDescriptorNumbers
13+
14+
15+
class MidiStreamingInterfaceDescriptorSubtypes(IntEnum):
16+
# As defined in [Midi10], A.1
17+
MS_DESCRIPTOR_UNDEFINED = 0x00
18+
MS_HEADER = 0x01
19+
MIDI_IN_JACK = 0x02
20+
MIDI_OUT_JACK = 0x03
21+
ELEMENT = 0x04
22+
23+
24+
class MidiStreamingEndpointDescriptorSubtypes(IntEnum):
25+
# As defined in [Midi10], A.2
26+
DESCRIPTOR_UNDEFINED = 0x00
27+
MS_GENERAL = 0x01
28+
29+
30+
class MidiStreamingJackTypes(IntEnum):
31+
# As defined in [Midi10], A.3
32+
JACK_TYPE_UNDEFINED = 0x00
33+
EMBEDDED = 0x01
34+
EXTERNAL = 0x02
35+
36+
37+
# As defined in [Midi10], Table 6-1
38+
StandardMidiStreamingInterfaceDescriptor = DescriptorFormat(
39+
"bLength" / construct.Const(9, construct.Int8ul),
40+
"bDescriptorType" / DescriptorNumber(DescriptorTypes.INTERFACE),
41+
"bInterfaceNumber" / DescriptorField(description="ID of the streaming interface"),
42+
"bAlternateSetting" / DescriptorField(description="alternate setting number for the interface", default=0),
43+
"bNumEndpoints" / DescriptorField(description="Number of data endpoints used (excluding endpoint 0). Can be: 0 (no data endpoint); 1 (data endpoint); 2 (data + explicit feedback endpoint)", default=0),
44+
"bInterfaceClass" / DescriptorNumber(AudioInterfaceClassCode.AUDIO),
45+
"bInterfaceSubClass" / DescriptorNumber(AudioInterfaceSubclassCodes.MIDI_STREAMING),
46+
"bInterfaceProtocol" / DescriptorNumber(0),
47+
"iInterface" / DescriptorField(description="index of a string descriptor describing this interface (0 = unused)", default=0)
48+
)
49+
50+
# As defined in [Midi10], Table 6-2
51+
ClassSpecificMidiStreamingInterfaceHeaderDescriptor = DescriptorFormat(
52+
"bLength" / construct.Const(7, construct.Int8ul),
53+
"bDescriptorType" / DescriptorNumber(AudioClassSpecificDescriptorTypes.CS_INTERFACE),
54+
"bDescriptorSubtype" / DescriptorNumber(AudioClassSpecificACInterfaceDescriptorSubtypes.HEADER),
55+
"bcdADC" / DescriptorField(description="Midi Streaming Class specification release version", default=1.0),
56+
"wTotalLength" / DescriptorField(description="Total number of bytes of the class-specific MIDIStreaming interface descriptor. Includes the combined length of this descriptor header and all Jack and Element descriptors."),
57+
)
58+
59+
# As defined in [Midi10], Table 6-3
60+
MidiInJackDescriptor = DescriptorFormat(
61+
"bLength" / construct.Const(6, construct.Int8ul),
62+
"bDescriptorType" / DescriptorNumber(AudioClassSpecificDescriptorTypes.CS_INTERFACE),
63+
"bDescriptorSubtype" / DescriptorNumber(MidiStreamingInterfaceDescriptorSubtypes.MIDI_IN_JACK),
64+
"bJackType" / DescriptorField(description="see MidiStreamingJackTypes"),
65+
"bJackID" / DescriptorField(description="Constant uniquely identifying the MIDI IN Jack within the USB-MIDI function"),
66+
"iJack" / DescriptorField(description="index of a string descriptor describing this jack (0 = unused)", default=0)
67+
)
68+
69+
# As defined in [Midi10], Table 6-4
70+
MidiOutJackDescriptorHead = DescriptorFormat(
71+
"bLength" / DescriptorField(description="Size of this descriptor, in bytes: 6+2*p"),
72+
"bDescriptorType" / DescriptorNumber(AudioClassSpecificDescriptorTypes.CS_INTERFACE),
73+
"bDescriptorSubtype" / DescriptorNumber(MidiStreamingInterfaceDescriptorSubtypes.MIDI_OUT_JACK),
74+
"bJackType" / DescriptorField(description="see MidiStreamingJackTypes"),
75+
"bJackID" / DescriptorField(description="Constant uniquely identifying the MIDI IN Jack within the USB-MIDI function"),
76+
"bNrInputPins" / DescriptorField(description="Number of Input Pins of this MIDI OUT Jack: p", default=1)
77+
)
78+
79+
MidiOutJackDescriptorElement = DescriptorFormat(
80+
"baSourceID" / construct.Int8ul, # ID of the Entity to which the first Input Pin of this MIDI OUT Jack is connected
81+
"BaSourcePin" / construct.Int8ul, #Output Pin number of the Entity to which the first Input Pin of this MIDI OUT Jack is connected
82+
)
83+
84+
MidiOutJackDescriptorFoot = DescriptorFormat(
85+
"iJack" / DescriptorField(description="index of a string descriptor describing this jack (0 = unused)", default=0)
86+
)
87+
88+
# As defined in [Midi10], Table 6-6
89+
StandardMidiStreamingBulkDataEndpointDescriptor = DescriptorFormat(
90+
"bLength" / construct.Const(9, construct.Int8ul),
91+
"bDescriptorType" / DescriptorNumber(DescriptorTypes.ENDPOINT),
92+
"bEndpointAddress" / DescriptorField(description="The address of the endpoint, use USBDirection.*.from_endpoint_address()"),
93+
"bmAttributes" / DescriptorField(description="D1..0: transfer type (10=bulk), D3..2: synchronization type (00=no sync);", default=USBTransferType.BULK | USBSynchronizationType.NONE | USBUsageType.DATA),
94+
"wMaxPacketSize" / DescriptorField(description="Maximum packet size this endpoint is capable of", default=512),
95+
"bInterval" / DescriptorField(description="Interval for polling endpoint for data transfers expressed in milliseconds. This field is ignored for bulk endpoints. Must be set to 0", default=0),
96+
"bRefresh" / DescriptorField(description="must be set to 0", default=0),
97+
"bSynchAddress" / DescriptorField(description="The address of the endpoint used to communicate synchronization information if required by this endpoint. Must be set to 0", default=0)
98+
)
99+
100+
# As defined in [Midi10], Table 6-7
101+
ClassSpecificMidiStreamingBulkDataEndpointDescriptorHead = DescriptorFormat(
102+
"bLength" / DescriptorField(description="Size of this descriptor, in bytes: 4+n"),
103+
"bDescriptorType" / DescriptorNumber(AudioClassSpecificDescriptorTypes.CS_ENDPOINT),
104+
"bDescriptorSubtype" / DescriptorField(description="see MidiStreamingEndpointDescriptorSubtypes", default=MidiStreamingEndpointDescriptorSubtypes.MS_GENERAL),
105+
"bNumEmbMIDIJack" / DescriptorField(description="Number of Embedded MIDI Jacks: n", default=1)
106+
)
107+
108+
ClassSpecificMidiStreamingBulkDataEndpointDescriptorElement = DescriptorFormat(
109+
"baAssocJackID" / construct.Int8ul # ID of the embedded eack that is associated with this endpoint
110+
)
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#
2+
# This file is part of usb-protocol.
3+
#
4+
"""
5+
Descriptors for USB MIDI Class Devices
6+
7+
[Midi20] refers to "Universal Serial Bus Device Class Definition for MIDI Devices", Release 2.0, May 5, 2020
8+
"""
9+
10+
from enum import IntEnum
11+
12+
from .standard import StandardDescriptorNumbers
13+
14+
15+
class MidiStreamingInterfaceDescriptorTypes(IntEnum):
16+
# As defined in [Midi20], A.1
17+
CS_UNDEFINED = 0x20
18+
CS_DEVICE = 0x21
19+
CS_CONFIGURATION = 0x22
20+
CS_STRING = 0x23
21+
CS_INTERFACE = 0x24
22+
CS_ENDPOINT = 0x25
23+
CS_GR_TRM_BLOCK = 0x26
24+
25+
26+
class MidiStreamingInterfaceDescriptorSubtypes(IntEnum):
27+
# As defined in [Midi20], A.1
28+
MS_DESCRIPTOR_UNDEFINED = 0x00
29+
MS_HEADER = 0x01
30+
MIDI_IN_JACK = 0x02
31+
MIDI_OUT_JACK = 0x03
32+
ELEMENT = 0x04
33+
34+
35+
class MidiStreamingEndpointDescriptorSubtypes(IntEnum):
36+
# As defined in [Midi20], A.2
37+
DESCRIPTOR_UNDEFINED = 0x00
38+
MS_GENERAL = 0x01
39+
MS_GENERAL_2_0 = 0x02
40+
41+
42+
class MidiStreamingInterfaceHeaderClassRevision(IntEnum):
43+
# As defined in [Midi20], A.4
44+
MS_MIDI_1_0 = 0x0100
45+
MS_MIDI_2_0 = 0x0200
46+
47+
48+
class MidiStreamingJackTypes(IntEnum):
49+
# As defined in [Midi20], A.5
50+
JACK_TYPE_UNDEFINED = 0x00
51+
EMBEDDED = 0x01
52+
EXTERNAL = 0x02
53+
54+
55+
# As defined in [Midi20], Table B-5
56+
StandardMidiStreamingInterfaceDescriptor = DescriptorFormat(
57+
"bLength" / construct.Const(9, construct.Int8ul),
58+
"bDescriptorType" / DescriptorNumber(DescriptorTypes.INTERFACE),
59+
"bInterfaceNumber" / DescriptorField(description="ID of the streaming interface"),
60+
"bAlternateSetting" / DescriptorField(description="alternate setting number for the interface", default=0),
61+
"bNumEndpoints" / DescriptorField(description="Number of data endpoints used (excluding endpoint 0). Can be: 0 (no data endpoint); 1 (data endpoint); 2 (data + explicit feedback endpoint)", default=0),
62+
"bInterfaceClass" / DescriptorNumber(AudioInterfaceClassCode.AUDIO),
63+
"bInterfaceSubClass" / DescriptorNumber(AudioInterfaceSubclassCodes.MIDI_STREAMING),
64+
"bInterfaceProtocol" / DescriptorNumber(0),
65+
"iInterface" / DescriptorField(description="index of a string descriptor describing this interface (0 = unused)", default=0)
66+
)
67+
68+
# As defined in [Midi20], Table B-6
69+
ClassSpecificMidiStreamingInterfaceHeaderDescriptor = DescriptorFormat(
70+
"bLength" / construct.Const(7, construct.Int8ul),
71+
"bDescriptorType" / DescriptorNumber(AudioClassSpecificDescriptorTypes.CS_INTERFACE),
72+
"bDescriptorSubtype" / DescriptorNumber(AudioClassSpecificACInterfaceDescriptorSubtypes.HEADER),
73+
"bcdADC" / DescriptorField(description="Midi Streaming Class specification release version", default=1.0),
74+
"wTotalLength" / DescriptorField(description="Total number of bytes of the class-specific MIDIStreaming interface descriptor. Includes the combined length of this descriptor header and all Jack and Element descriptors."),
75+
)
76+
77+
# As defined in [Midi20], Table 5-3
78+
StandardMidiStreamingDataEndpointDescriptor = DescriptorFormat(
79+
"bLength" / construct.Const(7, construct.Int8ul),
80+
"bDescriptorType" / DescriptorNumber(AudioClassSpecificDescriptorTypes.CS_ENDPOINT),
81+
"bEndpointAddress" / DescriptorField(description="endpoint address, use USBDirection.*.from_endpoint_address()"),
82+
"bmAttributes" / DescriptorField(description="endpoint type, see USBTransferType (only NONE, BULK or INTERRUPT allowed)", default=USBTransferType.BULK),
83+
"wMaxPacketSize" / DescriptorField(description="Maximum packet size this endpoint is capable of sending or receiving"),
84+
"bInterval" / DescriptorField(description="Interval for polling endpoint for Interrupt data transfers. For bulk endpoints this field is ignored and must be reset to 0", default=0)
85+
)
86+
87+
88+

0 commit comments

Comments
 (0)