blob: aa0083283a88bfa4f89ba41eb11283a5ee4f5ffb [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.
#include <fuchsia/hardware/usb/cpp/banjo.h>
#include <ddktl/device.h>
#include <ddktl/init-txn.h>
#include <fbl/array.h>
#include <fbl/mutex.h>
#include <fbl/vector.h>
#include <usb/usb.h>
namespace usb_composite {
class UsbComposite;
class UsbInterface;
using UsbCompositeType = ddk::Device<UsbComposite, ddk::Initializable, ddk::Unbindable>;
// This class represents a USB composite device and manages creating devmgr devices
// for multiple USB interfaces.
class UsbComposite : public UsbCompositeType {
UsbComposite(zx_device_t* parent) : UsbCompositeType(parent), usb_(parent) {}
static zx_status_t Create(void* ctx, zx_device_t* parent);
// Device protocol implementation.
void DdkInit(ddk::InitTxn txn);
void DdkUnbind(ddk::UnbindTxn txn);
void DdkRelease();
zx_status_t ClaimInterface(uint8_t interface_id);
zx_status_t SetInterface(uint8_t interface_id, uint8_t alt_setting);
zx_status_t GetAdditionalDescriptorList(uint8_t last_interface_id, uint8_t* out_desc_list,
size_t desc_count, size_t* out_desc_actual);
inline const usb_device_descriptor_t* device_descriptor() const { return &device_desc_; }
inline const usb_configuration_descriptor_t* GetConfigurationDescriptor() const {
return reinterpret_cast<usb_configuration_descriptor_t*>(;
template <auto* descriptors>
friend class UsbInterfaceTest;
template <auto* descriptors>
friend class UsbCompositeTest;
enum class InterfaceStatus : uint8_t {
// The interface has not been claimed and no device has been created for it.
// Another interface has claimed the interface.
// A child device has been created for the interface.
zx_status_t Init();
zx_status_t AddInterface(const usb_interface_descriptor_t* interface_desc, size_t length);
zx_status_t AddInterfaceAssoc(const usb_interface_assoc_descriptor_t* assoc_desc, size_t length);
zx_status_t AddInterfaces();
UsbInterface* GetInterfaceById(uint8_t interface_id) __TA_REQUIRES(lock_);
bool RemoveInterfaceById(uint8_t interface_id) __TA_REQUIRES(lock_);
// Our parent's USB protocol.
const ddk::UsbProtocolClient usb_;
// Array of all our USB interfaces.
fbl::Vector<UsbInterface*> interfaces_ __TA_GUARDED(lock_);
InterfaceStatus interface_statuses_[UINT8_MAX] __TA_GUARDED(lock_) = {};
usb_device_descriptor_t device_desc_;
fbl::Array<uint8_t> config_desc_;
fbl::Mutex lock_;
} // namespace usb_composite