# SPDX-License-Identifier: BSD-3-Clause
#
# This file is part of usb-construct.
#
'''
	Descriptors for USB Audio Class Devices (UAC), Release 2

	[Audio20]  refers to 'Universal Serial Bus Device Class Definition for Audio Devices', Release 2.0, May 31, 2006
	[Frmts20] refers to 'Universal Serial Bus Device Class Definition for Audio Data Formats', Release 2.0, May 31, 2006
	[TermT20] refers to 'Universal Serial Bus Device Class Definition for Terminal Types', Release 2.0, May 31, 2006

	NOTE: This is not complete yet and will be extended as needed
'''

from enum         import IntEnum

import construct

from ..descriptor import DescriptorField, DescriptorFormat, DescriptorNumber
from .standard    import StandardDescriptorNumbers


class AudioInterfaceClassCode(IntEnum):
	# As defined in [Audio20], Table A-4
	AUDIO = 0x01


class AudioFunctionClassCode(IntEnum):
	# As defined in [Audio20], Table A-1
	AUDIO_FUNCTION = AudioInterfaceClassCode.AUDIO


class AudioFunctionSubclassCodes(IntEnum):
	# As defined in [Audio20], Table A-2
	FUNCTION_SUBCLASS_UNDEFINED = 0x00


class AudioInterfaceProtocolCodes(IntEnum):
	# As defined in [Audio20], Table A-6
	INTERFACE_PROTOCOL_UNDEFINED = 0x00
	IP_VERSION_02_00             = 0x20


class AudioFunctionProtocolCodes(IntEnum):
	# As defined in [Audio20], Table A-3
	FUNCTION_PROTOCOL_UNDEFINED = 0x00
	AF_VERSION_02_00 = AudioInterfaceProtocolCodes.IP_VERSION_02_00


class AudioInterfaceSubclassCodes(IntEnum):
	# As defined in [Audio20], Table A-5
	INTERFACE_SUBCLASS_UNDEFINED = 0x00
	AUDIO_CONTROL                = 0x01
	AUDIO_STREAMING              = 0x02
	MIDI_STREAMING               = 0x03


class AudioFunctionCategoryCodes(IntEnum):
	# As defined in [Audio20], Table A-7
	FUNCTION_SUBCLASS_UNDEFINED = 0x00
	DESKTOP_SPEAKER             = 0x01
	HOME_THEATER                = 0x02
	MICROPHONE                  = 0x03
	HEADSET                     = 0x04
	TELEPHONE                   = 0x05
	CONVERTER                   = 0x06
	VOICE_SOUND_RECORDER        = 0x07
	IO_BOX                      = 0x08
	MUSICAL_INSTRUMENT          = 0x09
	PRO_AUDIO                   = 0x0A
	AUDIO_VIDEO                 = 0x0B
	CONTROL_PANEL               = 0x0C
	OTHER                       = 0xFF


class AudioClassSpecificStandardDescriptorNumbers(IntEnum):
	# As defined in [Audio20], Table A-8
	CS_UNDEFINED     = 0x20
	CS_DEVICE        = 0x21
	CS_CONFIGURATION = 0x22
	CS_STRING        = 0x23
	CS_INTERFACE     = 0x24
	CS_ENDPOINT      = 0x25


class AudioClassSpecificACInterfaceDescriptorSubtypes(IntEnum):
	# As defined in [Audio20], Table A-9
	AC_DESCRIPTOR_UNDEFINED  = 0x00
	HEADER                   = 0x01
	INPUT_TERMINAL           = 0x02
	OUTPUT_TERMINAL          = 0x03
	MIXER_UNIT               = 0x04
	SELECTOR_UNIT            = 0x05
	FEATURE_UNIT             = 0x06
	EFFECT_UNIT              = 0x07
	PROCESSING_UNIT          = 0x08
	EXTENSION_UNIT           = 0x09
	CLOCK_SOURCE             = 0x0A
	CLOCK_SELECTOR           = 0x0B
	CLOCK_MULTIPLIER         = 0x0C
	SAMPLE_RATE_CONVERTER    = 0x0D


class AudioClassSpecificASInterfaceDescriptorSubtypes(IntEnum):
	# As defined in [Audio20], Table A-10
	AS_DESCRIPTOR_UNDEFINED = 0x00
	AS_GENERAL              = 0x01
	FORMAT_TYPE             = 0x02
	ENCODER                 = 0x03
	DECODER                 = 0x04


class EffectUnitEffectTypes(IntEnum):
	# As defined in [Audio20], Table A-11
	EFFECT_UNDEFINED        = 0x00
	PARAM_EQ_SECTION_EFFECT = 0x01
	REVERBERATION_EFFECT    = 0x02
	MOD_DELAY_EFFECT        = 0x03
	DYN_RANGE_COMP_EFFECT   = 0x04


class ProcessingUnitProcessTypes(IntEnum):
	# As defined in [Audio20], Table A-12
	PROCESS_UNDEFINED       = 0x00
	UP_DOWNMIX_PROCESS      = 0x01
	DOLBY_PROLOGIC_PROCESS  = 0x02
	STEREO_EXTENDER_PROCESS = 0x03


class AudioClassSpecificEndpointDescriptorSubtypes(IntEnum):
	# As defined in [Audio20], Table A-13
	DESCRIPTOR_UNDEFINED = 0x00
	EP_GENERAL           = 0x01


class AudioClassSpecificRequestCodes(IntEnum):
	# As defined in [Audio20], Table A-14
	REQUEST_CODE_UNDEFINED = 0x00
	CUR                    = 0x01
	RANGE                  = 0x02
	MEM                    = 0x03


