/*
* Copyright (c) 2010 Matus Dekanek
* Copyright (c) 2018 Ondrej Hlavaty
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** @addtogroup libusb
* @{
*/
/** @file
* @brief USB hub related structures.
*/
#ifndef LIBUSB_CLASS_HUB_H_
#define LIBUSB_CLASS_HUB_H_
#include <stdint.h>
/** Hub class feature selector.
* @warning The constants are not unique (feature selectors are used
* for hub and port).
*/
typedef enum {
USB_HUB_FEATURE_C_HUB_LOCAL_POWER = 0,
USB_HUB_FEATURE_C_HUB_OVER_CURRENT = 1,
USB_HUB_FEATURE_HUB_LOCAL_POWER = 0,
USB_HUB_FEATURE_HUB_OVER_CURRENT = 1,
USB_HUB_FEATURE_PORT_CONNECTION = 0,
USB2_HUB_FEATURE_PORT_ENABLE = 1,
USB2_HUB_FEATURE_PORT_SUSPEND = 2,
USB_HUB_FEATURE_PORT_OVER_CURRENT = 3,
USB_HUB_FEATURE_PORT_RESET = 4,
USB3_HUB_FEATURE_PORT_LINK_STATE = 5,
USB_HUB_FEATURE_PORT_POWER = 8,
USB2_HUB_FEATURE_PORT_LOW_SPEED = 9,
USB_HUB_FEATURE_C_PORT_CONNECTION = 16,
USB2_HUB_FEATURE_C_PORT_ENABLE = 17,
USB2_HUB_FEATURE_C_PORT_SUSPEND = 18,
USB_HUB_FEATURE_C_PORT_OVER_CURRENT = 19,
USB_HUB_FEATURE_C_PORT_RESET = 20,
USB2_HUB_FEATURE_PORT_TEST = 21,
USB2_HUB_FEATURE_PORT_INDICATOR = 22,
USB3_HUB_FEATURE_C_PORT_LINK_STATE = 25,
USB3_HUB_FEATURE_BH_PORT_RESET = 28,
USB3_HUB_FEATURE_C_BH_PORT_RESET = 29,
/* USB_HUB_FEATURE_ = , */
} usb_hub_class_feature_t;
/**
* Dword holding port status and changes flags.
*
* For more information refer to tables 11-15 and 11-16 in
* "Universal Serial Bus Specification Revision 1.1" pages 274 and 277
* (290 and 293 in pdf)
*
* Beware that definition of bits changed between USB 2 and 3,
* so some fields are prefixed with USB2 or USB3 instead.
*/
typedef uint32_t usb_port_status_t;
#define USB_HUB_PORT_STATUS_BIT(bit) (uint32_usb2host(1 << (bit)))
#define USB_HUB_PORT_STATUS_CONNECTION USB_HUB_PORT_STATUS_BIT(0)
#define USB_HUB_PORT_STATUS_ENABLE USB_HUB_PORT_STATUS_BIT(1)
#define USB2_HUB_PORT_STATUS_SUSPEND USB_HUB_PORT_STATUS_BIT(2)
#define USB_HUB_PORT_STATUS_OC USB_HUB_PORT_STATUS_BIT(3)
#define USB_HUB_PORT_STATUS_RESET USB_HUB_PORT_STATUS_BIT(4)
#define USB2_HUB_PORT_STATUS_POWER USB_HUB_PORT_STATUS_BIT(8)
#define USB2_HUB_PORT_STATUS_LOW_SPEED USB_HUB_PORT_STATUS_BIT(9)
#define USB3_HUB_PORT_STATUS_POWER USB_HUB_PORT_STATUS_BIT(9)
#define USB2_HUB_PORT_STATUS_HIGH_SPEED USB_HUB_PORT_STATUS_BIT(10)
#define USB2_HUB_PORT_STATUS_TEST USB_HUB_PORT_STATUS_BIT(11)
#define USB2_HUB_PORT_STATUS_INDICATOR USB_HUB_PORT_STATUS_BIT(12)
#define USB_HUB_PORT_STATUS_C_CONNECTION USB_HUB_PORT_STATUS_BIT(16)
#define USB2_HUB_PORT_STATUS_C_ENABLE USB_HUB_PORT_STATUS_BIT(17)
#define USB2_HUB_PORT_STATUS_C_SUSPEND USB_HUB_PORT_STATUS_BIT(18)
#define USB_HUB_PORT_STATUS_C_OC USB_HUB_PORT_STATUS_BIT(19)
#define USB_HUB_PORT_STATUS_C_RESET USB_HUB_PORT_STATUS_BIT(20)
#define USB3_HUB_PORT_STATUS_C_BH_RESET USB_HUB_PORT_STATUS_BIT(21)
#define USB3_HUB_PORT_STATUS_C_LINK_STATE USB_HUB_PORT_STATUS_BIT(22)
#define USB3_HUB_PORT_STATUS_C_CONFIG_ERROR USB_HUB_PORT_STATUS_BIT(23)
/** Header of standard hub descriptor without the "variadic" part. */
typedef struct {
/** Descriptor length. */
uint8_t length;
/** Descriptor type (0x29 or 0x2a for superspeed hub). */
uint8_t descriptor_type;
/** Number of downstream ports. */
uint8_t port_count;
/** Characteristics bitmask.
*
* D1..D0: Logical Power Switching Mode
* 00: Ganged power switching (all ports power at
* once)
* 01: Individual port power switching
* 1X: Reserved. Used only on 1.0 compliant hubs
* that implement no power switching.
* D2: Identifies a Compound Device
* 0: Hub is not part of a compound device
* 1: Hub is part of a compound device
* D4..D3: Over-current Protection Mode
* 00: Global Over-current Protection. The hub
* reports over-current as a summation of all
* ports current draw, without a breakdown of
* individual port over-current status.
* 01: Individual Port Over-current Protection. The
* hub reports over-current on a per-port basis.
* Each port has an over-current indicator.
* 1X: No Over-current Protection. This option is
* allowed only for bus-powered hubs that do not
* implement over-current protection.
* D6..D5: TT think time
* 00: At most 8 FS bit times
* 01: At most 16 FS bit times
* 10: At most 24 FS bit times
* 11: At most 32 FS bit times
* D7: Port indicators
* 0: Not supported
* 1: Supported
* D15...D8: Reserved
*/
uint8_t characteristics;
/** Unused part of characteristics field */
uint8_t characteristics_reserved;
/** Time from power-on to stabilization of current on the port.
*
* Time (in 2ms intervals) from the time the power-on
* sequence begins on a port until power is good on that
* port. The USB System Software uses this value to
* determine how long to wait before accessing a
* powered-on port.
*/
uint8_t power_good_time;
/** Maximum current requirements in mA.
*
* Maximum current requirements of the Hub Controller
* electronics in mA.
*/
uint8_t max_current;
} __attribute__((packed)) usb_hub_descriptor_header_t;
/*
* USB hub characteristics
*/
#define HUB_CHAR_POWER_PER_PORT_FLAG (1 << 0)
#define HUB_CHAR_NO_POWER_SWITCH_FLAG (1 << 1)
#define HUB_CHAR_COMPOUND_DEVICE (1 << 2)
#define HUB_CHAR_OC_PER_PORT_FLAG (1 << 3)
#define HUB_CHAR_NO_OC_FLAG (1 << 4)
/* These are invalid for superspeed hub */
#define HUB_CHAR_TT_THINK_16 (1 << 5)
#define HUB_CHAR_TT_THINK_8 (1 << 6)
#define HUB_CHAR_INDICATORS_FLAG (1 << 7)
/** One bit for the device and one bit for every port */
#define STATUS_BYTES(ports) ((1 + ports + 7) / 8)
/**
* @brief usb hub specific request types.
*/
typedef enum {
/** This request resets a value reported in the hub status. */
USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE = 0x20,
/** This request resets a value reported in the port status. */
USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE = 0x23,
/**
* This is an optional per-port diagnostic request that returns the bus
* state value, as sampled at the last EOF2 point.
*/
USB_HUB_REQ_TYPE_GET_STATE = 0xA3,
/** This request returns the hub descriptor. */
USB_HUB_REQ_TYPE_GET_DESCRIPTOR = 0xA0,
/**
* This request returns the current hub status and the states that have
* changed since the previous acknowledgment.
*/
USB_HUB_REQ_TYPE_GET_HUB_STATUS = 0xA0,
/**
* This request returns the current port status and the current value of the
* port status change bits.
*/
USB_HUB_REQ_TYPE_GET_PORT_STATUS = 0xA3,
/** This request overwrites the hub descriptor. */
USB_HUB_REQ_TYPE_SET_DESCRIPTOR = 0x20,
/** This request sets a value reported in the hub status. */
USB_HUB_REQ_TYPE_SET_HUB_FEATURE = 0x20,
/**
* This request sets the value that the hub uses to determine the index
* into the Route String Index for the hub.
*/
USB_HUB_REQ_TYPE_SET_HUB_DEPTH = 0x20,
/** This request sets a value reported in the port status. */
USB_HUB_REQ_TYPE_SET_PORT_FEATURE = 0x23,
} usb_hub_bm_request_type_t;
/**
* @brief hub class request codes
*/
typedef enum {
USB_HUB_REQUEST_GET_STATUS = 0,
USB_HUB_REQUEST_CLEAR_FEATURE = 1,
/** USB 1.0 only */
USB_HUB_REQUEST_GET_STATE = 2,
USB_HUB_REQUEST_SET_FEATURE = 3,
USB_HUB_REQUEST_GET_DESCRIPTOR = 6,
USB_HUB_REQUEST_SET_DESCRIPTOR = 7,
USB_HUB_REQUEST_CLEAR_TT_BUFFER = 8,
USB_HUB_REQUEST_RESET_TT = 9,
USB_HUB_GET_TT_STATE = 10,
USB_HUB_STOP_TT = 11,
/** USB 3+ only */
USB_HUB_REQUEST_SET_HUB_DEPTH = 12,
} usb_hub_request_t;
/**
* Maximum size of usb hub descriptor in bytes
*/
/* 7 (basic size) + 2*32 (port bitmasks) */
#define USB_HUB_MAX_DESCRIPTOR_SIZE (7 + 2 * 32)
#endif
/**
* @}
*/