blob: 21ca6aaefc42155abca80c1fbc771bb5bdcd5699 [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.
#ifndef SRC_DEVICES_USB_DRIVERS_USB_COMPOSITE_USB_COMPOSITE_H_
#define SRC_DEVICES_USB_DRIVERS_USB_COMPOSITE_USB_COMPOSITE_H_
#include <ddk/binding.h>
#include <ddktl/device.h>
#include <ddktl/protocol/usb.h>
#include <fbl/array.h>
#include <fbl/mutex.h>
#include <fbl/ref_ptr.h>
#include <fbl/vector.h>
namespace usb_composite {
class UsbComposite;
class UsbInterface;
using UsbCompositeType = ddk::Device<UsbComposite, ddk::Unbindable>;
// This class represents a USB composite device and manages creating devmgr devices
// for multiple USB interfaces.
class UsbComposite : public UsbCompositeType {
public:
UsbComposite(zx_device_t* parent) : UsbCompositeType(parent), usb_(parent) {}
static zx_status_t Create(void* ctx, zx_device_t* parent);
// Device protocol implementation.
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*>(config_desc_.data());
}
private:
enum class InterfaceStatus : uint8_t {
// The interface has not been claimed and no device has been created for it.
AVAILABLE,
// Another interface has claimed the interface.
CLAIMED,
// A child device has been created for the interface.
CHILD_DEVICE,
};
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();
fbl::RefPtr<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<fbl::RefPtr<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
#endif // SRC_DEVICES_USB_DRIVERS_USB_COMPOSITE_USB_COMPOSITE_H_