summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsakumisu <[email protected]>2021-11-27 10:10:06 +0800
committersakumisu <[email protected]>2021-11-29 10:32:06 +0800
commitd3c47164922a79f9d665759e47aff8a94fee19a7 (patch)
treec0249148de2444a02b2b1c921e78388b261f44b1
parent6e15f6898beb890cf0b0da3185c0fc919956a883 (diff)
add hub class
-rw-r--r--class/hub/usb_hub.h118
-rw-r--r--class/hub/usbd_hub.c84
-rw-r--r--class/hub/usbd_hub.h22
3 files changed, 224 insertions, 0 deletions
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_ */