class ClockSourceControlSelectors(IntEnum):
	# As defined in [Audio20], Table A-17
	CS_CONTROL_UNDEFINED   = 0x00
	CS_SAM_FREQ_CONTROL    = 0x01
	CS_CLOCK_VALID_CONTROL = 0x02


class ClockSelectorControlSelectors(IntEnum):
	# As defined in [Audio20], Table A-18
	CX_CONTROL_UNDEFINED      = 0x00
	CX_CLOCK_SELECTOR_CONTROL = 0x01


class ClockMultiplierControlSelectors(IntEnum):
	# As defined in [Audio20], Table A-19
	CM_CONTROL_UNDEFINED   = 0x00
	CM_NUMERATOR_CONTROL   = 0x01
	CM_DENOMINATOR_CONTROL = 0x02


class TerminalControlSelectors(IntEnum):
	# As defined in [Audio20], Table A-20
	TE_CONTROL_UNDEFINED    = 0x00
	TE_COPY_PROTECT_CONTROL = 0x01
	TE_CONNECTOR_CONTROL    = 0x02
	TE_OVERLOAD_CONTROL     = 0x03
	TE_CLUSTER_CONTROL      = 0x04
	TE_UNDERFLOW_CONTROL    = 0x05
	TE_OVERFLOW_CONTROL     = 0x06
	TE_LATENCY_CONTROL      = 0x07


class MixerControlSelectors(IntEnum):
	# As defined in [Audio20], Table A-21
	MU_CONTROL_UNDEFINED = 0x00
	MU_MIXER_CONTROL     = 0x01
	MU_CLUSTER_CONTROL   = 0x02
	MU_UNDERFLOW_CONTROL = 0x03
	MU_OVERFLOW_CONTROL  = 0x04
	MU_LATENCY_CONTROL   = 0x05


class SelectorControlSelectors(IntEnum):
	# As defined in [Audio20], Table A-22
	SU_CONTROL_UNDEFINED = 0x00
	SU_SELECTOR_CONTROL  = 0x01
	SU_LATENCY_CONTROL   = 0x02


class FeatureUnitControlSelectors(IntEnum):
	# As defined in [Audio20], Table A-23
	FU_CONTROL_UNDEFINED         = 0x00
	FU_MUTE_CONTROL              = 0x01
	FU_VOLUME_CONTROL            = 0x02
	FU_BASS_CONTROL              = 0x03
	FU_MID_CONTROL               = 0x04
	FU_TREBLE_CONTROL            = 0x05
	FU_GRAPHIC_EQUALIZER_CONTROL = 0x06
	FU_AUTOMATIC_GAIN_CONTROL    = 0x07
	FU_DELAY_CONTROL             = 0x08
	FU_BASS_BOOST_CONTROL        = 0x09
	FU_LOUDNESS_CONTROL          = 0x0A
	FU_INPUT_GAIN_CONTROL        = 0x0B
	FU_INPUT_GAIN_PAD_CONTROL    = 0x0C
	FU_PHASE_INVERTER_CONTROL    = 0x0D
	FU_UNDERFLOW_CONTROL         = 0x0E
	FU_OVERFLOW_CONTROL          = 0x0F
	FU_LATENCY_CONTROL           = 0x10


class ParametricEqualizerSectionEffectUnitControlSelectors(IntEnum):
	# As defined in [Audio20], Table A-24
	PE_CONTROL_UNDEFINED  = 0x00
	PE_ENABLE_CONTROL     = 0x01
	PE_CENTERFREQ_CONTROL = 0x02
	PE_QFACTOR_CONTROL    = 0x03
	PE_GAIN_CONTROL       = 0x04
	PE_UNDERFLOW_CONTROL  = 0x05
	PE_OVERFLOW_CONTROL   = 0x06
	PE_LATENCY_CONTROL    = 0x07


class ReverberationEffectUnitControlSelectors(IntEnum):
	# As defined in [Audio20], Table A-25
	RV_CONTROL_UNDEFINED      = 0x00
	RV_ENABLE_CONTROL         = 0x01
	RV_TYPE_CONTROL           = 0x02
	RV_LEVEL_CONTROL          = 0x03
	RV_TIME_CONTROL           = 0x04
	RV_FEEDBACK_CONTROL       = 0x05
	RV_PREDELAY_CONTROL       = 0x06
	RV_DENSITY_CONTROL        = 0x07
	RV_HIFREQ_ROLLOFF_CONTROL = 0x08
	RV_UNDERFLOW_CONTROL      = 0x09
	RV_OVERFLOW_CONTROL       = 0x0A
	RV_LATENCY_CONTROL        = 0x0B


class ModulationDelayEffectUnitControlSelectors(IntEnum):
	# As defined in [Audio20], Table A-26
	MD_CONTROL_UNDEFINED = 0x00
	MD_ENABLE_CONTROL    = 0x01
	MD_BALANCE_CONTROL   = 0x02
	MD_RATE_CONTROL      = 0x03
	MD_DEPTH_CONTROL     = 0x04
	MD_TIME_CONTROL      = 0x05
	MD_FEEDBACK_CONTROL  = 0x06
	MD_UNDERFLOW_CONTROL = 0x07
	MD_OVERFLOW_CONTROL  = 0x08
	MD_LATENCY_CONTROL   = 0x09


