reactos/lib/drivers/sound/libusbaudio/format.c
Amine Khaldi 527f2f9057 [SHELL/EXPERIMENTS]
* Create a branch for some evul shell experiments.

svn path=/branches/shell-experiments/; revision=61927
2014-02-02 19:37:27 +00:00

156 lines
6.5 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: lib/drivers/sound/libusbaudio/format.c
* PURPOSE: USB AUDIO Parser
* PROGRAMMER: Johannes Anderwald
*/
#include "priv.h"
KSDATARANGE StandardDataRange =
{
{
sizeof(KSDATARANGE),
0,
0,
0,
{STATIC_KSDATAFORMAT_TYPE_AUDIO},
{STATIC_KSDATAFORMAT_SUBTYPE_ANALOG},
{STATIC_KSDATAFORMAT_SPECIFIER_NONE}
}
};
GUID DataFormatTypeAudio = {STATIC_KSDATAFORMAT_TYPE_AUDIO};
GUID DataFormatSubTypePCM = {STATIC_KSDATAFORMAT_SUBTYPE_PCM};
GUID DataFormatSpecifierWaveFormat = {STATIC_KSDATAFORMAT_SPECIFIER_WAVEFORMATEX};
USBAUDIO_STATUS
UsbAudio_AssignDataRanges(
IN PUSBAUDIO_CONTEXT Context,
IN PUCHAR ConfigurationDescriptor,
IN ULONG ConfigurationDescriptorSize,
IN PKSFILTER_DESCRIPTOR FilterDescriptor,
IN PUSB_COMMON_DESCRIPTOR * InterfaceDescriptors,
IN ULONG InterfaceCount,
IN ULONG InterfaceIndex,
IN PULONG TerminalIds)
{
ULONG Count, Index;
USBAUDIO_STATUS Status;
PUSB_COMMON_DESCRIPTOR * Descriptors;
PUSB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR HeaderDescriptor;
PKSDATAFORMAT_WAVEFORMATEX WaveFormat;
PKSDATARANGE *DataRanges;
PKSPIN_DESCRIPTOR PinDescriptor;
PUSB_AUDIO_STREAMING_FORMAT_TYPE_1 FormatType;
/* count audio descriptors */
Status = UsbAudio_CountAudioDescriptors(ConfigurationDescriptor, ConfigurationDescriptorSize, InterfaceDescriptors, InterfaceCount, InterfaceIndex, &Count);
if (Status != UA_STATUS_SUCCESS || Count < 2)
{
/* ignore failure */
DPRINT1("[LIBUSBAUDIO] Failed to count descriptors with %x Count %lx for InterfaceIndex %lx InterfaceCount %lx\n", Status, Count, InterfaceIndex, InterfaceCount);
return UA_STATUS_SUCCESS;
}
/* create descriptor array */
Status = UsbAudio_CreateAudioDescriptorArray(Context, ConfigurationDescriptor, ConfigurationDescriptorSize, InterfaceDescriptors, InterfaceCount, InterfaceIndex, Count, &Descriptors);
if (Status != UA_STATUS_SUCCESS)
{
/* ignore failure */
DPRINT1("[LIBUSBAUDIO] Failed to create audio descriptor array Count %lx Status %x\n", Count, Status);
return UA_STATUS_SUCCESS;
}
/* get header */
HeaderDescriptor = (PUSB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR)Descriptors[0];
if (!HeaderDescriptor || HeaderDescriptor->bDescriptorType != USB_AUDIO_STREAMING_INTERFACE_INTERFACE_DESCRIPTOR_TYPE ||
HeaderDescriptor->bDescriptorSubtype != 0x01)
{
/* header missing or mis-aligned */
DPRINT1("[LIBUSBAUDIO] Failed to retrieve audio header %p\n", HeaderDescriptor);
return UA_STATUS_SUCCESS;
}
/* FIXME: only PCM is supported */
if (HeaderDescriptor->wFormatTag != WAVE_FORMAT_PCM)
{
/* not supported */
DPRINT1("[LIBUSBAUDIO] Only PCM is currenly supported wFormatTag %x\n", HTONS(HeaderDescriptor->wFormatTag));
return UA_STATUS_SUCCESS;
}
/* check format descriptor */
FormatType = (PUSB_AUDIO_STREAMING_FORMAT_TYPE_1)Descriptors[1];
if (!FormatType || FormatType->bDescriptorType != USB_AUDIO_STREAMING_INTERFACE_INTERFACE_DESCRIPTOR_TYPE ||
FormatType->bDescriptorSubtype != 0x02 || FormatType->bFormatType != 0x01 || FormatType->bSamFreqType != 1)
{
/* unexpected format descriptor */
DPRINT1("[LIBUSBAUDIO] Unexpected format descriptor %p bDescriptorType %x bDescriptorSubtype %x bFormatType %x bSamFreqType %x\n", FormatType,
FormatType->bDescriptorType, FormatType->bDescriptorSubtype, FormatType->bFormatType, FormatType->bSamFreqType);
return UA_STATUS_SUCCESS;
}
/* now search pin position */
for(Index = 0; Index < FilterDescriptor->PinDescriptorsCount; Index++)
{
//DPRINT("bTerminalLink %x Ids %lx\n", HeaderDescriptor->bTerminalLink, TerminalIds[Index]);
if (HeaderDescriptor->bTerminalLink == TerminalIds[Index])
{
/* alloc wave format */
WaveFormat = (PKSDATAFORMAT_WAVEFORMATEX)Context->Alloc(sizeof(KSDATAFORMAT_WAVEFORMATEX));
if (!WaveFormat)
return UA_STATUS_NO_MEMORY;
/* init wave format */
WaveFormat->WaveFormatEx.cbSize = sizeof(WAVEFORMATEX);
WaveFormat->WaveFormatEx.wFormatTag = WAVE_FORMAT_PCM;
WaveFormat->WaveFormatEx.nChannels = FormatType->bNrChannels;
WaveFormat->WaveFormatEx.wBitsPerSample = FormatType->bBitResolution;
WaveFormat->WaveFormatEx.nSamplesPerSec = ((FormatType->tSamFreq[2] & 0xFF) << 16) | ((FormatType->tSamFreq[1] & 0xFF)<< 8) | (FormatType->tSamFreq[0] & 0xFF);
WaveFormat->WaveFormatEx.nBlockAlign = (WaveFormat->WaveFormatEx.nChannels * WaveFormat->WaveFormatEx.wBitsPerSample) / 8;
WaveFormat->WaveFormatEx.nAvgBytesPerSec = WaveFormat->WaveFormatEx.nSamplesPerSec * WaveFormat->WaveFormatEx.nBlockAlign;
/* FIXME apply padding */
WaveFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT_WAVEFORMATEX);
Context->Copy(&WaveFormat->DataFormat.MajorFormat, &DataFormatTypeAudio, sizeof(GUID));
Context->Copy(&WaveFormat->DataFormat.SubFormat, &DataFormatSubTypePCM, sizeof(GUID));
Context->Copy(&WaveFormat->DataFormat.Specifier, &DataFormatSpecifierWaveFormat, sizeof(GUID));
//C_ASSERT(sizeof(WAVEFORMATEX) + sizeof(KSDATAFORMAT) == 82);
/* get corresponding pin descriptor */
PinDescriptor = (PKSPIN_DESCRIPTOR)&FilterDescriptor->PinDescriptors[Index].PinDescriptor;
/* alloc data range */
DataRanges = (PKSDATARANGE*)Context->Alloc(sizeof(PKSDATARANGE) * (PinDescriptor->DataRangesCount+1));
if (!DataRanges)
{
Context->Free(WaveFormat);
return UA_STATUS_NO_MEMORY;
}
if (PinDescriptor->DataRangesCount)
{
/* copy old range */
Context->Copy(DataRanges, (PVOID)PinDescriptor->DataRanges, sizeof(PKSDATARANGE) * PinDescriptor->DataRangesCount);
/* free old range */
Context->Free((PVOID)PinDescriptor->DataRanges);
}
/* assign new range */
PinDescriptor->DataRanges = DataRanges;
DataRanges[PinDescriptor->DataRangesCount] = (PKSDATARANGE)WaveFormat;
PinDescriptor->DataRangesCount++;
return UA_STATUS_SUCCESS;
}
}
return UA_STATUS_SUCCESS;
}