USB audio: cleanup and codestyle fixes.

* cleanup and codestyle fixes;
* AudioFunction module contents purged out as unused.
This commit is contained in:
Siarzhuk Zharski
2013-08-18 14:48:42 +02:00
parent 2cc4703b91
commit 673ef2cbaf
17 changed files with 827 additions and 2783 deletions
@@ -1,14 +1,16 @@
/* /*
* Driver for USB Audio Device Class devices. * Driver for USB Audio Device Class devices.
* Copyright (c) 2009,10,12 S.Zharski <[email protected]> * Copyright (c) 2009-13 S.Zharski <[email protected]>
* Distributed under the tems of the MIT license. * Distributed under the tems of the MIT license.
* *
*/ */
#include "AudioControlInterface.h" #include "AudioControlInterface.h"
#include "Settings.h"
#include "Device.h"
#include "audio.h" #include "audio.h"
#include "Device.h"
#include "Driver.h"
#include "Settings.h"
enum TerminalTypes { enum TerminalTypes {
@@ -185,14 +187,14 @@ GetTerminalDescription(uint16 TerminalType)
_AudioControl::_AudioControl(AudioControlInterface* interface, _AudioControl::_AudioControl(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header) usb_audiocontrol_header_descriptor* Header)
: :
fStatus(B_NO_INIT), fStatus(B_NO_INIT),
fInterface(interface), fInterface(interface),
fSubType(Header->descriptor_subtype), fSubType(Header->descriptor_subtype),
fID(0), fID(0),
fSourceID(0), fSourceID(0),
fStringIndex(0) fStringIndex(0)
{ {
} }
@@ -205,51 +207,45 @@ _AudioControl::~_AudioControl()
AudioChannelCluster* AudioChannelCluster*
_AudioControl::OutCluster() _AudioControl::OutCluster()
{ {
if (SourceID() == 0 || fInterface == NULL) { if (SourceID() == 0 || fInterface == NULL)
return NULL; return NULL;
}
_AudioControl* control = fInterface->Find(SourceID()); _AudioControl* control = fInterface->Find(SourceID());
if (control == NULL) { if (control == NULL)
return NULL; return NULL;
}
return control->OutCluster(); return control->OutCluster();
} }
AudioChannelCluster::AudioChannelCluster() AudioChannelCluster::AudioChannelCluster()
: :
fOutChannelsNumber(0), fOutChannelsNumber(0),
fChannelsConfig(0), fChannelsConfig(0),
fChannelNames(0) fChannelNames(0)
{ {
} }
AudioChannelCluster::~AudioChannelCluster() AudioChannelCluster::~AudioChannelCluster()
{ {
} }
_Terminal::_Terminal(AudioControlInterface* interface, _Terminal::_Terminal(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header) usb_audiocontrol_header_descriptor* Header)
: :
_AudioControl(interface, Header), _AudioControl(interface, Header),
fTerminalType(0), fTerminalType(0),
fAssociatedTerminal(0), fAssociatedTerminal(0),
fClockSourceId(0), fClockSourceId(0),
fControlsBitmap(0) fControlsBitmap(0)
{ {
} }
_Terminal::~_Terminal() _Terminal::~_Terminal()
{ {
} }
@@ -268,9 +264,9 @@ _Terminal::IsUSBIO()
InputTerminal::InputTerminal(AudioControlInterface* interface, InputTerminal::InputTerminal(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header) usb_audiocontrol_header_descriptor* Header)
: :
_AudioChannelCluster<_Terminal>(interface, Header) _AudioChannelCluster<_Terminal>(interface, Header)
{ {
usb_input_terminal_descriptor_r1* Terminal usb_input_terminal_descriptor_r1* Terminal
= (usb_input_terminal_descriptor_r1*) Header; = (usb_input_terminal_descriptor_r1*) Header;
@@ -280,7 +276,7 @@ InputTerminal::InputTerminal(AudioControlInterface* interface,
TRACE("Input Terminal ID:%d >>>\n", fID); TRACE("Input Terminal ID:%d >>>\n", fID);
TRACE("Terminal type:%s (%#06x)\n", TRACE("Terminal type:%s (%#06x)\n",
GetTerminalDescription(fTerminalType), fTerminalType); GetTerminalDescription(fTerminalType), fTerminalType);
TRACE("Assoc.terminal:%d\n", fAssociatedTerminal); TRACE("Assoc.terminal:%d\n", fAssociatedTerminal);
if (fInterface->SpecReleaseNumber() < 0x200) { if (fInterface->SpecReleaseNumber() < 0x200) {
@@ -317,9 +313,9 @@ InputTerminal::~InputTerminal()
OutputTerminal::OutputTerminal(AudioControlInterface* interface, OutputTerminal::OutputTerminal(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header) usb_audiocontrol_header_descriptor* Header)
: :
_Terminal(interface, Header) _Terminal(interface, Header)
{ {
usb_output_terminal_descriptor_r1* Terminal usb_output_terminal_descriptor_r1* Terminal
= (usb_output_terminal_descriptor_r1*) Header; = (usb_output_terminal_descriptor_r1*) Header;
@@ -331,7 +327,7 @@ OutputTerminal::OutputTerminal(AudioControlInterface* interface,
TRACE("Output Terminal ID:%d >>>\n", fID); TRACE("Output Terminal ID:%d >>>\n", fID);
TRACE("Terminal type:%s (%#06x)\n", TRACE("Terminal type:%s (%#06x)\n",
GetTerminalDescription(fTerminalType), fTerminalType); GetTerminalDescription(fTerminalType), fTerminalType);
TRACE("Assoc.terminal:%d\n", fAssociatedTerminal); TRACE("Assoc.terminal:%d\n", fAssociatedTerminal);
TRACE("Source ID:%d\n", fSourceID); TRACE("Source ID:%d\n", fSourceID);
@@ -361,10 +357,10 @@ OutputTerminal::~OutputTerminal()
MixerUnit::MixerUnit(AudioControlInterface* interface, MixerUnit::MixerUnit(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header) usb_audiocontrol_header_descriptor* Header)
: :
_AudioChannelCluster<_AudioControl>(interface, Header), _AudioChannelCluster<_AudioControl>(interface, Header),
fControlsBitmap(0) fControlsBitmap(0)
{ {
usb_mixer_unit_descriptor* Mixer usb_mixer_unit_descriptor* Mixer
= (usb_mixer_unit_descriptor*) Header; = (usb_mixer_unit_descriptor*) Header;
@@ -384,7 +380,7 @@ MixerUnit::MixerUnit(AudioControlInterface* interface,
if (fInterface->SpecReleaseNumber() < 0x200) { if (fInterface->SpecReleaseNumber() < 0x200) {
usb_output_channels_descriptor_r1* OutChannels usb_output_channels_descriptor_r1* OutChannels
= (usb_output_channels_descriptor_r1*) = (usb_output_channels_descriptor_r1*)
&Mixer->input_pins[Mixer->num_input_pins]; &Mixer->input_pins[Mixer->num_input_pins];
fOutChannelsNumber = OutChannels->num_output_pins; fOutChannelsNumber = OutChannels->num_output_pins;
fChannelsConfig = OutChannels->channel_config; fChannelsConfig = OutChannels->channel_config;
@@ -396,7 +392,7 @@ MixerUnit::MixerUnit(AudioControlInterface* interface,
} else { } else {
usb_output_channels_descriptor* OutChannels usb_output_channels_descriptor* OutChannels
= (usb_output_channels_descriptor*) = (usb_output_channels_descriptor*)
&Mixer->input_pins[Mixer->num_input_pins]; &Mixer->input_pins[Mixer->num_input_pins];
fOutChannelsNumber = OutChannels->num_output_pins; fOutChannelsNumber = OutChannels->num_output_pins;
fChannelsConfig = OutChannels->channel_config; fChannelsConfig = OutChannels->channel_config;
@@ -432,10 +428,10 @@ MixerUnit::~MixerUnit()
SelectorUnit::SelectorUnit(AudioControlInterface* interface, SelectorUnit::SelectorUnit(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header) usb_audiocontrol_header_descriptor* Header)
: :
_AudioControl(interface, Header), _AudioControl(interface, Header),
fControlsBitmap(0) fControlsBitmap(0)
{ {
usb_selector_unit_descriptor* Selector usb_selector_unit_descriptor* Selector
= (usb_selector_unit_descriptor*) Header; = (usb_selector_unit_descriptor*) Header;
@@ -450,10 +446,8 @@ SelectorUnit::SelectorUnit(AudioControlInterface* interface,
} }
if (fInterface->SpecReleaseNumber() < 0x200) { if (fInterface->SpecReleaseNumber() < 0x200) {
fStringIndex = Selector->input_pins[Selector->num_input_pins]; fStringIndex = Selector->input_pins[Selector->num_input_pins];
} else { } else {
fControlsBitmap = Selector->input_pins[Selector->num_input_pins]; fControlsBitmap = Selector->input_pins[Selector->num_input_pins];
fStringIndex = Selector->input_pins[Selector->num_input_pins + 1]; fStringIndex = Selector->input_pins[Selector->num_input_pins + 1];
@@ -474,19 +468,16 @@ SelectorUnit::~SelectorUnit()
AudioChannelCluster* AudioChannelCluster*
SelectorUnit::OutCluster() SelectorUnit::OutCluster()
{ {
if (fInterface == NULL) { if (fInterface == NULL)
return NULL; return NULL;
}
for (int i = 0; i < fInputPins.Count(); i++) { for (int i = 0; i < fInputPins.Count(); i++) {
_AudioControl* control = fInterface->Find(fInputPins[i]); _AudioControl* control = fInterface->Find(fInputPins[i]);
if (control == NULL) { if (control == NULL)
continue; continue;
}
if (control->OutCluster() != NULL) { if (control->OutCluster() != NULL)
return control->OutCluster(); return control->OutCluster();
}
} }
return NULL; return NULL;
@@ -494,9 +485,9 @@ SelectorUnit::OutCluster()
FeatureUnit::FeatureUnit(AudioControlInterface* interface, FeatureUnit::FeatureUnit(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header) usb_audiocontrol_header_descriptor* Header)
: :
_AudioControl(interface, Header) _AudioControl(interface, Header)
{ {
usb_feature_unit_descriptor* Feature usb_feature_unit_descriptor* Feature
= (usb_feature_unit_descriptor*) Header; = (usb_feature_unit_descriptor*) Header;
@@ -509,11 +500,11 @@ FeatureUnit::FeatureUnit(AudioControlInterface* interface,
uint8 controlSize = 4; uint8 controlSize = 4;
uint8 channelsCount = (Feature->length - 6) / controlSize; uint8 channelsCount = (Feature->length - 6) / controlSize;
uint8 *ControlsBitmapPointer = (uint8*)&Feature->bma_controls[0]; uint8* ControlsBitmapPointer = (uint8*)&Feature->bma_controls[0];
if (fInterface->SpecReleaseNumber() < 0x200) { if (fInterface->SpecReleaseNumber() < 0x200) {
usb_feature_unit_descriptor_r1* Feature usb_feature_unit_descriptor_r1* Feature
= (usb_feature_unit_descriptor_r1*) Header; = (usb_feature_unit_descriptor_r1*)Header;
controlSize = Feature->control_size; controlSize = Feature->control_size;
channelsCount = (Feature->length - 7) / Feature->control_size; channelsCount = (Feature->length - 7) / Feature->control_size;
ControlsBitmapPointer = &Feature->bma_controls[0]; ControlsBitmapPointer = &Feature->bma_controls[0];
@@ -523,7 +514,7 @@ FeatureUnit::FeatureUnit(AudioControlInterface* interface,
TRACE("Channels number:%d\n", channelsCount - 1); // not add master! TRACE("Channels number:%d\n", channelsCount - 1); // not add master!
for (size_t i = 0; i < channelsCount; i++) { for (size_t i = 0; i < channelsCount; i++) {
uint8 *controlPointer = &ControlsBitmapPointer[i * controlSize]; uint8* controlPointer = &ControlsBitmapPointer[i* controlSize];
switch(controlSize) { switch(controlSize) {
case 1: fControlBitmaps.PushBack(*controlPointer); break; case 1: fControlBitmaps.PushBack(*controlPointer); break;
case 2: fControlBitmaps.PushBack(*(uint16*)controlPointer); break; case 2: fControlBitmaps.PushBack(*(uint16*)controlPointer); break;
@@ -537,7 +528,7 @@ FeatureUnit::FeatureUnit(AudioControlInterface* interface,
NormalizeAndTraceChannel(i); NormalizeAndTraceChannel(i);
} }
fStringIndex = ControlsBitmapPointer[channelsCount * controlSize]; fStringIndex = ControlsBitmapPointer[channelsCount* controlSize];
TRACE("StringIndex:%d\n", fStringIndex); TRACE("StringIndex:%d\n", fStringIndex);
fStatus = B_OK; fStatus = B_OK;
@@ -553,9 +544,8 @@ const char*
FeatureUnit::Name() FeatureUnit::Name()
{ {
// first check if source of this FU is an input terminal // first check if source of this FU is an input terminal
_AudioControl *control = fInterface->Find(fSourceID); _AudioControl* control = fInterface->Find(fSourceID);
while (control != 0) { while (control != 0) {
if (control->SubType() != IDSInputTerminal) if (control->SubType() != IDSInputTerminal)
break; break;
@@ -570,7 +560,6 @@ FeatureUnit::Name()
// check if output of this FU is connected to output terminal // check if output of this FU is connected to output terminal
control = fInterface->FindOutputTerminal(fID); control = fInterface->FindOutputTerminal(fID);
while (control != 0) { while (control != 0) {
if (control->SubType() != IDSOutputTerminal) if (control->SubType() != IDSOutputTerminal)
break; break;
@@ -591,7 +580,7 @@ FeatureUnit::HasControl(int32 Channel, uint32 Control)
{ {
if (Channel >= fControlBitmaps.Count()) { if (Channel >= fControlBitmaps.Count()) {
TRACE_ALWAYS("Out of limits error of retrieving control %#010x " TRACE_ALWAYS("Out of limits error of retrieving control %#010x "
"for channel %d\n", Control, Channel); "for channel %d\n", Control, Channel);
return false; return false;
} }
@@ -640,9 +629,8 @@ FeatureUnit::NormalizeAndTraceChannel(int32 Channel)
for (size_t i = 0; i < _countof(remapInfos); i++) { for (size_t i = 0; i < _countof(remapInfos); i++) {
uint32 bits = isRev1 ? remapInfos[i].rev1Bits : remapInfos[i].rev2Bits; uint32 bits = isRev1 ? remapInfos[i].rev1Bits : remapInfos[i].rev2Bits;
if ((fControlBitmaps[Channel] & bits) > 0) { if ((fControlBitmaps[Channel] & bits) > 0) {
if (isRev1) { if (isRev1)
remappedBitmap |= remapInfos[i].rev2Bits; remappedBitmap |= remapInfos[i].rev2Bits;
}
TRACE("\t%s\n", remapInfos[i].name); TRACE("\t%s\n", remapInfos[i].name);
} }
} }
@@ -655,9 +643,9 @@ FeatureUnit::NormalizeAndTraceChannel(int32 Channel)
EffectUnit::EffectUnit(AudioControlInterface* interface, EffectUnit::EffectUnit(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header) usb_audiocontrol_header_descriptor* Header)
: :
_AudioControl(interface, Header) _AudioControl(interface, Header)
{ {
usb_input_terminal_descriptor* D usb_input_terminal_descriptor* D
= (usb_input_terminal_descriptor*) Header; = (usb_input_terminal_descriptor*) Header;
@@ -671,11 +659,11 @@ EffectUnit::~EffectUnit()
ProcessingUnit::ProcessingUnit(AudioControlInterface* interface, ProcessingUnit::ProcessingUnit(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header) usb_audiocontrol_header_descriptor* Header)
: :
_AudioChannelCluster<_AudioControl>(interface, Header), _AudioChannelCluster<_AudioControl>(interface, Header),
fProcessType(0), fProcessType(0),
fControlsBitmap(0) fControlsBitmap(0)
{ {
usb_processing_unit_descriptor* Processing usb_processing_unit_descriptor* Processing
= (usb_processing_unit_descriptor*) Header; = (usb_processing_unit_descriptor*) Header;
@@ -695,7 +683,7 @@ ProcessingUnit::ProcessingUnit(AudioControlInterface* interface,
if (fInterface->SpecReleaseNumber() < 0x200) { if (fInterface->SpecReleaseNumber() < 0x200) {
usb_output_channels_descriptor_r1* OutChannels usb_output_channels_descriptor_r1* OutChannels
= (usb_output_channels_descriptor_r1*) = (usb_output_channels_descriptor_r1*)
&Processing->input_pins[Processing->num_input_pins]; &Processing->input_pins[Processing->num_input_pins];
fOutChannelsNumber = OutChannels->num_output_pins; fOutChannelsNumber = OutChannels->num_output_pins;
fChannelsConfig = OutChannels->channel_config; fChannelsConfig = OutChannels->channel_config;
@@ -703,7 +691,7 @@ ProcessingUnit::ProcessingUnit(AudioControlInterface* interface,
} else { } else {
usb_output_channels_descriptor* OutChannels usb_output_channels_descriptor* OutChannels
= (usb_output_channels_descriptor*) = (usb_output_channels_descriptor*)
&Processing->input_pins[Processing->num_input_pins]; &Processing->input_pins[Processing->num_input_pins];
fOutChannelsNumber = OutChannels->num_output_pins; fOutChannelsNumber = OutChannels->num_output_pins;
fChannelsConfig = OutChannels->channel_config; fChannelsConfig = OutChannels->channel_config;
@@ -738,11 +726,11 @@ ProcessingUnit::~ProcessingUnit()
ExtensionUnit::ExtensionUnit(AudioControlInterface* interface, ExtensionUnit::ExtensionUnit(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header) usb_audiocontrol_header_descriptor* Header)
: :
_AudioChannelCluster<_AudioControl>(interface, Header), _AudioChannelCluster<_AudioControl>(interface, Header),
fExtensionCode(0), fExtensionCode(0),
fControlsBitmap(0) fControlsBitmap(0)
{ {
usb_extension_unit_descriptor* Extension usb_extension_unit_descriptor* Extension
= (usb_extension_unit_descriptor*) Header; = (usb_extension_unit_descriptor*) Header;
@@ -762,7 +750,7 @@ ExtensionUnit::ExtensionUnit(AudioControlInterface* interface,
if (fInterface->SpecReleaseNumber() < 0x200) { if (fInterface->SpecReleaseNumber() < 0x200) {
usb_output_channels_descriptor_r1* OutChannels usb_output_channels_descriptor_r1* OutChannels
= (usb_output_channels_descriptor_r1*) = (usb_output_channels_descriptor_r1*)
&Extension->input_pins[Extension->num_input_pins]; &Extension->input_pins[Extension->num_input_pins];
fOutChannelsNumber = OutChannels->num_output_pins; fOutChannelsNumber = OutChannels->num_output_pins;
fChannelsConfig = OutChannels->channel_config; fChannelsConfig = OutChannels->channel_config;
@@ -770,7 +758,7 @@ ExtensionUnit::ExtensionUnit(AudioControlInterface* interface,
} else { } else {
usb_output_channels_descriptor* OutChannels usb_output_channels_descriptor* OutChannels
= (usb_output_channels_descriptor*) = (usb_output_channels_descriptor*)
&Extension->input_pins[Extension->num_input_pins]; &Extension->input_pins[Extension->num_input_pins];
fOutChannelsNumber = OutChannels->num_output_pins; fOutChannelsNumber = OutChannels->num_output_pins;
fChannelsConfig = OutChannels->channel_config; fChannelsConfig = OutChannels->channel_config;
@@ -805,9 +793,9 @@ ExtensionUnit::~ExtensionUnit()
ClockSource::ClockSource(AudioControlInterface* interface, ClockSource::ClockSource(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header) usb_audiocontrol_header_descriptor* Header)
: :
_AudioControl(interface, Header) _AudioControl(interface, Header)
{ {
usb_input_terminal_descriptor* D usb_input_terminal_descriptor* D
= (usb_input_terminal_descriptor*) Header; = (usb_input_terminal_descriptor*) Header;
@@ -821,9 +809,9 @@ ClockSource::~ClockSource()
ClockSelector::ClockSelector(AudioControlInterface* interface, ClockSelector::ClockSelector(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header) usb_audiocontrol_header_descriptor* Header)
: :
_AudioControl(interface, Header) _AudioControl(interface, Header)
{ {
usb_input_terminal_descriptor* D usb_input_terminal_descriptor* D
= (usb_input_terminal_descriptor*) Header; = (usb_input_terminal_descriptor*) Header;
@@ -837,9 +825,9 @@ ClockSelector::~ClockSelector()
ClockMultiplier::ClockMultiplier(AudioControlInterface* interface, ClockMultiplier::ClockMultiplier(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header) usb_audiocontrol_header_descriptor* Header)
: :
_AudioControl(interface, Header) _AudioControl(interface, Header)
{ {
usb_input_terminal_descriptor* D usb_input_terminal_descriptor* D
= (usb_input_terminal_descriptor*) Header; = (usb_input_terminal_descriptor*) Header;
@@ -853,9 +841,9 @@ ClockMultiplier::~ClockMultiplier()
SampleRateConverter::SampleRateConverter(AudioControlInterface* interface, SampleRateConverter::SampleRateConverter(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header) usb_audiocontrol_header_descriptor* Header)
: :
_AudioControl(interface, Header) _AudioControl(interface, Header)
{ {
usb_input_terminal_descriptor* D usb_input_terminal_descriptor* D
= (usb_input_terminal_descriptor*) Header; = (usb_input_terminal_descriptor*) Header;
@@ -869,13 +857,13 @@ SampleRateConverter::~SampleRateConverter()
AudioControlInterface::AudioControlInterface(Device* device) AudioControlInterface::AudioControlInterface(Device* device)
: :
fInterface(0), fInterface(0),
fStatus(B_NO_INIT), fStatus(B_NO_INIT),
fADCSpecification(0), fADCSpecification(0),
fFunctionCategory(0), fFunctionCategory(0),
fControlsBitmap(0), fControlsBitmap(0),
fDevice(device) fDevice(device)
{ {
} }
@@ -883,9 +871,8 @@ AudioControlInterface::AudioControlInterface(Device* device)
AudioControlInterface::~AudioControlInterface() AudioControlInterface::~AudioControlInterface()
{ {
for (AudioControlsIterator I = fAudioControls.Begin(); for (AudioControlsIterator I = fAudioControls.Begin();
I != fAudioControls.End(); I++) { I != fAudioControls.End(); I++)
delete I->Value(); delete I->Value();
}
fAudioControls.MakeEmpty(); fAudioControls.MakeEmpty();
@@ -898,11 +885,11 @@ AudioControlInterface::~AudioControlInterface()
status_t status_t
AudioControlInterface::Init(size_t interface, usb_interface_info *Interface) AudioControlInterface::Init(size_t interface, usb_interface_info* Interface)
{ {
for (size_t i = 0; i < Interface->generic_count; i++) { for (size_t i = 0; i < Interface->generic_count; i++) {
usb_audiocontrol_header_descriptor *Header usb_audiocontrol_header_descriptor* Header
= (usb_audiocontrol_header_descriptor *)Interface->generic[i]; = (usb_audiocontrol_header_descriptor* )Interface->generic[i];
if (Header->descriptor_type != AC_CS_INTERFACE) { if (Header->descriptor_type != AC_CS_INTERFACE) {
TRACE_ALWAYS("Ignore Audio Control of " TRACE_ALWAYS("Ignore Audio Control of "
@@ -910,7 +897,7 @@ AudioControlInterface::Init(size_t interface, usb_interface_info *Interface)
continue; continue;
} }
_AudioControl *control = NULL; _AudioControl* control = NULL;
switch(Header->descriptor_subtype) { switch(Header->descriptor_subtype) {
default: default:
@@ -978,9 +965,8 @@ AudioControlInterface::Init(size_t interface, usb_interface_info *Interface)
} }
fAudioControls.Put(control->ID(), control); fAudioControls.Put(control->ID(), control);
} else { } else
delete control; delete control;
}
} }
return fStatus = B_OK; return fStatus = B_OK;
@@ -1003,11 +989,10 @@ AudioControlInterface::FindOutputTerminal(uint8 id)
status_t status_t
AudioControlInterface::InitACHeader(size_t interface, AudioControlInterface::InitACHeader(size_t interface,
usb_audiocontrol_header_descriptor* Header) usb_audiocontrol_header_descriptor* Header)
{ {
if (Header == NULL) { if (Header == NULL)
return fStatus = B_NO_INIT; return fStatus = B_NO_INIT;
}
fInterface = interface; fInterface = interface;
@@ -1034,11 +1019,10 @@ AudioControlInterface::InitACHeader(size_t interface,
} }
uint32 uint32
AudioControlInterface::GetChannelsDescription( AudioControlInterface::GetChannelsDescription(
Vector<multi_channel_info>& Channels, Vector<multi_channel_info>& Channels, multi_description* Description,
multi_description *Description, Vector<_AudioControl*>&Terminals)
AudioControlsVector &Terminals)
{ {
uint32 addedChannels = 0; uint32 addedChannels = 0;
// multi_channel_info* Channels = Description->channels; // multi_channel_info* Channels = Description->channels;
@@ -1070,8 +1054,7 @@ AudioControlInterface::GetChannelsDescription(
uint32 uint32
AudioControlInterface::GetTerminalChannels(Vector<multi_channel_info>& Channels, AudioControlInterface::GetTerminalChannels(Vector<multi_channel_info>& Channels,
AudioChannelCluster* cluster, channel_kind kind, AudioChannelCluster* cluster, channel_kind kind, uint32 connectors)
uint32 connectors)
{ {
if (cluster->ChannelsCount() < 2) { // mono channel if (cluster->ChannelsCount() < 2) { // mono channel
multi_channel_info info; multi_channel_info info;
@@ -1132,16 +1115,14 @@ AudioControlInterface::GetTerminalChannels(Vector<multi_channel_info>& Channels,
uint32 uint32
AudioControlInterface::GetBusChannelsDescription( AudioControlInterface::GetBusChannelsDescription(
Vector<multi_channel_info>& Channels, Vector<multi_channel_info>& Channels, multi_description* Description)
multi_description *Description)
{ {
uint32 addedChannels = 0; uint32 addedChannels = 0;
// multi_channel_info* Channels = Description->channels; // multi_channel_info* Channels = Description->channels;
// first iterate output channels // first iterate output channels
for (AudioControlsIterator I = fOutputTerminals.Begin(); for (AudioControlsIterator I = fOutputTerminals.Begin();
I != fOutputTerminals.End(); I++) { I != fOutputTerminals.End(); I++) {
_AudioControl* control = I->Value(); _AudioControl* control = I->Value();
if (static_cast<_Terminal*>(control)->IsUSBIO()) if (static_cast<_Terminal*>(control)->IsUSBIO())
continue; continue;
@@ -1162,8 +1143,7 @@ AudioControlInterface::GetBusChannelsDescription(
// output channels should follow too // output channels should follow too
for (AudioControlsIterator I = fInputTerminals.Begin(); for (AudioControlsIterator I = fInputTerminals.Begin();
I != fInputTerminals.End(); I++) { I != fInputTerminals.End(); I++) {
_AudioControl* control = I->Value(); _AudioControl* control = I->Value();
if (static_cast<_Terminal*>(control)->IsUSBIO()) if (static_cast<_Terminal*>(control)->IsUSBIO())
continue; continue;
@@ -1188,7 +1168,7 @@ AudioControlInterface::GetBusChannelsDescription(
void void
AudioControlInterface::_HarvestRecordFeatureUnits(_AudioControl* rootControl, AudioControlInterface::_HarvestRecordFeatureUnits(_AudioControl* rootControl,
AudioControlsMap& Map) AudioControlsMap& Map)
{ {
if (rootControl == 0) { if (rootControl == 0) {
TRACE_ALWAYS("Not processing due NULL root control.\n"); TRACE_ALWAYS("Not processing due NULL root control.\n");
@@ -1203,9 +1183,8 @@ AudioControlInterface::_HarvestRecordFeatureUnits(_AudioControl* rootControl,
case IDSSelectorUnit: case IDSSelectorUnit:
{ {
SelectorUnit* unit = static_cast<SelectorUnit*>(rootControl); SelectorUnit* unit = static_cast<SelectorUnit*>(rootControl);
for (int i = 0; i < unit->fInputPins.Count(); i++) { for (int i = 0; i < unit->fInputPins.Count(); i++)
_HarvestRecordFeatureUnits(Find(unit->fInputPins[i]), Map); _HarvestRecordFeatureUnits(Find(unit->fInputPins[i]), Map);
}
Map.Put(rootControl->ID(), rootControl); Map.Put(rootControl->ID(), rootControl);
} }
@@ -1238,14 +1217,14 @@ AudioControlInterface::_InitGainLimits(multi_mix_control& Control)
size_t actualLength = 0; size_t actualLength = 0;
for (size_t i = 0; i < _countof(gainInfos); i++) { for (size_t i = 0; i < _countof(gainInfos); i++) {
status_t status = gUSBModule->send_request(fDevice->USBDevice(), status_t status = gUSBModule->send_request(fDevice->USBDevice(),
USB_REQTYPE_INTERFACE_IN | USB_REQTYPE_CLASS, USB_REQTYPE_INTERFACE_IN | USB_REQTYPE_CLASS,
gainInfos[i].request, REQ_VALUE(Control.id), gainInfos[i].request, REQ_VALUE(Control.id),
REQ_INDEX(Control.id), sizeof(gainInfos[i].data), REQ_INDEX(Control.id), sizeof(gainInfos[i].data),
&gainInfos[i].data, &actualLength); &gainInfos[i].data, &actualLength);
if (status != B_OK || actualLength != sizeof(gainInfos[i].data)) { if (status != B_OK || actualLength != sizeof(gainInfos[i].data)) {
TRACE_ALWAYS("Request %d failed:%#08x; received %d of %d\n", TRACE_ALWAYS("Request %d failed:%#08x; received %d of %d\n",
i, status, actualLength, sizeof(gainInfos[i].data)); i, status, actualLength, sizeof(gainInfos[i].data));
continue; continue;
} }
@@ -1253,16 +1232,14 @@ AudioControlInterface::_InitGainLimits(multi_mix_control& Control)
} }
TRACE_ALWAYS("Control %s: from %f to %f dB, step %f dB.\n", Control.name, TRACE_ALWAYS("Control %s: from %f to %f dB, step %f dB.\n", Control.name,
Control.gain.min_gain, Control.gain.max_gain, Control.gain.min_gain, Control.gain.max_gain, Control.gain.granularity);
Control.gain.granularity);
} }
uint32 uint32
AudioControlInterface::_ListFeatureUnitOption(uint32 controlType, AudioControlInterface::_ListFeatureUnitOption(uint32 controlType,
int32& index, int32 parentIndex, int32& index, int32 parentIndex, multi_mix_control_info* Info,
multi_mix_control_info* Info, FeatureUnit* unit, FeatureUnit* unit, uint32 channel, uint32 channels)
uint32 channel, uint32 channels)
{ {
int32 startIndex = index; int32 startIndex = index;
uint32 id = 0; uint32 id = 0;
@@ -1296,11 +1273,11 @@ AudioControlInterface::_ListFeatureUnitOption(uint32 controlType,
multi_mix_control* Controls = Info->controls; multi_mix_control* Controls = Info->controls;
if (unit->HasControl(channel, controlType)) { if (unit->HasControl(channel, controlType)) {
uint32 masterIndex uint32 masterIndex = CTL_ID(id, channel, unit->ID(), fInterface);
= Controls[index].id = CTL_ID(id, channel, unit->ID(), fInterface); Controls[index].id = masterIndex;
Controls[index].flags = flags; Controls[index].flags = flags;
Controls[index].parent = parentIndex; Controls[index].parent = parentIndex;
Controls[index].string = string; Controls[index].string = string;
if (name != NULL) if (name != NULL)
strlcpy(Controls[index].name, name, sizeof(Controls[index].name)); strlcpy(Controls[index].name, name, sizeof(Controls[index].name));
if (initGainLimits) if (initGainLimits)
@@ -1309,15 +1286,13 @@ AudioControlInterface::_ListFeatureUnitOption(uint32 controlType,
index++; index++;
if (channels == 2) { if (channels == 2) {
Controls[index].id = CTL_ID(id, channel + 1, Controls[index].id = CTL_ID(id, channel + 1, unit->ID(), fInterface);
unit->ID(), fInterface); Controls[index].flags = flags;
Controls[index].flags = flags; Controls[index].parent = parentIndex;
Controls[index].parent = parentIndex; Controls[index].master = masterIndex;
Controls[index].master = masterIndex; Controls[index].string = string;
Controls[index].string = string;
if (name != NULL) if (name != NULL)
strlcpy(Controls[index].name, name, strlcpy(Controls[index].name, name, sizeof(Controls[index].name));
sizeof(Controls[index].name));
if (initGainLimits) if (initGainLimits)
_InitGainLimits(Controls[index]); _InitGainLimits(Controls[index]);
index++; index++;
@@ -1330,7 +1305,7 @@ AudioControlInterface::_ListFeatureUnitOption(uint32 controlType,
int32 int32
AudioControlInterface::_ListFeatureUnitControl(int32& index, int32 parentIndex, AudioControlInterface::_ListFeatureUnitControl(int32& index, int32 parentIndex,
multi_mix_control_info* Info, _AudioControl* control) multi_mix_control_info* Info, _AudioControl* control)
{ {
FeatureUnit* unit = static_cast<FeatureUnit*>(control); FeatureUnit* unit = static_cast<FeatureUnit*>(control);
if (unit == 0) { if (unit == 0) {
@@ -1391,12 +1366,12 @@ AudioControlInterface::_ListFeatureUnitControl(int32& index, int32 parentIndex,
} }
if (masterIndex == 0) { if (masterIndex == 0) {
groupIndex groupIndex = index;
= Controls[index].id = index; Controls[index].id = groupIndex;
Controls[index].flags = B_MULTI_MIX_GROUP; Controls[index].flags = B_MULTI_MIX_GROUP;
Controls[index].parent = parentIndex; Controls[index].parent = parentIndex;
snprintf(Controls[index].name, sizeof(Controls[index].name), snprintf(Controls[index].name, sizeof(Controls[index].name),
"%s %s", unit->Name(), channelInfos[i].Name); "%s %s", unit->Name(), channelInfos[i].Name);
index++; index++;
} else { } else {
groupIndex = masterIndex; groupIndex = masterIndex;
@@ -1405,19 +1380,18 @@ AudioControlInterface::_ListFeatureUnitControl(int32& index, int32 parentIndex,
// First list possible Mute controls // First list possible Mute controls
_ListFeatureUnitOption(MuteControl, index, groupIndex, Info, _ListFeatureUnitOption(MuteControl, index, groupIndex, Info,
unit, channel, channelInfos[i].channels); unit, channel, channelInfos[i].channels);
// Gain controls may be usefull too // Gain controls may be usefull too
if (_ListFeatureUnitOption(VolumeControl, index, groupIndex, Info, if (_ListFeatureUnitOption(VolumeControl, index, groupIndex, Info,
unit, channel, channelInfos[i].channels) == 0) unit, channel, channelInfos[i].channels) == 0) {
{
masterIndex = (i == 0) ? groupIndex : 0 ; masterIndex = (i == 0) ? groupIndex : 0 ;
TRACE("channel:%d set master index to %d\n", channel, masterIndex); TRACE("channel:%d set master index to %d\n", channel, masterIndex);
} }
// Auto Gain checkbox will be listed too // Auto Gain checkbox will be listed too
_ListFeatureUnitOption(AutoGainControl, index, groupIndex, Info, _ListFeatureUnitOption(AutoGainControl, index, groupIndex, Info,
unit, channel, channelInfos[i].channels); unit, channel, channelInfos[i].channels);
// Now check if the group filled with something usefull. // Now check if the group filled with something usefull.
// In case no controls were added into it - "remove" it // In case no controls were added into it - "remove" it
@@ -1439,10 +1413,9 @@ AudioControlInterface::_ListFeatureUnitControl(int32& index, int32 parentIndex,
break; break;
} }
if (channelsConfig > 0) { if (channelsConfig > 0)
TRACE_ALWAYS("Following channels were " TRACE_ALWAYS("Following channels were not processed: %#08x.\n",
"not processed: %#08x.\n", channelsConfig); channelsConfig);
}
// return last group index to stick possible selector unit to it. ;-) // return last group index to stick possible selector unit to it. ;-)
return groupIndex; return groupIndex;
@@ -1451,53 +1424,49 @@ AudioControlInterface::_ListFeatureUnitControl(int32& index, int32 parentIndex,
void void
AudioControlInterface::_ListSelectorUnitControl(int32& index, int32 parentGroup, AudioControlInterface::_ListSelectorUnitControl(int32& index, int32 parentGroup,
multi_mix_control_info* Info, _AudioControl* control) multi_mix_control_info* Info, _AudioControl* control)
{ {
SelectorUnit* selector = static_cast<SelectorUnit*>(control); SelectorUnit* selector = static_cast<SelectorUnit*>(control);
if (selector == 0 || selector->SubType() != IDSSelectorUnit) { if (selector == 0 || selector->SubType() != IDSSelectorUnit)
return; return;
}
multi_mix_control* Controls = Info->controls; multi_mix_control* Controls = Info->controls;
int32 recordMUX int32 recordMUX = CTL_ID(0, 0, selector->ID(), fInterface);
= Controls[index].id = CTL_ID(0, 0, selector->ID(), fInterface); Controls[index].id = recordMUX;
Controls[index].flags = B_MULTI_MIX_MUX; Controls[index].flags = B_MULTI_MIX_MUX;
Controls[index].parent = parentGroup; Controls[index].parent = parentGroup;
Controls[index].string = S_null; Controls[index].string = S_null;
strlcpy(Controls[index].name, "Source", sizeof(Controls[index].name)); strlcpy(Controls[index].name, "Source", sizeof(Controls[index].name));
index++; index++;
for (int i = 0; i < selector->fInputPins.Count(); i++) { for (int i = 0; i < selector->fInputPins.Count(); i++) {
Controls[index].id = CTL_ID(0, 1, selector->ID(), fInterface); Controls[index].id = CTL_ID(0, 1, selector->ID(), fInterface);
Controls[index].flags = B_MULTI_MIX_MUX_VALUE; Controls[index].flags = B_MULTI_MIX_MUX_VALUE;
Controls[index].master = 0; Controls[index].master = 0;
Controls[index].string = S_null; Controls[index].string = S_null;
Controls[index].parent = recordMUX; Controls[index].parent = recordMUX;
_AudioControl* control = Find(selector->fInputPins[i]); _AudioControl* control = Find(selector->fInputPins[i]);
if (control != NULL) { if (control != NULL)
strlcpy(Controls[index].name, strlcpy(Controls[index].name,
control->Name(), sizeof(Controls[index].name)); control->Name(), sizeof(Controls[index].name));
} else { else
snprintf(Controls[index].name, snprintf(Controls[index].name,
sizeof(Controls[index].name), "Input #%d", i + 1); sizeof(Controls[index].name), "Input #%d", i + 1);
}
index++; index++;
} }
} }
void void
AudioControlInterface::_ListMixControlsPage(int32& index, AudioControlInterface::_ListMixControlsPage(int32& index,
multi_mix_control_info* Info, multi_mix_control_info* Info, AudioControlsMap& Map, const char* Name)
AudioControlsMap& Map, const char* Name)
{ {
multi_mix_control* Controls = Info->controls; multi_mix_control* Controls = Info->controls;
int32 groupIndex int32 groupIndex = index | 0x10000;
= Controls[index].id = index | 0x10000; Controls[index].id = groupIndex;
Controls[index].flags = B_MULTI_MIX_GROUP; Controls[index].flags = B_MULTI_MIX_GROUP;
Controls[index].parent = 0; Controls[index].parent = 0;
strlcpy(Controls[index].name, Name, sizeof(Controls[index].name)); strlcpy(Controls[index].name, Name, sizeof(Controls[index].name));
index++; index++;
@@ -1507,7 +1476,7 @@ AudioControlInterface::_ListMixControlsPage(int32& index,
switch(I->Value()->SubType()) { switch(I->Value()->SubType()) {
case IDSFeatureUnit: case IDSFeatureUnit:
group = _ListFeatureUnitControl(index, groupIndex, group = _ListFeatureUnitControl(index, groupIndex,
Info, I->Value()); Info, I->Value());
break; break;
case IDSSelectorUnit: case IDSSelectorUnit:
_ListSelectorUnitControl(index, group, Info, I->Value()); _ListSelectorUnitControl(index, group, Info, I->Value());
@@ -1524,61 +1493,51 @@ AudioControlInterface::ListMixControls(multi_mix_control_info* Info)
AudioControlsMap RecordControlsMap; AudioControlsMap RecordControlsMap;
for (AudioControlsIterator I = fOutputTerminals.Begin(); for (AudioControlsIterator I = fOutputTerminals.Begin();
I != fOutputTerminals.End(); I++) I != fOutputTerminals.End(); I++) {
{
_Terminal* terminal = static_cast<_Terminal*>(I->Value()); _Terminal* terminal = static_cast<_Terminal*>(I->Value());
if (terminal->IsUSBIO()) { if (terminal->IsUSBIO())
_HarvestRecordFeatureUnits(terminal, RecordControlsMap); _HarvestRecordFeatureUnits(terminal, RecordControlsMap);
}
} }
AudioControlsMap InputControlsMap; AudioControlsMap InputControlsMap;
AudioControlsMap OutputControlsMap; AudioControlsMap OutputControlsMap;
for (AudioControlsIterator I = fAudioControls.Begin(); for (AudioControlsIterator I = fAudioControls.Begin();
I != fAudioControls.End(); I++) I != fAudioControls.End(); I++) {
{
_AudioControl* control = I->Value(); _AudioControl* control = I->Value();
// filter out feature units // filter out feature units
if (control->SubType() != IDSFeatureUnit) { if (control->SubType() != IDSFeatureUnit)
continue; continue;
}
// ignore controls that are already in the record controls map // ignore controls that are already in the record controls map
if (RecordControlsMap.Find(control->ID()) != RecordControlsMap.End()) { if (RecordControlsMap.Find(control->ID()) != RecordControlsMap.End())
continue; continue;
}
_AudioControl* sourceControl = Find(control->SourceID()); _AudioControl* sourceControl = Find(control->SourceID());
if (sourceControl != 0 && sourceControl->SubType() == IDSInputTerminal) { if (sourceControl != 0 && sourceControl->SubType() == IDSInputTerminal)
InputControlsMap.Put(control->ID(), control); InputControlsMap.Put(control->ID(), control);
} else { else
OutputControlsMap.Put(control->ID(), control); OutputControlsMap.Put(control->ID(), control);
}
} }
int32 index = 0; int32 index = 0;
if (InputControlsMap.Count() > 0) { if (InputControlsMap.Count() > 0)
_ListMixControlsPage(index, Info, InputControlsMap, "Input"); _ListMixControlsPage(index, Info, InputControlsMap, "Input");
}
if (OutputControlsMap.Count() > 0) { if (OutputControlsMap.Count() > 0)
_ListMixControlsPage(index, Info, OutputControlsMap, "Output"); _ListMixControlsPage(index, Info, OutputControlsMap, "Output");
}
if (RecordControlsMap.Count() > 0) { if (RecordControlsMap.Count() > 0)
_ListMixControlsPage(index, Info, RecordControlsMap, "Record"); _ListMixControlsPage(index, Info, RecordControlsMap, "Record");
}
return B_OK; return B_OK;
} }
status_t status_t
AudioControlInterface::GetMix(multi_mix_value_info *Info) AudioControlInterface::GetMix(multi_mix_value_info* Info)
{ {
for (int32 i = 0; i < Info->item_count; i++) { for (int32 i = 0; i < Info->item_count; i++) {
uint16 length = 0; uint16 length = 0;
int16 data = 0; int16 data = 0;
switch(CS_FROM_CTLID(Info->values[i].id)) { switch(CS_FROM_CTLID(Info->values[i].id)) {
@@ -1592,19 +1551,19 @@ AudioControlInterface::GetMix(multi_mix_value_info *Info)
break; break;
default: default:
TRACE_ALWAYS("Unsupported control type %#02x ignored.\n", TRACE_ALWAYS("Unsupported control type %#02x ignored.\n",
CS_FROM_CTLID(Info->values[i].id)); CS_FROM_CTLID(Info->values[i].id));
continue; continue;
} }
size_t actualLength = 0; size_t actualLength = 0;
status_t status = gUSBModule->send_request(fDevice->USBDevice(), status_t status = gUSBModule->send_request(fDevice->USBDevice(),
USB_REQTYPE_INTERFACE_IN | USB_REQTYPE_CLASS, UAS_GET_CUR, USB_REQTYPE_INTERFACE_IN | USB_REQTYPE_CLASS, UAS_GET_CUR,
REQ_VALUE(Info->values[i].id), REQ_INDEX(Info->values[i].id), REQ_VALUE(Info->values[i].id), REQ_INDEX(Info->values[i].id),
length, &data, &actualLength); length, &data, &actualLength);
if (status != B_OK || actualLength != length) { if (status != B_OK || actualLength != length) {
TRACE_ALWAYS("Request failed:%#08x; received %d of %d\n", TRACE_ALWAYS("Request failed:%#08x; received %d of %d\n",
status, actualLength, length); status, actualLength, length);
continue; continue;
} }
@@ -1612,29 +1571,29 @@ AudioControlInterface::GetMix(multi_mix_value_info *Info)
case UAS_VOLUME_CONTROL: case UAS_VOLUME_CONTROL:
Info->values[i].gain = static_cast<float>(data) / 256.; Info->values[i].gain = static_cast<float>(data) / 256.;
TRACE("Gain control %d; channel: %d; is %f dB.\n", TRACE("Gain control %d; channel: %d; is %f dB.\n",
ID_FROM_CTLID(Info->values[i].id), ID_FROM_CTLID(Info->values[i].id),
CN_FROM_CTLID(Info->values[i].id), CN_FROM_CTLID(Info->values[i].id),
Info->values[i].gain); Info->values[i].gain);
break; break;
case UAS_MUTE_CONTROL: case UAS_MUTE_CONTROL:
Info->values[i].enable = data > 0; Info->values[i].enable = data > 0;
TRACE("Mute control %d; channel: %d; is %d.\n", TRACE("Mute control %d; channel: %d; is %d.\n",
ID_FROM_CTLID(Info->values[i].id), ID_FROM_CTLID(Info->values[i].id),
CN_FROM_CTLID(Info->values[i].id), CN_FROM_CTLID(Info->values[i].id),
Info->values[i].enable); Info->values[i].enable);
break; break;
case UAS_AUTOMATIC_GAIN_CONTROL: case UAS_AUTOMATIC_GAIN_CONTROL:
Info->values[i].enable = data > 0; Info->values[i].enable = data > 0;
TRACE("AGain control %d; channel: %d; is %d.\n", TRACE("AGain control %d; channel: %d; is %d.\n",
ID_FROM_CTLID(Info->values[i].id), ID_FROM_CTLID(Info->values[i].id),
CN_FROM_CTLID(Info->values[i].id), CN_FROM_CTLID(Info->values[i].id),
Info->values[i].enable); Info->values[i].enable);
break; break;
case 0: // Selector Unit case 0: // Selector Unit
Info->values[i].mux = data; Info->values[i].mux = data;
TRACE("Selector control %d; is %d.\n", TRACE("Selector control %d; is %d.\n",
ID_FROM_CTLID(Info->values[i].id), ID_FROM_CTLID(Info->values[i].id),
Info->values[i].mux); Info->values[i].mux);
break; break;
default: default:
break; break;
@@ -1646,10 +1605,9 @@ AudioControlInterface::GetMix(multi_mix_value_info *Info)
status_t status_t
AudioControlInterface::SetMix(multi_mix_value_info *Info) AudioControlInterface::SetMix(multi_mix_value_info* Info)
{ {
for (int32 i = 0; i < Info->item_count; i++) { for (int32 i = 0; i < Info->item_count; i++) {
uint16 length = 0; uint16 length = 0;
int16 data = 0; int16 data = 0;
@@ -1658,48 +1616,48 @@ AudioControlInterface::SetMix(multi_mix_value_info *Info)
data = static_cast<int16>(Info->values[i].gain * 256.); data = static_cast<int16>(Info->values[i].gain * 256.);
length = 2; length = 2;
TRACE("Gain control %d; channel: %d; about to set to %f dB.\n", TRACE("Gain control %d; channel: %d; about to set to %f dB.\n",
ID_FROM_CTLID(Info->values[i].id), ID_FROM_CTLID(Info->values[i].id),
CN_FROM_CTLID(Info->values[i].id), CN_FROM_CTLID(Info->values[i].id),
Info->values[i].gain); Info->values[i].gain);
break; break;
case UAS_MUTE_CONTROL: case UAS_MUTE_CONTROL:
data = (Info->values[i].enable ? 1 : 0); data = (Info->values[i].enable ? 1 : 0);
length = 1; length = 1;
TRACE("Mute control %d; channel: %d; about to set to %d.\n", TRACE("Mute control %d; channel: %d; about to set to %d.\n",
ID_FROM_CTLID(Info->values[i].id), ID_FROM_CTLID(Info->values[i].id),
CN_FROM_CTLID(Info->values[i].id), CN_FROM_CTLID(Info->values[i].id),
Info->values[i].enable); Info->values[i].enable);
break; break;
case UAS_AUTOMATIC_GAIN_CONTROL: case UAS_AUTOMATIC_GAIN_CONTROL:
data = (Info->values[i].enable ? 1 : 0); data = (Info->values[i].enable ? 1 : 0);
length = 1; length = 1;
TRACE("AGain control %d; channel: %d; about to set to %d.\n", TRACE("AGain control %d; channel: %d; about to set to %d.\n",
ID_FROM_CTLID(Info->values[i].id), ID_FROM_CTLID(Info->values[i].id),
CN_FROM_CTLID(Info->values[i].id), CN_FROM_CTLID(Info->values[i].id),
Info->values[i].enable); Info->values[i].enable);
break; break;
case 0: // Selector Unit case 0: // Selector Unit
data = Info->values[i].mux; data = Info->values[i].mux;
length = 1; length = 1;
TRACE("Selector Control %d about to set to %d.\n", TRACE("Selector Control %d about to set to %d.\n",
ID_FROM_CTLID(Info->values[i].id), ID_FROM_CTLID(Info->values[i].id),
Info->values[i].mux); Info->values[i].mux);
break; break;
default: default:
TRACE_ALWAYS("Unsupported control type %#02x ignored.\n", TRACE_ALWAYS("Unsupported control type %#02x ignored.\n",
CS_FROM_CTLID(Info->values[i].id)); CS_FROM_CTLID(Info->values[i].id));
continue; continue;
} }
size_t actualLength = 0; size_t actualLength = 0;
status_t status = gUSBModule->send_request(fDevice->USBDevice(), status_t status = gUSBModule->send_request(fDevice->USBDevice(),
USB_REQTYPE_INTERFACE_OUT | USB_REQTYPE_CLASS, UAS_SET_CUR, USB_REQTYPE_INTERFACE_OUT | USB_REQTYPE_CLASS, UAS_SET_CUR,
REQ_VALUE(Info->values[i].id), REQ_INDEX(Info->values[i].id), REQ_VALUE(Info->values[i].id), REQ_INDEX(Info->values[i].id),
length, &data, &actualLength); length, &data, &actualLength);
if (status != B_OK || actualLength != length) { if (status != B_OK || actualLength != length) {
TRACE_ALWAYS("Request failed:%#08x; send %d of %d\n", TRACE_ALWAYS("Request failed:%#08x; send %d of %d\n",
status, actualLength, length); status, actualLength, length);
continue; continue;
} }
@@ -1,6 +1,6 @@
/* /*
* Driver for USB Audio Device Class devices. * Driver for USB Audio Device Class devices.
* Copyright (c) 2009,10,12 S.Zharski <[email protected]> * Copyright (c) 2009-13 S.Zharski <[email protected]>
* Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
* *
*/ */
@@ -8,97 +8,100 @@
#define _AUDIO_CONTROL_INTERFACE_H_ #define _AUDIO_CONTROL_INTERFACE_H_
#include <util/VectorMap.h>
#include "Driver.h"
#include "USB_audio_spec.h" #include "USB_audio_spec.h"
#include <hmulti_audio.h>
#include <util/VectorMap.h>
#include <USB3.h>
class Device;
class AudioControlInterface; class AudioControlInterface;
class _AudioControl;
typedef VectorMap<uint32, _AudioControl*> AudioControlsMap;
typedef VectorMap<uint32, _AudioControl*>::Iterator AudioControlsIterator;
class AudioChannelCluster { class AudioChannelCluster {
public: public:
AudioChannelCluster(); AudioChannelCluster();
virtual ~AudioChannelCluster(); virtual ~AudioChannelCluster();
uint8 ChannelsCount() { return fOutChannelsNumber; } uint8 ChannelsCount() { return fOutChannelsNumber; }
uint32 ChannelsConfig() { return fChannelsConfig; } uint32 ChannelsConfig() { return fChannelsConfig; }
protected: protected:
uint8 fOutChannelsNumber; uint8 fOutChannelsNumber;
uint32 fChannelsConfig; uint32 fChannelsConfig;
uint8 fChannelNames; uint8 fChannelNames;
}; };
template< class __base_class_name > template<class __base_class_name>
class _AudioChannelCluster class _AudioChannelCluster : public __base_class_name,
: public __base_class_name, public AudioChannelCluster { public AudioChannelCluster {
public: public:
_AudioChannelCluster(AudioControlInterface* interface, _AudioChannelCluster(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header) usb_audiocontrol_header_descriptor* Header)
: :
__base_class_name(interface, Header) {} __base_class_name(interface, Header) {}
virtual ~_AudioChannelCluster() {} virtual ~_AudioChannelCluster() {}
virtual AudioChannelCluster*
OutCluster() { return this; }
virtual AudioChannelCluster*
OutCluster() { return this; }
}; };
//
// base class for Audio Controls (Units and Terminals)
//
//
class _AudioControl { class _AudioControl {
public: public:
_AudioControl(AudioControlInterface* interface, _AudioControl(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header); usb_audiocontrol_header_descriptor* Header);
virtual ~_AudioControl(); virtual ~_AudioControl();
uint8 ID() { return fID; } uint8 ID() { return fID; }
uint8 SourceID() { return fSourceID; } uint8 SourceID() { return fSourceID; }
uint8 SubType() { return fSubType; } uint8 SubType() { return fSubType; }
status_t InitCheck() { return fStatus; }; status_t InitCheck() { return fStatus; };
virtual const char* Name() { return ""; }
virtual AudioChannelCluster* OutCluster(); virtual const char* Name() { return ""; }
virtual AudioChannelCluster*
OutCluster();
protected: protected:
// state tracking status_t fStatus;
status_t fStatus; AudioControlInterface* fInterface;
AudioControlInterface* fInterface; uint8 fSubType;
uint8 fSubType; uint8 fID;
uint8 fID; uint8 fSourceID;
uint8 fSourceID; uint8 fStringIndex;
uint8 fStringIndex;
}; };
class _Terminal : public _AudioControl { class _Terminal : public _AudioControl {
public: public:
_Terminal(AudioControlInterface* interface, _Terminal(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header); usb_audiocontrol_header_descriptor* Header);
virtual ~_Terminal(); virtual ~_Terminal();
uint16 TerminalType() { return fTerminalType; } uint16 TerminalType() { return fTerminalType; }
bool IsUSBIO(); bool IsUSBIO();
virtual const char* Name(); virtual const char* Name();
protected: protected:
uint16 fTerminalType; uint16 fTerminalType;
uint8 fAssociatedTerminal; uint8 fAssociatedTerminal;
uint8 fClockSourceId; uint8 fClockSourceId;
uint16 fControlsBitmap; uint16 fControlsBitmap;
}; };
class InputTerminal : public _AudioChannelCluster<_Terminal> { class InputTerminal : public _AudioChannelCluster<_Terminal> {
public: public:
InputTerminal(AudioControlInterface* interface, InputTerminal(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header); usb_audiocontrol_header_descriptor* Header);
virtual ~InputTerminal(); virtual ~InputTerminal();
protected: protected:
}; };
@@ -108,7 +111,7 @@ class OutputTerminal : public _Terminal {
public: public:
OutputTerminal(AudioControlInterface* interface, OutputTerminal(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header); usb_audiocontrol_header_descriptor* Header);
virtual ~OutputTerminal(); virtual ~OutputTerminal();
protected: protected:
}; };
@@ -118,12 +121,12 @@ class MixerUnit : public _AudioChannelCluster<_AudioControl> {
public: public:
MixerUnit(AudioControlInterface* interface, MixerUnit(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header); usb_audiocontrol_header_descriptor* Header);
virtual ~MixerUnit(); virtual ~MixerUnit();
protected: protected:
Vector<uint8> fInputPins; Vector<uint8> fInputPins;
Vector<uint8> fProgrammableControls; Vector<uint8> fProgrammableControls;
uint8 fControlsBitmap; uint8 fControlsBitmap;
}; };
@@ -131,12 +134,14 @@ class SelectorUnit : public _AudioControl {
public: public:
SelectorUnit(AudioControlInterface* interface, SelectorUnit(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header); usb_audiocontrol_header_descriptor* Header);
virtual ~SelectorUnit(); virtual ~SelectorUnit();
virtual AudioChannelCluster*
OutCluster();
virtual AudioChannelCluster* OutCluster();
// protected: // protected:
Vector<uint8> fInputPins; Vector<uint8> fInputPins;
uint8 fControlsBitmap; uint8 fControlsBitmap;
}; };
@@ -144,29 +149,29 @@ class FeatureUnit : public _AudioControl {
public: public:
FeatureUnit(AudioControlInterface* interface, FeatureUnit(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header); usb_audiocontrol_header_descriptor* Header);
virtual ~FeatureUnit(); virtual ~FeatureUnit();
virtual const char* Name(); virtual const char* Name();
bool HasControl(int32 Channel, uint32 Control); bool HasControl(int32 Channel, uint32 Control);
// protected: // protected:
void NormalizeAndTraceChannel(int32 Channel); void NormalizeAndTraceChannel(int32 Channel);
Vector<uint32> fControlBitmaps; Vector<uint32> fControlBitmaps;
}; };
class EffectUnit : public _AudioControl/*, public _AudioChannelsCluster*/ { class EffectUnit : public _AudioControl {
public: public:
EffectUnit(AudioControlInterface* interface, EffectUnit(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header); usb_audiocontrol_header_descriptor* Header);
virtual ~EffectUnit(); virtual ~EffectUnit();
protected: protected:
/* uint16 fProcessType; /* uint16 fProcessType;
Vector<uint8> fInputPins; Vector<uint8> fInputPins;
uint8 fControlsBitmap; uint8 fControlsBitmap;
Vector<uint16> fModes; Vector<uint16> fModes;
*/}; */};
@@ -174,13 +179,13 @@ class ProcessingUnit : public _AudioChannelCluster<_AudioControl> {
public: public:
ProcessingUnit(AudioControlInterface* interface, ProcessingUnit(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header); usb_audiocontrol_header_descriptor* Header);
virtual ~ProcessingUnit(); virtual ~ProcessingUnit();
protected: protected:
uint16 fProcessType; uint16 fProcessType;
Vector<uint8> fInputPins; Vector<uint8> fInputPins;
uint8 fControlsBitmap; uint8 fControlsBitmap;
Vector<uint16> fModes; Vector<uint16> fModes;
}; };
@@ -188,12 +193,12 @@ class ExtensionUnit : public _AudioChannelCluster<_AudioControl> {
public: public:
ExtensionUnit(AudioControlInterface* interface, ExtensionUnit(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header); usb_audiocontrol_header_descriptor* Header);
virtual ~ExtensionUnit(); virtual ~ExtensionUnit();
protected: protected:
uint16 fExtensionCode; uint16 fExtensionCode;
Vector<uint8> fInputPins; Vector<uint8> fInputPins;
uint8 fControlsBitmap; uint8 fControlsBitmap;
}; };
@@ -201,7 +206,7 @@ class ClockSource : public _AudioControl {
public: public:
ClockSource(AudioControlInterface* interface, ClockSource(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header); usb_audiocontrol_header_descriptor* Header);
virtual ~ClockSource(); virtual ~ClockSource();
protected: protected:
}; };
@@ -211,7 +216,7 @@ class ClockSelector : public _AudioControl {
public: public:
ClockSelector(AudioControlInterface* interface, ClockSelector(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header); usb_audiocontrol_header_descriptor* Header);
virtual ~ClockSelector(); virtual ~ClockSelector();
protected: protected:
}; };
@@ -221,7 +226,7 @@ class ClockMultiplier : public _AudioControl {
public: public:
ClockMultiplier(AudioControlInterface* interface, ClockMultiplier(AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header); usb_audiocontrol_header_descriptor* Header);
virtual ~ClockMultiplier(); virtual ~ClockMultiplier();
protected: protected:
}; };
@@ -232,88 +237,82 @@ public:
SampleRateConverter( SampleRateConverter(
AudioControlInterface* interface, AudioControlInterface* interface,
usb_audiocontrol_header_descriptor* Header); usb_audiocontrol_header_descriptor* Header);
virtual ~SampleRateConverter(); virtual ~SampleRateConverter();
protected: protected:
}; };
typedef VectorMap<uint32, _AudioControl*> AudioControlsMap;
typedef VectorMap<uint32, _AudioControl*>::Iterator AudioControlsIterator;
typedef Vector<_AudioControl*> AudioControlsVector;
// typedef Vector<_AudioControl*>::Iterator AudioControlsIterator;
class Device;
class AudioControlInterface { class AudioControlInterface {
public: public:
AudioControlInterface(Device* device); AudioControlInterface(Device* device);
~AudioControlInterface(); ~AudioControlInterface();
status_t InitCheck() { return fStatus; } status_t InitCheck() { return fStatus; }
status_t Init(size_t interface, usb_interface_info *Interface); status_t Init(size_t interface, usb_interface_info* Interface);
_AudioControl* Find(uint8 id); _AudioControl* Find(uint8 id);
_AudioControl* FindOutputTerminal(uint8 id); _AudioControl* FindOutputTerminal(uint8 id);
uint16 SpecReleaseNumber() { return fADCSpecification; } uint16 SpecReleaseNumber() { return fADCSpecification; }
AudioControlsMap& Controls() { return fAudioControls; } AudioControlsMap&
Controls() { return fAudioControls; }
uint32 GetChannelsDescription( uint32 GetChannelsDescription(
Vector<multi_channel_info>& Channels, Vector<multi_channel_info>& Channels,
multi_description *Description, multi_description* Description,
AudioControlsVector &USBTerminals); Vector<_AudioControl*>& USBTerminals);
uint32 GetBusChannelsDescription( uint32 GetBusChannelsDescription(
Vector<multi_channel_info>& Channels, Vector<multi_channel_info>& Channels,
multi_description *Description); multi_description* Description);
status_t GetMix(multi_mix_value_info *Info); status_t GetMix(multi_mix_value_info* Info);
status_t SetMix(multi_mix_value_info *Info); status_t SetMix(multi_mix_value_info* Info);
status_t ListMixControls(multi_mix_control_info* Info); status_t ListMixControls(multi_mix_control_info* Info);
protected: protected:
status_t InitACHeader(size_t interface, status_t InitACHeader(size_t interface,
usb_audiocontrol_header_descriptor* Header); usb_audiocontrol_header_descriptor* Header);
uint32 GetTerminalChannels( uint32 GetTerminalChannels(
Vector<multi_channel_info>& Channels, Vector<multi_channel_info>& Channels,
AudioChannelCluster* cluster, AudioChannelCluster* cluster,
channel_kind kind, uint32 connectors = 0); channel_kind kind, uint32 connectors = 0);
void _HarvestRecordFeatureUnits(_AudioControl* rootControl, void _HarvestRecordFeatureUnits(_AudioControl* rootControl,
AudioControlsMap& Map); AudioControlsMap& Map);
void _ListMixControlsPage(int32& index, void _ListMixControlsPage(int32& index,
multi_mix_control_info* Info, multi_mix_control_info* Info,
AudioControlsMap& Map, const char* Name); AudioControlsMap& Map, const char* Name);
int32 _ListFeatureUnitControl(int32& index, int32 parentId, int32 _ListFeatureUnitControl(int32& index, int32 parentId,
multi_mix_control_info* Info, multi_mix_control_info* Info,
_AudioControl* control); _AudioControl* control);
uint32 _ListFeatureUnitOption(uint32 controlType, uint32 _ListFeatureUnitOption(uint32 controlType,
int32& index, int32 parentIndex, int32& index, int32 parentIndex,
multi_mix_control_info* Info, FeatureUnit* unit, multi_mix_control_info* Info, FeatureUnit* unit,
uint32 channel, uint32 channels); uint32 channel, uint32 channels);
void _ListSelectorUnitControl(int32& index, int32 parentGroup, void _ListSelectorUnitControl(int32& index,
multi_mix_control_info* Info, int32 parentGroup, multi_mix_control_info* Info,
_AudioControl* control); _AudioControl* control);
void _InitGainLimits(multi_mix_control& Control); void _InitGainLimits(multi_mix_control& Control);
size_t fInterface; size_t fInterface;
status_t fStatus; status_t fStatus;
// part of AudioControl Header description // part of AudioControl Header description
uint16 fADCSpecification; uint16 fADCSpecification;
Vector<uint8> fStreams; Vector<uint8> fStreams;
uint8 fFunctionCategory; uint8 fFunctionCategory;
uint8 fControlsBitmap; uint8 fControlsBitmap;
Device* fDevice; Device* fDevice;
// map to store all controls and lookup by control ID // map to store all controls and lookup by control ID
AudioControlsMap fAudioControls; AudioControlsMap fAudioControls;
// map to store output terminal and lookup them by source ID // map to store output terminal and lookup them by source ID
AudioControlsMap fOutputTerminals; AudioControlsMap fOutputTerminals;
// map to store output terminal and lookup them by control ID // map to store output terminal and lookup them by control ID
AudioControlsMap fInputTerminals; AudioControlsMap fInputTerminals;
}; };
#endif // _AUDIO_CONTROL_INTERFACE_H_ #endif // _AUDIO_CONTROL_INTERFACE_H_
File diff suppressed because it is too large Load Diff
@@ -1,349 +0,0 @@
/*
* Driver for USB Audio Device Class devices.
* Copyright (c) 2009,10,12 S.Zharski <[email protected]>
* Distributed under the terms of the MIT license.
*
*/
#ifndef _AUDIO_FUNCTION_H_
#define _AUDIO_FUNCTION_H_
#include <VectorMap.h>
#include "Driver.h"
#include "USB_audio_spec.h"
class Device;
//
// base class for all entities in Audio Function
//
//
class _AudioFunctionEntity {
public:
_AudioFunctionEntity(Device* device, size_t interface);
~_AudioFunctionEntity();
status_t InitCheck() { return fStatus; };
protected:
// state tracking
status_t fStatus;
Device* fDevice;
size_t fInterface;
};
class _AudioChannelsCluster {
public:
_AudioChannelsCluster();
virtual ~_AudioChannelsCluster();
virtual _AudioChannelsCluster* OutputCluster();
protected:
uint8 fOutChannelsNumber;
uint32 fChannelsConfig;
uint8 fChannelNames;
};
//
// base class for Audio Controls (Units and Terminals)
//
//
class _AudioControl : public _AudioFunctionEntity {
public:
_AudioControl(Device* device, size_t interface,
usb_audiocontrol_header_descriptor* Header);
virtual ~_AudioControl();
uint8 ID() { return fID; }
uint8 SourceID() { return fSourceID; }
uint8 SubType() { return fSubType; }
virtual const char* Name() { return ""; }
virtual _AudioChannelsCluster* OutputCluster();
protected:
// state tracking
uint8 fSubType;
uint8 fID;
uint8 fSourceID;
uint8 fStringIndex;
};
class AudioControlHeader : public _AudioControl {
public:
AudioControlHeader(Device* device, size_t interface,
usb_audiocontrol_header_descriptor* Header);
virtual ~AudioControlHeader();
// protected:
uint16 fADCSpecification;
Vector<uint8> fStreams;
uint8 fFunctionCategory;
uint8 fControlsBitmap;
};
class _Terminal : public _AudioControl {
public:
_Terminal(Device* device, size_t interface,
usb_audiocontrol_header_descriptor* Header);
virtual ~_Terminal();
uint16 TerminalType() { return fTerminalType; }
bool IsUSBIO();
virtual const char* Name();
protected:
uint16 fTerminalType;
uint8 fAssociatedTerminal;
uint8 fClockSourceId;
uint16 fControlsBitmap;
};
class InputTerminal : public _Terminal, public _AudioChannelsCluster {
public:
InputTerminal(Device* device, size_t interface,
usb_audiocontrol_header_descriptor* Header);
virtual ~InputTerminal();
protected:
};
class OutputTerminal : public _Terminal {
public:
OutputTerminal(Device* device, size_t interface,
usb_audiocontrol_header_descriptor* Header);
virtual ~OutputTerminal();
protected:
};
class MixerUnit : public _AudioControl, public _AudioChannelsCluster {
public:
MixerUnit(Device* device, size_t interface,
usb_audiocontrol_header_descriptor* Header);
virtual ~MixerUnit();
protected:
Vector<uint8> fInputPins;
Vector<uint8> fProgrammableControls;
uint8 fControlsBitmap;
};
class SelectorUnit : public _AudioControl {
public:
SelectorUnit(Device* device, size_t interface,
usb_audiocontrol_header_descriptor* Header);
virtual ~SelectorUnit();
protected:
Vector<uint8> fInputPins;
uint8 fControlsBitmap;
};
class FeatureUnit : public _AudioControl {
public:
FeatureUnit(Device* device, size_t interface,
usb_audiocontrol_header_descriptor* Header);
virtual ~FeatureUnit();
virtual const char* Name();
bool HasControl(int32 Channel, uint32 Control);
protected:
void TraceChannel(Device* device, int32 Channel);
Vector<uint32> fControlBitmaps;
};
class EffectUnit : public _AudioControl/*, public _AudioChannelsCluster*/ {
public:
EffectUnit(Device* device, size_t interface,
usb_audiocontrol_header_descriptor* Header);
virtual ~EffectUnit();
protected:
/* uint16 fProcessType;
Vector<uint8> fInputPins;
uint8 fControlsBitmap;
Vector<uint16> fModes;
*/};
class ProcessingUnit : public _AudioControl, public _AudioChannelsCluster {
public:
ProcessingUnit(Device* device, size_t interface,
usb_audiocontrol_header_descriptor* Header);
virtual ~ProcessingUnit();
protected:
uint16 fProcessType;
Vector<uint8> fInputPins;
uint8 fControlsBitmap;
Vector<uint16> fModes;
};
class ExtensionUnit : public _AudioControl, public _AudioChannelsCluster {
public:
ExtensionUnit(Device* device, size_t interface,
usb_audiocontrol_header_descriptor* Header);
virtual ~ExtensionUnit();
protected:
uint16 fExtensionCode;
Vector<uint8> fInputPins;
uint8 fControlsBitmap;
};
class ClockSource : public _AudioControl {
public:
ClockSource(Device* device, size_t interface,
usb_audiocontrol_header_descriptor* Header);
virtual ~ClockSource();
protected:
};
class ClockSelector : public _AudioControl {
public:
ClockSelector(Device* device, size_t interface,
usb_audiocontrol_header_descriptor* Header);
virtual ~ClockSelector();
protected:
};
class ClockMultiplier : public _AudioControl {
public:
ClockMultiplier(Device* device, size_t interface,
usb_audiocontrol_header_descriptor* Header);
virtual ~ClockMultiplier();
protected:
};
class SampleRateConverter : public _AudioControl {
public:
SampleRateConverter(Device* device, size_t interface,
usb_audiocontrol_header_descriptor* Header);
virtual ~SampleRateConverter();
protected:
};
//
// Audio Streaming Interface information entities
//
//
class ASInterfaceDescriptor : public _AudioFunctionEntity {
public:
ASInterfaceDescriptor(Device* device, size_t interface,
usb_as_interface_descriptor_r1* Descriptor);
~ASInterfaceDescriptor();
// protected:
uint8 fTerminalLink;
uint8 fDelay;
uint16 fFormatTag;
};
class ASEndpointDescriptor : public _AudioFunctionEntity {
public:
ASEndpointDescriptor(Device* device, size_t interface,
usb_as_cs_endpoint_descriptor* Descriptor);
~ASEndpointDescriptor();
// protected:
uint8 fAttributes;
uint8 fLockDelayUnits;
uint16 fLockDelay;
};
class _ASFormatDescriptor : public _AudioFunctionEntity {
public:
_ASFormatDescriptor(Device* device, size_t interface);
virtual ~_ASFormatDescriptor();
// protected:
uint32 GetSamFreq(uint8* freq);
};
class TypeIFormatDescriptor : public _ASFormatDescriptor {
public:
TypeIFormatDescriptor(Device* device, size_t interface,
usb_type_I_format_descriptor* Descriptor);
virtual ~TypeIFormatDescriptor();
status_t Init(usb_type_I_format_descriptor* Descriptor);
// protected:
uint8 fNumChannels;
uint8 fSubframeSize;
uint8 fBitResolution;
uint8 fSampleFrequencyType;
Vector<uint32> fSampleFrequencies;
};
class TypeIIFormatDescriptor : public _ASFormatDescriptor {
public:
TypeIIFormatDescriptor(Device* device, size_t interface,
usb_type_II_format_descriptor* Descriptor);
virtual ~TypeIIFormatDescriptor();
// protected:
uint16 fMaxBitRate;
uint16 fSamplesPerFrame;
uint8 fSampleFrequencyType;
Vector<uint32> fSampleFrequencies;
};
class TypeIIIFormatDescriptor : public TypeIFormatDescriptor {
public:
TypeIIIFormatDescriptor(Device* device, size_t interface,
usb_type_III_format_descriptor* Descriptor);
virtual ~TypeIIIFormatDescriptor();
// protected:
};
class AudioStreamAlternate {
public:
AudioStreamAlternate(size_t alternate,
ASInterfaceDescriptor* interface,
ASEndpointDescriptor* endpoint,
_ASFormatDescriptor* format);
~AudioStreamAlternate();
ASInterfaceDescriptor* Interface() { return fInterface; }
ASEndpointDescriptor* Endpoint() { return fEndpoint; }
_ASFormatDescriptor* Format() { return fFormat; }
protected:
size_t fAlternate;
ASInterfaceDescriptor* fInterface;
ASEndpointDescriptor* fEndpoint;
_ASFormatDescriptor* fFormat;
};
#endif // _AUDIO_FUNCTION_H_
@@ -5,10 +5,13 @@
* *
*/ */
#include "AudioStreamingInterface.h" #include "AudioStreamingInterface.h"
#include "Settings.h"
#include "Device.h"
#include "audio.h" #include "audio.h"
#include "Driver.h"
#include "Settings.h"
static struct RatePair { static struct RatePair {
@@ -38,13 +41,12 @@ static struct RatePair {
// Audio Stream information entities // Audio Stream information entities
// //
// //
ASInterfaceDescriptor::ASInterfaceDescriptor(/*Device* device, size_t interface,*/ ASInterfaceDescriptor::ASInterfaceDescriptor(
usb_as_interface_descriptor_r1* Descriptor) usb_as_interface_descriptor_r1* Descriptor)
: :
// _AudioFunctionEntity(device, interface), fTerminalLink(0),
fTerminalLink(0), fDelay(0),
fDelay(0), fFormatTag(0)
fFormatTag(0)
{ {
fTerminalLink = Descriptor->terminal_link; fTerminalLink = Descriptor->terminal_link;
fDelay = Descriptor->delay; fDelay = Descriptor->delay;
@@ -60,22 +62,21 @@ ASInterfaceDescriptor::ASInterfaceDescriptor(/*Device* device, size_t interface,
ASInterfaceDescriptor::~ASInterfaceDescriptor() ASInterfaceDescriptor::~ASInterfaceDescriptor()
{ {
} }
ASEndpointDescriptor::ASEndpointDescriptor(usb_endpoint_descriptor* Endpoint, ASEndpointDescriptor::ASEndpointDescriptor(usb_endpoint_descriptor* Endpoint,
usb_as_cs_endpoint_descriptor* Descriptor) usb_as_cs_endpoint_descriptor* Descriptor)
: :
fCSAttributes(0), fCSAttributes(0),
fLockDelayUnits(0), fLockDelayUnits(0),
fLockDelay(0), fLockDelay(0),
fMaxPacketSize(0), fMaxPacketSize(0),
fEndpointAddress(0), fEndpointAddress(0),
fEndpointAttributes(0) fEndpointAttributes(0)
{ {
// usb_audiocontrol_header_descriptor *Header // usb_audiocontrol_header_descriptor* Header
// = (usb_audiocontrol_header_descriptor *)Interface->generic[i]; // = (usb_audiocontrol_header_descriptor*)Interface->generic[i];
fCSAttributes = Descriptor->attributes; fCSAttributes = Descriptor->attributes;
fLockDelayUnits = Descriptor->lock_delay_units; fLockDelayUnits = Descriptor->lock_delay_units;
@@ -100,10 +101,10 @@ ASEndpointDescriptor::~ASEndpointDescriptor()
} }
_ASFormatDescriptor::_ASFormatDescriptor(usb_type_I_format_descriptor* Descriptor) _ASFormatDescriptor::_ASFormatDescriptor(
: usb_type_I_format_descriptor* Descriptor)
/*_AudioFunctionEntity(device, interface)*/ :
fFormatType(UAF_FORMAT_TYPE_UNDEFINED) fFormatType(UAF_FORMAT_TYPE_UNDEFINED)
{ {
fFormatType = Descriptor->format_type; fFormatType = Descriptor->format_type;
} }
@@ -121,14 +122,14 @@ _ASFormatDescriptor::GetSamFreq(uint8* freq)
} }
TypeIFormatDescriptor::TypeIFormatDescriptor(/*Device* device, size_t interface,*/ TypeIFormatDescriptor::TypeIFormatDescriptor(
usb_type_I_format_descriptor* Descriptor) usb_type_I_format_descriptor* Descriptor)
: :
_ASFormatDescriptor(Descriptor), _ASFormatDescriptor(Descriptor),
fNumChannels(0), fNumChannels(0),
fSubframeSize(0), fSubframeSize(0),
fBitResolution(0), fBitResolution(0),
fSampleFrequencyType(0) fSampleFrequencyType(0)
{ {
/*fStatus =*/ Init(Descriptor); /*fStatus =*/ Init(Descriptor);
} }
@@ -149,37 +150,34 @@ TypeIFormatDescriptor::Init(usb_type_I_format_descriptor* Descriptor)
if (fSampleFrequencyType == 0) { if (fSampleFrequencyType == 0) {
fSampleFrequencies.PushBack( fSampleFrequencies.PushBack(
GetSamFreq(Descriptor->sf.cont.lower_sam_freq)); GetSamFreq(Descriptor->sf.cont.lower_sam_freq));
fSampleFrequencies.PushBack( fSampleFrequencies.PushBack(
GetSamFreq(Descriptor->sf.cont.upper_sam_freq)); GetSamFreq(Descriptor->sf.cont.upper_sam_freq));
} else { } else
for (size_t i = 0; i < fSampleFrequencyType; i++) { for (size_t i = 0; i < fSampleFrequencyType; i++)
fSampleFrequencies.PushBack( fSampleFrequencies.PushBack(
GetSamFreq(Descriptor->sf.discr.sam_freq[i])); GetSamFreq(Descriptor->sf.discr.sam_freq[i]));
}
}
TRACE("fNumChannels:%d\n", fNumChannels); TRACE("fNumChannels:%d\n", fNumChannels);
TRACE("fSubframeSize:%d\n", fSubframeSize); TRACE("fSubframeSize:%d\n", fSubframeSize);
TRACE("fBitResolution:%d\n", fBitResolution); TRACE("fBitResolution:%d\n", fBitResolution);
TRACE("fSampleFrequencyType:%d\n", fSampleFrequencyType); TRACE("fSampleFrequencyType:%d\n", fSampleFrequencyType);
for (int32 i = 0; i < fSampleFrequencies.Count(); i++) { for (int32 i = 0; i < fSampleFrequencies.Count(); i++)
TRACE("Frequency #%d: %d\n", i, fSampleFrequencies[i]); TRACE("Frequency #%d: %d\n", i, fSampleFrequencies[i]);
}
return B_OK; return B_OK;
} }
TypeIIFormatDescriptor::TypeIIFormatDescriptor(/*Device* device, size_t interface,*/ TypeIIFormatDescriptor::TypeIIFormatDescriptor(
usb_type_II_format_descriptor* Descriptor) usb_type_II_format_descriptor* Descriptor)
: :
_ASFormatDescriptor((usb_type_I_format_descriptor*)Descriptor), _ASFormatDescriptor((usb_type_I_format_descriptor*)Descriptor),
fMaxBitRate(0), fMaxBitRate(0),
fSamplesPerFrame(0), fSamplesPerFrame(0),
fSampleFrequencyType(0), fSampleFrequencyType(0),
fSampleFrequencies(0) fSampleFrequencies(0)
{ {
} }
@@ -189,13 +187,11 @@ TypeIIFormatDescriptor::~TypeIIFormatDescriptor()
} }
TypeIIIFormatDescriptor::TypeIIIFormatDescriptor(/*Device* device, size_t interface,*/ TypeIIIFormatDescriptor::TypeIIIFormatDescriptor(
usb_type_III_format_descriptor* Descriptor) usb_type_III_format_descriptor* Descriptor)
: :
TypeIFormatDescriptor(/*device, interface, */ TypeIFormatDescriptor((usb_type_I_format_descriptor*)Descriptor)
(usb_type_I_format_descriptor*) Descriptor)
{ {
} }
@@ -205,17 +201,15 @@ TypeIIIFormatDescriptor::~TypeIIIFormatDescriptor()
AudioStreamAlternate::AudioStreamAlternate(size_t alternate, AudioStreamAlternate::AudioStreamAlternate(size_t alternate,
ASInterfaceDescriptor* interface, ASInterfaceDescriptor* interface, ASEndpointDescriptor* endpoint,
ASEndpointDescriptor* endpoint, _ASFormatDescriptor* format)
_ASFormatDescriptor* format) :
: fAlternate(alternate),
fAlternate(alternate), fInterface(interface),
fInterface(interface), fEndpoint(endpoint),
fEndpoint(endpoint), fFormat(format),
fFormat(format), fSamplingRate(0)
fSamplingRate(0)
{ {
// SetSamplingRate(0); // init to default (max) sampling rate
} }
@@ -269,7 +263,6 @@ AudioStreamAlternate::SetSamplingRate(uint32 newRate)
} }
} }
// newRate = fSamplingRate;
return B_OK; return B_OK;
} }
@@ -388,13 +381,13 @@ AudioStreamAlternate::SetFormatId(uint32 /*newFormatId*/)
AudioStreamingInterface::AudioStreamingInterface( AudioStreamingInterface::AudioStreamingInterface(
AudioControlInterface* controlInterface, AudioControlInterface* controlInterface,
size_t interface, usb_interface_list *List) size_t interface, usb_interface_list* List)
: :
fInterface(interface), fInterface(interface),
fControlInterface(controlInterface), fControlInterface(controlInterface),
fIsInput(false), fIsInput(false),
fActiveAlternate(0) fActiveAlternate(0)
{ {
TRACE_ALWAYS("if[%d]:alt_count:%d\n", interface, List->alt_count); TRACE_ALWAYS("if[%d]:alt_count:%d\n", interface, List->alt_count);
@@ -403,34 +396,33 @@ AudioStreamingInterface::AudioStreamingInterface(
ASEndpointDescriptor* ASEndpoint = NULL; ASEndpointDescriptor* ASEndpoint = NULL;
_ASFormatDescriptor* ASFormat = NULL; _ASFormatDescriptor* ASFormat = NULL;
usb_interface_info *Interface = &List->alt[alt]; usb_interface_info* Interface = &List->alt[alt];
TRACE_ALWAYS("if[%d]:alt[%d]:descrs_count:%d\n", TRACE_ALWAYS("if[%d]:alt[%d]:descrs_count:%d\n",
interface, alt, Interface->generic_count); interface, alt, Interface->generic_count);
for (size_t i = 0; i < Interface->generic_count; i++) { for (size_t i = 0; i < Interface->generic_count; i++) {
usb_audiocontrol_header_descriptor *Header usb_audiocontrol_header_descriptor* Header
= (usb_audiocontrol_header_descriptor *)Interface->generic[i]; = (usb_audiocontrol_header_descriptor*)Interface->generic[i];
if (Header->descriptor_type == AC_CS_INTERFACE) { if (Header->descriptor_type == AC_CS_INTERFACE) {
switch(Header->descriptor_subtype) { switch(Header->descriptor_subtype) {
case UAS_AS_GENERAL: case UAS_AS_GENERAL:
if (ASInterface == 0) { if (ASInterface == 0)
ASInterface = new ASInterfaceDescriptor( ASInterface = new ASInterfaceDescriptor(
/*this, interface, */ (usb_as_interface_descriptor_r1*) Header);
(usb_as_interface_descriptor_r1*) Header); else
} else
TRACE_ALWAYS("Duplicate AStream interface ignored.\n"); TRACE_ALWAYS("Duplicate AStream interface ignored.\n");
break; break;
case UAS_FORMAT_TYPE: case UAS_FORMAT_TYPE:
if (ASFormat == 0) { if (ASFormat == 0)
ASFormat = new TypeIFormatDescriptor( ASFormat = new TypeIFormatDescriptor(
(usb_type_I_format_descriptor*) Header); (usb_type_I_format_descriptor*) Header);
} else else
TRACE_ALWAYS("Duplicate AStream format ignored.\n"); TRACE_ALWAYS("Duplicate AStream format ignored.\n");
break; break;
default: default:
TRACE_ALWAYS("Ignore AStream descr subtype %#04x\n", TRACE_ALWAYS("Ignore AStream descr subtype %#04x\n",
Header->descriptor_subtype); Header->descriptor_subtype);
break; break;
} }
continue; continue;
@@ -439,9 +431,9 @@ AudioStreamingInterface::AudioStreamingInterface(
if (Header->descriptor_type == AC_CS_ENDPOINT) { if (Header->descriptor_type == AC_CS_ENDPOINT) {
if (ASEndpoint == 0) { if (ASEndpoint == 0) {
usb_endpoint_descriptor* Endpoint usb_endpoint_descriptor* Endpoint
= Interface->endpoint[0].descr; = Interface->endpoint[0].descr;
ASEndpoint = new ASEndpointDescriptor(Endpoint, ASEndpoint = new ASEndpointDescriptor(Endpoint,
(usb_as_cs_endpoint_descriptor*)Header); (usb_as_cs_endpoint_descriptor*)Header);
} else } else
TRACE_ALWAYS("Duplicate AStream endpoint ignored.\n"); TRACE_ALWAYS("Duplicate AStream endpoint ignored.\n");
continue; continue;
@@ -452,21 +444,18 @@ AudioStreamingInterface::AudioStreamingInterface(
} }
fAlternates.Add(new AudioStreamAlternate(alt, ASInterface, fAlternates.Add(new AudioStreamAlternate(alt, ASInterface,
ASEndpoint, ASFormat)); ASEndpoint, ASFormat));
} }
} }
AudioStreamingInterface::~AudioStreamingInterface() AudioStreamingInterface::~AudioStreamingInterface()
{ {
// alternates of the streams
// StreamAlternatesVector fAlternates;
// size_t fActiveAlternate;
// we own stream header objects too, so free them // we own stream header objects too, so free them
for (StreamAlternatesIterator I = fAlternates.Begin(); for (Vector<AudioStreamAlternate*>::Iterator I = fAlternates.Begin();
I != fAlternates.End(); I++) { I != fAlternates.End(); I++)
delete *I; delete *I;
}
fAlternates.MakeEmpty(); fAlternates.MakeEmpty();
} }
@@ -474,10 +463,8 @@ AudioStreamingInterface::~AudioStreamingInterface()
uint8 uint8
AudioStreamingInterface::TerminalLink() AudioStreamingInterface::TerminalLink()
{ {
if (fAlternates[fActiveAlternate]->Interface() != 0) { if (fAlternates[fActiveAlternate]->Interface() != 0)
return fAlternates[fActiveAlternate]->Interface()->fTerminalLink; return fAlternates[fActiveAlternate]->Interface()->fTerminalLink;
}
return 0; return 0;
} }
@@ -496,71 +483,12 @@ AudioStreamingInterface::ChannelCluster()
} }
/*
ASInterfaceDescriptor*
Stream::ASInterface()
{
return fAlternates[fActiveAlternate]->Interface();
}
_ASFormatDescriptor*
Stream::ASFormat()
{
return fAlternates[fActiveAlternate]->Format();
} */
void void
AudioStreamingInterface::GetFormatsAndRates(multi_description *Description) AudioStreamingInterface::GetFormatsAndRates(multi_description* Description)
{ {
// TODO: fIsInput ??????
Description->interface_flags Description->interface_flags
|= fIsInput ? B_MULTI_INTERFACE_RECORD : B_MULTI_INTERFACE_PLAYBACK; |= fIsInput ? B_MULTI_INTERFACE_RECORD : B_MULTI_INTERFACE_PLAYBACK;
// uint32 rates = 0;
/*
TypeIFormatDescriptor* format
= static_cast<TypeIFormatDescriptor*>(
fAlternates[fActiveAlternate]->Format());
if (format == NULL || fAlternates[fActiveAlternate]->Interface() == NULL) {
TRACE_ALWAYS("Ignore alternate %d due format "
"%#08x or interface %#08x null.\n", fActiveAlternate, format,
fAlternates[fActiveAlternate]->Interface());
}
if (format->fSampleFrequencyType == 0) { // continuous frequencies
rates = B_SR_CVSR;
Description->min_cvsr_rate = float(format->fSampleFrequencies[0]);
Description->max_cvsr_rate = float(format->fSampleFrequencies[1]);
} else {
for (int i = 0; i < format->fSampleFrequencies.Count(); i++) {
switch(format->fSampleFrequencies[i]) {
case 8000: rates |= B_SR_8000; break;
case 11025: rates |= B_SR_11025; break;
case 12000: rates |= B_SR_12000; break;
case 16000: rates |= B_SR_16000; break;
case 22050: rates |= B_SR_22050; break;
case 24000: rates |= B_SR_24000; break;
case 32000: rates |= B_SR_32000; break;
case 44100: rates |= B_SR_44100; break;
case 48000: rates |= B_SR_48000; break;
case 64000: rates |= B_SR_64000; break;
case 88200: rates |= B_SR_88200; break;
case 96000: rates |= B_SR_96000; break;
case 176400: rates |= B_SR_176400; break;
case 192000: rates |= B_SR_192000; break;
case 384000: rates |= B_SR_384000; break;
case 1536000: rates |= B_SR_1536000; break;
default:
TRACE_ALWAYS("Ignore unsupported "
"sample rate %d for alternate %d.\n",
format->fSampleFrequencies[i], fActiveAlternate);
break;
}
}
}
*/
uint32 rates = fAlternates[fActiveAlternate]->GetSamplingRateIds(); uint32 rates = fAlternates[fActiveAlternate]->GetSamplingRateIds();
uint32 formats = fAlternates[fActiveAlternate]->GetFormatId(); uint32 formats = fAlternates[fActiveAlternate]->GetFormatId();
@@ -1,6 +1,6 @@
/* /*
* Driver for USB Audio Device Class devices. * Driver for USB Audio Device Class devices.
* Copyright (c) 2009,10,12 S.Zharski <[email protected]> * Copyright (c) 2009-13 S.Zharski <[email protected]>
* Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
* *
*/ */
@@ -8,31 +8,27 @@
#define _AUDIO_STREAMING_INTERFACE_H_ #define _AUDIO_STREAMING_INTERFACE_H_
#include "Driver.h"
#include "AudioControlInterface.h"
#include <util/VectorMap.h> #include <util/VectorMap.h>
#include <USB3.h>
#include "AudioControlInterface.h"
#include "USB_audio_spec.h" #include "USB_audio_spec.h"
// class ASInterfaceDescriptor {
// Audio Streaming Interface information entities
//
//
class ASInterfaceDescriptor /*: public _AudioFunctionEntity*/ {
public: public:
ASInterfaceDescriptor(/*Device* device, size_t interface,*/ ASInterfaceDescriptor(
usb_as_interface_descriptor_r1* Descriptor); usb_as_interface_descriptor_r1* Descriptor);
~ASInterfaceDescriptor(); ~ASInterfaceDescriptor();
// protected: // protected:
uint8 fTerminalLink; uint8 fTerminalLink;
uint8 fDelay; uint8 fDelay;
uint16 fFormatTag; uint16 fFormatTag;
}; };
class ASEndpointDescriptor /*: public _AudioFunctionEntity*/ { class ASEndpointDescriptor {
public: public:
ASEndpointDescriptor( ASEndpointDescriptor(
usb_endpoint_descriptor* Endpoint, usb_endpoint_descriptor* Endpoint,
@@ -40,63 +36,63 @@ public:
~ASEndpointDescriptor(); ~ASEndpointDescriptor();
// protected: // protected:
uint8 fCSAttributes; uint8 fCSAttributes;
uint8 fLockDelayUnits; uint8 fLockDelayUnits;
uint16 fLockDelay; uint16 fLockDelay;
uint16 fMaxPacketSize; uint16 fMaxPacketSize;
uint8 fEndpointAddress; uint8 fEndpointAddress;
uint8 fEndpointAttributes; uint8 fEndpointAttributes;
}; };
class _ASFormatDescriptor /*: public _AudioFunctionEntity*/ { class _ASFormatDescriptor {
public: public:
_ASFormatDescriptor( _ASFormatDescriptor(
usb_type_I_format_descriptor* Descriptor); usb_type_I_format_descriptor* Descriptor);
virtual ~_ASFormatDescriptor(); virtual ~_ASFormatDescriptor();
// protected: // protected:
uint8 fFormatType; uint8 fFormatType;
uint32 GetSamFreq(uint8* freq); uint32 GetSamFreq(uint8* freq);
}; };
class TypeIFormatDescriptor : public _ASFormatDescriptor { class TypeIFormatDescriptor : public _ASFormatDescriptor {
public: public:
TypeIFormatDescriptor(/*Device* device, size_t interface,*/ TypeIFormatDescriptor(
usb_type_I_format_descriptor* Descriptor); usb_type_I_format_descriptor* Descriptor);
virtual ~TypeIFormatDescriptor(); virtual ~TypeIFormatDescriptor();
status_t Init(usb_type_I_format_descriptor* Descriptor); status_t Init(usb_type_I_format_descriptor* Descriptor);
// protected: // protected:
uint8 fNumChannels; uint8 fNumChannels;
uint8 fSubframeSize; uint8 fSubframeSize;
uint8 fBitResolution; uint8 fBitResolution;
uint8 fSampleFrequencyType; uint8 fSampleFrequencyType;
Vector<uint32> fSampleFrequencies; Vector<uint32> fSampleFrequencies;
}; };
class TypeIIFormatDescriptor : public _ASFormatDescriptor { class TypeIIFormatDescriptor : public _ASFormatDescriptor {
public: public:
TypeIIFormatDescriptor(/*Device* device, size_t interface,*/ TypeIIFormatDescriptor(
usb_type_II_format_descriptor* Descriptor); usb_type_II_format_descriptor* Descriptor);
virtual ~TypeIIFormatDescriptor(); virtual ~TypeIIFormatDescriptor();
// protected: // protected:
uint16 fMaxBitRate; uint16 fMaxBitRate;
uint16 fSamplesPerFrame; uint16 fSamplesPerFrame;
uint8 fSampleFrequencyType; uint8 fSampleFrequencyType;
Vector<uint32> fSampleFrequencies; Vector<uint32> fSampleFrequencies;
}; };
class TypeIIIFormatDescriptor : public TypeIFormatDescriptor { class TypeIIIFormatDescriptor : public TypeIFormatDescriptor {
public: public:
TypeIIIFormatDescriptor(/*Device* device, size_t interface, */ TypeIIIFormatDescriptor(
usb_type_III_format_descriptor* Descriptor); usb_type_III_format_descriptor* Descriptor);
virtual ~TypeIIIFormatDescriptor(); virtual ~TypeIIIFormatDescriptor();
// protected: // protected:
}; };
@@ -104,63 +100,59 @@ public:
class AudioStreamAlternate { class AudioStreamAlternate {
public: public:
AudioStreamAlternate(size_t alternate, AudioStreamAlternate(size_t alternate,
ASInterfaceDescriptor* interface, ASInterfaceDescriptor* interface,
ASEndpointDescriptor* endpoint, ASEndpointDescriptor* endpoint,
_ASFormatDescriptor* format); _ASFormatDescriptor* format);
~AudioStreamAlternate(); ~AudioStreamAlternate();
ASInterfaceDescriptor* Interface() { return fInterface; } ASInterfaceDescriptor* Interface() { return fInterface; }
ASEndpointDescriptor* Endpoint() { return fEndpoint; } ASEndpointDescriptor* Endpoint() { return fEndpoint; }
_ASFormatDescriptor* Format() { return fFormat; } _ASFormatDescriptor* Format() { return fFormat; }
status_t SetSamplingRate(uint32 newRate); status_t SetSamplingRate(uint32 newRate);
status_t SetSamplingRateById(uint32 newId); status_t SetSamplingRateById(uint32 newId);
uint32 GetSamplingRate() { return fSamplingRate; } uint32 GetSamplingRate() { return fSamplingRate; }
uint32 GetSamplingRateId(uint32 rate); uint32 GetSamplingRateId(uint32 rate);
uint32 GetSamplingRateIds(); uint32 GetSamplingRateIds();
uint32 GetFormatId(); uint32 GetFormatId();
status_t SetFormatId(uint32 newFormatId); status_t SetFormatId(uint32 newFormatId);
uint32 SamplingRateFromId(uint32 id); uint32 SamplingRateFromId(uint32 id);
protected: protected:
size_t fAlternate; size_t fAlternate;
ASInterfaceDescriptor* fInterface; ASInterfaceDescriptor* fInterface;
ASEndpointDescriptor* fEndpoint; ASEndpointDescriptor* fEndpoint;
_ASFormatDescriptor* fFormat; _ASFormatDescriptor* fFormat;
uint32 fSamplingRate; uint32 fSamplingRate;
}; };
typedef Vector<AudioStreamAlternate*> StreamAlternatesVector;
typedef Vector<AudioStreamAlternate*>::Iterator StreamAlternatesIterator;
class AudioStreamingInterface { class AudioStreamingInterface {
public: public:
AudioStreamingInterface( AudioStreamingInterface(
AudioControlInterface* controlInterface, AudioControlInterface* controlInterface,
size_t interface, usb_interface_list *List); size_t interface, usb_interface_list* List);
~AudioStreamingInterface(); ~AudioStreamingInterface();
// status_t InitCheck() { return fStatus; } // status_t InitCheck() { return fStatus; }
uint8 TerminalLink(); uint8 TerminalLink();
bool IsInput() { return fIsInput; } bool IsInput() { return fIsInput; }
AudioChannelCluster* ChannelCluster(); AudioChannelCluster* ChannelCluster();
void GetFormatsAndRates(multi_description *Description);
void GetFormatsAndRates(
multi_description* Description);
protected: protected:
size_t fInterface; size_t fInterface;
AudioControlInterface* fControlInterface; AudioControlInterface* fControlInterface;
// status_t fStatus; // status_t fStatus;
bool fIsInput; bool fIsInput;
// alternates of the streams // alternates of the streams
StreamAlternatesVector fAlternates; Vector<AudioStreamAlternate*> fAlternates;
size_t fActiveAlternate; size_t fActiveAlternate;
}; };
@@ -1,36 +1,27 @@
/* /*
* Driver for USB Audio Device Class devices. * Driver for USB Audio Device Class devices.
* Copyright (c) 2009,10,12 S.Zharski <[email protected]> * Copyright (c) 2009-13 S.Zharski <[email protected]>
* Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
* *
*/ */
#include "Driver.h"
#include "Device.h"
#include "Settings.h"
//#include "audio.h"
#include "AudioStreamingInterface.h"
// #include "StreamFormats.h"
#include <malloc.h> #include "Device.h"
#include "Driver.h"
#include "Settings.h"
Device::Device(usb_device device) Device::Device(usb_device device)
: :
fStatus(B_ERROR), fStatus(B_ERROR),
fOpen(false), fOpen(false),
fRemoved(false), fRemoved(false),
fInsideNotify(0), // fInsideNotify(0),
fDevice(device), fDevice(device),
fNonBlocking(false), fNonBlocking(false),
fAudioControl(this), fAudioControl(this),
// fControlEndpoint(0), fBuffersReadySem(-1)
// fInStreamEndpoint(0),
// fOutStreamEndpoint(0),
fNotifyReadSem(-1),
fNotifyWriteSem(-1),
fNotifyBuffer(NULL),
fNotifyBufferLength(0),
fBuffersReadySem(-1)
{ {
const usb_device_descriptor* deviceDescriptor const usb_device_descriptor* deviceDescriptor
= gUSBModule->get_device_descriptor(device); = gUSBModule->get_device_descriptor(device);
@@ -44,30 +35,15 @@ Device::Device(usb_device device)
fProductID = deviceDescriptor->product_id; fProductID = deviceDescriptor->product_id;
fUSBVersion = deviceDescriptor->usb_version; fUSBVersion = deviceDescriptor->usb_version;
fNotifyReadSem = create_sem(0, DRIVER_NAME"_notify_read");
if (fNotifyReadSem < B_OK) {
TRACE_ALWAYS("Error of creating read notify semaphore:%#010x\n",
fNotifyReadSem);
return;
}
fNotifyWriteSem = create_sem(0, DRIVER_NAME"_notify_write");
if (fNotifyWriteSem < B_OK) {
TRACE_ALWAYS("Error of creating write notify semaphore:%#010x\n",
fNotifyWriteSem);
return;
}
fBuffersReadySem = create_sem(0, DRIVER_NAME "_buffers_ready"); fBuffersReadySem = create_sem(0, DRIVER_NAME "_buffers_ready");
if (fBuffersReadySem < B_OK) { if (fBuffersReadySem < B_OK) {
TRACE_ALWAYS("Error of creating ready buffers semaphore:%#010x\n", TRACE_ALWAYS("Error of creating ready "
fBuffersReadySem); "buffers semaphore:%#010x\n", fBuffersReadySem);
return; return;
} }
if (_SetupEndpoints() != B_OK) { if (_SetupEndpoints() != B_OK)
return; return;
}
// must be set in derived class constructor // must be set in derived class constructor
fStatus = B_OK; fStatus = B_OK;
@@ -76,40 +52,14 @@ Device::Device(usb_device device)
Device::~Device() Device::~Device()
{ {
// we have to clear because we own those objects here for (Vector<Stream*>::Iterator I = fStreams.Begin();
/* I != fStreams.End(); I++)
for (AudioControlsIterator I = fAudioControls.Begin();
I != fAudioControls.End(); I++) {
delete I->Value();
}
fAudioControls.MakeEmpty();
// object already freed. just purge the map
fOutputTerminals.MakeEmpty();
// object already freed. just purge the map
fInputTerminals.MakeEmpty();
*/
// free stream objects too.
for (AudioStreamsIterator I = fStreams.Begin();
I != fStreams.End(); I++) {
delete *I; delete *I;
}
fStreams.MakeEmpty();
if (fNotifyReadSem >= B_OK) fStreams.MakeEmpty();
delete_sem(fNotifyReadSem);
if (fNotifyWriteSem >= B_OK)
delete_sem(fNotifyWriteSem);
if (fBuffersReadySem > B_OK) if (fBuffersReadySem > B_OK)
delete_sem(fBuffersReadySem); delete_sem(fBuffersReadySem);
// if (!fRemoved) // ???
// gUSBModule->cancel_queued_transfers(fNotifyEndpoint);
if (fNotifyBuffer)
free(fNotifyBuffer);
} }
@@ -122,19 +72,10 @@ Device::Open(uint32 flags)
return B_ERROR; return B_ERROR;
status_t result = StartDevice(); status_t result = StartDevice();
if (result != B_OK) { if (result != B_OK)
return result; return result;
}
// setup state notifications
/* result = gUSBModule->queue_interrupt(fNotifyEndpoint, fNotifyBuffer,
fNotifyBufferLength, _NotifyCallback, this);
if (result != B_OK) {
TRACE_ALWAYS("Error of requesting notify interrupt:%#010x\n", result);
return result;
}
*/
// TODO: are we need this???
fNonBlocking = (flags & O_NONBLOCK) == O_NONBLOCK; fNonBlocking = (flags & O_NONBLOCK) == O_NONBLOCK;
fOpen = true; fOpen = true;
return result; return result;
@@ -149,13 +90,12 @@ Device::Close()
return B_OK; return B_OK;
} }
for (int i = 0; i < fStreams.Count(); i++) { for (int i = 0; i < fStreams.Count(); i++)
fStreams[i]->Stop(); fStreams[i]->Stop();
}
// wait until possible notification handling finished... // wait until possible notification handling finished...
while (atomic_add(&fInsideNotify, 0) != 0) // while (atomic_add(&fInsideNotify, 0) != 0)
snooze(100); // snooze(100);
// gUSBModule->cancel_queued_transfers(fControlEndpoint); // gUSBModule->cancel_queued_transfers(fControlEndpoint);
// gUSBModule->cancel_queued_transfers(fInStreamEndpoint); // gUSBModule->cancel_queued_transfers(fInStreamEndpoint);
// gUSBModule->cancel_queued_transfers(fOutStreamEndpoint); // gUSBModule->cancel_queued_transfers(fOutStreamEndpoint);
@@ -174,7 +114,7 @@ Device::Free()
status_t status_t
Device::Read(uint8 *buffer, size_t *numBytes) Device::Read(uint8* buffer, size_t* numBytes)
{ {
*numBytes = 0; *numBytes = 0;
return B_IO_ERROR; return B_IO_ERROR;
@@ -182,7 +122,7 @@ Device::Read(uint8 *buffer, size_t *numBytes)
status_t status_t
Device::Write(const uint8 *buffer, size_t *numBytes) Device::Write(const uint8* buffer, size_t* numBytes)
{ {
*numBytes = 0; *numBytes = 0;
return B_IO_ERROR; return B_IO_ERROR;
@@ -190,7 +130,7 @@ Device::Write(const uint8 *buffer, size_t *numBytes)
status_t status_t
Device::Control(uint32 op, void *buffer, size_t length) Device::Control(uint32 op, void* buffer, size_t length)
{ {
switch (op) { switch (op) {
case B_MULTI_GET_DESCRIPTION: case B_MULTI_GET_DESCRIPTION:
@@ -224,15 +164,15 @@ Device::Control(uint32 op, void *buffer, size_t length)
TRACE(("B_MULTI_GET_CHANNEL_FORMATS\n")); TRACE(("B_MULTI_GET_CHANNEL_FORMATS\n"));
return B_ERROR; return B_ERROR;
case B_MULTI_SET_CHANNEL_FORMATS: /* only implemented if possible */ case B_MULTI_SET_CHANNEL_FORMATS:
TRACE(("B_MULTI_SET_CHANNEL_FORMATS\n")); TRACE(("B_MULTI_SET_CHANNEL_FORMATS\n"));
return B_ERROR; return B_ERROR;
case B_MULTI_GET_MIX: case B_MULTI_GET_MIX:
return _MultiGetMix((multi_mix_value_info *)buffer); return _MultiGetMix((multi_mix_value_info*)buffer);
case B_MULTI_SET_MIX: case B_MULTI_SET_MIX:
return _MultiSetMix((multi_mix_value_info *)buffer); return _MultiSetMix((multi_mix_value_info*)buffer);
case B_MULTI_LIST_MIX_CHANNELS: case B_MULTI_LIST_MIX_CHANNELS:
TRACE(("B_MULTI_LIST_MIX_CHANNELS\n")); TRACE(("B_MULTI_LIST_MIX_CHANNELS\n"));
@@ -279,7 +219,6 @@ void
Device::Removed() Device::Removed()
{ {
fRemoved = true; fRemoved = true;
// fHasConnection = false;
// the notify hook is different from the read and write hooks as it does // the notify hook is different from the read and write hooks as it does
// itself schedule traffic (while the other hooks only release a semaphore // itself schedule traffic (while the other hooks only release a semaphore
@@ -287,16 +226,13 @@ Device::Removed()
// case) - so we must ensure that we are not inside the notify hook anymore // case) - so we must ensure that we are not inside the notify hook anymore
// before returning, as we would otherwise violate the promise not to use // before returning, as we would otherwise violate the promise not to use
// any of the pipes after returning from the removed hook // any of the pipes after returning from the removed hook
while (atomic_add(&fInsideNotify, 0) != 0) // TODO??????
snooze(100); // while (atomic_add(&fInsideNotify, 0) != 0)
// snooze(100);
// gUSBModule->cancel_queued_transfers(fControlEndpoint); // gUSBModule->cancel_queued_transfers(fControlEndpoint);
// gUSBModule->cancel_queued_transfers(fInStreamEndpoint); // gUSBModule->cancel_queued_transfers(fInStreamEndpoint);
// gUSBModule->cancel_queued_transfers(fOutStreamEndpoint); // gUSBModule->cancel_queued_transfers(fOutStreamEndpoint);
/*
if (fLinkStateChangeSem >= B_OK)
release_sem_etc(fLinkStateChangeSem, 1, B_DO_NOT_RESCHEDULE);
*/
} }
@@ -310,7 +246,7 @@ Device::SetupDevice(bool deviceReplugged)
status_t status_t
Device::CompareAndReattach(usb_device device) Device::CompareAndReattach(usb_device device)
{ {
const usb_device_descriptor *deviceDescriptor const usb_device_descriptor* deviceDescriptor
= gUSBModule->get_device_descriptor(device); = gUSBModule->get_device_descriptor(device);
if (deviceDescriptor == NULL) { if (deviceDescriptor == NULL) {
@@ -319,10 +255,9 @@ Device::CompareAndReattach(usb_device device)
} }
if (deviceDescriptor->vendor_id != fVendorID if (deviceDescriptor->vendor_id != fVendorID
&& deviceDescriptor->product_id != fProductID) { && deviceDescriptor->product_id != fProductID)
// this certainly isn't the same device // this certainly isn't the same device
return B_BAD_VALUE; return B_BAD_VALUE;
}
// this is the same device that was replugged - clear the removed state, // this is the same device that was replugged - clear the removed state,
// re- setup the endpoints and transfers and open the device if it was // re- setup the endpoints and transfers and open the device if it was
@@ -337,9 +272,8 @@ Device::CompareAndReattach(usb_device device)
// we need to setup hardware on device replug // we need to setup hardware on device replug
result = SetupDevice(true); result = SetupDevice(true);
if (result != B_OK) { if (result != B_OK)
return result; return result;
}
if (fOpen) { if (fOpen) {
fOpen = false; fOpen = false;
@@ -351,51 +285,50 @@ Device::CompareAndReattach(usb_device device)
status_t status_t
Device::_MultiGetDescription(multi_description *multiDescription) Device::_MultiGetDescription(multi_description* multiDescription)
{ {
multi_description Description; multi_description Description;
if (user_memcpy(&Description, multiDescription, if (user_memcpy(&Description, multiDescription,
sizeof(multi_description)) != B_OK) { sizeof(multi_description)) != B_OK)
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
}
Description.interface_version = B_CURRENT_INTERFACE_VERSION; Description.interface_version = B_CURRENT_INTERFACE_VERSION;
Description.interface_minimum = B_CURRENT_INTERFACE_VERSION; Description.interface_minimum = B_CURRENT_INTERFACE_VERSION;
strlcpy(Description.friendly_name, "USB Audio", // TODO: ???? strlcpy(Description.friendly_name, "USB Audio",
sizeof(Description.friendly_name)); sizeof(Description.friendly_name));
strlcpy(Description.vendor_info, "S.Zharski", strlcpy(Description.vendor_info, "S.Zharski",
sizeof(Description.vendor_info)); sizeof(Description.vendor_info));
Description.output_channel_count = 0; Description.output_channel_count = 0;
Description.input_channel_count = 0; Description.input_channel_count = 0;
Description.output_bus_channel_count = 0; Description.output_bus_channel_count = 0;
Description.input_bus_channel_count = 0; Description.input_bus_channel_count = 0;
Description.aux_bus_channel_count = 0; Description.aux_bus_channel_count = 0;
Description.output_rates = 0; Description.output_rates = 0;
Description.input_rates = 0; Description.input_rates = 0;
Description.min_cvsr_rate = 0; Description.min_cvsr_rate = 0;
Description.max_cvsr_rate = 0; Description.max_cvsr_rate = 0;
Description.output_formats = 0; Description.output_formats = 0;
Description.input_formats = 0; Description.input_formats = 0;
Description.lock_sources = B_MULTI_LOCK_INTERNAL; Description.lock_sources = B_MULTI_LOCK_INTERNAL;
Description.timecode_sources = 0; Description.timecode_sources = 0;
Description.interface_flags = 0; Description.interface_flags = 0;
Description.start_latency = 3000; Description.start_latency = 3000;
Description.control_panel[0] = '\0'; Description.control_panel[0] = '\0';
AudioControlsVector USBTerminals; Vector<_AudioControl*> USBTerminals;
// channels (USB I/O terminals) are already in fStreams // channels (USB I/O terminals) are already in fStreams
// in outputs->inputs order, use them. // in outputs->inputs order, use them.
for (int i = 0; i < fStreams.Count(); i++) { for (int i = 0; i < fStreams.Count(); i++) {
uint8 id = fStreams[i]->TerminalLink(); uint8 id = fStreams[i]->TerminalLink();
_AudioControl *control = fAudioControl.Find(id); _AudioControl* control = fAudioControl.Find(id);
// if (control->SubType() == IDSOutputTerminal) { // if (control->SubType() == IDSOutputTerminal) {
// USBTerminals.PushFront(control); // USBTerminals.PushFront(control);
// fStreams[i]->GetFormatsAndRates(Description); // fStreams[i]->GetFormatsAndRates(Description);
@@ -406,35 +339,29 @@ Device::_MultiGetDescription(multi_description *multiDescription)
// } // }
} }
// int32 index = 0;
Vector<multi_channel_info> Channels; Vector<multi_channel_info> Channels;
/*uint32 channels =*/ fAudioControl.GetChannelsDescription(Channels, &Description, USBTerminals); fAudioControl.GetChannelsDescription(Channels, &Description, USBTerminals);
/*uint32 bus_channels =*/ fAudioControl.GetBusChannelsDescription(Channels, &Description ); fAudioControl.GetBusChannelsDescription(Channels, &Description );
// Description.request_channel_count = channels + bus_channels; // Description.request_channel_count = channels + bus_channels;
TraceMultiDescription(&Description, Channels); TraceMultiDescription(&Description, Channels);
if (user_memcpy(multiDescription, &Description, if (user_memcpy(multiDescription, &Description,
sizeof(multi_description)) != B_OK) { sizeof(multi_description)) != B_OK)
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
}
// if (Description.request_channel_count >=
// (int)(sizeof(channel_descriptions) / sizeof(channel_descriptions[0])))
// {
if (user_memcpy(multiDescription->channels, if (user_memcpy(multiDescription->channels,
&Channels[0], min_c(Channels.Count(), &Channels[0], min_c(Channels.Count(),
Description.request_channel_count)) != B_OK) Description.request_channel_count)) != B_OK)
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
// }
return B_OK; return B_OK;
} }
void void
Device::TraceMultiDescription(multi_description *Description, Device::TraceMultiDescription(multi_description* Description,
Vector<multi_channel_info>& Channels) Vector<multi_channel_info>& Channels)
{ {
TRACE("interface_version:%d\n", Description->interface_version); TRACE("interface_version:%d\n", Description->interface_version);
@@ -472,36 +399,34 @@ Device::TraceMultiDescription(multi_description *Description,
status_t status_t
Device::_MultiGetEnabledChannels(multi_channel_enable *Enable) Device::_MultiGetEnabledChannels(multi_channel_enable* Enable)
{ {
status_t status = B_OK; status_t status = B_OK;
Enable->lock_source = B_MULTI_LOCK_INTERNAL; Enable->lock_source = B_MULTI_LOCK_INTERNAL;
uint32 offset = 0; uint32 offset = 0;
for (int i = 0; i < fStreams.Count() && status == B_OK; i++) { for (int i = 0; i < fStreams.Count() && status == B_OK; i++)
status = fStreams[i]->GetEnabledChannels(offset, Enable); status = fStreams[i]->GetEnabledChannels(offset, Enable);
}
return status; return status;
} }
status_t status_t
Device::_MultiSetEnabledChannels(multi_channel_enable *Enable) Device::_MultiSetEnabledChannels(multi_channel_enable* Enable)
{ {
status_t status = B_OK; status_t status = B_OK;
uint32 offset = 0; uint32 offset = 0;
for (int i = 0; i < fStreams.Count() && status == B_OK; i++) { for (int i = 0; i < fStreams.Count() && status == B_OK; i++)
status = fStreams[i]->SetEnabledChannels(offset, Enable); status = fStreams[i]->SetEnabledChannels(offset, Enable);
}
return status; return status;
} }
status_t status_t
Device::_MultiGetGlobalFormat(multi_format_info *Format) Device::_MultiGetGlobalFormat(multi_format_info* Format)
{ {
status_t status = B_OK; status_t status = B_OK;
@@ -510,16 +435,15 @@ Device::_MultiGetGlobalFormat(multi_format_info *Format)
Format->timecode_kind = 0; Format->timecode_kind = 0;
// uint32 offset = 0; // uint32 offset = 0;
for (int i = 0; i < fStreams.Count() && status == B_OK; i++) { for (int i = 0; i < fStreams.Count() && status == B_OK; i++)
status = fStreams[i]->GetGlobalFormat(Format); status = fStreams[i]->GetGlobalFormat(Format);
}
return status; return status;
} }
status_t status_t
Device::_MultiSetGlobalFormat(multi_format_info *Format) Device::_MultiSetGlobalFormat(multi_format_info* Format)
{ {
status_t status = B_OK; status_t status = B_OK;
@@ -528,9 +452,8 @@ Device::_MultiSetGlobalFormat(multi_format_info *Format)
TRACE("timecode_kind:%#08x\n", Format->timecode_kind); TRACE("timecode_kind:%#08x\n", Format->timecode_kind);
// uint32 offset = 0; // uint32 offset = 0;
for (int i = 0; i < fStreams.Count() && status == B_OK; i++) { for (int i = 0; i < fStreams.Count() && status == B_OK; i++)
status = fStreams[i]->SetGlobalFormat(Format); status = fStreams[i]->SetGlobalFormat(Format);
}
return status; return status;
} }
@@ -560,9 +483,8 @@ Device::_MultiGetBuffers(multi_buffer_list* List)
List->return_playback_channels = 0; List->return_playback_channels = 0;
List->return_record_channels = 0; List->return_record_channels = 0;
for (int i = 0; i < fStreams.Count() && status == B_OK; i++) { for (int i = 0; i < fStreams.Count() && status == B_OK; i++)
status = fStreams[i]->GetBuffers(List); status = fStreams[i]->GetBuffers(List);
}
return B_OK; return B_OK;
} }
@@ -575,17 +497,10 @@ Device::_MultiBufferExchange(multi_buffer_info* multiInfo)
if (user_memcpy(&Info, multiInfo, sizeof(multi_buffer_info)) != B_OK) if (user_memcpy(&Info, multiInfo, sizeof(multi_buffer_info)) != B_OK)
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
for (int i = 0; i < fStreams.Count(); i++) { for (int i = 0; i < fStreams.Count(); i++)
if (!fStreams[i]->IsRunning()) { if (!fStreams[i]->IsRunning())
fStreams[i]->Start(); fStreams[i]->Start();
}
}
// TRACE_ALWAYS("Exchange!\n");
/*
snooze(1000000);
return B_OK;
*/
status_t status = B_ERROR; status_t status = B_ERROR;
bool anyBufferProcessed = false; bool anyBufferProcessed = false;
for (int i = 0; i < fStreams.Count() && !anyBufferProcessed; i++) { for (int i = 0; i < fStreams.Count() && !anyBufferProcessed; i++) {
@@ -610,22 +525,21 @@ Device::_MultiBufferExchange(multi_buffer_info* multiInfo)
status_t status_t
Device::_MultiBufferForceStop() Device::_MultiBufferForceStop()
{ {
for (int i = 0; i < fStreams.Count(); i++) { for (int i = 0; i < fStreams.Count(); i++)
fStreams[i]->Stop(); fStreams[i]->Stop();
}
return B_OK; return B_OK;
} }
status_t status_t
Device::_MultiGetMix(multi_mix_value_info *Info) Device::_MultiGetMix(multi_mix_value_info* Info)
{ {
return fAudioControl.GetMix(Info); return fAudioControl.GetMix(Info);
} }
status_t status_t
Device::_MultiSetMix(multi_mix_value_info *Info) Device::_MultiSetMix(multi_mix_value_info* Info)
{ {
return fAudioControl.SetMix(Info); return fAudioControl.SetMix(Info);
} }
@@ -641,7 +555,7 @@ Device::_MultiListMixControls(multi_mix_control_info* Info)
void void
Device::TraceListMixControls(multi_mix_control_info *Info) Device::TraceListMixControls(multi_mix_control_info* Info)
{ {
TRACE("control_count:%d\n.", Info->control_count); TRACE("control_count:%d\n.", Info->control_count);
@@ -662,7 +576,7 @@ Device::TraceListMixControls(multi_mix_control_info *Info)
status_t status_t
Device::_SetupEndpoints() Device::_SetupEndpoints()
{ {
const usb_configuration_info *config const usb_configuration_info* config
= gUSBModule->get_nth_configuration(fDevice, 0); = gUSBModule->get_nth_configuration(fDevice, 0);
if (config == NULL) { if (config == NULL) {
@@ -676,10 +590,9 @@ Device::_SetupEndpoints()
} }
for (size_t i = 0; i < config->interface_count; i++) { for (size_t i = 0; i < config->interface_count; i++) {
usb_interface_info *Interface = config->interface[i].active; usb_interface_info* Interface = config->interface[i].active;
if (Interface->descr->interface_class != UAS_AUDIO) { if (Interface->descr->interface_class != UAS_AUDIO)
continue; continue;
}
switch (Interface->descr->interface_subclass) { switch (Interface->descr->interface_subclass) {
case UAS_AUDIOCONTROL: case UAS_AUDIOCONTROL:
@@ -687,23 +600,21 @@ Device::_SetupEndpoints()
break; break;
case UAS_AUDIOSTREAMING: case UAS_AUDIOSTREAMING:
{ {
Stream *stream = new Stream(this, i, &config->interface[i]); Stream* stream = new Stream(this, i, &config->interface[i]);
if (B_OK == stream->Init()) { if (B_OK == stream->Init()) {
// put the stream in the correct order: // put the stream in the correct order:
// first output that input ones. // first output that input ones.
if (stream->IsInput()) { if (stream->IsInput())
fStreams.PushBack(stream); fStreams.PushBack(stream);
} else { else
fStreams.PushFront(stream); fStreams.PushFront(stream);
} } else
} else {
delete stream; delete stream;
}
} }
break; break;
default: default:
TRACE_ALWAYS("Ignore interface of unsupported subclass %#x.\n", TRACE_ALWAYS("Ignore interface of unsupported subclass %#x.\n",
Interface->descr->interface_subclass); Interface->descr->interface_subclass);
break; break;
} }
} }
@@ -712,9 +623,8 @@ Device::_SetupEndpoints()
TRACE("Found device %#06x:%#06x\n", fVendorID, fProductID); TRACE("Found device %#06x:%#06x\n", fVendorID, fProductID);
gUSBModule->set_configuration(fDevice, config); gUSBModule->set_configuration(fDevice, config);
for (int i = 0; i < fStreams.Count(); i++) { for (int i = 0; i < fStreams.Count(); i++)
fStreams[i]->OnSetConfiguration(fDevice, config); fStreams[i]->OnSetConfiguration(fDevice, config);
}
return B_OK; return B_OK;
} }
@@ -728,58 +638,33 @@ Device::StopDevice()
{ {
status_t result = B_OK; status_t result = B_OK;
if (result != B_OK) { if (result != B_OK)
TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", 0, result); TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", 0, result);
}
TRACE_RET(result); TRACE_RET(result);
return result; return result;
} }
void /*void
Device::_ReadCallback(void *cookie, int32 status, void *data, Device::_NotifyCallback(void* cookie, int32 status, void* data,
uint32 actualLength) uint32 actualLength)
{ {
TRACE_FLOW("ReadCB: %d bytes; status:%#010x\n", actualLength, status); Device* device = (Device*)cookie;
Device *device = (Device *)cookie;
device->fActualLengthRead = actualLength;
device->fStatusRead = status;
release_sem_etc(device->fNotifyReadSem, 1, B_DO_NOT_RESCHEDULE);
}
void
Device::_WriteCallback(void *cookie, int32 status, void *data,
uint32 actualLength)
{
TRACE_FLOW("WriteCB: %d bytes; status:%#010x\n", actualLength, status);
Device *device = (Device *)cookie;
device->fActualLengthWrite = actualLength;
device->fStatusWrite = status;
release_sem_etc(device->fNotifyWriteSem, 1, B_DO_NOT_RESCHEDULE);
}
void
Device::_NotifyCallback(void *cookie, int32 status, void *data,
uint32 actualLength)
{
Device *device = (Device *)cookie;
atomic_add(&device->fInsideNotify, 1); atomic_add(&device->fInsideNotify, 1);
if (status == B_CANCELED || device->fRemoved) { if (status == B_CANCELED || device->fRemoved) {
atomic_add(&device->fInsideNotify, -1); atomic_add(&device->fInsideNotify, -1);
return; return;
} }
/* if (status != B_OK) { / * if (status != B_OK) {
TRACE_ALWAYS("Device status error:%#010x\n", status); TRACE_ALWAYS("Device status error:%#010x\n", status);
status_t result = gUSBModule->clear_feature(device->fControLeNDPOint, status_t result = gUSBModule->clear_feature(device->fControLeNDPOint,
USB_FEATURE_ENDPOINT_HALT); USB_FEATURE_ENDPOINT_HALT);
if (result != B_OK) if (result != B_OK)
TRACE_ALWAYS("Error during clearing of HALT state:%#010x.\n", result); TRACE_ALWAYS("Error during clearing of HALT state:%#010x.\n", result);
} }
*/ * /
// parse data in overriden class // parse data in overriden class
// device->OnNotify(actualLength); // device->OnNotify(actualLength);
@@ -788,4 +673,5 @@ Device::_NotifyCallback(void *cookie, int32 status, void *data,
// device->fNotifyBufferLength, _NotifyCallback, device); // device->fNotifyBufferLength, _NotifyCallback, device);
atomic_add(&device->fInsideNotify, -1); atomic_add(&device->fInsideNotify, -1);
} }
*/
@@ -1,6 +1,6 @@
/* /*
* Driver for USB Audio Device Class devices. * Driver for USB Audio Device Class devices.
* Copyright (c) 2009,10,12 S.Zharski <[email protected]> * Copyright (c) 2009-13 S.Zharski <[email protected]>
* Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
* *
*/ */
@@ -8,131 +8,80 @@
#define _USB_AUDIO_DEVICE_H_ #define _USB_AUDIO_DEVICE_H_
#include "Driver.h"
#include "USB_audio_spec.h"
#include "AudioControlInterface.h" #include "AudioControlInterface.h"
#include "AudioStreamingInterface.h"
#include "Stream.h" #include "Stream.h"
// typedef VectorMap<uint32, _AudioControl*> AudioControlsMap;
// typedef VectorMap<uint32, _AudioControl*>::Iterator AudioControlsIterator;
typedef Vector<Stream*> AudioStreamsVector;
typedef Vector<Stream*>::Iterator AudioStreamsIterator;
class FeatureUnit;
class Device { class Device {
friend class FeatureUnit; friend class Stream;
friend class Stream;
public: public:
Device(usb_device device); Device(usb_device device);
virtual ~Device(); virtual ~Device();
status_t InitCheck() { return fStatus; }; status_t InitCheck() { return fStatus; };
status_t Open(uint32 flags); status_t Open(uint32 flags);
bool IsOpen() { return fOpen; }; bool IsOpen() { return fOpen; };
status_t Close(); status_t Close();
status_t Free(); status_t Free();
status_t Read(uint8 *buffer, size_t *numBytes); status_t Read(uint8* buffer, size_t* numBytes);
status_t Write(const uint8 *buffer, size_t *numBytes); status_t Write(const uint8* buffer, size_t* numBytes);
status_t Control(uint32 op, void *buffer, size_t length); status_t Control(uint32 op, void* buffer, size_t length);
void Removed(); void Removed();
bool IsRemoved() { return fRemoved; }; bool IsRemoved() { return fRemoved; };
status_t CompareAndReattach(usb_device device); status_t CompareAndReattach(usb_device device);
virtual status_t SetupDevice(bool deviceReplugged); virtual status_t SetupDevice(bool deviceReplugged);
// uint16 SpecReleaseNumber();
// _AudioControl* FindAudioControl(uint8 ID); usb_device USBDevice() { return fDevice; }
usb_device USBDevice() { return fDevice; }
AudioControlInterface& AudioControl() { return fAudioControl; } AudioControlInterface&
AudioControl() { return fAudioControl; }
private: private:
static void _ReadCallback(void *cookie, int32 status, status_t _SetupEndpoints();
void *data, uint32 actualLength);
static void _WriteCallback(void *cookie, int32 status,
void *data, uint32 actualLength);
static void _NotifyCallback(void *cookie, int32 status,
void *data, uint32 actualLength);
status_t _SetupEndpoints(); // protected:
// void ParseAudioControlInterface(usb_device device, virtual status_t StartDevice() { return B_OK; }
// size_t interface, usb_interface_info *Interface); virtual status_t StopDevice();
// void ParseAudioStreamingInterface(usb_device device,
// size_t interface, usb_interface_list *List);
protected: void TraceMultiDescription(multi_description* Description,
virtual status_t StartDevice() { return B_OK; } Vector<multi_channel_info>& Channels);
virtual status_t StopDevice(); void TraceListMixControls(multi_mix_control_info* Info);
void TraceMultiDescription(multi_description *Description,
Vector<multi_channel_info>& Channels);
void TraceListMixControls(multi_mix_control_info *Info);
// state tracking // state tracking
status_t fStatus; status_t fStatus;
bool fOpen; bool fOpen;
bool fRemoved; bool fRemoved;
vint32 fInsideNotify; // int32 fInsideNotify; // TODO: move to Stream!
usb_device fDevice; usb_device fDevice;
uint16 fUSBVersion; uint16 fUSBVersion;
uint16 fVendorID; uint16 fVendorID;
uint16 fProductID; uint16 fProductID;
const char * fDescription; const char* fDescription;
bool fNonBlocking; bool fNonBlocking;
AudioControlInterface fAudioControl; AudioControlInterface fAudioControl;
/* Vector<Stream*> fStreams;
AudioControlHeader* fAudioControlHeader;
// map to store all controls and lookup by control ID
AudioControlsMap fAudioControls;
// map to store output terminal and lookup them by source ID
AudioControlsMap fOutputTerminals;
// map to store output terminal and lookup them by control ID
AudioControlsMap fInputTerminals;
*/
// vector of audio streams
AudioStreamsVector fStreams;
protected: // protected:
status_t _MultiGetDescription(multi_description *Description); status_t _MultiGetDescription(multi_description* Description);
status_t _MultiGetEnabledChannels(multi_channel_enable *Enable); status_t _MultiGetEnabledChannels(multi_channel_enable* Enable);
status_t _MultiSetEnabledChannels(multi_channel_enable *Enable); status_t _MultiSetEnabledChannels(multi_channel_enable* Enable);
status_t _MultiGetBuffers(multi_buffer_list* List); status_t _MultiGetBuffers(multi_buffer_list* List);
status_t _MultiGetGlobalFormat(multi_format_info *Format); status_t _MultiGetGlobalFormat(multi_format_info* Format);
status_t _MultiSetGlobalFormat(multi_format_info *Format); status_t _MultiSetGlobalFormat(multi_format_info* Format);
status_t _MultiGetMix(multi_mix_value_info *Info); status_t _MultiGetMix(multi_mix_value_info* Info);
status_t _MultiSetMix(multi_mix_value_info *Info); status_t _MultiSetMix(multi_mix_value_info* Info);
status_t _MultiListMixControls(multi_mix_control_info* Info); status_t _MultiListMixControls(multi_mix_control_info* Info);
status_t _MultiBufferExchange(multi_buffer_info* Info); status_t _MultiBufferExchange(multi_buffer_info* Info);
status_t _MultiBufferForceStop(); status_t _MultiBufferForceStop();
// interface and device infos sem_id fBuffersReadySem;
// uint16 fFrameSize;
// pipes for notifications and data io
// usb_pipe fControlEndpoint;
// usb_pipe fInStreamEndpoint;
// usb_pipe fOutStreamEndpoint;
// data stores for async usb transfers
uint32 fActualLengthRead;
uint32 fActualLengthWrite;
int32 fStatusRead;
int32 fStatusWrite;
sem_id fNotifyReadSem;
sem_id fNotifyWriteSem;
uint8 * fNotifyBuffer;
uint32 fNotifyBufferLength;
sem_id fBuffersReadySem;
}; };
@@ -1,47 +1,35 @@
/* /*
* Driver for USB Audio Device Class devices. * Driver for USB Audio Device Class devices.
* Copyright (c) 2009,10,12 S.Zharski <[email protected]> * Copyright (c) 2009-13 S.Zharski <[email protected]>
* Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
* *
*/ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <lock.h> // for mutex
#include "Driver.h" #include "Driver.h"
#include "Settings.h"
#include <AutoLock.h>
#include "Device.h" #include "Device.h"
#include "USB_audio_spec.h" #include "Settings.h"
static const char* sDeviceBaseName = "audio/hmulti/USB Audio/";
usb_module_info* gUSBModule = NULL;
Device* gDevices[MAX_DEVICES];
char* gDeviceNames[MAX_DEVICES + 1];
mutex gDriverLock;
int32 api_version = B_CUR_DRIVER_API_VERSION; int32 api_version = B_CUR_DRIVER_API_VERSION;
static const char *sDeviceBaseName = "audio/hmulti/USB Audio/";
Device *gDevices[MAX_DEVICES];
char *gDeviceNames[MAX_DEVICES + 1];
usb_module_info *gUSBModule = NULL;
mutex gDriverLock;
// auto - release helper class
class DriverSmartLock {
public:
DriverSmartLock() { mutex_lock(&gDriverLock); }
~DriverSmartLock() { mutex_unlock(&gDriverLock); }
};
status_t status_t
usb_audio_device_added(usb_device device, void **cookie) usb_audio_device_added(usb_device device, void** cookie)
{ {
*cookie = NULL; *cookie = NULL;
DriverSmartLock driverLock; // released on exit MutexLocker driverLock;
// check if this is a replug of an existing device first // check if this is a replug of an existing device first
for (int32 i = 0; i < MAX_DEVICES; i++) { for (int32 i = 0; i < MAX_DEVICES; i++) {
@@ -57,10 +45,9 @@ usb_audio_device_added(usb_device device, void **cookie)
} }
// no such device yet, create a new one // no such device yet, create a new one
Device *audioDevice = new Device(device); Device* audioDevice = new Device(device);
if (audioDevice == 0) { if (audioDevice == 0)
return ENODEV; return ENODEV;
}
status_t status = audioDevice->InitCheck(); status_t status = audioDevice->InitCheck();
if (status < B_OK) { if (status < B_OK) {
@@ -94,11 +81,11 @@ usb_audio_device_added(usb_device device, void **cookie)
status_t status_t
usb_audio_device_removed(void *cookie) usb_audio_device_removed(void* cookie)
{ {
DriverSmartLock driverLock; // released on exit MutexLocker driverLock;
Device *device = (Device *)cookie; Device* device = (Device*)cookie;
for (int32 i = 0; i < MAX_DEVICES; i++) { for (int32 i = 0; i < MAX_DEVICES; i++) {
if (gDevices[i] == device) { if (gDevices[i] == device) {
if (device->IsOpen()) { if (device->IsOpen()) {
@@ -128,7 +115,7 @@ status_t
init_driver() init_driver()
{ {
status_t status = get_module(B_USB_MODULE_NAME, status_t status = get_module(B_USB_MODULE_NAME,
(module_info **)&gUSBModule); (module_info**)&gUSBModule);
if (status < B_OK) if (status < B_OK)
return status; return status;
@@ -148,7 +135,7 @@ init_driver()
}; };
static usb_support_descriptor supportedDevices[] = { static usb_support_descriptor supportedDevices[] = {
{UAS_AUDIO, 0, 0, 0, 0 } { UAS_AUDIO, 0, 0, 0, 0 }
}; };
gUSBModule->register_driver(DRIVER_NAME, supportedDevices, 0, NULL); gUSBModule->register_driver(DRIVER_NAME, supportedDevices, 0, NULL);
@@ -183,9 +170,9 @@ uninit_driver()
static status_t static status_t
usb_audio_open(const char *name, uint32 flags, void **cookie) usb_audio_open(const char* name, uint32 flags, void** cookie)
{ {
DriverSmartLock driverLock; // released on exit MutexLocker driverLock;
*cookie = NULL; *cookie = NULL;
status_t status = ENODEV; status_t status = ENODEV;
@@ -200,44 +187,44 @@ usb_audio_open(const char *name, uint32 flags, void **cookie)
static status_t static status_t
usb_audio_read(void *cookie, off_t position, void *buffer, size_t *numBytes) usb_audio_read(void* cookie, off_t position, void* buffer, size_t* numBytes)
{ {
Device *device = (Device *)cookie; Device* device = (Device*)cookie;
return device->Read((uint8 *)buffer, numBytes); return device->Read((uint8*)buffer, numBytes);
} }
static status_t static status_t
usb_audio_write(void *cookie, off_t position, const void *buffer, usb_audio_write(void* cookie, off_t position, const void* buffer,
size_t *numBytes) size_t* numBytes)
{ {
Device *device = (Device *)cookie; Device* device = (Device*)cookie;
return device->Write((const uint8 *)buffer, numBytes); return device->Write((const uint8*)buffer, numBytes);
} }
static status_t static status_t
usb_audio_control(void *cookie, uint32 op, void *buffer, size_t length) usb_audio_control(void* cookie, uint32 op, void* buffer, size_t length)
{ {
Device *device = (Device *)cookie; Device* device = (Device*)cookie;
return device->Control(op, buffer, length); return device->Control(op, buffer, length);
} }
static status_t static status_t
usb_audio_close(void *cookie) usb_audio_close(void* cookie)
{ {
Device *device = (Device *)cookie; Device* device = (Device*)cookie;
return device->Close(); return device->Close();
} }
static status_t static status_t
usb_audio_free(void *cookie) usb_audio_free(void* cookie)
{ {
Device *device = (Device *)cookie; Device* device = (Device*)cookie;
DriverSmartLock driverLock; // released on exit MutexLocker driverLock;
status_t status = device->Free(); status_t status = device->Free();
for (int32 i = 0; i < MAX_DEVICES; i++) { for (int32 i = 0; i < MAX_DEVICES; i++) {
@@ -255,7 +242,7 @@ usb_audio_free(void *cookie)
} }
const char ** const char**
publish_devices() publish_devices()
{ {
for (int32 i = 0; gDeviceNames[i]; i++) { for (int32 i = 0; gDeviceNames[i]; i++) {
@@ -263,14 +250,14 @@ publish_devices()
gDeviceNames[i] = NULL; gDeviceNames[i] = NULL;
} }
DriverSmartLock driverLock; // released on exit MutexLocker driverLock;
int32 deviceCount = 0; int32 deviceCount = 0;
for (int32 i = 0; i < MAX_DEVICES; i++) { for (int32 i = 0; i < MAX_DEVICES; i++) {
if (gDevices[i] == NULL) if (gDevices[i] == NULL)
continue; continue;
gDeviceNames[deviceCount] = (char *)malloc(strlen(sDeviceBaseName) + 4); gDeviceNames[deviceCount] = (char*)malloc(strlen(sDeviceBaseName) + 4);
if (gDeviceNames[deviceCount]) { if (gDeviceNames[deviceCount]) {
sprintf(gDeviceNames[deviceCount], "%s%ld", sDeviceBaseName, i); sprintf(gDeviceNames[deviceCount], "%s%ld", sDeviceBaseName, i);
TRACE("publishing %s\n", gDeviceNames[deviceCount]); TRACE("publishing %s\n", gDeviceNames[deviceCount]);
@@ -280,12 +267,12 @@ publish_devices()
} }
gDeviceNames[deviceCount] = NULL; gDeviceNames[deviceCount] = NULL;
return (const char **)&gDeviceNames[0]; return (const char**)&gDeviceNames[0];
} }
device_hooks * device_hooks*
find_device(const char *name) find_device(const char* name)
{ {
static device_hooks deviceHooks = { static device_hooks deviceHooks = {
usb_audio_open, usb_audio_open,
@@ -294,8 +281,8 @@ find_device(const char *name)
usb_audio_control, usb_audio_control,
usb_audio_read, usb_audio_read,
usb_audio_write, usb_audio_write,
NULL, /* select */ NULL, // select
NULL /* deselect */ NULL // deselect
}; };
return &deviceHooks; return &deviceHooks;
@@ -1,6 +1,6 @@
/* /*
* Driver for USB Audio Device Class devices. * Driver for USB Audio Device Class devices.
* Copyright (c) 2009,10,12 S.Zharski <[email protected]> * Copyright (c) 2009-13 S.Zharski <[email protected]>
* Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
* *
*/ */
@@ -8,22 +8,20 @@
#define _USB_AUDIO_DRIVER_H_ #define _USB_AUDIO_DRIVER_H_
#include <OS.h>
#include <KernelExport.h>
#include <Drivers.h> #include <Drivers.h>
#include <USB3.h> #include <USB3.h>
#include <hmulti_audio.h>
#define DRIVER_NAME "usb_audio" #define DRIVER_NAME "usb_audio"
#define MAX_DEVICES 8 #define MAX_DEVICES 8
const char* const kVersion = "ver.0.0.4"; const char* const kVersion = "ver.0.0.5";
// initial buffer size in samples
const uint32 kSamplesBufferSize = 1024; const uint32 kSamplesBufferSize = 1024;
// [sub]buffers count
const uint32 kSamplesBufferCount = 2; const uint32 kSamplesBufferCount = 2;
// calculate count of array members // calculate count of array members
#ifdef _countof #ifdef _countof
#warning "countof(...) WAS ALREADY DEFINED!!! Remove local definition!" #warning "countof(...) WAS ALREADY DEFINED!!! Remove local definition!"
@@ -32,21 +30,16 @@ const uint32 kSamplesBufferCount = 2;
#define _countof(array)(sizeof(array) / sizeof(array[0])) #define _countof(array)(sizeof(array) / sizeof(array[0]))
extern usb_module_info *gUSBModule; extern usb_module_info* gUSBModule;
extern "C" status_t usb_audio_device_added(usb_device device, void** cookie);
extern "C" status_t usb_audio_device_removed(void* cookie);
extern "C" { extern "C" status_t init_hardware();
extern "C" void uninit_driver();
status_t usb_audio_device_added(usb_device device, void **cookie); extern "C" const char** publish_devices();
status_t usb_audio_device_removed(void *cookie); extern "C" device_hooks *find_device(const char* name);
status_t init_hardware();
void uninit_driver();
const char **publish_devices();
device_hooks *find_device(const char *name);
}
#endif // _USB_AUDIO_DRIVER_H_ #endif // _USB_AUDIO_DRIVER_H_
@@ -2,11 +2,10 @@ SubDir HAIKU_TOP src add-ons kernel drivers audio usb_audio ;
SetSubDirSupportedPlatformsBeOSCompatible ; SetSubDirSupportedPlatformsBeOSCompatible ;
UsePrivateHeaders kernel media ;
UsePrivateHeaders kernel net ; UsePrivateHeaders kernel net ;
UsePrivateKernelHeaders ;
UsePrivateHeaders [ FDirName kernel util ] ; UsePrivateHeaders [ FDirName kernel util ] ;
UsePrivateHeaders kernel media ;
KernelAddon usb_audio : KernelAddon usb_audio :
Driver.cpp Driver.cpp
@@ -1,22 +1,28 @@
/* /*
* Driver for USB Audio Device Class devices. * Driver for USB Audio Device Class devices.
* Copyright (c) 2009,10,12 S.Zharski <[email protected]> * Copyright (c) 2009-13 S.Zharski <[email protected]>
* Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
* *
*/ */
#include <lock.h> // for mutex
#include <stdlib.h> // for file operation
#include <string.h> // for file operation
#include <stdio.h> // for file operation
#include "Settings.h" #include "Settings.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <driver_settings.h>
#include <lock.h>
#include "Driver.h"
bool gTraceOn = false; bool gTraceOn = false;
bool gTruncateLogFile = false; bool gTruncateLogFile = false;
bool gAddTimeStamp = true; bool gAddTimeStamp = true;
bool gTraceFlow = false; bool gTraceFlow = false;
static char *gLogFilePath = NULL; static char* gLogFilePath = NULL;
mutex gLogLock; mutex gLogLock;
static static
@@ -36,7 +42,7 @@ void create_log()
void load_settings() void load_settings()
{ {
void *handle = load_driver_settings(DRIVER_NAME); void* handle = load_driver_settings(DRIVER_NAME);
if (handle == 0) if (handle == 0)
return; return;
@@ -47,11 +53,10 @@ void load_settings()
gTruncateLogFile, true); gTruncateLogFile, true);
gAddTimeStamp = get_driver_boolean_parameter(handle, "add_timestamp", gAddTimeStamp = get_driver_boolean_parameter(handle, "add_timestamp",
gAddTimeStamp, true); gAddTimeStamp, true);
const char * logFilePath = get_driver_parameter(handle, "logfile", const char* logFilePath = get_driver_parameter(handle, "logfile",
NULL, "/var/log/"DRIVER_NAME".log"); NULL, "/var/log/"DRIVER_NAME".log");
if (logFilePath != NULL) { if (logFilePath != NULL)
gLogFilePath = strdup(logFilePath); gLogFilePath = strdup(logFilePath);
}
unload_driver_settings(handle); unload_driver_settings(handle);
@@ -68,16 +73,15 @@ void release_settings()
} }
void usb_audio_trace(bool force, const char* func, const char *fmt, ...) void usb_audio_trace(bool force, const char* func, const char* fmt, ...)
{ {
if (!(force || gTraceOn)) { if (!(force || gTraceOn))
return; return;
}
va_list arg_list; va_list arg_list;
static const char *prefix = DRIVER_NAME":"; static const char* prefix = DRIVER_NAME":";
static char buffer[1024]; static char buffer[1024];
char *buf_ptr = buffer; char* buf_ptr = buffer;
if (gLogFilePath == NULL) { if (gLogFilePath == NULL) {
strlcpy(buffer, prefix, sizeof(buffer)); strlcpy(buffer, prefix, sizeof(buffer));
buf_ptr += strlen(prefix); buf_ptr += strlen(prefix);
@@ -1,6 +1,6 @@
/* /*
* Driver for USB Audio Device Class devices. * Driver for USB Audio Device Class devices.
* Copyright (c) 2009,10,12 S.Zharski <[email protected]> * Copyright (c) 2009-13 S.Zharski <[email protected]>
* Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
* *
*/ */
@@ -8,14 +8,10 @@
#define _USB_AUDIO_SETTINGS_H_ #define _USB_AUDIO_SETTINGS_H_
#include <driver_settings.h>
#include "Driver.h"
void load_settings(); void load_settings();
void release_settings(); void release_settings();
void usb_audio_trace(bool force, const char *func, const char *fmt, ...); void usb_audio_trace(bool force, const char* func, const char* fmt, ...);
#ifdef TRACE #ifdef TRACE
#undef TRACE #undef TRACE
@@ -30,5 +26,5 @@ extern bool gTraceFlow;
#define TRACE_RET(result) usb_audio_trace(false, __func__, \ #define TRACE_RET(result) usb_audio_trace(false, __func__, \
"Returns:%#010x\n", result); "Returns:%#010x\n", result);
#endif /*_USB_AUDIO_SETTINGS_H_*/ #endif // _USB_AUDIO_SETTINGS_H_
@@ -1,36 +1,36 @@
/* /*
* Driver for USB Audio Device Class devices. * Driver for USB Audio Device Class devices.
* Copyright (c) 2009,10,12 S.Zharski <[email protected]> * Copyright (c) 2009-13 S.Zharski <[email protected]>
* Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
* *
*/ */
#include "Stream.h" #include "Stream.h"
#include "Device.h" #include "Device.h"
#include "Driver.h" #include "Driver.h"
#include "Settings.h" #include "Settings.h"
Stream::Stream(Device *device, size_t interface, usb_interface_list *List Stream::Stream(Device* device, size_t interface, usb_interface_list* List)
/*, bool isInput, uint32 HWChannel*/) :
: AudioStreamingInterface(&device->AudioControl(), interface, List),
AudioStreamingInterface(&device->AudioControl(), interface, List), fDevice(device),
fDevice(device), fStatus(B_NO_INIT),
fStatus(B_NO_INIT), fStreamEndpoint(0),
fStreamEndpoint(0), fIsRunning(false),
fIsRunning(false), fArea(-1),
fArea(-1), fAreaSize(0),
fAreaSize(0), fDescriptors(NULL),
fDescriptors(NULL), fDescriptorsCount(0),
fDescriptorsCount(0), fCurrentBuffer(0),
fCurrentBuffer(0), fStartingFrame(0),
fStartingFrame(0), fSamplesCount(0),
fSamplesCount(0), fPacketSize(0),
fPacketSize(0), fProcessedBuffers(0)
fProcessedBuffers(0)
{ {
memset(&fFormat, 0, sizeof(_multi_format));
} }
@@ -58,7 +58,7 @@ Stream::_ChooseAlternate()
if (fAlternates[i]->Format()->fFormatType != UAF_FORMAT_TYPE_I) { if (fAlternates[i]->Format()->fFormatType != UAF_FORMAT_TYPE_I) {
TRACE("Ignore alternate %d - format type %#02x is not supported.\n", TRACE("Ignore alternate %d - format type %#02x is not supported.\n",
i, fAlternates[i]->Format()->fFormatType); i, fAlternates[i]->Format()->fFormatType);
continue; continue;
} }
@@ -71,16 +71,16 @@ Stream::_ChooseAlternate()
break; break;
default: default:
TRACE("Ignore alternate %d - format %#04x is not supported.\n", TRACE("Ignore alternate %d - format %#04x is not supported.\n",
i, fAlternates[i]->Interface()->fFormatTag); i, fAlternates[i]->Interface()->fFormatTag);
continue; continue;
} }
TypeIFormatDescriptor* format TypeIFormatDescriptor* format
= static_cast<TypeIFormatDescriptor*>(fAlternates[i]->Format()); = static_cast<TypeIFormatDescriptor*>(fAlternates[i]->Format());
if (format->fNumChannels > 2) { if (format->fNumChannels > 2) {
TRACE("Ignore alternate %d - channel count %d " TRACE("Ignore alternate %d - channel count %d "
"is not supported.\n", i, format->fNumChannels); "is not supported.\n", i, format->fNumChannels);
continue; continue;
} }
@@ -88,7 +88,7 @@ Stream::_ChooseAlternate()
switch(format->fBitResolution) { switch(format->fBitResolution) {
default: default:
TRACE("Ignore alternate %d - bit resolution %d " TRACE("Ignore alternate %d - bit resolution %d "
"is not supported.\n", i, format->fBitResolution); "is not supported.\n", i, format->fBitResolution);
continue; continue;
case 8: case 16: case 18: case 20: case 24: case 32: case 8: case 16: case 18: case 20: case 24: case 32:
break; break;
@@ -107,10 +107,11 @@ Stream::_ChooseAlternate()
return B_NO_INIT; return B_NO_INIT;
} }
const ASEndpointDescriptor* endpoint = fAlternates[ const ASEndpointDescriptor* endpoint
fActiveAlternate]->Endpoint(); = fAlternates[fActiveAlternate]->Endpoint();
fIsInput = (endpoint->fEndpointAddress & USB_ENDPOINT_ADDR_DIR_IN) fIsInput = (endpoint->fEndpointAddress & USB_ENDPOINT_ADDR_DIR_IN)
== USB_ENDPOINT_ADDR_DIR_IN; == USB_ENDPOINT_ADDR_DIR_IN;
TRACE("Alternate %d EP:%x selected for %s!\n", TRACE("Alternate %d EP:%x selected for %s!\n",
fActiveAlternate, endpoint->fEndpointAddress, fActiveAlternate, endpoint->fEndpointAddress,
fIsInput ? "recording" : "playback"); fIsInput ? "recording" : "playback");
@@ -158,8 +159,8 @@ Stream::_SetupBuffers()
B_READ_AREA | B_WRITE_AREA); B_READ_AREA | B_WRITE_AREA);
if (fArea < 0) { if (fArea < 0) {
TRACE_ALWAYS("Error of creating %#x - bytes size buffer area:%#010x\n", TRACE_ALWAYS("Error of creating %#x - "
fAreaSize, fArea); "bytes size buffer area:%#010x\n", fAreaSize, fArea);
fStatus = fArea; fStatus = fArea;
return fStatus; return fStatus;
} }
@@ -197,7 +198,7 @@ Stream::_SetupBuffers()
status_t status_t
Stream::OnSetConfiguration(usb_device device, Stream::OnSetConfiguration(usb_device device,
const usb_configuration_info *config) const usb_configuration_info* config)
{ {
if (config == NULL) { if (config == NULL) {
TRACE_ALWAYS("NULL configuration. Not set.\n"); TRACE_ALWAYS("NULL configuration. Not set.\n");
@@ -205,7 +206,7 @@ Stream::OnSetConfiguration(usb_device device,
} }
usb_interface_info* interface usb_interface_info* interface
= &config->interface[fInterface].alt[fActiveAlternate]; = &config->interface[fInterface].alt[fActiveAlternate];
if (interface == NULL) { if (interface == NULL) {
TRACE_ALWAYS("NULL interface. Not set.\n"); TRACE_ALWAYS("NULL interface. Not set.\n");
return B_ERROR; return B_ERROR;
@@ -220,29 +221,13 @@ Stream::OnSetConfiguration(usb_device device,
if (address == interface->endpoint[i].descr->endpoint_address) { if (address == interface->endpoint[i].descr->endpoint_address) {
fStreamEndpoint = interface->endpoint[i].handle; fStreamEndpoint = interface->endpoint[i].handle;
TRACE("%s Stream Endpoint [address %#04x] handle is: %#010x.\n", TRACE("%s Stream Endpoint [address %#04x] handle is: %#010x.\n",
fIsInput ? "Input" : "Output", address, fStreamEndpoint); fIsInput ? "Input" : "Output", address, fStreamEndpoint);
/*
size_t actualLength = 0;
uint32 speed = 48000;
uint8 data[3];
data[0] = 0xFF & speed;
data[1] = (uint8) 0xFF & speed >> 8;
data[2] = (uint8) 0xFF & speed >> 16;
status_t status = gUSBModule->send_request(device,
USB_REQTYPE_CLASS | USB_REQTYPE_ENDPOINT_OUT,
UAS_SET_CUR, UAS_SAMPLING_FREQ_CONTROL << 8,
address, 3, data, &actualLength);
TRACE_ALWAYS("set_speed for ep %#x %d: %x\n",
address, actualLength, status);
*/
return B_OK; return B_OK;
} }
} }
TRACE("%s Stream Endpoint [address %#04x] was not found.\n", TRACE("%s Stream Endpoint [address %#04x] was not found.\n",
fIsInput ? "Input" : "Output", address); fIsInput ? "Input" : "Output", address);
return B_ERROR; return B_ERROR;
} }
@@ -278,9 +263,8 @@ Stream::Stop()
status_t status_t
Stream::_QueueNextTransfer(size_t queuedBuffer, bool start) Stream::_QueueNextTransfer(size_t queuedBuffer, bool start)
{ {
TypeIFormatDescriptor* format TypeIFormatDescriptor* format = static_cast<TypeIFormatDescriptor*>(
= static_cast<TypeIFormatDescriptor*>(fAlternates[ fAlternates[fActiveAlternate]->Format());
fActiveAlternate]->Format());
size_t bufferSize = format->fNumChannels * format->fSubframeSize; size_t bufferSize = format->fNumChannels * format->fSubframeSize;
bufferSize *= fSamplesCount / kSamplesBufferCount; bufferSize *= fSamplesCount / kSamplesBufferCount;
@@ -290,34 +274,14 @@ Stream::_QueueNextTransfer(size_t queuedBuffer, bool start)
size_t packetsCount = fDescriptorsCount / kSamplesBufferCount; size_t packetsCount = fDescriptorsCount / kSamplesBufferCount;
TRACE("buffers:%#010x[%#x]\ndescrs:%#010x[%#x]\n", TRACE("buffers:%#010x[%#x]\ndescrs:%#010x[%#x]\n",
buffers + bufferSize * queuedBuffer, bufferSize, buffers + bufferSize * queuedBuffer, bufferSize,
fDescriptors + queuedBuffer * packetsCount, packetsCount); fDescriptors + queuedBuffer * packetsCount, packetsCount);
#if 0
{
static int16 sin[24] = { 0, 4277, 8481, 12540, 16384, 19948, 23170, 25996,
28378, 30273, 31651, 32487, 32767, 32487, 31651, 30273, 28378, 25996,
23170, 19948, 16384, 12540, 8481, 4277 };
static uint16 sample = 0;
static bool sign = true;
uint16* b = (uint16*)(buffers + bufferSize * queuedBuffer);
size_t length = bufferSize;
for (size_t u = 0; u < length / 2; u += 2) {
b[u] = b[u + 1] = sign ? sin[sample] : -sin[sample];
sample ++;
if (sample == 24) {
sample = 0;
sign = !sign;
}
}
}
#endif
status_t status = gUSBModule->queue_isochronous(fStreamEndpoint, status_t status = gUSBModule->queue_isochronous(fStreamEndpoint,
buffers + bufferSize * queuedBuffer, bufferSize, buffers + bufferSize * queuedBuffer, bufferSize,
fDescriptors + queuedBuffer * packetsCount, packetsCount, fDescriptors + queuedBuffer * packetsCount, packetsCount,
&fStartingFrame, start ? USB_ISO_ASAP : 0, &fStartingFrame, start ? USB_ISO_ASAP : 0,
Stream::_TransferCallback, this); Stream::_TransferCallback, this);
TRACE("frame:%#010x\n", fStartingFrame); TRACE("frame:%#010x\n", fStartingFrame);
return status; // B_OK; return status; // B_OK;
@@ -325,16 +289,16 @@ Stream::_QueueNextTransfer(size_t queuedBuffer, bool start)
void void
Stream::_TransferCallback(void *cookie, int32 status, void *data, Stream::_TransferCallback(void* cookie, int32 status, void* data,
uint32 actualLength) uint32 actualLength)
{ {
if (status == B_CANCELED) { if (status == B_CANCELED) {
TRACE_ALWAYS("Cancelled: c:%p st:%#010x, data:%#010x, len:%d\n", TRACE_ALWAYS("Cancelled: c:%p st:%#010x, data:%#010x, len:%d\n",
cookie, status, data, actualLength); cookie, status, data, actualLength);
return; return;
} }
Stream *stream = (Stream *)cookie; Stream* stream = (Stream*)cookie;
stream->fCurrentBuffer = (stream->fCurrentBuffer + 1) % kSamplesBufferCount; stream->fCurrentBuffer = (stream->fCurrentBuffer + 1) % kSamplesBufferCount;
@@ -342,9 +306,8 @@ Stream::_TransferCallback(void *cookie, int32 status, void *data,
/*status_t result =*/ stream->_QueueNextTransfer(stream->fCurrentBuffer, false); /*status_t result =*/ stream->_QueueNextTransfer(stream->fCurrentBuffer, false);
if (atomic_add(&stream->fProcessedBuffers, 1) > (int32)kSamplesBufferCount) { if (atomic_add(&stream->fProcessedBuffers, 1) > (int32)kSamplesBufferCount)
TRACE_ALWAYS("Processed buffers overflow:%d\n", stream->fProcessedBuffers); TRACE_ALWAYS("Processed buffers overflow:%d\n", stream->fProcessedBuffers);
}
release_sem_etc(stream->fDevice->fBuffersReadySem, 1, B_DO_NOT_RESCHEDULE); release_sem_etc(stream->fDevice->fBuffersReadySem, 1, B_DO_NOT_RESCHEDULE);
@@ -359,21 +322,19 @@ Stream::_DumpDescriptors()
//size_t packetsCount = fDescriptorsCount / kSamplesBufferCount; //size_t packetsCount = fDescriptorsCount / kSamplesBufferCount;
size_t from = /*fCurrentBuffer > 0 ? packetsCount :*/ 0 ; size_t from = /*fCurrentBuffer > 0 ? packetsCount :*/ 0 ;
size_t to = /*fCurrentBuffer > 0 ?*/ fDescriptorsCount /*: packetsCount*/ ; size_t to = /*fCurrentBuffer > 0 ?*/ fDescriptorsCount /*: packetsCount*/ ;
for (size_t i = from; i < to; i++) { for (size_t i = from; i < to; i++)
TRACE("%d:req_len:%d; act_len:%d; stat:%#010x\n", i, TRACE("%d:req_len:%d; act_len:%d; stat:%#010x\n", i,
fDescriptors[i].request_length, fDescriptors[i].actual_length, fDescriptors[i].request_length, fDescriptors[i].actual_length,
fDescriptors[i].status); fDescriptors[i].status);
}
} }
status_t status_t
Stream::GetEnabledChannels(uint32& offset, multi_channel_enable *Enable) Stream::GetEnabledChannels(uint32& offset, multi_channel_enable* Enable)
{ {
AudioChannelCluster* cluster = ChannelCluster(); AudioChannelCluster* cluster = ChannelCluster();
if (cluster == 0) { if (cluster == 0)
return B_ERROR; return B_ERROR;
}
for (size_t i = 0; i < cluster->ChannelsCount(); i++) { for (size_t i = 0; i < cluster->ChannelsCount(); i++) {
B_SET_CHANNEL(Enable->enable_bits, offset++, true); B_SET_CHANNEL(Enable->enable_bits, offset++, true);
@@ -385,24 +346,22 @@ Stream::GetEnabledChannels(uint32& offset, multi_channel_enable *Enable)
status_t status_t
Stream::SetEnabledChannels(uint32& offset, multi_channel_enable *Enable) Stream::SetEnabledChannels(uint32& offset, multi_channel_enable* Enable)
{ {
AudioChannelCluster* cluster = ChannelCluster(); AudioChannelCluster* cluster = ChannelCluster();
if (cluster == 0) { if (cluster == 0)
return B_ERROR; return B_ERROR;
}
for (size_t i = 0; i < cluster->ChannelsCount(); i++) { for (size_t i = 0; i < cluster->ChannelsCount(); i++)
TRACE("%s channel %d.\n", (B_TEST_CHANNEL(Enable->enable_bits, offset++) TRACE("%s channel %d.\n", (B_TEST_CHANNEL(Enable->enable_bits, offset++)
? "Enable" : "Disable"), offset + 1); ? "Enable" : "Disable"), offset + 1);
}
return B_OK; return B_OK;
} }
status_t status_t
Stream::GetGlobalFormat(multi_format_info *Format) Stream::GetGlobalFormat(multi_format_info* Format)
{ {
_multi_format* format = fIsInput ? &Format->input : &Format->output; _multi_format* format = fIsInput ? &Format->input : &Format->output;
format->cvsr = fAlternates[fActiveAlternate]->GetSamplingRate(); format->cvsr = fAlternates[fActiveAlternate]->GetSamplingRate();
@@ -416,12 +375,12 @@ Stream::GetGlobalFormat(multi_format_info *Format)
status_t status_t
Stream::SetGlobalFormat(multi_format_info *Format) Stream::SetGlobalFormat(multi_format_info* Format)
{ {
_multi_format* format = fIsInput ? &Format->input : &Format->output; _multi_format* format = fIsInput ? &Format->input : &Format->output;
AudioStreamAlternate* alternate = fAlternates[fActiveAlternate]; AudioStreamAlternate* alternate = fAlternates[fActiveAlternate];
if (format->rate == alternate->GetSamplingRateId(0) if (format->rate == alternate->GetSamplingRateId(0)
&& format->format == alternate->GetFormatId()) { && format->format == alternate->GetFormatId()) {
TRACE("No changes required\n"); TRACE("No changes required\n");
return B_OK; return B_OK;
} }
@@ -453,13 +412,13 @@ Stream::SetGlobalFormat(multi_format_info *Format)
uint8 address = fAlternates[fActiveAlternate]->Endpoint()->fEndpointAddress; uint8 address = fAlternates[fActiveAlternate]->Endpoint()->fEndpointAddress;
status = gUSBModule->send_request(fDevice->fDevice, status = gUSBModule->send_request(fDevice->fDevice,
USB_REQTYPE_CLASS | USB_REQTYPE_ENDPOINT_OUT, USB_REQTYPE_CLASS | USB_REQTYPE_ENDPOINT_OUT,
UAS_SET_CUR, UAS_SAMPLING_FREQ_CONTROL << 8, UAS_SET_CUR, UAS_SAMPLING_FREQ_CONTROL << 8,
address, 3, data, &actualLength); address, 3, data, &actualLength);
TRACE_ALWAYS("set_speed %02x%02x%02x for ep %#x %d: %x\n", TRACE_ALWAYS("set_speed %02x%02x%02x for ep %#x %d: %x\n",
data[0], data[1], data[2], data[0], data[1], data[2],
address, actualLength, status); address, actualLength, status);
return status; return status;
} }
@@ -494,9 +453,8 @@ Stream::GetBuffers(multi_buffer_list* List)
List->return_playback_buffer_size, List->return_playback_buffers); List->return_playback_buffer_size, List->return_playback_buffers);
} }
TypeIFormatDescriptor* format TypeIFormatDescriptor* format = static_cast<TypeIFormatDescriptor*>(
= static_cast<TypeIFormatDescriptor*>( fAlternates[fActiveAlternate]->Format());
fAlternates[fActiveAlternate]->Format());
// const ASEndpointDescriptor* endpoint // const ASEndpointDescriptor* endpoint
// = fAlternates[fActiveAlternate]->Endpoint(); // = fAlternates[fActiveAlternate]->Endpoint();
@@ -505,18 +463,17 @@ Stream::GetBuffers(multi_buffer_list* List)
TRACE("%s buffer #%d:\n", fIsInput ? "input" : "output", buffer + 1); TRACE("%s buffer #%d:\n", fIsInput ? "input" : "output", buffer + 1);
for (size_t channel = startChannel; for (size_t channel = startChannel;
channel < format->fNumChannels; channel++) channel < format->fNumChannels; channel++) {
{
// init stride to the same for all buffers // init stride to the same for all buffers
uint32 stride = format->fSubframeSize * format->fNumChannels; uint32 stride = format->fSubframeSize * format->fNumChannels;
Buffers[buffer][channel].stride = stride; Buffers[buffer][channel].stride = stride;
// init to buffers area begin // init to buffers area begin
Buffers[buffer][channel].base Buffers[buffer][channel].base
= (char*)(fDescriptors + fDescriptorsCount); = (char*)(fDescriptors + fDescriptorsCount);
// shift for whole buffer if required // shift for whole buffer if required
size_t bufferSize = fPacketSize/*endpoint->fMaxPacketSize*/ size_t bufferSize = fPacketSize/*endpoint->fMaxPacketSize*/
* (fDescriptorsCount / kSamplesBufferCount); * (fDescriptorsCount / kSamplesBufferCount);
Buffers[buffer][channel].base += buffer * bufferSize; Buffers[buffer][channel].base += buffer * bufferSize;
// shift for channel if required // shift for channel if required
Buffers[buffer][channel].base += channel * format->fSubframeSize; Buffers[buffer][channel].base += channel * format->fSubframeSize;
@@ -528,11 +485,12 @@ Stream::GetBuffers(multi_buffer_list* List)
if (fIsInput) { if (fIsInput) {
List->return_record_channels += format->fNumChannels; List->return_record_channels += format->fNumChannels;
TRACE("return_record_channels:%#010x\n", List->return_record_channels); TRACE("return_record_channels:%#010x\n",
List->return_record_channels);
} else { } else {
List->return_playback_channels += format->fNumChannels; List->return_playback_channels += format->fNumChannels;
TRACE("return_playback_channels:%#010x\n", TRACE("return_playback_channels:%#010x\n",
List->return_playback_channels); List->return_playback_channels);
} }
return B_OK; return B_OK;
@@ -563,18 +521,3 @@ Stream::ExchangeBuffer(multi_buffer_info* Info)
return true; return true;
} }
/*
ASInterfaceDescriptor*
Stream::ASInterface()
{
return fAlternates[fActiveAlternate]->Interface();
}
_ASFormatDescriptor*
Stream::ASFormat()
{
return fAlternates[fActiveAlternate]->Format();
}*/
@@ -1,95 +1,72 @@
/* /*
* Driver for USB Audio Device Class devices. * Driver for USB Audio Device Class devices.
* Copyright (c) 2009,10,12 S.Zharski <[email protected]> * Copyright (c) 2009-13 S.Zharski <[email protected]>
* Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
* *
*/ */
#ifndef _STREAM_H_ #ifndef _USB_AUDIO_STREAM_H_
#define _STREAM_H_ #define _USB_AUDIO_STREAM_H_
#include <OS.h>
#include "AudioStreamingInterface.h" #include "AudioStreamingInterface.h"
class Device; class Device;
// typedef Vector<AudioStreamAlternate*> StreamAlternatesVector;
// typedef Vector<AudioStreamAlternate*>::Iterator StreamAlternatesIterator;
class Stream : public AudioStreamingInterface { class Stream : public AudioStreamingInterface {
friend class Device; friend class Device;
public: public:
Stream(Device* device, size_t interface, Stream(Device* device, size_t interface,
usb_interface_list *List usb_interface_list* List);
/*, bool isInput, uint32 HWChannel*/);
~Stream(); ~Stream();
status_t Init();
status_t InitCheck() { return fStatus; }
status_t Start(); status_t Init();
status_t Stop(); status_t InitCheck() { return fStatus; }
bool IsRunning() { return fIsRunning; }
status_t GetBuffers(multi_buffer_list* List); status_t Start();
status_t Stop();
bool IsRunning() { return fIsRunning; }
status_t OnSetConfiguration(usb_device device, status_t GetBuffers(multi_buffer_list* List);
const usb_configuration_info *config);
bool ExchangeBuffer(multi_buffer_info* Info); status_t OnSetConfiguration(usb_device device,
/* const usb_configuration_info* config);
int32 InterruptHandler(uint32 SignaledChannelsMask);
*/
// ASInterfaceDescriptor* ASInterface();
// _ASFormatDescriptor* ASFormat();
status_t GetEnabledChannels(uint32& offset,
multi_channel_enable *Enable);
status_t SetEnabledChannels(uint32& offset,
multi_channel_enable *Enable);
status_t GetGlobalFormat(multi_format_info *Format);
status_t SetGlobalFormat(multi_format_info *Format);
bool ExchangeBuffer(multi_buffer_info* Info);
status_t GetEnabledChannels(uint32& offset,
multi_channel_enable* Enable);
status_t SetEnabledChannels(uint32& offset,
multi_channel_enable* Enable);
status_t GetGlobalFormat(multi_format_info* Format);
status_t SetGlobalFormat(multi_format_info* Format);
protected: protected:
Device* fDevice; Device* fDevice;
status_t fStatus; status_t fStatus;
// alternates of the streams uint8 fTerminalID;
// StreamAlternatesVector fAlternates; usb_pipe fStreamEndpoint;
// size_t fActiveAlternate; bool fIsRunning;
area_id fArea;
uint8 fTerminalID; size_t fAreaSize;
usb_pipe fStreamEndpoint; usb_iso_packet_descriptor* fDescriptors;
bool fIsRunning; size_t fDescriptorsCount;
area_id fArea; size_t fCurrentBuffer;
size_t fAreaSize; uint32 fStartingFrame;
usb_iso_packet_descriptor* fDescriptors; size_t fSamplesCount;
size_t fDescriptorsCount; size_t fPacketSize;
size_t fCurrentBuffer; int32 fProcessedBuffers;
uint32 fStartingFrame;
size_t fSamplesCount;
size_t fPacketSize;
int32 fProcessedBuffers;
_multi_format fFormat;
private: private:
status_t _ChooseAlternate(); status_t _ChooseAlternate();
status_t _SetupBuffers(); status_t _SetupBuffers();
status_t _QueueNextTransfer(size_t buffer, bool start); status_t _QueueNextTransfer(size_t buffer, bool start);
static void _TransferCallback(void *cookie, int32 status, static void _TransferCallback(void* cookie, int32 status,
void *data, uint32 actualLength); void* data, uint32 actualLength);
void _DumpDescriptors(); void _DumpDescriptors();
}; };
/*
class RecordStream : public Stream {
public:
RecordStream(Device* device, uint32 HWChannel);
~RecordStream();
status_t Start();
};
*/
#endif // _STREAM_H_ #endif // _USB_AUDIO_STREAM_H_
@@ -7,10 +7,11 @@
* And the USB Device Class Definition for Audio Formats Release 1.0 * And the USB Device Class Definition for Audio Formats Release 1.0
* (March 18, 1998) * (March 18, 1998)
*/ */
#ifndef __USB_AUDIO_SPEC_H__ #ifndef __USB_AUDIO_SPEC_H__
#define __USB_AUDIO_SPEC_H__ #define __USB_AUDIO_SPEC_H__
#include <SupportDefs.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@@ -1,127 +0,0 @@
## BeOS Generic Makefile v2.2 ##
## Fill in this file to specify the project being created, and the referenced
## makefile-engine will do all of the hard work for you. This handles both
## Intel and PowerPC builds of the BeOS.
## Application Specific Settings ---------------------------------------------
# specify the name of the binary
NAME=usb_audio
# specify the type of binary
# APP: Application
# SHARED: Shared library or add-on
# STATIC: Static library archive
# DRIVER: Kernel Driver
TYPE=DRIVER
# add support for new Pe and Eddie features
# to fill in generic makefile
#%{
# @src->@
# specify the source files to use
# full paths or paths relative to the makefile can be included
# all files, regardless of directory, will have their object
# files created in the common object directory.
# Note that this means this makefile will not work correctly
# if two source files with the same name (source.c or source.cpp)
# are included from different directories. Also note that spaces
# in folder names do not work well with this makefile.
SRCS=Driver.cpp\
Device.cpp\
AudioControlInterface.cpp\
AudioStreamingInterface.cpp\
Stream.cpp\
Settings.cpp
# specify the resource files to use
# full path or a relative path to the resource file can be used.
RSRCS=
# @<-src@
#%}
# end support for Pe and Eddie
# specify additional libraries to link against
# there are two acceptable forms of library specifications
# - if your library follows the naming pattern of:
# libXXX.so or libXXX.a you can simply specify XXX
# library: libbe.so entry: be
#
# - if your library does not follow the standard library
# naming scheme you need to specify the path to the library
# and it's name
# library: my_lib.a entry: my_lib.a or path/my_lib.a
LIBS=
# specify additional paths to directories following the standard
# libXXX.so or libXXX.a naming scheme. You can specify full paths
# or paths relative to the makefile. The paths included may not
# be recursive, so include all of the paths where libraries can
# be found. Directories where source files are found are
# automatically included.
LIBPATHS=
# additional paths to look for system headers
# thes use the form: #include <header>
# source file directories are NOT auto-included here
SYSTEM_INCLUDE_PATHS=../../../../../../headers/private/kernel \
../../../../../../headers/private/kernel/util \
../../../../../../headers/private/media
# additional paths to look for local headers
# thes use the form: #include "header"
# source file directories are automatically included
LOCAL_INCLUDE_PATHS=../../../../../../build/config_headers
# specify the level of optimization that you desire
# NONE, SOME, FULL
OPTIMIZE=
# specify any preprocessor symbols to be defined. The symbols will not
# have their values set automatically; you must supply the value (if any)
# to use. For example, setting DEFINES to "DEBUG=1" will cause the
# compiler option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG"
# would pass "-DDEBUG" on the compiler's command line.
DEFINES=
# specify special warning levels
# if unspecified default warnings will be used
# NONE = supress all warnings
# ALL = enable all warnings
WARNINGS=ALL
# specify whether image symbols will be created
# so that stack crawls in the debugger are meaningful
# if TRUE symbols will be created
SYMBOLS=
# specify debug settings
# if TRUE will allow application to be run from a source-level
# debugger. Note that this will disable all optimzation.
DEBUGGER=
# specify additional compiler flags for all files
COMPILER_FLAGS=
# specify additional linker flags
LINKER_FLAGS=
# specify the version of this particular item
# (for example, -app 3 4 0 d 0 -short 340 -long "340 "`echo -n -e '\302\251'`"1999 GNU GPL")
# This may also be specified in a resource.
APP_VERSION=
# (for TYPE == DRIVER only) Specify desired location of driver in the /dev
# hierarchy. Used by the driverinstall rule. E.g., DRIVER_PATH = video/usb will
# instruct the driverinstall rule to place a symlink to your driver's binary in
# ~/add-ons/kernel/drivers/dev/video/usb, so that your driver will appear at
# /dev/video/usb when loaded. Default is "misc".
DRIVER_PATH=audio/hmulti
## include the makefile-engine
include $(BUILDHOME)/etc/makefile-engine