478 lines
13 KiB
Objective-C
478 lines
13 KiB
Objective-C
/*
|
|
* Copyright © 1998-2012 Apple Inc. All rights reserved.
|
|
*
|
|
* @APPLE_LICENSE_HEADER_START@
|
|
*
|
|
* This file contains Original Code and/or Modifications of Original Code
|
|
* as defined in and that are subject to the Apple Public Source License
|
|
* Version 2.0 (the 'License'). You may not use this file except in
|
|
* compliance with the License. Please obtain a copy of the License at
|
|
* http://www.opensource.apple.com/apsl/ and read it before using this
|
|
* file.
|
|
*
|
|
* The Original Code and all software distributed under the License are
|
|
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
|
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
|
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
|
* Please see the License for the specific language governing rights and
|
|
* limitations under the License.
|
|
*
|
|
* @APPLE_LICENSE_HEADER_END@
|
|
*/
|
|
|
|
|
|
#import <Foundation/Foundation.h>
|
|
#import "DescriptorDecoder.h"
|
|
#import "BusProberSharedFunctions.h"
|
|
#import "BusProbeDevice.h"
|
|
|
|
#define kUSBAudioInterfaceDesc (0x24)
|
|
#define kUSBAudioEndPointDesc (0x25)
|
|
|
|
// <rdar://10009579>
|
|
#define kUSBAudioDescriptorBytesPerLine 16
|
|
// String buffer size to log desciptor:
|
|
// Each byte in descriptor requires 3 chars: 2 for nibbles + a space char
|
|
// One byte for null terminator
|
|
#define kUSBAudioMaxDescriptorStringSize ( ( kUSBAudioDescriptorBytesPerLine * 3 ) + 1 ) * sizeof ( char )
|
|
|
|
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 descLen;
|
|
UInt8 descType;
|
|
UInt8 descSubType;
|
|
UInt8 descContents[32];
|
|
} GenericAudioDescriptor, *GenericAudioDescriptorPtr;
|
|
#pragma options align=reset
|
|
|
|
enum AudioClassSpecific {
|
|
ACS_HEADER = 0x01,
|
|
ACS_INPUT_TERMINAL = 0x02,
|
|
ACS_OUTPUT_TERMINAL = 0x03,
|
|
ACS_MIXER_UNIT = 0x04,
|
|
ACS_SELECTOR_UNIT = 0x05,
|
|
ACS_FEATURE_UNIT = 0x06,
|
|
ACS_PROCESSING_UNIT = 0x07,
|
|
ACS_EXTENSION_UNIT = 0x08,
|
|
ACS_UNDEFINED = 0x20,
|
|
ACS_DEVICE = 0x21,
|
|
ACS_CONFIGURATION = 0x22,
|
|
ACS_STRING = 0x23,
|
|
ACS_INTERFACE = 0x24,
|
|
ACS_ENDPOINT = 0x25,
|
|
ACS_FORMAT_TYPE = 0x02,
|
|
ACS_FORMAT_SPECIFIC = 0x03,
|
|
ACS_FORMAT_TYPE_UNDEF = 0x00,
|
|
ACS_FORMAT_TYPE_I = 0x01,
|
|
ACS_FORMAT_TYPE_II = 0x02,
|
|
ACS_FORMAT_TYPE_III = 0x03,
|
|
ACS_ASTREAM_UNDEF = 0x00,
|
|
ACS_ASTREAM_GENERAL = 0x01,
|
|
ACS_ASTREAM_TYPE = 0x02,
|
|
ACS_ASTREAM_SPECIFIC = 0x03,
|
|
AC_CONTROL_SUBCLASS = 0x01,
|
|
AC_STREAM_SUBCLASS = 0x02,
|
|
AC_MIDI_SUBCLASS = 0x03
|
|
};
|
|
|
|
// Standard Audio Stream Isoc Audio Data Endpoint Descriptor
|
|
// Refer to USB Audio Class Devices pp. 61-62.
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 descLen;
|
|
UInt8 descType;
|
|
UInt8 asAddress;
|
|
UInt8 asAttributes;
|
|
UInt16 asMaxPacketSize;
|
|
UInt8 asInterval;
|
|
UInt8 asRefresh;
|
|
UInt8 asSynchAddress;
|
|
} AS_IsocEndPtDesc, *AS_IsocEndPtDescPtr;
|
|
#pragma options align=reset
|
|
|
|
// Class Specific Audio Stream Isoc Audio Data Endpoint Descriptor
|
|
// Refer to USB Audio Class Devices pp. 62-63.
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 descLen;
|
|
UInt8 descType;
|
|
UInt8 descSubtype;
|
|
UInt8 asAttributes;
|
|
UInt8 bLockDelayUnits;
|
|
UInt16 wLockDelay;
|
|
} CSAS_IsocEndPtDesc, *CSAS_IsocEndPtDescPtr;
|
|
#pragma options align=reset
|
|
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 descLen;
|
|
UInt8 descType;
|
|
UInt8 descSubType;
|
|
UInt16 descVersNum;
|
|
UInt16 descTotalLength;
|
|
UInt8 descAICNum; /* Number of elements in the Audio Interface Collection. */
|
|
UInt8 descInterfaceNum[1];
|
|
} AudioCtrlHdrDescriptor, *AudioCtrlHdrDescriptorPtr;
|
|
#pragma options align=reset
|
|
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 descLen;
|
|
UInt8 descType;
|
|
UInt8 descSubType;
|
|
UInt8 descTermID;
|
|
UInt16 descTermType;
|
|
UInt8 descOutTermID;
|
|
UInt8 descNumChannels;
|
|
UInt16 descChannelConfig;
|
|
UInt8 descChannelNames;
|
|
UInt8 descTermName;
|
|
} AudioCtrlInTermDescriptor, *AudioCtrlInTermDescriptorPtr;
|
|
#pragma options align=reset
|
|
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 descLen;
|
|
UInt8 descType;
|
|
UInt8 descSubType;
|
|
UInt8 descTermID;
|
|
UInt16 descTermType;
|
|
UInt8 descInTermID;
|
|
UInt8 descSourceID;
|
|
UInt8 descTermName;
|
|
} AudioCtrlOutTermDescriptor, *AudioCtrlOutTermDescriptorPtr;
|
|
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 descLen;
|
|
UInt8 descType;
|
|
UInt8 descSubType;
|
|
UInt8 descUnitID;
|
|
UInt8 descNumPins;
|
|
UInt8 descSourcePID[1];
|
|
} AudioCtrlMixerDescriptor, *AudioCtrlMixerDescriptorPtr;
|
|
#pragma options align=reset
|
|
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 descLen;
|
|
UInt8 descType;
|
|
UInt8 descSubType;
|
|
UInt8 descUnitID;
|
|
UInt8 descNumPins;
|
|
UInt8 descSourcePID[1];
|
|
} AudioCtrlSelectorDescriptor, *AudioCtrlSelectorDescriptorPtr;
|
|
#pragma options align=reset
|
|
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 descLen;
|
|
UInt8 descType;
|
|
UInt8 descSubType;
|
|
UInt8 descUnitID;
|
|
UInt8 descSourceID;
|
|
UInt8 descCtrlSize;
|
|
UInt8 descControls[1];
|
|
} AudioCtrlFeatureDescriptor, *AudioCtrlFeatureDescriptorPtr;
|
|
#pragma options align=reset
|
|
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 descLen;
|
|
UInt8 descType;
|
|
UInt8 descSubType;
|
|
UInt8 descUnitID;
|
|
UInt16 descExtensionCode;
|
|
UInt8 descNumPins;
|
|
UInt8 descSourcePID[1];
|
|
} AudioCtrlExtDescriptor, *AudioCtrlExtDescriptorPtr;
|
|
#pragma options align=reset
|
|
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 descLen;
|
|
UInt8 descType;
|
|
UInt8 descSubType;
|
|
UInt8 terminalID;
|
|
UInt8 delay;
|
|
UInt16 formatTag;
|
|
} CSAS_InterfaceDescriptor, *CSAS_InterfaceDescriptorPtr;
|
|
#pragma options align=reset
|
|
|
|
#pragma pack(1)
|
|
typedef struct acProcessingDescriptor{ // ¥¥¥¥ WARNING ¥¥¥ ADDING ELEMENTS WILL KILL CODE!!!
|
|
UInt8 descLen; // size of this descriptor in bytes
|
|
UInt8 bDescriptorType; // const CS_INTERFACE
|
|
UInt8 bDescriptorSubtype; // const FEATURE_UNIT
|
|
UInt8 bUnitID;
|
|
UInt16 wProcessType;
|
|
UInt8 bNrPins;
|
|
UInt8 bSourceID;
|
|
}acProcessingDescriptor;
|
|
#pragma options align=reset
|
|
typedef acProcessingDescriptor *acProcessingDescriptorPtr;
|
|
|
|
#pragma pack(1)
|
|
typedef struct acProcessingDescriptorCont{
|
|
UInt8 bNrChannels;
|
|
UInt16 wChannelConfig;
|
|
UInt8 iChannelNames;
|
|
UInt8 bControlSize;
|
|
UInt16 bmControls;
|
|
UInt8 iProcessing;
|
|
}acProcessingDescriptorCont;
|
|
#pragma options align=reset
|
|
typedef acProcessingDescriptorCont *acProcessingDescriptorContPtr;
|
|
|
|
/* Refer to USB PDF files for Frmts10.pdf pp. 10 for Type I Format Descriptor. */
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 byte1;
|
|
UInt8 byte2;
|
|
UInt8 byte3;
|
|
} CSAS_Freq3, *CSAS_Freq3Ptr;
|
|
#pragma options align=reset
|
|
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
CSAS_Freq3 lowerSamFreq;
|
|
CSAS_Freq3 upperSamFreq;
|
|
} CSAS_ContTbl, *CSAS_ContTblPtr;
|
|
#pragma options align=reset
|
|
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
CSAS_Freq3 samFreq[1];
|
|
} CSAS_DiscreteTbl, *CSAS_DiscreteTblPtr;
|
|
#pragma options align=reset
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 descLen;
|
|
UInt8 descType;
|
|
UInt8 descSubType;
|
|
UInt8 formatType;
|
|
UInt8 numberOfChannels;
|
|
UInt8 subFrameSize;
|
|
UInt8 bitResolution;
|
|
UInt8 sampleFreqType;
|
|
union {
|
|
CSAS_ContTbl cont;
|
|
CSAS_DiscreteTbl discrete;
|
|
} sampleFreqTables;
|
|
} CSAS_FormatTypeIDesc, *CSAS_FormatTypeIDescPtr;
|
|
#pragma options align=reset
|
|
|
|
enum Audio20ClassSpecific {
|
|
AC20S_HEADER = 0x01,
|
|
AC20S_INPUT_TERMINAL = 0x02,
|
|
AC20S_OUTPUT_TERMINAL = 0x03,
|
|
AC20S_MIXER_UNIT = 0x04,
|
|
AC20S_SELECTOR_UNIT = 0x05,
|
|
AC20S_FEATURE_UNIT = 0x06,
|
|
AC20S_EFFECT_UNIT = 0x07,
|
|
AC20S_PROCESSING_UNIT = 0x08,
|
|
AC20S_EXTENSION_UNIT = 0x09,
|
|
AC20S_CLOCK_SOURCE = 0x0A,
|
|
AC20S_CLOCK_SELECTOR = 0x0B,
|
|
AC20S_CLOCK_MULTIPLIER = 0x0C,
|
|
AC20S_SAMPLE_RATE_CONVERTER = 0x0D,
|
|
|
|
AC20S_FORMAT_TYPE_IV = 0x04,
|
|
AC20S_EXTENDED_FORMAT_TYPE_I = 0x81,
|
|
AC20S_EXTENDED_FORMAT_TYPE_II = 0x82,
|
|
AC20S_EXTENDED_FORMAT_TYPE_III = 0x83
|
|
|
|
};
|
|
|
|
// Standard Audio Stream Isoc Audio Data Endpoint Descriptor
|
|
// Refer to USB Audio Class Devices pp. 61-62.
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 descLen;
|
|
UInt8 descType;
|
|
UInt8 asAddress;
|
|
UInt8 asAttributes;
|
|
UInt16 asMaxPacketSize;
|
|
UInt8 asInterval;
|
|
} AS20_IsocEndPtDesc, *AS20_IsocEndPtDescPtr;
|
|
#pragma options align=reset
|
|
|
|
// Class Specific Audio Stream Isoc Audio Data Endpoint Descriptor
|
|
// Refer to USB Audio Class Devices pp. 62-63.
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 descLen;
|
|
UInt8 descType;
|
|
UInt8 descSubtype;
|
|
UInt8 asAttributes;
|
|
UInt8 bmControls;
|
|
UInt8 bLockDelayUnits;
|
|
UInt16 wLockDelay;
|
|
} CSA20S_IsocEndPtDesc, *CSAS20_IsocEndPtDescPtr;
|
|
#pragma options align=reset
|
|
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 descLen;
|
|
UInt8 descType;
|
|
UInt8 descSubType;
|
|
UInt16 descVersNum;
|
|
UInt8 descCategory;
|
|
UInt16 descTotalLength;
|
|
UInt8 descbmControls;
|
|
} Audio20CtrlHdrDescriptor, *Audio20CtrlHdrDescriptorPtr;
|
|
#pragma options align=reset
|
|
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 descLen;
|
|
UInt8 descType;
|
|
UInt8 descSubType;
|
|
UInt8 descTermID;
|
|
UInt16 descTermType;
|
|
UInt8 descOutTermID;
|
|
UInt8 descClockSourceID;
|
|
UInt8 descNumChannels;
|
|
UInt32 descChannelConfig;
|
|
UInt8 descChannelNames;
|
|
UInt16 descbmControls;
|
|
UInt8 descTermName;
|
|
} Audio20CtrlInTermDescriptor, *Audio20CtrlInTermDescriptorPtr;
|
|
#pragma options align=reset
|
|
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 descLen;
|
|
UInt8 descType;
|
|
UInt8 descSubType;
|
|
UInt8 descClockID;
|
|
UInt8 descAttributes;
|
|
UInt8 descbmControls;
|
|
UInt8 descAssocTermID;
|
|
UInt8 desciClockSourceName;
|
|
} Audio20ClockSourceDescriptor, *Audio20ClockSourceDescriptorPtr;
|
|
#pragma options align=reset
|
|
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 descLen;
|
|
UInt8 descType;
|
|
UInt8 descSubType;
|
|
UInt8 descClockID;
|
|
UInt8 descNumPins;
|
|
UInt8 descClockPID[1];
|
|
} Audio20ClockSelectorDescriptor, *Audio20ClockSelectorDescriptorPtr;
|
|
#pragma options align=reset
|
|
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 descLen;
|
|
UInt8 descType;
|
|
UInt8 descSubType;
|
|
UInt8 descClockID;
|
|
UInt8 descClockSourceID;
|
|
UInt8 descbmControls;
|
|
UInt8 desciClockMultiplierName;
|
|
} Audio20ClockMultiplierDescriptor, *Audio20ClockMultiplierDescriptorPtr;
|
|
#pragma options align=reset
|
|
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 descLen;
|
|
UInt8 descType;
|
|
UInt8 descSubType;
|
|
UInt8 descTermID;
|
|
UInt16 descTermType;
|
|
UInt8 descInTermID;
|
|
UInt8 descSourceID;
|
|
UInt8 descClockSourceID;
|
|
UInt16 bmControls;
|
|
UInt8 descTermName;
|
|
} Audio20CtrlOutTermDescriptor, *Audio20CtrlOutTermDescriptorPtr;
|
|
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 descLen;
|
|
UInt8 descType;
|
|
UInt8 descSubType;
|
|
UInt8 descUnitID;
|
|
UInt8 descSourceID;
|
|
UInt8 descControls[1];
|
|
} Audio20CtrlFeatureDescriptor, *Audio20CtrlFeatureDescriptorPtr;
|
|
#pragma options align=reset
|
|
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 descLen;
|
|
UInt8 descType;
|
|
UInt8 descSubType;
|
|
UInt8 descUnitID;
|
|
UInt16 descExtensionCode;
|
|
UInt8 descNumPins;
|
|
UInt8 descSourcePID[1];
|
|
} Audio20CtrlExtDescriptor, *Audio20CtrlExtDescriptorPtr;
|
|
#pragma options align=reset
|
|
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 descLen;
|
|
UInt8 descType;
|
|
UInt8 descSubType;
|
|
UInt8 terminalID;
|
|
UInt8 bmControls;
|
|
UInt8 formatType;
|
|
UInt32 bmFormats;
|
|
UInt8 numChannels;
|
|
UInt32 channelConfig;
|
|
UInt8 channelNames;
|
|
} CS20AS_InterfaceDescriptor, *CS20AS_InterfaceDescriptorPtr;
|
|
#pragma options align=reset
|
|
|
|
#pragma pack(1)
|
|
typedef struct ac20ProcessingDescriptor{ // ¥¥¥¥ WARNING ¥¥¥ ADDING ELEMENTS WILL KILL CODE!!!
|
|
UInt8 descLen; // size of this descriptor in bytes
|
|
UInt8 bDescriptorType; // const CS_INTERFACE
|
|
UInt8 bDescriptorSubtype; // const FEATURE_UNIT
|
|
UInt8 bUnitID;
|
|
UInt16 wProcessType;
|
|
UInt8 bNrPins;
|
|
UInt8 bSourceID[1];
|
|
}ac20ProcessingDescriptor, *ac20ProcessingDescriptorPtr;
|
|
#pragma options align=reset
|
|
typedef ac20ProcessingDescriptor *a20cProcessingDescriptorPtr;
|
|
|
|
#pragma pack(1)
|
|
typedef struct ac20ProcessingDescriptorCont{
|
|
UInt8 bNrChannels;
|
|
UInt32 wChannelConfig;
|
|
UInt8 iChannelNames;
|
|
UInt16 bmControls;
|
|
UInt8 iProcessing;
|
|
}ac20ProcessingDescriptorCont;
|
|
#pragma options align=reset
|
|
typedef ac20ProcessingDescriptorCont *ac20ProcessingDescriptorContPtr;
|
|
|
|
/* Refer to USB PDF files for Frmts10.pdf pp. 10 for Type I Format Descriptor. */
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UInt8 descLen;
|
|
UInt8 descType;
|
|
UInt8 descSubType;
|
|
UInt8 formatType;
|
|
UInt8 slotSize;
|
|
UInt8 bitResolution;
|
|
} CS20AS_FormatTypeIDesc, *CS20AS_FormatTypeIDescPtr;
|
|
#pragma options align=reset
|
|
|
|
@interface DecodeAudioInterfaceDescriptor : NSObject {
|
|
|
|
}
|
|
|
|
+(void)decodeBytes:(UInt8 *)descriptor forDevice:(BusProbeDevice *)thisDevice;
|
|
void decodeBytes10( UInt8 *descriptor, BusProbeDevice * thisDevice );
|
|
void decodeBytes20( UInt8 *descriptor, BusProbeDevice * thisDevice );
|
|
|
|
@end
|