class DynamicRangeCompressorEffectUnitControlSelectors(IntEnum):
	# As defined in [Audio20], Table A-27
	DR_CONTROL_UNDEFINED        = 0x00
	DR_ENABLE_CONTROL           = 0x01
	DR_COMPRESSION_RATE_CONTROL = 0x02
	DR_MAXAMPL_CONTROL          = 0x03
	DR_THRESHOLD_CONTROL        = 0x04
	DR_ATTACK_TIME_CONTROL      = 0x05
	DR_RELEASE_TIME_CONTROL     = 0x06
	DR_UNDERFLOW_CONTROL        = 0x07
	DR_OVERFLOW_CONTROL         = 0x08
	DR_LATENCY_CONTROL          = 0x09


class UpDownMixProcessingUnitControlSelectors(IntEnum):
	# As defined in [Audio20], Table A-28
	UD_CONTROL_UNDEFINED   = 0x00
	UD_ENABLE_CONTROL      = 0x01
	UD_MODE_SELECT_CONTROL = 0x02
	UD_CLUSTER_CONTROL     = 0x03
	UD_UNDERFLOW_CONTROL   = 0x04
	UD_OVERFLOW_CONTROL    = 0x05
	UD_LATENCY_CONTROL     = 0x06


class DolbyProLogicProcessingUnitControlSelectors(IntEnum):
	# As defined in [Audio20], Table A-29
	DP_CONTROL_UNDEFINED   = 0x00
	DP_ENABLE_CONTROL      = 0x01
	DP_MODE_SELECT_CONTROL = 0x02
	DP_CLUSTER_CONTROL     = 0x03
	DP_UNDERFLOW_CONTROL   = 0x04
	DP_OVERFLOW_CONTROL    = 0x05
	DP_LATENCY_CONTROL     = 0x06


class StereoExtenderProcessingUnitControlSelectors(IntEnum):
	# As defined in [Audio20], Table A-30
	ST_EXT_CONTROL_UNDEFINED = 0x00
	ST_EXT_ENABLE_CONTROL    = 0x01
	ST_EXT_UNDERFLOW_CONTROL = 0x03
	ST_EXT_OVERFLOW_CONTROL  = 0x04
	ST_EXT_LATENCY_CONTROL   = 0x05


class ExtensionUnitControlSelectors(IntEnum):
	# As defined in [Audio20], Table A-31
	XU_CONTROL_UNDEFINED = 0x00
	XU_ENABLE_CONTROL    = 0x01
	XU_CLUSTER_CONTROL   = 0x02
	XU_UNDERFLOW_CONTROL = 0x03
	XU_OVERFLOW_CONTROL  = 0x04
	XU_LATENCY_CONTROL   = 0x05


class AudioStreamingInterfaceControlSelectors(IntEnum):
	# As defined in [Audio20], Table A-32
	AS_CONTROL_UNDEFINED         = 0x00
	AS_ACT_ALT_SETTING_CONTROL   = 0x01
	AS_VAL_ALT_SETTINGS_CONTROL  = 0x02
	AS_AUDIO_DATA_FORMAT_CONTROL = 0x03


class EndpointControlSelectors(IntEnum):
	# As defined in [Audio20], Table A-33
	EP_CONTROL_UNDEFINED     = 0x00
	EN_BIT_RATE_CONTROL      = 0x01
	EN_QUALITY_CONTROL       = 0x02
	EN_VBR_CONTROL           = 0x03
	EN_TYPE_CONTROL          = 0x04
	EN_UNDERFLOW_CONTROL     = 0x05
	EN_OVERFLOW_CONTROL      = 0x06
	EN_ENCODER_ERROR_CONTROL = 0x07
	EN_PARAM1_CONTROL        = 0x08
	EN_PARAM2_CONTROL        = 0x09
	EN_PARAM3_CONTROL        = 0x0A
	EN_PARAM4_CONTROL        = 0x0B
	EN_PARAM5_CONTROL        = 0x0C
	EN_PARAM6_CONTROL        = 0x0D
	EN_PARAM7_CONTROL        = 0x0E
	EN_PARAM8_CONTROL        = 0x0F


class USBTerminalTypes(IntEnum):
	# As defined in [TermT20], Table 2-1
	USB_UNDEFINED       = 0x0100
	USB_STREAMING       = 0x0101
	USB_VENDOR_SPECIFIC = 0x01FF


class InputTerminalTypes(IntEnum):
	# As defined in [TermT20], Table 2-2
	INPUT_UNDEFINED             = 0x0200
	MICROPHONE                  = 0x0201
	DESKTOP_MICROPHONE          = 0x0202
	PERSONAL_MICROPHONE         = 0x0203
	OMNI_DIRECTIONAL_MICROPHONE = 0x0204
	MICROPHONE_ARRAY            = 0x0205
	PROCESSING_MICROPHONE_ARRAY = 0x0206


class OutputTerminalTypes(IntEnum):
	# As defined in [TermT20], Table 2-3
	OUTPUT_UNDEFINED              = 0x0300
	SPEAKER                       = 0x0301
	HEADPHONES                    = 0x0302
	DESKTOP_SPEAKER               = 0x0304
	ROOM_SPEAKER                  = 0x0305
	COMMUNICATION_SPEAKER         = 0x0306
	LOW_FREQUENCY_EFFECTS_SPEAKER = 0x0307


class BidirectionalTerminalTypes(IntEnum):
	# As defined in [TermT20], Table 2-4
	BIDIRECTIONAL_UNDEFINED       = 0x0400
	HANDSET                       = 0x0401
	HEADSET                       = 0x0402
	ECHO_SUPPRESSING_SPEAKERPHONE = 0x0404
	ECHO_CANCELING_SPEAKERPHONE   = 0x0405


