USB audio: cleanup and codestyle fixes.
* cleanup and codestyle fixes; * AudioFunction module contents purged out as unused.
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -559,10 +482,9 @@ Device::_MultiGetBuffers(multi_buffer_list* List)
|
|||||||
List->flags = 0;
|
List->flags = 0;
|
||||||
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; }
|
|
||||||
|
|
||||||
AudioControlInterface& AudioControl() { return fAudioControl; }
|
usb_device USBDevice() { return fDevice; }
|
||||||
|
|
||||||
|
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 <imker@gmx.li>
|
* Copyright (c) 2009-13 S.Zharski <imker@gmx.li>
|
||||||
* 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
|
|
||||||
Reference in New Issue
Block a user