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 <ddk/protocol/usb.h>
8#include <ddktl/device.h>
9#include <fbl/array.h>
10#include <fbl/intrusive_double_list.h>
11#include <fbl/mutex.h>
12#include <fbl/ref_counted.h>
13#include <fbl/ref_ptr.h>
14#include <zircon/thread_annotations.h>
15
16#include "usb-audio-control-interface.h"
17#include "usb-audio-descriptors.h"
18#include "debug-logging.h"
19
20namespace audio {
21namespace usb {
22
23class UsbAudioStream;
24
25class UsbAudioDevice;
26using UsbAudioDeviceBase = ddk::Device<UsbAudioDevice, ddk::Unbindable>;
27
28class UsbAudioDevice : public UsbAudioDeviceBase,
29                       public fbl::RefCounted<UsbAudioDevice> {
30public:
31    static zx_status_t DriverBind(zx_device_t* parent);
32    void DdkUnbind();
33    void DdkRelease();
34
35    void RemoveAudioStream(const fbl::RefPtr<UsbAudioStream>& stream);
36
37    const char* log_prefix() const { return log_prefix_; }
38    const usb_device_descriptor_t& desc() const { return usb_dev_desc_; }
39    const fbl::RefPtr<DescriptorListMemory>& desc_list() const { return desc_list_; }
40    const usb_protocol_t& usb_proto() const { return usb_proto_; }
41    uint16_t vid() const { return usb_dev_desc_.idVendor; }
42    uint16_t pid() const { return usb_dev_desc_.idProduct; }
43    const fbl::Array<uint8_t>& mfr_name() const { return mfr_name_; }
44    const fbl::Array<uint8_t>& prod_name() const { return prod_name_; }
45    const fbl::Array<uint8_t>& serial_num() const { return serial_num_; }
46
47private:
48    explicit UsbAudioDevice(zx_device_t* parent);
49
50    // A small struct used when searching descriptors for midi streaming
51    // interfaces.
52    //
53    // TODO(johngro) : Someday, turn this into something more like
54    // UsbAudioStreamingInterface and give it the ability to parse and
55    // understand its class specific interfaces, class specific endpoints, and
56    // manage multiple alternate interface settings.
57    struct MidiStreamingInfo {
58        explicit MidiStreamingInfo(const usb_interface_descriptor_t* i) : ifc(i) {}
59        const usb_interface_descriptor_t* ifc;
60        const usb_endpoint_descriptor_t*  in_ep  = nullptr;
61        const usb_endpoint_descriptor_t*  out_ep = nullptr;
62    };
63
64    zx_status_t Bind();
65    void Probe();
66    void ParseMidiStreamingIfc(DescriptorListMemory::Iterator* iter,
67                               MidiStreamingInfo* inout_info);
68
69    char log_prefix_[LOG_PREFIX_STORAGE] = { 0 };
70
71    usb_protocol_t usb_proto_;
72    fbl::Mutex lock_;
73    usb_device_descriptor_t usb_dev_desc_;
74    fbl::Array<uint8_t> mfr_name_;
75    fbl::Array<uint8_t> prod_name_;
76    fbl::Array<uint8_t> serial_num_;
77    fbl::RefPtr<DescriptorListMemory> desc_list_;
78    fbl::DoublyLinkedList<fbl::RefPtr<UsbAudioStream>> streams_ TA_GUARDED(lock_);
79
80    int midi_sink_index_ = 0;
81    int midi_source_index_ = 0;
82};
83
84}  // namespace usb
85}  // namespace audio
86