root/src/add-ons/kernel/drivers/audio/usb/AudioControlInterface.h
/*
 *      Driver for USB Audio Device Class devices.
 *      Copyright (c) 2009-13 S.Zharski <imker@gmx.li>
 *      Distributed under the terms of the MIT license.
 *
 */
#ifndef _AUDIO_CONTROL_INTERFACE_H_
#define _AUDIO_CONTROL_INTERFACE_H_


#include <USB3.h>
#include <hmulti_audio.h>
#include <usb/USB_audio.h>
#include <util/VectorMap.h>


class Device;
class AudioControlInterface;

class _AudioControl;
typedef VectorMap<uint32, _AudioControl*> AudioControlsMap;
typedef VectorMap<uint32, _AudioControl*>::Iterator AudioControlsIterator;


class AudioChannelCluster {
public:
                                                        AudioChannelCluster();
        virtual                                 ~AudioChannelCluster();

                        uint8                   ChannelsCount()         { return fOutChannelsNumber; }
                        uint32                  ChannelsConfig()        { return fChannelsConfig;        }

                        bool                    HasChannel(uint32 location);

protected:
                        uint8                   fOutChannelsNumber;
                        uint32                  fChannelsConfig;
                        uint8                   fChannelNames;
};


template<class __base_class_name>
class _AudioChannelCluster : public __base_class_name,
        public AudioChannelCluster {
public:
                                                        _AudioChannelCluster(AudioControlInterface* interface,
                                                                usb_audiocontrol_header_descriptor* Header)
                                                        :
                                                        __base_class_name(interface, Header) {}
        virtual                                 ~_AudioChannelCluster() {}

        virtual AudioChannelCluster*
                                                        OutCluster() { return this; }
};


class _AudioControl {
public:
                                                        _AudioControl(AudioControlInterface* interface,
                                                                usb_audiocontrol_header_descriptor* Header);
        virtual                                 ~_AudioControl();

                        uint8                   ID() { return fID; }
                        uint8                   SourceID() { return fSourceID; }
                        uint8                   SubType() { return fSubType; }
                        status_t                InitCheck() { return fStatus; };

        virtual const char*             Name() { return ""; }

        virtual AudioChannelCluster*
                                                        OutCluster();

protected:
                        status_t                fStatus;
                        AudioControlInterface*  fInterface;
                        uint8                   fSubType;
                        uint8                   fID;
                        uint8                   fSourceID;
                        uint8                   fStringIndex;
};


class _Terminal : public _AudioControl {
public:
                                                        _Terminal(AudioControlInterface* interface,
                                                                usb_audiocontrol_header_descriptor* Header);
        virtual                                 ~_Terminal();

                        uint16                  TerminalType() { return fTerminalType; }
                        bool                    IsUSBIO();
        virtual const char*             Name();
        static  const char*             _GetTerminalDescription(uint16 TerminalType);

protected:
                        uint16                  fTerminalType;
                        uint8                   fAssociatedTerminal;
                        uint8                   fClockSourceId;
                        uint16                  fControlsBitmap;
};


class InputTerminal : public _AudioChannelCluster<_Terminal> {
public:
                                                        InputTerminal(AudioControlInterface* interface,
                                                                usb_audiocontrol_header_descriptor* Header);
        virtual                                 ~InputTerminal();

        virtual const char*             Name();

protected:
};


class OutputTerminal : public _Terminal {
public:
                                                        OutputTerminal(AudioControlInterface* interface,
                                                                usb_audiocontrol_header_descriptor* Header);
        virtual                                 ~OutputTerminal();

        virtual const char*             Name();

protected:
};


class MixerUnit : public _AudioChannelCluster<_AudioControl> {
public:
                                                        MixerUnit(AudioControlInterface* interface,
                                                                usb_audiocontrol_header_descriptor* Header);
        virtual                                 ~MixerUnit();

        virtual const char*             Name() { return "Mixer"; }
                        bool                    HasProgrammableControls();
                        bool                    IsControlProgrammable(int inChannel, int outChannel);

//protected:
                        Vector<uint8>   fInputPins;
                        Vector<uint8>   fControlsBitmap;
                        uint8                   fBmControlsR2;
};


class SelectorUnit : public _AudioControl {
public:
                                                        SelectorUnit(AudioControlInterface* interface,
                                                                usb_audiocontrol_header_descriptor* Header);
        virtual                                 ~SelectorUnit();

        virtual AudioChannelCluster*
                                                        OutCluster();
        virtual const char*             Name() { return "Selector"; }

// protected:
                        Vector<uint8>   fInputPins;
                        uint8                   fControlsBitmap;
};


class FeatureUnit : public _AudioControl {
public:
                                                        FeatureUnit(AudioControlInterface* interface,
                                                                usb_audiocontrol_header_descriptor* Header);
        virtual                                 ~FeatureUnit();

        virtual const char*             Name();
                        bool                    HasControl(int32 Channel, uint32 Control);

// protected:
                        void                    NormalizeAndTraceChannel(int32 Channel);

                        Vector<uint32>  fControlBitmaps;
};


class EffectUnit : public _AudioControl {
public:
                                                        EffectUnit(AudioControlInterface* interface,
                                                                usb_audiocontrol_header_descriptor* Header);
        virtual                                 ~EffectUnit();

        virtual const char*             Name() { return "Effect"; }
protected:
/*                      uint16                  fProcessType;
                        Vector<uint8>   fInputPins;
                        uint8                   fControlsBitmap;
                        Vector<uint16>  fModes;
*/};


