blob: 7ca84ea07f93c523e080be0d0c0088ebaf253f3b [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include <ddk/protocol/usb-old.h>
#include <ddktl/device.h>
#include <fbl/array.h>
#include <fbl/intrusive_double_list.h>
#include <fbl/mutex.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
#include <zircon/thread_annotations.h>
#include "usb-audio-control-interface.h"
#include "usb-audio-descriptors.h"
#include "debug-logging.h"
namespace audio {
namespace usb {
class UsbAudioStream;
class UsbAudioDevice;
using UsbAudioDeviceBase = ddk::Device<UsbAudioDevice, ddk::Unbindable>;
class UsbAudioDevice : public UsbAudioDeviceBase,
public fbl::RefCounted<UsbAudioDevice> {
public:
static zx_status_t DriverBind(zx_device_t* parent);
void DdkUnbind();
void DdkRelease();
void RemoveAudioStream(const fbl::RefPtr<UsbAudioStream>& stream);
const char* log_prefix() const { return log_prefix_; }
const usb_device_descriptor_t& desc() const { return usb_dev_desc_; }
const fbl::RefPtr<DescriptorListMemory>& desc_list() const { return desc_list_; }
const usb_protocol_t& usb_proto() const { return usb_proto_; }
uint16_t vid() const { return usb_dev_desc_.idVendor; }
uint16_t pid() const { return usb_dev_desc_.idProduct; }
const fbl::Array<uint8_t>& mfr_name() const { return mfr_name_; }
const fbl::Array<uint8_t>& prod_name() const { return prod_name_; }
const fbl::Array<uint8_t>& serial_num() const { return serial_num_; }
size_t parent_req_size() const { return parent_req_size_; }
private:
explicit UsbAudioDevice(zx_device_t* parent);
// A small struct used when searching descriptors for midi streaming
// interfaces.
//
// TODO(johngro) : Someday, turn this into something more like
// UsbAudioStreamingInterface and give it the ability to parse and
// understand its class specific interfaces, class specific endpoints, and
// manage multiple alternate interface settings.
struct MidiStreamingInfo {
explicit MidiStreamingInfo(const usb_interface_descriptor_t* i) : ifc(i) {}
const usb_interface_descriptor_t* ifc;
const usb_endpoint_descriptor_t* in_ep = nullptr;
const usb_endpoint_descriptor_t* out_ep = nullptr;
};
zx_status_t Bind();
void Probe();
void ParseMidiStreamingIfc(DescriptorListMemory::Iterator* iter,
MidiStreamingInfo* inout_info);
char log_prefix_[LOG_PREFIX_STORAGE] = { 0 };
usb_protocol_t usb_proto_;
fbl::Mutex lock_;
usb_device_descriptor_t usb_dev_desc_;
fbl::Array<uint8_t> mfr_name_;
fbl::Array<uint8_t> prod_name_;
fbl::Array<uint8_t> serial_num_;
fbl::RefPtr<DescriptorListMemory> desc_list_;
fbl::DoublyLinkedList<fbl::RefPtr<UsbAudioStream>> streams_ TA_GUARDED(lock_);
size_t parent_req_size_ = 0;
int midi_sink_index_ = 0;
int midi_source_index_ = 0;
};
} // namespace usb
} // namespace audio