class TelephonyTerminalTypes(IntEnum):
	# As defined in [TermT20], Table 2-5
	TELEPHONY_UNDEFINED = 0x0500
	PHONE_LINE          = 0x0501
	TELEPHONE           = 0x0502
	DOWN_LINE_PHONE     = 0x0503


class ExternalTerminalTypes(IntEnum):
	# As defined in [TermT20], Table 2-6
	EXTERNAL_UNDEFINED             = 0x0600
	ANALOG_CONNECTOR               = 0x0601
	DIGITAL_AUDIO_INTERFACE        = 0x0602
	LINE_CONNECTOR                 = 0x0603
	SPDIF_INTERFACE                = 0x0605
	IEEE_1394_DA_STREAM            = 0x0606
	IEEE_1394_DV_STREAM_SOUNDTRACK = 0x0607
	ADAT_LIGHTPIPE                 = 0x0608
	TDIF                           = 0x0609
	MADI                           = 0x060A


class EmbeddedFunctionTerminalTypes(IntEnum):
	# As defined in [TermT20], Table 2-7
	EMBEDDED_UNDEFINED       = 0x0700
	EQUALIZATION_NOISE       = 0x0702
	CD_PLAYER                = 0x0703
	DAT                      = 0x0704
	DCC                      = 0x0705
	ANALOG_TAPE              = 0x0707
	PHONOGRAPH               = 0x0708
	VCR_AUDIO                = 0x0709
	VIDEO_DISC_AUDIO         = 0x070A
	DVD_AUDIO                = 0x070B
	TV_TUNER_AUDIO           = 0x070C
	SATELLITE_RECEIVER_AUDIO = 0x070D
	CABLE_TUNER_AUDIO        = 0x070E
	DSS_AUDIO                = 0x070F
	RADIO_RECEIVER           = 0x0710
	RADIO_TRANSMITTER        = 0x0711
	MULTI_TRACK_RECORDER     = 0x0712
	SYNTHESIZER              = 0x0713
	PIANO                    = 0x0714
	GUITAR                   = 0x0715
	DRUMS_RHYTHM             = 0x0716
	OTHER_MUSICAL_INSTRUMENT = 0x0717


class ClockAttributes(IntEnum):
	EXTERNAL_CLOCK              = 0b00
	INTERNAL_FIXED_CLOCK        = 0b01
	INTERNAL_VARIABLE_CLOCK     = 0b10
	INTERNAL_PROGRAMMABLE_CLOCK = 0b11


class ClockFrequencyControl(IntEnum):
	NOT_PRESENT       = 0b00
	HOST_READ_ONLY    = 0b01
	HOST_PROGRAMMABLE = 0b11


class CopyProtectControl(IntEnum):
	NOT_PRESENT       = 0b00
	HOST_READ_ONLY    = 0b10
	HOST_PROGRAMMABLE = 0b11


class ConnectorControl(IntEnum):
	NOT_PRESENT       = (0b00) << 2
	HOST_READ_ONLY    = (0b10) << 2
	HOST_PROGRAMMABLE = (0b11) << 2


class OverloadControl(IntEnum):
	NOT_PRESENT       = (0b00) << 4
	HOST_READ_ONLY    = (0b10) << 4
	HOST_PROGRAMMABLE = (0b11) << 4


class ClusterControl(IntEnum):
	NOT_PRESENT       = (0b00) << 6
	HOST_READ_ONLY    = (0b10) << 6
	HOST_PROGRAMMABLE = (0b11) << 6


class UnderflowControl(IntEnum):
	NOT_PRESENT       = (0b00) << 8
	HOST_READ_ONLY    = (0b10) << 8
	HOST_PROGRAMMABLE = (0b11) << 8


class OverflowControl(IntEnum):
	NOT_PRESENT       = (0b00) << 10
	HOST_READ_ONLY    = (0b10) << 10
	HOST_PROGRAMMABLE = (0b11) << 10


class FormatTypes(IntEnum):
	FORMAT_TYPE_UNDEFINED = 0x00
	FORMAT_TYPE_I         = 0x01
	FORMAT_TYPE_II        = 0x02
	FORMAT_TYPE_III       = 0x03
	FORMAT_TYPE_IV        = 0x04
	EXT_FORMAT_TYPE_I     = 0x81
	EXT_FORMAT_TYPE_II    = 0x82
	EXT_FORMAT_TYPE_III   = 0x83


class TypeIFormats(IntEnum):
	PCM             = (1 << 0)
	PCM8            = (1 << 1)
	IEEE_FLOAT      = (1 << 2)
	ALAW            = (1 << 3)
	MULAW           = (1 << 4)
	TYPE_I_RAW_DATA = (1 << 31)


class TypeIIFormats(IntEnum):
	MPEG             = (1 << 0)
	AC_3             = (1 << 1)
	WMA              = (1 << 2)
	DTS              = (1 << 3)
	TYPE_II_RAW_DATA = (1 << 31)


class TypeIIIFormats(IntEnum):
	IEC61937_AC_3               = (1 << 0)
	IEC61937_MPEG_1_Layer1      = (1 << 1)
	IEC61937_MPEG_1_Layer2_3    = (1 << 2) # same bit!
	IEC61937_MPEG_2_NOEXT       = (1 << 2) # same bit!
	IEC61937_MPEG_2_EXT         = (1 << 3)
	IEC61937_MPEG_2_AAC_ADTS    = (1 << 4)
	IEC61937_MPEG_2_Layer1_LS   = (1 << 5)
	IEC61937_MPEG_2_Layer2_3_LS = (1 << 6)
	IEC61937_DTS_I              = (1 << 7)
	IEC61937_DTS_II             = (1 << 8)
	IEC61937_DTS_III            = (1 << 9)
	IEC61937_ATRAC              = (1 << 10)
	IEC61937_ATRAC2_3           = (1 << 11)
	TYPE_III_WMA                = (1 << 12)


