1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <fbl/macros.h>
8 #include <fbl/intrusive_double_list.h>
9 #include <fbl/unique_ptr.h>
10 
11 #include <utility>
12 
13 #include "usb-audio.h"
14 #include "usb-audio-units.h"
15 
16 namespace audio {
17 namespace usb {
18 
19 class UsbAudioControlInterface;
20 
21 // A small container class used by the audio control interface for describing a
22 // path through the unit/terminal graph from host to pin (or vice-versa)
23 class AudioPath : public fbl::DoublyLinkedListable<fbl::unique_ptr<AudioPath>> {
24   public:
direction()25     Direction direction() const { return direction_; }
stream_terminal()26     const Terminal& stream_terminal() const {
27         // If we do not have a stashed pointer to our terminal yet, then someone
28         // is calling this accessor before Setup completed successfully.  This
29         // should never happen.
30         ZX_DEBUG_ASSERT(stream_terminal_ != nullptr);
31         return *stream_terminal_;
32     }
33 
has_gain()34     bool  has_gain() const { return feature_unit_ && feature_unit_->has_vol(); }
has_agc()35     bool  has_agc()  const { return feature_unit_ && feature_unit_->has_agc(); }
has_mute()36     bool  has_mute() const { return feature_unit_ && feature_unit_->has_mute(); }
cur_gain()37     float cur_gain() const { return feature_unit_ ? feature_unit_->vol_cur_db() : 0.0f; }
min_gain()38     float min_gain() const { return feature_unit_ ? feature_unit_->vol_min_db() : 0.0f; }
max_gain()39     float max_gain() const { return feature_unit_ ? feature_unit_->vol_max_db() : 0.0f; }
gain_res()40     float gain_res() const { return feature_unit_ ? feature_unit_->vol_res_db() : 0.0f; }
cur_agc()41     bool  cur_agc()  const { return feature_unit_ ? feature_unit_->agc_cur() : false; }
cur_mute()42     bool  cur_mute() const { return feature_unit_ ? feature_unit_->mute_cur() : false; }
43 
SetGain(const usb_protocol_t & proto,float db)44     float SetGain(const usb_protocol_t& proto, float db) {
45         return feature_unit_ ? feature_unit_->SetVol(proto, db) : 0.0f;
46     }
47 
SetMute(const usb_protocol_t & proto,bool mute)48     bool SetMute(const usb_protocol_t& proto, bool mute) {
49         return feature_unit_ ? feature_unit_->SetMute(proto, mute) : false;
50     }
51 
SetAgc(const usb_protocol_t & proto,bool enabled)52     bool SetAgc(const usb_protocol_t& proto, bool enabled) {
53         return feature_unit_ ? feature_unit_->SetAgc(proto, enabled) : false;
54     }
55 
56   private:
57     friend class fbl::unique_ptr<AudioPath>;
58     friend class UsbAudioControlInterface;
59 
60     // Methods use by the audio control interface class to build audio paths
61     // during its walk of the unit/terminal graph.  Basically, the control
62     // interface class calls...
63     //
64     // 1) 'Create' when it finds what looks like a valid path during its recursive
65     //    walk of the graph.
66     // 2) 'AddUnit' as it unwinds from the walk in order to store references
67     //    which form the path in the proper order inside of the path.
68     // 3) 'Setup' when it is finished in order to sanity check the path and to
69     //    stash pointers to important elements, such as the stream terminal
70     //    node and the feature unit node (if found).
71     //
72     static fbl::unique_ptr<AudioPath> Create(uint32_t unit_count);
73     void AddUnit(uint32_t ndx, fbl::RefPtr<AudioUnit> unit);
74     zx_status_t Setup(const usb_protocol_t& proto);
75 
AudioPath(fbl::unique_ptr<fbl::RefPtr<AudioUnit>[]> units,uint32_t unit_count)76      AudioPath(fbl::unique_ptr<fbl::RefPtr<AudioUnit>[]> units, uint32_t unit_count)
77          : units_(std::move(units)), unit_count_(unit_count) {}
~AudioPath()78     ~AudioPath() {}
79 
80     DISALLOW_COPY_ASSIGN_AND_MOVE(AudioPath);
81 
82     const fbl::unique_ptr<fbl::RefPtr<AudioUnit>[]> units_;
83     const uint32_t unit_count_;
84     Direction direction_ = Direction::Unknown;
85 
86     // Note: Strictly speaking, these cached references do not have to be
87     // RefPtrs.  In theory, the members of units_ should always outlive these
88     // cache references.   This said, the cost of holding an extra reference on
89     // the objects is basically zero, and storing the pointers internally as
90     // RefPtr<>s makes it easy to know that this is safe from a lifecycle
91     // perspective, if perhaps a tiny bit paranoid.
92     fbl::RefPtr<const Terminal> stream_terminal_;
93     fbl::RefPtr<FeatureUnit> feature_unit_;
94 };
95 
96 }  // namespace usb
97 }  // namespace audio
98 
99