From d3c47164922a79f9d665759e47aff8a94fee19a7 Mon Sep 17 00:00:00 2001 From: sakumisu <1203593632@qq.com> Date: Sat, 27 Nov 2021 10:10:06 +0800 Subject: [PATCH] add hub class --- class/hub/usb_hub.h | 118 +++++++++++++++++++++++++++++++++++++++++++ class/hub/usbd_hub.c | 84 ++++++++++++++++++++++++++++++ class/hub/usbd_hub.h | 22 ++++++++ 3 files changed, 224 insertions(+) create mode 100644 class/hub/usb_hub.h create mode 100644 class/hub/usbd_hub.c create mode 100644 class/hub/usbd_hub.h diff --git a/class/hub/usb_hub.h b/class/hub/usb_hub.h new file mode 100644 index 00000000..78223b4d --- /dev/null +++ b/class/hub/usb_hub.h @@ -0,0 +1,118 @@ +/** + * @file + * @brief USB HUB Device Class public header + * + */ + +#ifndef _USB_HUB_H_ +#define _USB_HUB_H_ + +/* HUB Class Descriptor Types */ +#define HUB_DESCRIPTOR_TYPE_HUB 0x29 + +/* Hub class requests */ +#define HUB_REQUEST_GET_STATUS USB_REQUEST_GET_STATUS +#define HUB_REQUEST_CLEAR_FEATURE USB_REQUEST_CLEAR_FEATURE +#define HUB_REQUEST_SET_FEATURE USB_REQUEST_SET_FEATURE +#define HUB_REQUEST_GET_DESCRIPTOR USB_REQUEST_GET_DESCRIPTOR +#define HUB_REQUEST_SET_DESCRIPTOR USB_REQUEST_SET_DESCRIPTOR +#define HUB_REQUEST_CLEAR_TT_BUFFER (0x08) +#define HUB_REQUEST_RESET_TT (0x09) +#define HUB_REQUEST_GET_TT_STATE (0x0a) +#define HUB_REQUEST_STOP_TT (0x0b) + +/* Hub class features */ +#define HUB_FEATURE_HUB_LOCALPOWER_CHANGE (0x0) +#define HUB_FEATURE_HUB_OVERCURRENT_CHANGE (0x1) + +/* Port features */ +#define HUB_PORT_FEATURE_CONNECTION (0x00) +#define HUB_PORT_FEATURE_ENABLE (0x01) +#define HUB_PORT_FEATURE_SUSPEND (0x02) +#define HUB_PORT_FEATURE_OVERCURRENT (0x03) +#define HUB_PORT_FEATURE_RESET (0x04) +#define HUB_PORT_FEATURE_L1 (0x05) +#define HUB_PORT_FEATURE_POWER (0x08) +#define HUB_PORT_FEATURE_LOWSPEED (0x09) +#define HUB_PORT_FEATURE_HIGHSPEED (0x0a) +#define HUB_PORT_FEATURE_CONNECTION_CHANGE (0x10) +#define HUB_PORT_FEATURE_ENABLE_CHANGE (0x11) +#define HUB_PORT_FEATURE_SUSPEND_CHANGE (0x12) +#define HUB_PORT_FEATURE_OVER_CURRENT_CHANGE (0x13) +#define HUB_PORT_FEATURE_RESET_CHANGE (0x14) +#define HUB_PORT_FEATURE_TEST (0x15) +#define HUB_PORT_FEATURE_INDICATOR (0x16) +#define HUB_PORT_FEATURE_PORTL1_CHANGE (0x17) + +/* Hub status */ +#define HUB_STATUS_LOCALPOWER (1 << 0) +#define HUB_STATUS_OVERCURRENT (1 << 1) + +/* Hub status change */ +#define HUB_STATUS_CHANGE_LOCALPOWER (1 << 0) +#define HUB_STATUS_CHANGE_OVERCURRENT (1 << 1) + +/* Hub port status */ +#define HUB_PORT_STATUS_CONNECTION (1 << 0) +#define HUB_PORT_STATUS_ENABLE (1 << 1) +#define HUB_PORT_STATUS_SUSPEND (1 << 2) +#define HUB_PORT_STATUS_OVERCURRENT (1 << 3) +#define HUB_PORT_STATUS_RESET (1 << 4) +#define HUB_PORT_STATUS_L1 (1 << 5) +#define HUB_PORT_STATUS_POWER (1 << 8) +#define HUB_PORT_STATUS_LOW_SPEED (1 << 9) +#define HUB_PORT_STATUS_HIGH_SPEED (1 << 10) +#define HUB_PORT_STATUS_TEST (1 << 11) +#define HUB_PORT_STATUS_INDICATOR (1 << 12) + +/* Hub port status change */ +#define HUB_PORT_STATUS_CHANGE_CONNECTION (1 << 0) +#define HUB_PORT_STATUS_CHANGE_ENABLE (1 << 1) +#define HUB_PORT_STATUS_CHANGE_SUSPEND (1 << 2) +#define HUB_PORT_STATUS_CHANGE_OVERCURRENT (1 << 3) +#define HUB_PORT_STATUS_CHANGE_RESET (1 << 4) +#define HUB_PORT_STATUS_CHANGE_L1 (1 << 5) + +/* Hub characteristics */ +#define HUB_CHAR_LPSM_SHIFT (0) /* Bits 0-1: Logical Power Switching Mode */ +#define HUB_CHAR_LPSM_MASK (3 << HUB_CHAR_LPSM_SHIFT) +#define HUB_CHAR_LPSM_GANGED (0 << HUB_CHAR_LPSM_SHIFT) +#define HUB_CHAR_LPSM_INDIVIDUAL (1 << HUB_CHAR_LPSM_SHIFT) +#define HUB_CHAR_COMPOUND (1 << 2) /* Bit 2: Compound device */ +#define HUB_CHAR_OCPM_SHIFT (3) /* Bits 3-4: Over-current Protection Mode */ +#define HUB_CHAR_OCPM_MASK (3 << HUB_CHAR_OCPM_SHIFT) +#define HUB_CHAR_OCPM_GLOBAL (0 << HUB_CHAR_OCPM_SHIFT) +#define HUB_CHAR_OCPM_INDIVIDUAL (1 << HUB_CHAR_OCPM_SHIFT) +#define HUB_CHAR_TTTT_SHIFT (5) /* Bits 5-6: TT Think Time */ +#define HUB_CHAR_TTTT_MASK (3 << HUB_CHAR_TTTT_SHIFT) +#define HUB_CHAR_TTTT_8_BITS (0 << HUB_CHAR_TTTT_SHIFT) +#define HUB_CHAR_TTTT_16_BITS (1 << HUB_CHAR_TTTT_SHIFT) +#define HUB_CHAR_TTTT_24_BITS (2 << HUB_CHAR_TTTT_SHIFT) +#define HUB_CHAR_TTTT_32_BITS (3 << HUB_CHAR_TTTT_SHIFT) +#define HUB_CHAR_PORTIND (1 << 7) /* Bit 7: Port Indicators Supported */ + +/* Hub descriptor */ +struct usb_hub_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bNbrPorts; + uint16_t wHubCharacteristics; + uint8_t bPwrOn2PwrGood; + uint8_t bHubContrCurrent; + uint8_t DeviceRemovable; + uint8_t PortPwrCtrlMask; +}; + +/* Hub status */ +struct hub_status { + uint8_t status[2]; + uint8_t change[2]; +}; + +/* Hub port status */ +struct hub_port_status { + uint8_t status[2]; + uint8_t change[2]; +}; + +#endif /* _USB_HUB_H_ */ diff --git a/class/hub/usbd_hub.c b/class/hub/usbd_hub.c new file mode 100644 index 00000000..9af0d245 --- /dev/null +++ b/class/hub/usbd_hub.c @@ -0,0 +1,84 @@ +#include "usbd_core.h" +#include "usbd_hub.h" + +static struct usb_hub_descriptor hub_desc = { + .bLength = 0x09, + .bDescriptorType = HUB_DESCRIPTOR_TYPE_HUB, + .bNbrPorts = 4, + .wHubCharacteristics = HUB_CHAR_PORTIND | HUB_CHAR_TTTT_32_BITS, + .bPwrOn2PwrGood = 0x32, + .bHubContrCurrent = 0x64, + .DeviceRemovable = 0x00, + .PortPwrCtrlMask = 0xff +}; + +int hub_custom_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len) +{ + USBD_LOG_DBG("HUB Class Custom request: " + "bRequest 0x%02x\r\n", + setup->bRequest); + + if (((setup->bmRequestType & USB_REQUEST_TYPE_MASK) == USB_REQUEST_CLASS) && + ((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) == USB_REQUEST_TO_DEVICE) && + (setup->bRequest == HUB_REQUEST_GET_DESCRIPTOR)) { + uint8_t value = (uint8_t)(setup->wValue >> 8); + uint8_t intf_num = (uint8_t)setup->wIndex; + + switch (value) { + case HUB_DESCRIPTOR_TYPE_HUB: + *data = (uint8_t *)&hub_desc; + *len = hub_desc.bLength; + break; + default: + return -1; + } + return 0; + } + + else if (((setup->bmRequestType & USB_REQUEST_TYPE_MASK) == USB_REQUEST_CLASS) && + ((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) == USB_REQUEST_TO_OTHER)) { + uint8_t hub_port_feature = (uint8_t)(setup->wValue); + uint8_t hub_port = (uint8_t)setup->wIndex; + + switch (setup->bRequest) { + case HUB_REQUEST_GET_STATUS: + break; + case HUB_REQUEST_CLEAR_FEATURE: + break; + case HUB_REQUEST_SET_FEATURE: + break; + default: + USBD_LOG_WRN("Unhandled HUB Class Custom bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + return 0; + } + return -1; +} + +void hub_notify_handler(uint8_t event, void *arg) +{ + switch (event) { + case USBD_EVENT_RESET: + + break; + default: + break; + } +} + +void usbd_hub_add_interface(usbd_class_t *class, usbd_interface_t *intf) +{ + static usbd_class_t *last_class = NULL; + + if (last_class != class) { + last_class = class; + usbd_class_register(class); + } + + intf->class_handler = NULL; + intf->custom_handler = hub_custom_request_handler; + intf->vendor_handler = NULL; + intf->notify_handler = hub_notify_handler; + usbd_class_add_interface(class, intf); +} \ No newline at end of file diff --git a/class/hub/usbd_hub.h b/class/hub/usbd_hub.h new file mode 100644 index 00000000..f5ad3e14 --- /dev/null +++ b/class/hub/usbd_hub.h @@ -0,0 +1,22 @@ +/** + * @file + * @brief USB HUB Device Class public header + * + */ + +#ifndef _USBD_HUB_H_ +#define _USBD_HUB_H_ + +#include "usb_hub.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void usbd_hub_add_interface(usbd_class_t *class, usbd_interface_t *intf); + +#ifdef __cplusplus +} +#endif + +#endif /* _USBD_HUB_H_ */