class TypeIVFormats(IntEnum):
	PCM                           = (1 << 0)
	PCM8                          = (1 << 1)
	IEEE_FLOAT                    = (1 << 2)
	ALAW                          = (1 << 3)
	MULAW                         = (1 << 4)
	MPEG                          = (1 << 5)
	AC_3                          = (1 << 6)
	WMA                           = (1 << 7)
	IEC61937_AC_3                 = (1 << 8)
	IEC61937_MPEG_1_Layer1        = (1 << 9)
	IEC61937_MPEG_1_Layer2_3      = (1 << 10) # same bit!
	IEC61937_MPEG_2_NOEXT         = (1 << 10) # same bit!
	IEC61937_MPEG_2_EXT           = (1 << 11)
	IEC61937_MPEG_2_AAC_ADTS      = (1 << 12)
	IEC61937_MPEG_2_Layer1_LS     = (1 << 13)
	IEC61937_MPEG_2_Layer2_3_LS   = (1 << 14)
	IEC61937_DTS_I                = (1 << 15)
	IEC61937_DTS_II               = (1 << 16)
	IEC61937_DTS_III              = (1 << 17)
	IEC61937_ATRAC                = (1 << 18)
	IEC61937_ATRAC2_3             = (1 << 19)
	TYPE_III_WMA                  = (1 << 20)
	IEC60958_PCM                  = (1 << 21)


class SidebandProtocols(IntEnum):
	PROTOCOL_UNDEFINED      = 0x00
	PRES_TIMESTAMP_PROTOCOL = 0x02


# As defined in [Audio20], Table 4-25
AudioControlInterruptEndpointDescriptor = DescriptorFormat(
	'bLength'          / construct.Const(7, construct.Int8ul),
	'bDescriptorType'  / DescriptorNumber(AudioClassSpecificStandardDescriptorNumbers.CS_ENDPOINT),
	'bEndpointAddress' / DescriptorField(description = 'The address of the endpoint, use USBDirection.*.from_endpoint_address()'),
	'bmAttributes'     / DescriptorField(description = 'D1..0: Transfer type (0b11 = Interrupt)', default = 0b11),
	'wMaxPacketSize'   / DescriptorField(
		description = 'Maximum packet size this endpoint is capable of. Used here to pass 6-byte interrupt information.',
		default = 6
	),
	'bInterval'        / DescriptorField(description = 'Interval for polling the Interrupt endpoint')
)

# As defined in [Audio30], Table 4-33
AudioStreamingIsochronousEndpointDescriptor = DescriptorFormat(
	'bLength'          / construct.Const(7, construct.Int8ul),
	'bDescriptorType'  / DescriptorNumber(StandardDescriptorNumbers.ENDPOINT),
	'bEndpointAddress' / DescriptorField(description = 'The address of the endpoint, use USBDirection.*.from_endpoint_address()'),
	'bmAttributes'     / DescriptorField(description =
		'D1..0: transfer type (01 = isochronous); D3..2: synchronization type (01 = asynchronous/10 = adaptive/11 = synchronous); '
		'D5..4: usage (00 = data/10 = feedback)',
		default = 0b000101
	),
	'wMaxPacketSize'   / DescriptorField(
		description = 'Maximum packet size this endpoint is capable of. Used here to pass 6-byte interrupt information.',
		default = 6
	),
	'bInterval'        / DescriptorField(description = 'Interval for polling the Interrupt endpoint')
)

# As defined in [Audio30], Table 4-35
AudioStreamingIsochronousFeedbackEndpointDescriptor = DescriptorFormat(
	'bLength'          / construct.Const(7, construct.Int8ul),
	'bDescriptorType'  / DescriptorNumber(StandardDescriptorNumbers.ENDPOINT),
	'bEndpointAddress' / DescriptorField(description = 'The address of the endpoint, use USBDirection.*.from_endpoint_address()'),
	'bmAttributes'     / DescriptorField(
		description = 'D1..0: transfer type (01 = isochronous); D3..2: synchronization type (00 = no sync); D5..4: usage (10 = feedback)',
		default = 0b00100001
	),
	'wMaxPacketSize'   / DescriptorField(
		description = 'Maximum packet size this endpoint is capable of. Used here to pass 6-byte interrupt information.',
		default = 6
	),
	'bInterval'        / DescriptorField(description = 'Interval for polling the Interrupt endpoint')
)

StandardAudioControlInterfaceDescriptor = DescriptorFormat(
	'bLength'            / construct.Const(9, construct.Int8ul),
	'bDescriptorType'    / DescriptorNumber(StandardDescriptorNumbers.INTERFACE),
	'bInterfaceNumber'   / DescriptorField(description = 'ID of the control interface'),
	'bAlternateSetting'  / DescriptorField(description = 'alternate setting for the interface (must be 0)', default = 0),
	'bNumEndpoints'      / DescriptorField(description =
		'number of endpoints used by this interface (excluding endpoint 0). This number is either 0 or 1 if the optional'
		' interrupt endpoint is present',
		default = 0
	),
	'bInterfaceClass'    / DescriptorNumber(AudioInterfaceClassCode.AUDIO),
	'bInterfaceSubClass' / DescriptorNumber(AudioInterfaceSubclassCodes.AUDIO_CONTROL),
	'bInterfaceProtocol' / DescriptorNumber(AudioInterfaceProtocolCodes.IP_VERSION_02_00),
	'iInterface'         / DescriptorField(description = 'index of string descriptor describing this interface', default = 0),
)