class ProcessingUnit : public _AudioChannelCluster<_AudioControl> {
public:
                                                        ProcessingUnit(AudioControlInterface* interface,
                                                                usb_audiocontrol_header_descriptor* Header);
        virtual                                 ~ProcessingUnit();

        virtual const char*             Name() { return "Processing"; }

protected:
                        uint16                  fProcessType;
                        Vector<uint8>   fInputPins;
                        uint8                   fControlsBitmap;
                        Vector<uint16>  fModes;
};


class ExtensionUnit : public _AudioChannelCluster<_AudioControl> {
public:
                                                        ExtensionUnit(AudioControlInterface* interface,
                                                                usb_audiocontrol_header_descriptor* Header);
        virtual                                 ~ExtensionUnit();

        virtual const char*             Name() { return "Extension"; }

protected:
                        uint16                  fExtensionCode;
                        Vector<uint8>   fInputPins;
                        uint8                   fControlsBitmap;
};


class ClockSource : public _AudioControl {
public:
                                                        ClockSource(AudioControlInterface* interface,
                                                                usb_audiocontrol_header_descriptor* Header);
        virtual                                 ~ClockSource();

protected:
};


class ClockSelector : public _AudioControl {
public:
                                                        ClockSelector(AudioControlInterface* interface,
                                                                usb_audiocontrol_header_descriptor* Header);
        virtual                                 ~ClockSelector();

protected:
};


class ClockMultiplier : public _AudioControl {
public:
                                                        ClockMultiplier(AudioControlInterface* interface,
                                                                usb_audiocontrol_header_descriptor* Header);
        virtual                                 ~ClockMultiplier();

protected:
};


class SampleRateConverter : public _AudioControl {
public:
                                                        SampleRateConverter(
                                                                AudioControlInterface* interface,
                                                                usb_audiocontrol_header_descriptor* Header);
        virtual                                 ~SampleRateConverter();

protected:
};


class AudioControlInterface {
public:
                        enum {
                                kLeftChannel = 0,
                                kRightChannel = 1,
                                kChannels = 18
                        };

                                                        AudioControlInterface(Device* device);
                                                        ~AudioControlInterface();

                        status_t                InitCheck() { return fStatus; }
                        status_t                Init(size_t interface, usb_interface_info* Interface);

                        _AudioControl*  Find(uint8 id);
                        _AudioControl*  FindOutputTerminal(uint8 id);
                        uint16                  SpecReleaseNumber() { return fADCSpecification; }

                        AudioControlsMap&
                                                        Controls() { return fAudioControls; }

                        uint32                  GetChannelsDescription(
                                                                Vector<multi_channel_info>& Channels,
                                                                multi_description* Description,
                                                                Vector<_AudioControl*>& USBTerminals,
                                                                bool isForInput);
                        uint32                  GetBusChannelsDescription(
                                                                Vector<multi_channel_info>& Channels,
                                                                multi_description* Description);

                        status_t                GetMix(multi_mix_value_info* Info);
                        status_t                SetMix(multi_mix_value_info* Info);
                        status_t                ListMixControls(multi_mix_control_info* Info);

protected:
                        status_t                InitACHeader(size_t interface,
                                                                usb_audiocontrol_header_descriptor* Header);

                        uint32                  GetTerminalChannels(
                                                                Vector<multi_channel_info>& Channels,
                                                                AudioChannelCluster* cluster,
                                                                channel_kind kind, uint32 connectors = 0);

                        void                    _HarvestRecordFeatureUnits(_AudioControl* rootControl,
                                                                AudioControlsMap& Map);
                        void                    _HarvestOutputFeatureUnits(_AudioControl* rootControl,
                                                                AudioControlsMap& Map);
                        void                    _ListMixControlsPage(int32& index,
                                                                multi_mix_control_info* Info,
                                                                AudioControlsMap& Map, const char* Name);
                        int32                   _ListFeatureUnitControl(int32& index, int32 parentId,
                                                                multi_mix_control_info* Info,
                                                                _AudioControl* control);
                        uint32                  _ListFeatureUnitOption(uint32 controlType,
                                                                int32& index, int32 parentIndex,
                                                                multi_mix_control_info* Info, FeatureUnit* unit,
                                                                uint32 channel, uint32 channels);
                        void                    _ListSelectorUnitControl(int32& index,
                                                                int32 parentGroup, multi_mix_control_info* Info,
                                                                _AudioControl* control);
                        void                    _ListMixControlsForMixerUnit(int32& index,
                                                                multi_mix_control_info* Info,
                                                                _AudioControl* control);
                        void                    _ListMixerUnitControls(int32& index,
                                                                multi_mix_control_info* Info,
                                                                Vector<multi_mix_control>& controls);
                        size_t                  _CollectMixerUnitControls(
                                                                const uint32 controlIds[kChannels][kChannels],
                                                                size_t inLeft, size_t outLeft,
                                                                size_t inRight, size_t outRight,
                                                                const char* inputName, const char* name,
                                                                Vector<multi_mix_control>& Controls);
                        bool                    _InitGainLimits(multi_mix_control& Control);

                        size_t                  fInterface;
                        status_t                fStatus;
                        // part of AudioControl Header description
                        uint16                  fADCSpecification;
                        Vector<uint8>   fStreams;
                        uint8                   fFunctionCategory;
                        uint8                   fControlsBitmap;
                        Device*                 fDevice;

                        // 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;
};


#endif // _AUDIO_CONTROL_INTERFACE_H_