[USBAUDIO]
[reactos.git] / reactos / sdk / lib / drivers / sound / libusbaudio / format.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: lib/drivers/sound/libusbaudio/format.c
5 * PURPOSE: USB AUDIO Parser
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "priv.h"
10
11 KSDATARANGE StandardDataRange =
12 {
13 {
14 sizeof(KSDATARANGE),
15 0,
16 0,
17 0,
18 {STATIC_KSDATAFORMAT_TYPE_AUDIO},
19 {STATIC_KSDATAFORMAT_SUBTYPE_ANALOG},
20 {STATIC_KSDATAFORMAT_SPECIFIER_NONE}
21 }
22 };
23
24 GUID DataFormatTypeAudio = {STATIC_KSDATAFORMAT_TYPE_AUDIO};
25 GUID DataFormatSubTypePCM = {STATIC_KSDATAFORMAT_SUBTYPE_PCM};
26 GUID DataFormatSpecifierWaveFormat = {STATIC_KSDATAFORMAT_SPECIFIER_WAVEFORMATEX};
27
28 USBAUDIO_STATUS
29 UsbAudio_AssignDataRanges(
30 IN PUSBAUDIO_CONTEXT Context,
31 IN PUCHAR ConfigurationDescriptor,
32 IN ULONG ConfigurationDescriptorSize,
33 IN PKSFILTER_DESCRIPTOR FilterDescriptor,
34 IN PUSB_COMMON_DESCRIPTOR * InterfaceDescriptors,
35 IN ULONG InterfaceCount,
36 IN ULONG InterfaceIndex,
37 IN PULONG TerminalIds)
38 {
39 ULONG Count, Index;
40 USBAUDIO_STATUS Status;
41 PUSB_COMMON_DESCRIPTOR * Descriptors;
42 PUSB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR HeaderDescriptor;
43 PKSDATAFORMAT_WAVEFORMATEX WaveFormat;
44 PKSDATARANGE *DataRanges;
45 PKSPIN_DESCRIPTOR PinDescriptor;
46 PUSB_AUDIO_STREAMING_FORMAT_TYPE_1 FormatType;
47
48 /* count audio descriptors */
49 Status = UsbAudio_CountAudioDescriptors(ConfigurationDescriptor, ConfigurationDescriptorSize, InterfaceDescriptors, InterfaceCount, InterfaceIndex, &Count);
50 if (Status != UA_STATUS_SUCCESS || Count < 2)
51 {
52 /* ignore failure */
53 DPRINT1("[LIBUSBAUDIO] Failed to count descriptors with %x Count %lx for InterfaceIndex %lx InterfaceCount %lx\n", Status, Count, InterfaceIndex, InterfaceCount);
54 return UA_STATUS_SUCCESS;
55 }
56
57 /* create descriptor array */
58 Status = UsbAudio_CreateAudioDescriptorArray(Context, ConfigurationDescriptor, ConfigurationDescriptorSize, InterfaceDescriptors, InterfaceCount, InterfaceIndex, Count, &Descriptors);
59 if (Status != UA_STATUS_SUCCESS)
60 {
61 /* ignore failure */
62 DPRINT1("[LIBUSBAUDIO] Failed to create audio descriptor array Count %lx Status %x\n", Count, Status);
63 return UA_STATUS_SUCCESS;
64 }
65
66 /* get header */
67 HeaderDescriptor = (PUSB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR)Descriptors[0];
68 if (!HeaderDescriptor || HeaderDescriptor->bDescriptorType != USB_AUDIO_STREAMING_INTERFACE_INTERFACE_DESCRIPTOR_TYPE ||
69 HeaderDescriptor->bDescriptorSubtype != 0x01)
70 {
71 /* header missing or mis-aligned */
72 DPRINT1("[LIBUSBAUDIO] Failed to retrieve audio header %p\n", HeaderDescriptor);
73 return UA_STATUS_SUCCESS;
74 }
75
76 /* FIXME: only PCM is supported */
77 if (HeaderDescriptor->wFormatTag != WAVE_FORMAT_PCM)
78 {
79 /* not supported */
80 DPRINT1("[LIBUSBAUDIO] Only PCM is currenly supported wFormatTag %x\n", HTONS(HeaderDescriptor->wFormatTag));
81 return UA_STATUS_SUCCESS;
82 }
83
84 /* check format descriptor */
85 FormatType = (PUSB_AUDIO_STREAMING_FORMAT_TYPE_1)Descriptors[1];
86 if (!FormatType || FormatType->bDescriptorType != USB_AUDIO_STREAMING_INTERFACE_INTERFACE_DESCRIPTOR_TYPE ||
87 FormatType->bDescriptorSubtype != 0x02 || FormatType->bFormatType != 0x01 || FormatType->bSamFreqType != 1)
88 {
89 /* unexpected format descriptor */
90 DPRINT1("[LIBUSBAUDIO] Unexpected format descriptor %p bDescriptorType %x bDescriptorSubtype %x bFormatType %x bSamFreqType %x\n", FormatType,
91 FormatType->bDescriptorType, FormatType->bDescriptorSubtype, FormatType->bFormatType, FormatType->bSamFreqType);
92 return UA_STATUS_SUCCESS;
93 }
94
95
96 /* now search pin position */
97 for(Index = 0; Index < FilterDescriptor->PinDescriptorsCount; Index++)
98 {
99 //DPRINT("bTerminalLink %x Ids %lx\n", HeaderDescriptor->bTerminalLink, TerminalIds[Index]);
100 if (HeaderDescriptor->bTerminalLink == TerminalIds[Index])
101 {
102 /* alloc wave format */
103 WaveFormat = (PKSDATAFORMAT_WAVEFORMATEX)Context->Alloc(sizeof(KSDATAFORMAT_WAVEFORMATEX));
104 if (!WaveFormat)
105 return UA_STATUS_NO_MEMORY;
106
107 /* init wave format */
108 WaveFormat->WaveFormatEx.cbSize = sizeof(WAVEFORMATEX);
109 WaveFormat->WaveFormatEx.wFormatTag = WAVE_FORMAT_PCM;
110 WaveFormat->WaveFormatEx.nChannels = FormatType->bNrChannels;
111 WaveFormat->WaveFormatEx.wBitsPerSample = FormatType->bBitResolution;
112 WaveFormat->WaveFormatEx.nSamplesPerSec = ((FormatType->tSamFreq[2] & 0xFF) << 16) | ((FormatType->tSamFreq[1] & 0xFF)<< 8) | (FormatType->tSamFreq[0] & 0xFF);
113 WaveFormat->WaveFormatEx.nBlockAlign = (WaveFormat->WaveFormatEx.nChannels * WaveFormat->WaveFormatEx.wBitsPerSample) / 8;
114 WaveFormat->WaveFormatEx.nAvgBytesPerSec = WaveFormat->WaveFormatEx.nSamplesPerSec * WaveFormat->WaveFormatEx.nBlockAlign;
115
116 /* FIXME apply padding */
117 WaveFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT_WAVEFORMATEX);
118 Context->Copy(&WaveFormat->DataFormat.MajorFormat, &DataFormatTypeAudio, sizeof(GUID));
119 Context->Copy(&WaveFormat->DataFormat.SubFormat, &DataFormatSubTypePCM, sizeof(GUID));
120 Context->Copy(&WaveFormat->DataFormat.Specifier, &DataFormatSpecifierWaveFormat, sizeof(GUID));
121
122 //C_ASSERT(sizeof(WAVEFORMATEX) + sizeof(KSDATAFORMAT) == 82);
123
124 /* get corresponding pin descriptor */
125 PinDescriptor = (PKSPIN_DESCRIPTOR)&FilterDescriptor->PinDescriptors[Index].PinDescriptor;
126
127 /* alloc data range */
128 DataRanges = (PKSDATARANGE*)Context->Alloc(sizeof(PKSDATARANGE) * (PinDescriptor->DataRangesCount+1));
129 if (!DataRanges)
130 {
131 Context->Free(WaveFormat);
132 return UA_STATUS_NO_MEMORY;
133 }
134
135 if (PinDescriptor->DataRangesCount)
136 {
137 /* copy old range */
138 Context->Copy(DataRanges, (PVOID)PinDescriptor->DataRanges, sizeof(PKSDATARANGE) * PinDescriptor->DataRangesCount);
139
140 /* free old range */
141 Context->Free((PVOID)PinDescriptor->DataRanges);
142 }
143
144 /* assign new range */
145 PinDescriptor->DataRanges = DataRanges;
146 DataRanges[PinDescriptor->DataRangesCount] = (PKSDATARANGE)WaveFormat;
147 PinDescriptor->DataRangesCount++;
148 return UA_STATUS_SUCCESS;
149 }
150
151 }
152 return UA_STATUS_SUCCESS;
153 }
154
155