ClassSpecificAudioControlInterfaceDescriptor = DescriptorFormat(
	'bLength'            / construct.Const(9, construct.Int8ul),
	'bDescriptorType'    / DescriptorNumber(AudioClassSpecificStandardDescriptorNumbers.CS_INTERFACE),
	'bDescriptorSubtype' / DescriptorNumber(AudioClassSpecificACInterfaceDescriptorSubtypes.HEADER),
	'bcdADC'             / DescriptorField(description = 'Audio Device Class specification release version', default = 2.0),
	'bCategory'          / DescriptorField(
		description = 'primary use of this audio function (see AudioFunctionCategoryCodes)',
		default = AudioFunctionCategoryCodes.IO_BOX
	),
	'wTotalLength'       / DescriptorField(description =
		'total number of bytes for the class specific audio control interface descriptor; Includes the combined length of this descriptor '
		'header and all Clock Source, Unit and Terminal descriptors'
	),
	'bmControls'         / DescriptorField(description = 'D1..0: latency control', default = 0),
)

ClockSourceDescriptor = DescriptorFormat(
	'bLength'            / construct.Const(8, construct.Int8ul),
	'bDescriptorType'    / DescriptorNumber(AudioClassSpecificStandardDescriptorNumbers.CS_INTERFACE),
	'bDescriptorSubtype' / DescriptorNumber(AudioClassSpecificACInterfaceDescriptorSubtypes.CLOCK_SOURCE),
	'bClockID'           / DescriptorField(description = 'ID of the clock source entity within the audio function (used in requests)'),
	'bmAttributes'       / DescriptorField(description = 'D1..0: clock type (see ClockAttributs)'),
	'bmControls'         / DescriptorField(
		description = 'D1..0: clock frequency control (D0..1: See ClockFrequencyControl, D3..2: clock validity control (0))',
		default = ClockFrequencyControl.NOT_PRESENT
	),
	'bAssocTerminal'     / DescriptorField(description = 'ID of the terminal which is associated with this clock', default = 0),
	'iClockSource'       / DescriptorField(description = 'index of the string description of this clock source', default = 0),
)

InputTerminalDescriptor = DescriptorFormat(
	'bLength'            / construct.Const(17, construct.Int8ul),
	'bDescriptorType'    / DescriptorNumber(AudioClassSpecificStandardDescriptorNumbers.CS_INTERFACE),
	'bDescriptorSubtype' / DescriptorNumber(AudioClassSpecificACInterfaceDescriptorSubtypes.INPUT_TERMINAL),
	'bTerminalID'        / DescriptorField(
		description = 'unique identifier for the terminal within the audio function (used in requests)'
	),
	'wTerminalType'      / DescriptorField(
		description = 'a value of one of the terminal types Enums (eg InputTerminaTypes, ExternalTerminalTypes)'
	),
	'bAssocTerminal'     / DescriptorField(description = 'ID of the associated output terminal', default = 0),
	'bCSourceID'         / DescriptorField(description = 'ID of the clock which is connected to this terminal'),
	'bNrChannels'        / DescriptorField(description = 'number of logical output channels in the terminal’s output channel cluster'),
	'bmChannelConfig'    / DescriptorField(
		description = 'describes the spatial location of the logical channels',
		default = 0,
		length = 4
	),
	'iChannelNames'      / DescriptorField(description = 'string descriptor index of the first logical channel name', default = 0),
	'bmControls'         / DescriptorField(
		description = 'OR combination of CopyProtectControl, ConnectorControl, OverloadControl, ClusterControl, UnderflowControl and OverflowControl', # noqa: E501
		default = 0,
		length = 2
	),
	'iTerminal'          / DescriptorField(description = 'ID of the input terminal string descriptor', default = 0)
)

OutputTerminalDescriptor = DescriptorFormat(
	'bLength'            / construct.Const(12, construct.Int8ul),
	'bDescriptorType'    / DescriptorNumber(AudioClassSpecificStandardDescriptorNumbers.CS_INTERFACE),
	'bDescriptorSubtype' / DescriptorNumber(AudioClassSpecificACInterfaceDescriptorSubtypes.OUTPUT_TERMINAL),
	'bTerminalID'        / DescriptorField(description = 'unique identifier for the terminal within the audio function.'),
	'wTerminalType'      / DescriptorField(
		description = 'a value of one of the terminal types Enums (eg OutputTerminaTypes, ExternalTerminalTypes)'
	),
	'bAssocTerminal'     / DescriptorField(description = 'ID of the associated input terminal', default = 0),
	'bSourceID'          / DescriptorField(description = 'ID of the unit or terminal which is connected to this terminal'),
	'bCSourceID'         / DescriptorField(description = 'ID of the clock which is connected to this terminal'),
	'bmControls'         / DescriptorField(
		description = 'OR combination of  ClockFrequencyControl, CopyProtectControl, ConnectorControl, UnderflowControl>>2 and OverflowControl>>2', # noqa: E501
		default = 0,
		length = 2
	),
	'iTerminal'          / DescriptorField(description = 'ID of the input terminal string descriptor', default = 0)
)

FeatureUnitDescriptorLength = construct.Rebuild(construct.Int8ul, construct.len_(construct.this.bmaControls) * 4 + 6)

