blob: 7b68127286d9d8616a57da2729e1fc0d36022673 [file] [log] [blame]
// Copyright 2016 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_INTERFACE_H_
#define SRC_DEVICES_USB_DRIVERS_USB_COMPOSITE_USB_INTERFACE_H_
#include <ddktl/device.h>
#include <ddktl/protocol/usb.h>
#include <ddktl/protocol/usb/composite.h>
#include <fbl/array.h>
#include <fbl/mutex.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
#include "usb-composite.h"
namespace usb_composite {
class UsbComposite;
class UsbInterface;
using UsbInterfaceType = ddk::Device<UsbInterface, ddk::GetProtocolable, ddk::Unbindable>;
// This class represents a USB interface in a composite device.
class UsbInterface : public UsbInterfaceType,
public ddk::UsbProtocol<UsbInterface, ddk::base_protocol>,
public ddk::UsbCompositeProtocol<UsbInterface>,
public fbl::RefCounted<UsbInterface> {
public:
UsbInterface(zx_device_t* parent, UsbComposite* composite, const ddk::UsbProtocolClient& usb)
: UsbInterfaceType(parent), composite_(composite), usb_(usb) {}
static zx_status_t Create(zx_device_t* parent, UsbComposite* composite,
const ddk::UsbProtocolClient& usb,
const usb_interface_descriptor_t* interface_desc, size_t desc_length,
fbl::RefPtr<UsbInterface>* out_interface);
static zx_status_t Create(zx_device_t* parent, UsbComposite* composite,
const ddk::UsbProtocolClient& usb,
const usb_interface_assoc_descriptor_t* assoc_desc, size_t desc_length,
fbl::RefPtr<UsbInterface>* out_interface);
// Device protocol implementation.
zx_status_t DdkGetProtocol(uint32_t proto_id, void* out);
void DdkUnbind(ddk::UnbindTxn txn);
void DdkRelease();
// USB protocol implementation.
zx_status_t UsbControlOut(uint8_t request_type, uint8_t request, uint16_t value, uint16_t index,
int64_t timeout, const void* write_buffer, size_t write_size);
zx_status_t UsbControlIn(uint8_t request_type, uint8_t request, uint16_t value, uint16_t index,
int64_t timeout, void* out_read_buffer, size_t read_size,
size_t* out_read_actual);
void UsbRequestQueue(usb_request_t* usb_request, const usb_request_complete_t* complete_cb);
usb_speed_t UsbGetSpeed();
zx_status_t UsbSetInterface(uint8_t interface_number, uint8_t alt_setting);
uint8_t UsbGetConfiguration();
zx_status_t UsbSetConfiguration(uint8_t configuration);
zx_status_t UsbEnableEndpoint(const usb_endpoint_descriptor_t* ep_desc,
const usb_ss_ep_comp_descriptor_t* ss_com_desc, bool enable);
zx_status_t UsbResetEndpoint(uint8_t ep_address);
zx_status_t UsbResetDevice();
size_t UsbGetMaxTransferSize(uint8_t ep_address);
uint32_t UsbGetDeviceId();
void UsbGetDeviceDescriptor(usb_device_descriptor_t* out_desc);
zx_status_t UsbGetConfigurationDescriptorLength(uint8_t configuration, size_t* out_length);
zx_status_t UsbGetConfigurationDescriptor(uint8_t configuration, void* out_desc_buffer,
size_t desc_size, size_t* out_desc_actual);
size_t UsbGetDescriptorsLength();
void UsbGetDescriptors(void* out_descs_buffer, size_t descs_size, size_t* out_descs_actual);
zx_status_t UsbGetStringDescriptor(uint8_t desc_id, uint16_t lang_id, uint16_t* out_lang_id,
void* out_string_buffer, size_t string_size,
size_t* out_string_actual);
zx_status_t UsbCancelAll(uint8_t ep_address);
uint64_t UsbGetCurrentFrame();
size_t UsbGetRequestSize();
// USB composite protocol implementation.
size_t UsbCompositeGetAdditionalDescriptorLength();
zx_status_t UsbCompositeGetAdditionalDescriptorList(uint8_t* out_desc_list, size_t desc_count,
size_t* out_desc_actual);
zx_status_t UsbCompositeClaimInterface(const usb_interface_descriptor_t* desc, uint32_t length);
// FIDL messages.
zx_status_t MsgGetDeviceSpeed(fidl_txn_t* txn);
zx_status_t MsgGetDeviceDescriptor(fidl_txn_t* txn);
zx_status_t MsgGetConfigurationDescriptorSize(uint8_t config, fidl_txn_t* txn);
zx_status_t MsgGetConfigurationDescriptor(uint8_t config, fidl_txn_t* txn);
zx_status_t MsgGetStringDescriptor(uint8_t desc_id, uint16_t lang_id, fidl_txn_t* txn);
zx_status_t MsgSetInterface(uint8_t interface_number, uint8_t alt_setting, fidl_txn_t* txn);
zx_status_t MsgGetDeviceId(fidl_txn_t* txn);
zx_status_t MsgGetHubDeviceId(fidl_txn_t* txn);
zx_status_t MsgGetConfiguration(fidl_txn_t* txn);
zx_status_t MsgSetConfiguration(uint8_t configuration, fidl_txn_t* txn);
bool ContainsInterface(uint8_t interface_id);
zx_status_t SetAltSetting(uint8_t interface_id, uint8_t alt_setting);
inline uint8_t usb_class() const { return usb_class_; }
inline uint8_t usb_subclass() const { return usb_subclass_; }
inline uint8_t usb_protocol() const { return usb_protocol_; }
private:
zx_status_t Init(const void* descriptors, size_t desc_length, uint8_t last_interface_id,
uint8_t usb_class, uint8_t usb_subclass, uint8_t usb_protocol);
zx_status_t ConfigureEndpoints(uint8_t interface_id, uint8_t alt_setting);
UsbComposite* composite_;
const ddk::UsbProtocolClient usb_;
uint8_t usb_class_;
uint8_t usb_subclass_;
uint8_t usb_protocol_;
// ID of the last interface in the descriptor list.
uint8_t last_interface_id_;
fbl::Array<uint8_t> descriptors_;
// Descriptors for currently active endpoints.
// These point into descriptor_'s storage.
const usb_endpoint_descriptor_t* active_endpoints_[USB_MAX_EPS] = {};
};
} // namespace usb_composite
#endif // SRC_DEVICES_USB_DRIVERS_USB_COMPOSITE_USB_INTERFACE_H_