FeatureUnitDescriptor = DescriptorFormat(
	'bLength'            / FeatureUnitDescriptorLength,
	'bDescriptorType'    / DescriptorNumber(AudioClassSpecificStandardDescriptorNumbers.CS_INTERFACE),
	'bDescriptorSubtype' / DescriptorNumber(AudioClassSpecificACInterfaceDescriptorSubtypes.FEATURE_UNIT),
	'bUnitID'            / DescriptorField(description = 'unique identifier for the unit within the audio function.'),
	'bSourceID'          / DescriptorField(description = 'ID of the unit or terminal which is connected to this terminal'),
	'bmaControls'        / construct.Array((construct.this.bLength - 6)//4, construct.Int32ul) * 'The control bitmap for all channels',
	'iFeature'           / DescriptorField(description = 'ID of the feature unit string descriptor', default = 0)
)

AudioStreamingInterfaceDescriptor = DescriptorFormat(
	'bLength'            / construct.Const(9, construct.Int8ul),
	'bDescriptorType'    / DescriptorNumber(StandardDescriptorNumbers.INTERFACE),
	'bInterfaceNumber'   / DescriptorField(description = 'ID of the streaming interface'),
	'bAlternateSetting'  / DescriptorField(description = 'alternate setting number for the interface', default = 0),
	'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
	),
	'bInterfaceClass'    / DescriptorNumber(AudioInterfaceClassCode.AUDIO),
	'bInterfaceSubClass' / DescriptorNumber(AudioInterfaceSubclassCodes.AUDIO_STREAMING),
	'bInterfaceProtocol' / DescriptorNumber(AudioInterfaceProtocolCodes.IP_VERSION_02_00),
	'iInterface'         / DescriptorField(
		description = 'index of a string descriptor describing this interface (0 = unused)',
		default = 0
	)
)

ClassSpecificAudioStreamingInterfaceDescriptor = DescriptorFormat(
	'bLength'            / construct.Const(16, construct.Int8ul),
	'bDescriptorType'    / DescriptorNumber(AudioClassSpecificStandardDescriptorNumbers.CS_INTERFACE),
	'bDescriptorSubtype' / DescriptorNumber(AudioClassSpecificASInterfaceDescriptorSubtypes.AS_GENERAL),
	'bTerminalLink'      / DescriptorField(description = 'the ID of the terminal to which this interface is connected'),
	'bmControls'         / DescriptorField(
		description = 'D1..0: active alternate setting control; D3..2: valid alternate settings control; D7..4: reserved, must be 0',
		default = 0
	),
	'bFormatType'        / DescriptorField(description = 'see FormatTypes'),
	'bmFormats'          / DescriptorField(description = 'audio data formats which can be used with this interface', length = 4),
	'bNrChannels'        / DescriptorField(description = 'Number of physical channels in the AS Interface audio channel cluster'),
	'bmChannelConfig'    / DescriptorField(description = 'spatial location of the physical channels', default = 0, length = 4),
	'iChannelNames'      / DescriptorField(
		description = 'ndex of a string descriptor, describing the name of the first physical channel.',
		default = 0
	)
)

TypeIFormatTypeDescriptor = DescriptorFormat(
	'bLength'            / construct.Const(6, construct.Int8ul),
	'bDescriptorType'    / DescriptorNumber(AudioClassSpecificStandardDescriptorNumbers.CS_INTERFACE),
	'bDescriptorSubtype' / DescriptorNumber(AudioClassSpecificASInterfaceDescriptorSubtypes.FORMAT_TYPE),
	'bFormatType'        / DescriptorNumber(FormatTypes.FORMAT_TYPE_I),
	'bSubslotSize'       / DescriptorField(description = 'number of bytes occupied by one audio subslot (1, 2, 3 or 4)'),
	'bBitResolution'     / DescriptorField(description = 'number of effectively used bits out of the available bits in an audio subslot')
)

ExtendedTypeIFormatTypeDescriptor = DescriptorFormat(
	'bLength'            / construct.Const(9, construct.Int8ul),
	'bDescriptorType'    / DescriptorNumber(AudioClassSpecificStandardDescriptorNumbers.CS_INTERFACE),
	'bDescriptorSubtype' / DescriptorNumber(AudioClassSpecificASInterfaceDescriptorSubtypes.FORMAT_TYPE),
	'bFormatType'        / DescriptorNumber(FormatTypes.EXT_FORMAT_TYPE_I),
	'bSubslotSize'       / DescriptorField(description = 'number of bytes occupied by one audio subslot (1, 2, 3 or 4)'),
	'bBitResolution'     / DescriptorField(description = 'number of effectively used bits out of the available bits in an audio subslot'),
	'bHeaderLength'      / DescriptorField(description = 'size of the packet header in bytes'),
	'bControlSize'       / DescriptorField(description = 'size of the control channel words in bytes'),
	'bSideBandProtocol'  / DescriptorField(
		description = 'side band protocol, see SidebandProtocols',
		default = SidebandProtocols.PROTOCOL_UNDEFINED
	)
)

TypeIIFormatTypeDescriptor = DescriptorFormat(
	'bLength'            / construct.Const(8, construct.Int8ul),
	'bDescriptorType'    / DescriptorNumber(AudioClassSpecificStandardDescriptorNumbers.CS_INTERFACE),
	'bDescriptorSubtype' / DescriptorNumber(AudioClassSpecificASInterfaceDescriptorSubtypes.FORMAT_TYPE),
	'bFormatType'        / DescriptorNumber(FormatTypes.FORMAT_TYPE_II),
	'wMaxBitRate'        / DescriptorField(description = 'maximum bitrate of this interface in kbits/s'),
	'wSlotsPerFrame'     / DescriptorField(description = 'number of PCM audio slots in one audio frame')
)

ExtendedTypeIIFormatTypeDescriptor = DescriptorFormat(
	'bLength'            / construct.Const(10, construct.Int8ul),
	'bDescriptorType'    / DescriptorNumber(AudioClassSpecificStandardDescriptorNumbers.CS_INTERFACE),
	'bDescriptorSubtype' / DescriptorNumber(AudioClassSpecificASInterfaceDescriptorSubtypes.FORMAT_TYPE),
	'bFormatType'        / DescriptorNumber(FormatTypes.EXT_FORMAT_TYPE_II),
	'wMaxBitRate'        / DescriptorField(description = 'maximum bitrate of this interface in kbits/s'),
	'wSamplesPerFrame'   / DescriptorField(description = 'number of PCM audio samples in one audio frame'),
	'bHeaderLength'      / DescriptorField(description = 'size of the packet header in bytes'),
	'bSideBandProtocol'  / DescriptorField(
		description = 'side band protocol, see SidebandProtocols',
		default = SidebandProtocols.PROTOCOL_UNDEFINED
	)
)

TypeIIIFormatTypeDescriptor = DescriptorFormat(
	'bLength'            / construct.Const(6, construct.Int8ul),
	'bDescriptorType'    / DescriptorNumber(AudioClassSpecificStandardDescriptorNumbers.CS_INTERFACE),
	'bDescriptorSubtype' / DescriptorNumber(AudioClassSpecificASInterfaceDescriptorSubtypes.FORMAT_TYPE),
	'bFormatType'        / DescriptorNumber(FormatTypes.FORMAT_TYPE_III),
	'bSubslotSize'       / DescriptorField(description = 'number of bytes occupied by one audio subslot (must be 2)', default = 2),
	'bBitResolution'     / DescriptorField(description = 'number of effectively used bits out of the available bits in an audio subslot'),
)

ExtendedTypeIIIFormatTypeDescriptor = DescriptorFormat(
	'bLength'            / construct.Const(8, construct.Int8ul),
	'bDescriptorType'    / DescriptorNumber(AudioClassSpecificStandardDescriptorNumbers.CS_INTERFACE),
	'bDescriptorSubtype' / DescriptorNumber(AudioClassSpecificASInterfaceDescriptorSubtypes.FORMAT_TYPE),
	'bFormatType'        / DescriptorNumber(FormatTypes.EXT_FORMAT_TYPE_III),
	'bSubslotSize'       / DescriptorField(description = 'number of bytes occupied by one audio subslot (must be 2)', default = 2),
	'bBitResolution'     / DescriptorField(description = 'number of effectively used bits out of the available bits in an audio subslot'),
	'bHeaderLength'      / DescriptorField(description = 'size of the packet header in bytes'),
	'bSideBandProtocol'  / DescriptorField(
		description = 'side band protocol, see SidebandProtocols',
		default = SidebandProtocols.PROTOCOL_UNDEFINED
	)
)

ClassSpecificAudioStreamingIsochronousAudioDataEndpointDescriptor = DescriptorFormat(
	'bLength'            / construct.Const(8, construct.Int8ul),
	'bDescriptorType'    / DescriptorNumber(AudioClassSpecificStandardDescriptorNumbers.CS_ENDPOINT),
	'bDescriptorSubtype' / DescriptorNumber(AudioClassSpecificEndpointDescriptorSubtypes.EP_GENERAL),
	'bmAttributes'       / DescriptorField(description = 'bit D7 = 1: only packets with size wMaxPacketSize allowed', default = 0),
	'bmControls'         / DescriptorField(
		description = 'D1..0: pitch control D3..2: data overrun control; D5..4: data underrun control;',
		default = 0
	),
	'bLockDelayUnits'    / DescriptorField(
		description = 'wLockDelay unit: 0: undefined; 1: milliseconds; 2: decoded PCM samples;',
		default = 0
	),
	'wLockDelay'         / DescriptorField(
		description = 'the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units see bLockDelayUnits',
		default = 0
	)
)

# MIDI #

class MidiStreamingGroupTerminalBlockDescriptorSubtypes(IntEnum):
	GR_TRM_BLOCK_UNDEFINED = 0x00
	GR_TRM_BLOCK_HEADER    = 0x01
	GR_TRM_BLOCK           = 0x02

class GroupTerminalBlockType(IntEnum):
	BIDIRECTIONAL = 0x00
	INPUT_ONLY    = 0x01
	OUTPUT_ONLY   = 0x02

class GroupTerminalDefaultMidiProtocol(IntEnum):
	USE_MIDI_CI                      = 0x00
	MIDI_1_0_UP_TO_64_BITS           = 0x01
	MIDI_1_0_UP_TO_64_BITS_AND_JRTS  = 0x02
	MIDI_1_0_UP_TO_128_BITS          = 0x03
	MIDI_1_0_UP_TO_128_BITS_AND_JRTS = 0x04
	MIDI_2_0                         = 0x11
	MIDI_2_0_AND_JRTS                = 0x12

class GroupTerminalNumber(IntEnum):
	GROUP_1  = 0x00
	GROUP_2  = 0x01
	GROUP_3  = 0x02
	GROUP_4  = 0x03
	GROUP_5  = 0x04
	GROUP_6  = 0x05
	GROUP_7  = 0x06
	GROUP_8  = 0x07
	GROUP_9  = 0x08
	GROUP_10 = 0x09
	GROUP_11 = 0x0A
	GROUP_12 = 0x0B
	GROUP_13 = 0x0C
	GROUP_14 = 0x0D
	GROUP_15 = 0x0E
	GROUP_16 = 0x0F
