From 5c36affc3c9ba9384b7e42297c59facd0279c98d Mon Sep 17 00:00:00 2001 From: sakumisu <1203593632@qq.com> Date: Sat, 24 Feb 2024 13:35:41 +0800 Subject: classify vendor class --- class/vendor/net/usbh_asix.c | 797 ++++++++++++++++++++++++++++++++++++++ class/vendor/net/usbh_asix.h | 180 +++++++++ class/vendor/serial/usbh_ch34x.c | 352 +++++++++++++++++ class/vendor/serial/usbh_ch34x.h | 74 ++++ class/vendor/serial/usbh_cp210x.c | 291 ++++++++++++++ class/vendor/serial/usbh_cp210x.h | 71 ++++ class/vendor/serial/usbh_ftdi.c | 368 ++++++++++++++++++ class/vendor/serial/usbh_ftdi.h | 74 ++++ class/vendor/usbh_asix.c | 797 -------------------------------------- class/vendor/usbh_asix.h | 180 --------- class/vendor/usbh_ch34x.c | 352 ----------------- class/vendor/usbh_ch34x.h | 74 ---- class/vendor/usbh_cp210x.c | 291 -------------- class/vendor/usbh_cp210x.h | 71 ---- class/vendor/usbh_ftdi.c | 368 ------------------ class/vendor/usbh_ftdi.h | 74 ---- 16 files changed, 2207 insertions(+), 2207 deletions(-) create mode 100644 class/vendor/net/usbh_asix.c create mode 100644 class/vendor/net/usbh_asix.h create mode 100644 class/vendor/serial/usbh_ch34x.c create mode 100644 class/vendor/serial/usbh_ch34x.h create mode 100644 class/vendor/serial/usbh_cp210x.c create mode 100644 class/vendor/serial/usbh_cp210x.h create mode 100644 class/vendor/serial/usbh_ftdi.c create mode 100644 class/vendor/serial/usbh_ftdi.h delete mode 100644 class/vendor/usbh_asix.c delete mode 100644 class/vendor/usbh_asix.h delete mode 100644 class/vendor/usbh_ch34x.c delete mode 100644 class/vendor/usbh_ch34x.h delete mode 100644 class/vendor/usbh_cp210x.c delete mode 100644 class/vendor/usbh_cp210x.h delete mode 100644 class/vendor/usbh_ftdi.c delete mode 100644 class/vendor/usbh_ftdi.h diff --git a/class/vendor/net/usbh_asix.c b/class/vendor/net/usbh_asix.c new file mode 100644 index 00000000..d6c017bb --- /dev/null +++ b/class/vendor/net/usbh_asix.c @@ -0,0 +1,797 @@ +/* + * Copyright (c) 2024, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "usbh_core.h" +#include "usbh_asix.h" +#include "usb_cdc.h" + +#undef USB_DBG_TAG +#define USB_DBG_TAG "asix" +#include "usb_log.h" + +#define DEV_FORMAT "/dev/asix" + +static struct usbh_asix g_asix_class; +#define CONFIG_USBHOST_ASIX_ETH_MAX_SEGSZE (1514U + 8) + +static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_rx_buffer[CONFIG_USBHOST_ASIX_ETH_MAX_SEGSZE]; +static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_tx_buffer[CONFIG_USBHOST_ASIX_ETH_MAX_SEGSZE]; +static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_inttx_buffer[16]; +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_buf[32]; + +#define ETH_ALEN 6 + +#define PHY_MODE_MARVELL 0x0000 +#define MII_MARVELL_LED_CTRL 0x0018 +#define MII_MARVELL_STATUS 0x001b +#define MII_MARVELL_CTRL 0x0014 + +#define MARVELL_LED_MANUAL 0x0019 + +#define MARVELL_STATUS_HWCFG 0x0004 + +#define MARVELL_CTRL_TXDELAY 0x0002 +#define MARVELL_CTRL_RXDELAY 0x0080 + +#define PHY_MODE_RTL8211CL 0x000C + +#define AX88772A_PHY14H 0x14 +#define AX88772A_PHY14H_DEFAULT 0x442C + +#define AX88772A_PHY15H 0x15 +#define AX88772A_PHY15H_DEFAULT 0x03C8 + +#define AX88772A_PHY16H 0x16 +#define AX88772A_PHY16H_DEFAULT 0x4044 + +#define SPEED_100 0 +#define SPEED_10 1 + +static int usbh_asix_read_cmd(struct usbh_asix *asix_class, + uint8_t cmd, + uint16_t value, + uint16_t index, + void *data, + uint16_t size) +{ + struct usb_setup_packet *setup = asix_class->hport->setup; + int ret; + + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = cmd; + setup->wValue = value; + setup->wIndex = index; + setup->wLength = size; + + ret = usbh_control_transfer(asix_class->hport, setup, g_asix_buf); + if (ret < 0) { + return ret; + } + memcpy(data, g_asix_buf, ret - 8); + + return ret; +} + +static int usbh_asix_write_cmd(struct usbh_asix *asix_class, + uint8_t cmd, + uint16_t value, + uint16_t index, + void *data, + uint16_t size) +{ + struct usb_setup_packet *setup = asix_class->hport->setup; + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = cmd; + setup->wValue = value; + setup->wIndex = index; + setup->wLength = size; + + memcpy(g_asix_buf, data, size); + + return usbh_control_transfer(asix_class->hport, setup, g_asix_buf); +} + +static int usbh_asix_mdio_write(struct usbh_asix *asix_class, int phy_id, int loc, int val) +{ + uint8_t smsr; + uint16_t res = (uint16_t)val; + int ret; + + for (uint8_t i = 0; i < 10; i++) { + ret = usbh_asix_write_cmd(asix_class, AX_CMD_SET_SW_MII, 0, 0, NULL, 0); + if (ret < 0) { + return ret; + } + usb_osal_msleep(1); + ret = usbh_asix_read_cmd(asix_class, AX_CMD_STATMNGSTS_REG, 0, 0, &smsr, 1); + if (ret < 0) { + return ret; + } + + if (smsr & AX_HOST_EN) { + break; + } + } + + ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_MII_REG, phy_id, loc, &res, 2); + if (ret < 0) { + return ret; + } + + ret = usbh_asix_write_cmd(asix_class, AX_CMD_SET_HW_MII, 0, 0, NULL, 0); + if (ret < 0) { + return ret; + } + return 0; +} + +static int usbh_asix_mdio_read(struct usbh_asix *asix_class, int phy_id, int loc) +{ + uint8_t smsr; + uint16_t res; + int ret; + + for (uint8_t i = 0; i < 10; i++) { + ret = usbh_asix_write_cmd(asix_class, AX_CMD_SET_SW_MII, 0, 0, NULL, 0); + if (ret < 0) { + return ret; + } + usb_osal_msleep(1); + ret = usbh_asix_read_cmd(asix_class, AX_CMD_STATMNGSTS_REG, 0, 0, &smsr, 1); + if (ret < 0) { + return ret; + } + + if (smsr & AX_HOST_EN) { + break; + } + } + + ret = usbh_asix_read_cmd(asix_class, AX_CMD_READ_MII_REG, phy_id, loc, &res, 2); + if (ret < 0) { + return ret; + } + + ret = usbh_asix_write_cmd(asix_class, AX_CMD_SET_HW_MII, 0, 0, NULL, 0); + if (ret < 0) { + return ret; + } + return res; +} + +static int usbh_asix_read_phy_addr(struct usbh_asix *asix_class, bool internal) +{ + int ret, offset; + uint8_t buf[2]; + + ret = usbh_asix_read_cmd(asix_class, AX_CMD_READ_PHY_ID, 0, 0, buf, 2); + if (ret < 0) { + return ret; + } + + offset = (internal ? 1 : 0); + ret = buf[offset]; + + USB_LOG_INFO("%s PHY address 0x%x\r\n", internal ? "internal" : "external", ret); + + return ret; +} + +static int usbh_asix_sw_reset(struct usbh_asix *asix_class, uint8_t flags) +{ + int ret; + + ret = usbh_asix_write_cmd(asix_class, AX_CMD_SW_RESET, flags, 0, NULL, 0); + if (ret < 0) + USB_LOG_ERR("Failed to send software reset: %d\r\n", ret); + + return ret; +} + +static uint16_t usbh_asix_read_rx_ctl(struct usbh_asix *asix_class) +{ + uint16_t v; + int ret = usbh_asix_read_cmd(asix_class, AX_CMD_READ_RX_CTL, 0, 0, &v, 2); + if (ret < 0) { + return ret; + } + return v; +} + +static int usbh_asix_write_rx_ctl(struct usbh_asix *asix_class, uint16_t mode) +{ + int ret; + + USB_LOG_DBG("asix_write_rx_ctl() - mode = 0x%04x\r\n", mode); + ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_RX_CTL, mode, 0, NULL, 0); + if (ret < 0) + USB_LOG_ERR("Failed to write RX_CTL mode to 0x%04x: %02x\r\n", + mode, ret); + + return ret; +} + +static uint16_t usbh_asix_read_medium_status(struct usbh_asix *asix_class) +{ + uint16_t v; + int ret = usbh_asix_read_cmd(asix_class, AX_CMD_READ_MEDIUM_STATUS, 0, 0, &v, 2); + + if (ret < 0) { + USB_LOG_ERR("Error reading Medium Status register: %02x\r\n", + ret); + return ret; /* TODO: callers not checking for error ret */ + } + + return v; +} + +static int usbh_asix_write_medium_mode(struct usbh_asix *asix_class, uint16_t mode) +{ + int ret; + + USB_LOG_DBG("asix_write_medium_mode() - mode = 0x%04x\r\n", mode); + ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, NULL, 0); + if (ret < 0) + USB_LOG_ERR("Failed to write Medium Mode mode to 0x%04x: %02x\r\n", + mode, ret); + + return ret; +} + +static int usbh_asix_write_gpio(struct usbh_asix *asix_class, uint16_t value, int sleep) +{ + int ret; + + USB_LOG_DBG("asix_write_gpio() - value = 0x%04x\r\n", value); + ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_GPIOS, value, 0, NULL, 0); + if (ret < 0) + USB_LOG_ERR("Failed to write GPIO value 0x%04x: %d\r\n", + value, ret); + + if (sleep) + usb_osal_msleep(sleep); + + return ret; +} + +/* + * AX88772 & AX88178 have a 16-bit RX_CTL value + */ +static void usbh_asix_set_multicast(struct usbh_asix *asix_class) +{ + uint16_t rx_ctl = AX_DEFAULT_RX_CTL | AX_RX_CTL_AM; + const uint8_t multi_filter[] = { 0x00, 0x00, 0x20, 0x80, 0x00, 0x00, 0x00, 0x40 }; + + usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_MULTI_FILTER, 0, 0, (uint8_t *)multi_filter, AX_MCAST_FILTER_SIZE); + usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, NULL, 0); +} + +static int usbh_ax88772_hw_reset(struct usbh_asix *asix_class) +{ + uint16_t rx_ctl; + int ret; + + ret = usbh_asix_write_gpio(asix_class, AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5); + if (ret < 0) + goto out; + + ret = usbh_asix_write_cmd(asix_class, AX_CMD_SW_PHY_SELECT, asix_class->embd_phy, + 0, NULL, 0); + if (ret < 0) { + USB_LOG_ERR("Select PHY #1 failed: %d\r\n", ret); + goto out; + } + + if (asix_class->embd_phy) { + ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_IPPD); + if (ret < 0) + goto out; + + usb_osal_msleep(10); + + ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_CLEAR); + if (ret < 0) + goto out; + + usb_osal_msleep(60); + + ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_IPRL | AX_SWRESET_PRL); + if (ret < 0) + goto out; + } else { + ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_IPPD | AX_SWRESET_PRL); + if (ret < 0) + goto out; + } + + usb_osal_msleep(150); + + ret = usbh_asix_write_rx_ctl(asix_class, AX_DEFAULT_RX_CTL); + if (ret < 0) + goto out; + + ret = usbh_asix_write_medium_mode(asix_class, AX88772_MEDIUM_DEFAULT); + if (ret < 0) + goto out; + + ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_IPG0, + AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT, + AX88772_IPG2_DEFAULT, NULL, 0); + if (ret < 0) { + USB_LOG_ERR("Write IPG,IPG1,IPG2 failed: %d\r\n", ret); + goto out; + } + + /* Rewrite MAC address */ + ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_NODE_ID, 0, 0, asix_class->mac, ETH_ALEN); + if (ret < 0) + goto out; + + /* Set RX_CTL to default values with 2k buffer, and enable cactus */ + ret = usbh_asix_write_rx_ctl(asix_class, AX_DEFAULT_RX_CTL); + if (ret < 0) + goto out; + + rx_ctl = usbh_asix_read_rx_ctl(asix_class); + USB_LOG_INFO("RX_CTL is 0x%04x after all initializations\r\n", + rx_ctl); + + rx_ctl = usbh_asix_read_medium_status(asix_class); + USB_LOG_INFO("Medium Status is 0x%04x after all initializations\r\n", + rx_ctl); + + return 0; + +out: + return ret; +} + +static int usbh_ax88772a_hw_reset(struct usbh_asix *asix_class) +{ + uint16_t rx_ctl, phy14h, phy15h, phy16h; + int ret; + + ret = usbh_asix_write_gpio(asix_class, AX_GPIO_RSE, 5); + if (ret < 0) + goto out; + + ret = usbh_asix_write_cmd(asix_class, AX_CMD_SW_PHY_SELECT, asix_class->embd_phy | AX_PHYSEL_SSEN, 0, 0, NULL); + if (ret < 0) { + USB_LOG_ERR("Select PHY #1 failed: %d\r\n", ret); + goto out; + } + usb_osal_msleep(10); + + ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_IPPD | AX_SWRESET_IPRL); + if (ret < 0) + goto out; + + usb_osal_msleep(10); + + ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_IPRL); + if (ret < 0) + goto out; + + usb_osal_msleep(160); + + ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_CLEAR); + if (ret < 0) + goto out; + + ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_IPRL); + if (ret < 0) + goto out; + + usb_osal_msleep(200); + + if (asix_class->chipcode == AX_AX88772B_CHIPCODE) { + ret = usbh_asix_write_cmd(asix_class, AX_QCTCTRL, 0x8000, 0x8001, NULL, 0); + if (ret < 0) { + USB_LOG_ERR("Write BQ setting failed: %d\r\n", ret); + goto out; + } + } else if (asix_class->chipcode == AX_AX88772A_CHIPCODE) { + /* Check if the PHY registers have default settings */ + phy14h = usbh_asix_mdio_read(asix_class, asix_class->phy_addr, + AX88772A_PHY14H); + phy15h = usbh_asix_mdio_read(asix_class, asix_class->phy_addr, + AX88772A_PHY15H); + phy16h = usbh_asix_mdio_read(asix_class, asix_class->phy_addr, + AX88772A_PHY16H); + + USB_LOG_DBG("772a_hw_reset: MR20=0x%x MR21=0x%x MR22=0x%x\r\n", + phy14h, phy15h, phy16h); + + /* Restore PHY registers default setting if not */ + if (phy14h != AX88772A_PHY14H_DEFAULT) + usbh_asix_mdio_write(asix_class, asix_class->phy_addr, + AX88772A_PHY14H, + AX88772A_PHY14H_DEFAULT); + if (phy15h != AX88772A_PHY15H_DEFAULT) + usbh_asix_mdio_write(asix_class, asix_class->phy_addr, + AX88772A_PHY15H, + AX88772A_PHY15H_DEFAULT); + if (phy16h != AX88772A_PHY16H_DEFAULT) + usbh_asix_mdio_write(asix_class, asix_class->phy_addr, + AX88772A_PHY16H, + AX88772A_PHY16H_DEFAULT); + } + + ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_IPG0, + AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT, + AX88772_IPG2_DEFAULT, 0, NULL); + if (ret < 0) { + USB_LOG_ERR("Write IPG,IPG1,IPG2 failed: %d\r\n", ret); + goto out; + } + + /* Rewrite MAC address */ + ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_NODE_ID, 0, 0, asix_class->mac, ETH_ALEN); + if (ret < 0) + goto out; + + /* Set RX_CTL to default values with 2k buffer, and enable cactus */ + ret = usbh_asix_write_rx_ctl(asix_class, AX_DEFAULT_RX_CTL); + if (ret < 0) + goto out; + + ret = usbh_asix_write_medium_mode(asix_class, AX88772_MEDIUM_DEFAULT); + if (ret < 0) + return ret; + + /* Set RX_CTL to default values with 2k buffer, and enable cactus */ + ret = usbh_asix_write_rx_ctl(asix_class, AX_DEFAULT_RX_CTL); + if (ret < 0) + goto out; + + rx_ctl = usbh_asix_read_rx_ctl(asix_class); + USB_LOG_INFO("RX_CTL is 0x%04x after all initializations\r\n", rx_ctl); + + rx_ctl = usbh_asix_read_medium_status(asix_class); + USB_LOG_INFO("Medium Status is 0x%04x after all initializations\r\n", rx_ctl); + + return 0; + +out: + return ret; +} + +static void usbh_ax88772_mac_link_down(struct usbh_asix *asix_class) +{ + usbh_asix_write_medium_mode(asix_class, 0); +} + +static void usbh_ax88772_mac_link_up(struct usbh_asix *asix_class, int speed, int duplex, bool tx_pause, bool rx_pause) +{ + uint16_t m = AX_MEDIUM_AC | AX_MEDIUM_RE; + + m |= duplex ? AX_MEDIUM_FD : 0; + + switch (speed) { + case SPEED_100: + m |= AX_MEDIUM_PS; + break; + case SPEED_10: + break; + default: + return; + } + + if (tx_pause) + m |= AX_MEDIUM_TFC; + + if (rx_pause) + m |= AX_MEDIUM_RFC; + + usbh_asix_write_medium_mode(asix_class, m); +} + +static int usbh_asix_connect(struct usbh_hubport *hport, uint8_t intf) +{ + struct usb_endpoint_descriptor *ep_desc; + int ret; + + struct usbh_asix *asix_class = &g_asix_class; + + memset(asix_class, 0, sizeof(struct usbh_asix)); + + asix_class->hport = hport; + asix_class->intf = intf; + + hport->config.intf[intf].priv = asix_class; + + if ((hport->device_desc.idVendor == 0x0b95) && (hport->device_desc.idProduct == 0x772b)) { + asix_class->name = "ASIX AX88772B"; + } else if ((hport->device_desc.idVendor == 0x0b95) && (hport->device_desc.idProduct == 0x7720)) { + asix_class->name = "ASIX AX88772"; + } else if ((hport->device_desc.idVendor == 0x0b95) && (hport->device_desc.idProduct == 0x1780)) { + asix_class->name = "ASIX AX88178"; + } + + for (uint8_t i = 0; i < (ETH_ALEN >> 1); i++) { + ret = usbh_asix_read_cmd(asix_class, AX_CMD_READ_EEPROM, + 0x04 + i, 0, &asix_class->mac[i * 2], 2); + if (ret < 0) { + return ret; + } + } + + USB_LOG_INFO("asix MAC address %02x:%02x:%02x:%02x:%02x:%02x\r\n", + asix_class->mac[0], + asix_class->mac[1], + asix_class->mac[2], + asix_class->mac[3], + asix_class->mac[4], + asix_class->mac[5]); + + ret = usbh_asix_read_phy_addr(asix_class, true); + if (ret < 0) { + USB_LOG_ERR("Failed to read phy addr: %d\r\n", ret); + return ret; + } + asix_class->phy_addr = ret; + asix_class->embd_phy = ((ret & 0x1f) == AX_EMBD_PHY_ADDR); + + ret = usbh_asix_read_cmd(asix_class, AX_CMD_STATMNGSTS_REG, 0, 0, &asix_class->chipcode, 1); + if (ret < 0) { + USB_LOG_ERR("Failed to read STATMNGSTS_REG: %d\r\n", ret); + return ret; + } + + asix_class->chipcode &= AX_CHIPCODE_MASK; + USB_LOG_INFO("asix chipcode 0x%x\r\n", asix_class->chipcode); + + if (asix_class->chipcode == AX_AX88772_CHIPCODE) { + usbh_ax88772_hw_reset(asix_class); + } else { + usbh_ax88772a_hw_reset(asix_class); + } + for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) { + ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc; + + if (USB_GET_ENDPOINT_TYPE(ep_desc->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) { + if (ep_desc->bEndpointAddress & 0x80) { + USBH_EP_INIT(asix_class->intin, ep_desc); + } else { + return -USB_ERR_NOTSUPP; + } + } else { + if (ep_desc->bEndpointAddress & 0x80) { + USBH_EP_INIT(asix_class->bulkin, ep_desc); + } else { + USBH_EP_INIT(asix_class->bulkout, ep_desc); + } + } + } + + if (asix_class->chipcode == AX_AX88772B_CHIPCODE) { + usbh_asix_mdio_write(asix_class, asix_class->phy_addr, 0, 0); + usbh_asix_mdio_read(asix_class, asix_class->phy_addr, 0); + + usbh_asix_mdio_write(asix_class, asix_class->phy_addr, 0, 0x8200); + usbh_asix_mdio_read(asix_class, asix_class->phy_addr, 0); + + usbh_asix_mdio_write(asix_class, asix_class->phy_addr, 0, 0x3900); + usbh_asix_mdio_read(asix_class, asix_class->phy_addr, 0); + + usbh_asix_mdio_write(asix_class, asix_class->phy_addr, 0, 0x3100); + usbh_asix_mdio_read(asix_class, asix_class->phy_addr, 4); + + usbh_asix_mdio_write(asix_class, asix_class->phy_addr, 4, 0x01e1); + usbh_asix_mdio_read(asix_class, asix_class->phy_addr, 1); + + usbh_asix_mdio_write(asix_class, asix_class->phy_addr, 0, 0x3300); + usbh_asix_mdio_read(asix_class, asix_class->phy_addr, 0); + } + + USB_LOG_INFO("Init %s done\r\n", asix_class->name); + + memcpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN); + + USB_LOG_INFO("Register ASIX Class:%s\r\n", hport->config.intf[intf].devname); + usbh_asix_run(asix_class); + return ret; +} + +static int usbh_asix_disconnect(struct usbh_hubport *hport, uint8_t intf) +{ + int ret = 0; + + struct usbh_asix *asix_class = (struct usbh_asix *)hport->config.intf[intf].priv; + + if (asix_class) { + if (asix_class->bulkin) { + usbh_kill_urb(&asix_class->bulkin_urb); + } + + if (asix_class->bulkout) { + usbh_kill_urb(&asix_class->bulkout_urb); + } + + if (asix_class->intin) { + usbh_kill_urb(&asix_class->intin_urb); + } + + if (hport->config.intf[intf].devname[0] != '\0') { + USB_LOG_INFO("Unregister ASIX Class:%s\r\n", hport->config.intf[intf].devname); + usbh_asix_stop(asix_class); + } + + memset(asix_class, 0, sizeof(struct usbh_asix)); + } + + return ret; +} + +int usbh_asix_get_connect_status(struct usbh_asix *asix_class) +{ + int ret; + + usbh_int_urb_fill(&asix_class->intin_urb, asix_class->hport, asix_class->intin, g_asix_inttx_buffer, 8, USB_OSAL_WAITING_FOREVER, NULL, NULL); + ret = usbh_submit_urb(&asix_class->intin_urb); + if (ret < 0) { + return ret; + } + + if (g_asix_inttx_buffer[1] == 0x00) { + if (g_asix_inttx_buffer[2] & 0x01) { + asix_class->connect_status = true; + usbh_ax88772_mac_link_up(asix_class, SPEED_100, 1, 1, 1); + usbh_asix_set_multicast(asix_class); + } else { + asix_class->connect_status = false; + usbh_ax88772_mac_link_down(asix_class); + } + } + return 0; +} + +void usbh_asix_rx_thread(void *argument) +{ + uint32_t g_asix_rx_length; + int ret; + err_t err; + uint16_t len; + uint16_t len_crc; + struct pbuf *p; + struct netif *netif = (struct netif *)argument; + + USB_LOG_INFO("Create asix rx thread\r\n"); + // clang-format off +find_class: + // clang-format on + g_asix_class.connect_status = false; + if (usbh_find_class_instance("/dev/asix") == NULL) { + goto delete; + } + + while (g_asix_class.connect_status == false) { + ret = usbh_asix_get_connect_status(&g_asix_class); + if (ret < 0) { + usb_osal_msleep(100); + goto find_class; + } + } + + g_asix_rx_length = 0; + while (1) { + usbh_bulk_urb_fill(&g_asix_class.bulkin_urb, g_asix_class.hport, g_asix_class.bulkin, &g_asix_rx_buffer[g_asix_rx_length], USB_GET_MAXPACKETSIZE(g_asix_class.bulkin->wMaxPacketSize), USB_OSAL_WAITING_FOREVER, NULL, NULL); + ret = usbh_submit_urb(&g_asix_class.bulkin_urb); + if (ret < 0) { + goto find_class; + } + + g_asix_rx_length += g_asix_class.bulkin_urb.actual_length; + + if (g_asix_rx_length % USB_GET_MAXPACKETSIZE(g_asix_class.bulkin->wMaxPacketSize)) { + len = ((uint16_t)g_asix_rx_buffer[0] | ((uint16_t)(g_asix_rx_buffer[1]) << 8)) & 0x7ff; + len_crc = g_asix_rx_buffer[2] | ((uint16_t)(g_asix_rx_buffer[3]) << 8); + + if (len != (~len_crc & 0x7ff)) { + USB_LOG_ERR("asix rx header error\r\n"); + continue; + } + + USB_LOG_DBG("rxlen:%d\r\n", g_asix_rx_length); + + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + if (p != NULL) { + memcpy(p->payload, (uint8_t *)&g_asix_rx_buffer[4], len); + g_asix_rx_length = 0; + + err = netif->input(p, netif); + if (err != ERR_OK) { + pbuf_free(p); + } + } else { + g_asix_rx_length = 0; + USB_LOG_ERR("No memory to alloc pbuf for asix rx\r\n"); + } + } else { + } + } + // clang-format off +delete: + USB_LOG_INFO("Delete asix rx thread\r\n"); + usb_osal_thread_delete(NULL); + // clang-format on +} + +err_t usbh_asix_linkoutput(struct netif *netif, struct pbuf *p) +{ + int ret; + struct pbuf *q; + uint16_t actual_len; + uint8_t *buffer = &g_asix_tx_buffer[4]; + + if (g_asix_class.connect_status == false) { + return ERR_BUF; + } + + for (q = p; q != NULL; q = q->next) { + memcpy(buffer, q->payload, q->len); + buffer += q->len; + } + + g_asix_tx_buffer[0] = p->tot_len & 0xff; + g_asix_tx_buffer[1] = (p->tot_len >> 8) & 0xff; + g_asix_tx_buffer[2] = ~g_asix_tx_buffer[0]; + g_asix_tx_buffer[3] = ~g_asix_tx_buffer[1]; + + if ((p->tot_len + 4) % USB_GET_MAXPACKETSIZE(g_asix_class.bulkout->wMaxPacketSize)) { + USB_LOG_DBG("txlen:%d\r\n", p->tot_len + 8); + g_asix_tx_buffer[p->tot_len + 4 + 0] = 0x00; + g_asix_tx_buffer[p->tot_len + 4 + 1] = 0x00; + g_asix_tx_buffer[p->tot_len + 4 + 2] = 0xff; + g_asix_tx_buffer[p->tot_len + 4 + 3] = 0xff; + actual_len = p->tot_len + 8; + } else { + USB_LOG_DBG("txlen:%d\r\n", p->tot_len + 4); + actual_len = p->tot_len + 4; + } + + usbh_bulk_urb_fill(&g_asix_class.bulkout_urb, g_asix_class.hport, g_asix_class.bulkout, g_asix_tx_buffer, actual_len, USB_OSAL_WAITING_FOREVER, NULL, NULL); + ret = usbh_submit_urb(&g_asix_class.bulkout_urb); + if (ret < 0) { + return ERR_BUF; + } + + return ERR_OK; +} + +__WEAK void usbh_asix_run(struct usbh_asix *asix_class) +{ +} + +__WEAK void usbh_asix_stop(struct usbh_asix *asix_class) +{ +} + +static const struct usbh_class_driver asix_class_driver = { + .driver_name = "asix", + .connect = usbh_asix_connect, + .disconnect = usbh_asix_disconnect +}; + +CLASS_INFO_DEFINE const struct usbh_class_info ax88772b_class_info = { + .match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS, + .class = 0xff, + .subclass = 0x00, + .protocol = 0x00, + .vid = 0x0B95, + .pid = 0x772B, + .class_driver = &asix_class_driver +}; + +CLASS_INFO_DEFINE const struct usbh_class_info ax88772_class_info = { + .match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS, + .class = 0xff, + .subclass = 0x00, + .protocol = 0x00, + .vid = 0x0B95, + .pid = 0x7720, + .class_driver = &asix_class_driver +}; diff --git a/class/vendor/net/usbh_asix.h b/class/vendor/net/usbh_asix.h new file mode 100644 index 00000000..8be79dfd --- /dev/null +++ b/class/vendor/net/usbh_asix.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2024, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef USBH_ASIX_H +#define USBH_ASIX_H + +#include "lwip/netif.h" +#include "lwip/pbuf.h" + +/* ASIX AX8817X based USB 2.0 Ethernet Devices */ + +#define AX_CMD_SET_SW_MII 0x06 +#define AX_CMD_READ_MII_REG 0x07 +#define AX_CMD_WRITE_MII_REG 0x08 +#define AX_CMD_STATMNGSTS_REG 0x09 +#define AX_CMD_SET_HW_MII 0x0a +#define AX_CMD_READ_EEPROM 0x0b +#define AX_CMD_WRITE_EEPROM 0x0c +#define AX_CMD_WRITE_ENABLE 0x0d +#define AX_CMD_WRITE_DISABLE 0x0e +#define AX_CMD_READ_RX_CTL 0x0f +#define AX_CMD_WRITE_RX_CTL 0x10 +#define AX_CMD_READ_IPG012 0x11 +#define AX_CMD_WRITE_IPG0 0x12 +#define AX_CMD_WRITE_IPG1 0x13 +#define AX_CMD_READ_NODE_ID 0x13 +#define AX_CMD_WRITE_NODE_ID 0x14 +#define AX_CMD_WRITE_IPG2 0x14 +#define AX_CMD_WRITE_MULTI_FILTER 0x16 +#define AX88172_CMD_READ_NODE_ID 0x17 +#define AX_CMD_READ_PHY_ID 0x19 +#define AX_CMD_READ_MEDIUM_STATUS 0x1a +#define AX_CMD_WRITE_MEDIUM_MODE 0x1b +#define AX_CMD_READ_MONITOR_MODE 0x1c +#define AX_CMD_WRITE_MONITOR_MODE 0x1d +#define AX_CMD_READ_GPIOS 0x1e +#define AX_CMD_WRITE_GPIOS 0x1f +#define AX_CMD_SW_RESET 0x20 +#define AX_CMD_SW_PHY_STATUS 0x21 +#define AX_CMD_SW_PHY_SELECT 0x22 +#define AX_QCTCTRL 0x2A + +#define AX_CHIPCODE_MASK 0x70 +#define AX_AX88772_CHIPCODE 0x00 +#define AX_AX88772A_CHIPCODE 0x10 +#define AX_AX88772B_CHIPCODE 0x20 +#define AX_HOST_EN 0x01 + +#define AX_PHYSEL_PSEL 0x01 +#define AX_PHYSEL_SSMII 0 +#define AX_PHYSEL_SSEN 0x10 + +#define AX_PHY_SELECT_MASK (BIT(3) | BIT(2)) +#define AX_PHY_SELECT_INTERNAL 0 +#define AX_PHY_SELECT_EXTERNAL BIT(2) + +#define AX_MONITOR_MODE 0x01 +#define AX_MONITOR_LINK 0x02 +#define AX_MONITOR_MAGIC 0x04 +#define AX_MONITOR_HSFS 0x10 + +/* AX88172 Medium Status Register values */ +#define AX88172_MEDIUM_FD 0x02 +#define AX88172_MEDIUM_TX 0x04 +#define AX88172_MEDIUM_FC 0x10 +#define AX88172_MEDIUM_DEFAULT \ + (AX88172_MEDIUM_FD | AX88172_MEDIUM_TX | AX88172_MEDIUM_FC) + +#define AX_MCAST_FILTER_SIZE 8 +#define AX_MAX_MCAST 64 + +#define AX_SWRESET_CLEAR 0x00 +#define AX_SWRESET_RR 0x01 +#define AX_SWRESET_RT 0x02 +#define AX_SWRESET_PRTE 0x04 +#define AX_SWRESET_PRL 0x08 +#define AX_SWRESET_BZ 0x10 +#define AX_SWRESET_IPRL 0x20 +#define AX_SWRESET_IPPD 0x40 + +#define AX88772_IPG0_DEFAULT 0x15 +#define AX88772_IPG1_DEFAULT 0x0c +#define AX88772_IPG2_DEFAULT 0x12 + +/* AX88772 & AX88178 Medium Mode Register */ +#define AX_MEDIUM_PF 0x0080 +#define AX_MEDIUM_JFE 0x0040 +#define AX_MEDIUM_TFC 0x0020 +#define AX_MEDIUM_RFC 0x0010 +#define AX_MEDIUM_ENCK 0x0008 +#define AX_MEDIUM_AC 0x0004 +#define AX_MEDIUM_FD 0x0002 +#define AX_MEDIUM_GM 0x0001 +#define AX_MEDIUM_SM 0x1000 +#define AX_MEDIUM_SBP 0x0800 +#define AX_MEDIUM_PS 0x0200 +#define AX_MEDIUM_RE 0x0100 + +#define AX88178_MEDIUM_DEFAULT \ + (AX_MEDIUM_PS | AX_MEDIUM_FD | AX_MEDIUM_AC | \ + AX_MEDIUM_RFC | AX_MEDIUM_TFC | AX_MEDIUM_JFE | \ + AX_MEDIUM_RE) + +#define AX88772_MEDIUM_DEFAULT \ + (AX_MEDIUM_FD | AX_MEDIUM_PS | \ + AX_MEDIUM_AC | AX_MEDIUM_RE) + +/* AX88772 & AX88178 RX_CTL values */ +#define AX_RX_CTL_SO 0x0080 +#define AX_RX_CTL_AP 0x0020 +#define AX_RX_CTL_AM 0x0010 +#define AX_RX_CTL_AB 0x0008 +#define AX_RX_CTL_SEP 0x0004 +#define AX_RX_CTL_AMALL 0x0002 +#define AX_RX_CTL_PRO 0x0001 +#define AX_RX_CTL_MFB_2048 0x0000 +#define AX_RX_CTL_MFB_4096 0x0100 +#define AX_RX_CTL_MFB_8192 0x0200 +#define AX_RX_CTL_MFB_16384 0x0300 + +#define AX_DEFAULT_RX_CTL (AX_RX_CTL_SO | AX_RX_CTL_AB) + +/* GPIO 0 .. 2 toggles */ +#define AX_GPIO_GPO0EN 0x01 /* GPIO0 Output enable */ +#define AX_GPIO_GPO_0 0x02 /* GPIO0 Output value */ +#define AX_GPIO_GPO1EN 0x04 /* GPIO1 Output enable */ +#define AX_GPIO_GPO_1 0x08 /* GPIO1 Output value */ +#define AX_GPIO_GPO2EN 0x10 /* GPIO2 Output enable */ +#define AX_GPIO_GPO_2 0x20 /* GPIO2 Output value */ +#define AX_GPIO_RESERVED 0x40 /* Reserved */ +#define AX_GPIO_RSE 0x80 /* Reload serial EEPROM */ + +#define AX_EEPROM_MAGIC 0xdeadbeef +#define AX_EEPROM_LEN 0x200 + +#define AX_EMBD_PHY_ADDR 0x10 + +struct usbh_asix { + struct usbh_hubport *hport; + struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */ + struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */ + struct usb_endpoint_descriptor *intin; /* INTR IN endpoint */ + struct usbh_urb bulkout_urb; + struct usbh_urb bulkin_urb; + struct usbh_urb intin_urb; + + uint8_t intf; + char *name; + uint8_t phy_addr; + uint8_t embd_phy; + uint8_t chipcode; + uint16_t mac_capabilities; + + bool connect_status; + uint8_t mac[6]; + + ip_addr_t ipaddr; + ip_addr_t netmask; + ip_addr_t gateway; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +int usbh_asix_get_connect_status(struct usbh_asix *asix_class); + +void usbh_asix_run(struct usbh_asix *asix_class); +void usbh_asix_stop(struct usbh_asix *asix_class); + +void usbh_asix_rx_thread(void *argument); +err_t usbh_asix_linkoutput(struct netif *netif, struct pbuf *p); + +#ifdef __cplusplus +} +#endif + +#endif /* USBH_ASIX_H */ \ No newline at end of file diff --git a/class/vendor/serial/usbh_ch34x.c b/class/vendor/serial/usbh_ch34x.c new file mode 100644 index 00000000..1effdba8 --- /dev/null +++ b/class/vendor/serial/usbh_ch34x.c @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2024, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "usbh_core.h" +#include "usbh_ch34x.h" + +#define DEV_FORMAT "/dev/ttyUSB%d" + +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_ch34x_buf[64]; + +#define CONFIG_USBHOST_MAX_CP210X_CLASS 1 + +static struct usbh_ch34x g_ch34x_class[CONFIG_USBHOST_MAX_CP210X_CLASS]; +static uint32_t g_devinuse = 0; + +static struct usbh_ch34x *usbh_ch34x_class_alloc(void) +{ + int devno; + + for (devno = 0; devno < CONFIG_USBHOST_MAX_CP210X_CLASS; devno++) { + if ((g_devinuse & (1 << devno)) == 0) { + g_devinuse |= (1 << devno); + memset(&g_ch34x_class[devno], 0, sizeof(struct usbh_ch34x)); + g_ch34x_class[devno].minor = devno; + return &g_ch34x_class[devno]; + } + } + return NULL; +} + +static void usbh_ch34x_class_free(struct usbh_ch34x *ch34x_class) +{ + int devno = ch34x_class->minor; + + if (devno >= 0 && devno < 32) { + g_devinuse &= ~(1 << devno); + } + memset(ch34x_class, 0, sizeof(struct usbh_ch34x)); +} + +static int usbh_ch34x_get_baudrate_div(uint32_t baudrate, uint8_t *factor, uint8_t *divisor) +{ + uint8_t a; + uint8_t b; + uint32_t c; + + switch (baudrate) { + case 921600: + a = 0xf3; + b = 7; + break; + + case 307200: + a = 0xd9; + b = 7; + break; + + default: + if (baudrate > 6000000 / 255) { + b = 3; + c = 6000000; + } else if (baudrate > 750000 / 255) { + b = 2; + c = 750000; + } else if (baudrate > 93750 / 255) { + b = 1; + c = 93750; + } else { + b = 0; + c = 11719; + } + a = (uint8_t)(c / baudrate); + if (a == 0 || a == 0xFF) { + return -USB_ERR_INVAL; + } + if ((c / a - baudrate) > (baudrate - c / (a + 1))) { + a++; + } + a = (uint8_t)(256 - a); + break; + } + + *factor = a; + *divisor = b; + + return 0; +} + +static int usbh_ch34x_get_version(struct usbh_ch34x *ch34x_class) +{ + struct usb_setup_packet *setup = ch34x_class->hport->setup; + int ret; + + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = CH34X_READ_VERSION; + setup->wValue = 0; + setup->wIndex = 0; + setup->wLength = 2; + + ret = usbh_control_transfer(ch34x_class->hport, setup, g_ch34x_buf); + if (ret < 0) { + return ret; + } + + USB_LOG_INFO("Ch34x chip version %02x:%02x\r\n", g_ch34x_buf[0], g_ch34x_buf[1]); + return ret; +} + +static int usbh_ch34x_flow_ctrl(struct usbh_ch34x *ch34x_class) +{ + struct usb_setup_packet *setup = ch34x_class->hport->setup; + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = CH34X_WRITE_REG; + setup->wValue = 0x2727; + setup->wIndex = 0; + setup->wLength = 0; + + return usbh_control_transfer(ch34x_class->hport, setup, NULL); +} + +int usbh_ch34x_set_line_coding(struct usbh_ch34x *ch34x_class, struct cdc_line_coding *line_coding) +{ + struct usb_setup_packet *setup = ch34x_class->hport->setup; + uint16_t reg_value = 0; + uint16_t value = 0; + uint8_t factor = 0; + uint8_t divisor = 0; + + memcpy((uint8_t *)&ch34x_class->line_coding, line_coding, sizeof(struct cdc_line_coding)); + + /* refer to https://github.com/WCHSoftGroup/ch341ser_linux/blob/main/driver/ch341.c */ + + switch (line_coding->bParityType) { + case 0: + break; + case 1: + reg_value |= CH341_L_PO; + break; + case 2: + reg_value |= CH341_L_PE; + break; + case 3: + reg_value |= CH341_L_PM; + break; + case 4: + reg_value |= CH341_L_PS; + break; + default: + return -USB_ERR_INVAL; + } + + switch (line_coding->bDataBits) { + case 5: + reg_value |= CH341_L_D5; + break; + case 6: + reg_value |= CH341_L_D6; + break; + case 7: + reg_value |= CH341_L_D7; + break; + case 8: + reg_value |= CH341_L_D8; + break; + default: + return -USB_ERR_INVAL; + } + + if (line_coding->bCharFormat == 2) { + reg_value |= CH341_L_SB; + } + + reg_value |= 0xC0; + + value |= 0x9c; + value |= reg_value << 8; + + usbh_ch34x_get_baudrate_div(line_coding->dwDTERate, &factor, &divisor); + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = CH34X_SERIAL_INIT; + setup->wValue = value; + setup->wIndex = (factor << 8) | 0x80 | divisor; + setup->wLength = 0; + + return usbh_control_transfer(ch34x_class->hport, setup, NULL); +} + +int usbh_ch34x_get_line_coding(struct usbh_ch34x *ch34x_class, struct cdc_line_coding *line_coding) +{ + memcpy(line_coding, (uint8_t *)&ch34x_class->line_coding, sizeof(struct cdc_line_coding)); + return 0; +} + +int usbh_ch34x_set_line_state(struct usbh_ch34x *ch34x_class, bool dtr, bool rts) +{ + struct usb_setup_packet *setup = ch34x_class->hport->setup; + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = CH34X_MODEM_CTRL; + setup->wValue = 0x0f | (dtr << 5) | (rts << 6); + setup->wIndex = 0; + setup->wLength = 0; + + return usbh_control_transfer(ch34x_class->hport, setup, NULL); +} + +static int usbh_ch34x_connect(struct usbh_hubport *hport, uint8_t intf) +{ + struct usb_endpoint_descriptor *ep_desc; + int ret = 0; + + struct usbh_ch34x *ch34x_class = usbh_ch34x_class_alloc(); + if (ch34x_class == NULL) { + USB_LOG_ERR("Fail to alloc ch34x_class\r\n"); + return -USB_ERR_NOMEM; + } + + ch34x_class->hport = hport; + ch34x_class->intf = intf; + + hport->config.intf[intf].priv = ch34x_class; + + usbh_ch34x_get_version(ch34x_class); + usbh_ch34x_flow_ctrl(ch34x_class); + + for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) { + ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc; + if (USB_GET_ENDPOINT_TYPE(ep_desc->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) { + continue; + } else { + if (ep_desc->bEndpointAddress & 0x80) { + USBH_EP_INIT(ch34x_class->bulkin, ep_desc); + } else { + USBH_EP_INIT(ch34x_class->bulkout, ep_desc); + } + } + } + + snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, ch34x_class->minor); + + USB_LOG_INFO("Register CH34X Class:%s\r\n", hport->config.intf[intf].devname); + +#if 0 + USB_LOG_INFO("Test ch34x rx and tx and rx for 5 times, baudrate is 115200\r\n"); + + struct cdc_line_coding linecoding; + uint8_t count = 5; + + linecoding.dwDTERate = 115200; + linecoding.bDataBits = 8; + linecoding.bParityType = 0; + linecoding.bCharFormat = 0; + usbh_ch34x_set_line_coding(ch34x_class, &linecoding); + usbh_ch34x_set_line_state(ch34x_class, true, false); + + memset(g_ch34x_buf, 'a', sizeof(g_ch34x_buf)); + ret = usbh_ch34x_bulk_out_transfer(ch34x_class, g_ch34x_buf, sizeof(g_ch34x_buf), 0xfffffff); + USB_LOG_RAW("out ret:%d\r\n", ret); + while (count--) { + ret = usbh_ch34x_bulk_in_transfer(ch34x_class, g_ch34x_buf, sizeof(g_ch34x_buf), 0xfffffff); + USB_LOG_RAW("in ret:%d\r\n", ret); + if (ret > 0) { + for (uint32_t i = 0; i < ret; i++) { + USB_LOG_RAW("%02x ", g_ch34x_buf[i]); + } + USB_LOG_RAW("\r\n"); + } + } +#endif + usbh_ch34x_run(ch34x_class); + return ret; +} + +static int usbh_ch34x_disconnect(struct usbh_hubport *hport, uint8_t intf) +{ + int ret = 0; + + struct usbh_ch34x *ch34x_class = (struct usbh_ch34x *)hport->config.intf[intf].priv; + + if (ch34x_class) { + if (ch34x_class->bulkin) { + usbh_kill_urb(&ch34x_class->bulkin_urb); + } + + if (ch34x_class->bulkout) { + usbh_kill_urb(&ch34x_class->bulkout_urb); + } + + if (hport->config.intf[intf].devname[0] != '\0') { + USB_LOG_INFO("Unregister CH34X Class:%s\r\n", hport->config.intf[intf].devname); + usbh_ch34x_stop(ch34x_class); + } + + usbh_ch34x_class_free(ch34x_class); + } + + return ret; +} + +int usbh_ch34x_bulk_in_transfer(struct usbh_ch34x *ch34x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout) +{ + int ret; + struct usbh_urb *urb = &ch34x_class->bulkin_urb; + + usbh_bulk_urb_fill(urb, ch34x_class->hport, ch34x_class->bulkin, buffer, buflen, timeout, NULL, NULL); + ret = usbh_submit_urb(urb); + if (ret == 0) { + ret = urb->actual_length; + } + return ret; +} + +int usbh_ch34x_bulk_out_transfer(struct usbh_ch34x *ch34x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout) +{ + int ret; + struct usbh_urb *urb = &ch34x_class->bulkout_urb; + + usbh_bulk_urb_fill(urb, ch34x_class->hport, ch34x_class->bulkout, buffer, buflen, timeout, NULL, NULL); + ret = usbh_submit_urb(urb); + if (ret == 0) { + ret = urb->actual_length; + } + return ret; +} + +__WEAK void usbh_ch34x_run(struct usbh_ch34x *ch34x_class) +{ +} + +__WEAK void usbh_ch34x_stop(struct usbh_ch34x *ch34x_class) +{ +} + +const struct usbh_class_driver ch34x_class_driver = { + .driver_name = "ch34x", + .connect = usbh_ch34x_connect, + .disconnect = usbh_ch34x_disconnect +}; + +CLASS_INFO_DEFINE const struct usbh_class_info ch34x_class_info = { + .match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS, + .class = 0xff, + .subclass = 0xff, + .protocol = 0xff, + .vid = 0x1A86, + .pid = 0x7523, + .class_driver = &ch34x_class_driver +}; \ No newline at end of file diff --git a/class/vendor/serial/usbh_ch34x.h b/class/vendor/serial/usbh_ch34x.h new file mode 100644 index 00000000..9918c3be --- /dev/null +++ b/class/vendor/serial/usbh_ch34x.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2024, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef USBH_CH34X_H +#define USBH_CH34X_H + +#include "usb_cdc.h" + +/* Requests */ +#define CH34X_READ_VERSION 0x5F +#define CH34X_WRITE_REG 0x9A +#define CH34X_READ_REG 0x95 +#define CH34X_SERIAL_INIT 0xA1 +#define CH34X_MODEM_CTRL 0xA4 + +// modem control bits +#define CH34X_BIT_RTS (1 << 6) +#define CH34X_BIT_DTR (1 << 5) + +#define CH341_CTO_O 0x10 +#define CH341_CTO_D 0x20 +#define CH341_CTO_R 0x40 +#define CH341_CTI_C 0x01 +#define CH341_CTI_DS 0x02 +#define CH341_CTRL_RI 0x04 +#define CH341_CTI_DC 0x08 +#define CH341_CTI_ST 0x0f + +#define CH341_L_ER 0x80 +#define CH341_L_ET 0x40 +#define CH341_L_PS 0x38 +#define CH341_L_PM 0x28 +#define CH341_L_PE 0x18 +#define CH341_L_PO 0x08 +#define CH341_L_SB 0x04 +#define CH341_L_D8 0x03 +#define CH341_L_D7 0x02 +#define CH341_L_D6 0x01 +#define CH341_L_D5 0x00 + +struct usbh_ch34x { + struct usbh_hubport *hport; + struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */ + struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */ + struct usbh_urb bulkout_urb; + struct usbh_urb bulkin_urb; + + struct cdc_line_coding line_coding; + + uint8_t intf; + uint8_t minor; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +int usbh_ch34x_set_line_coding(struct usbh_ch34x *ch34x_class, struct cdc_line_coding *line_coding); +int usbh_ch34x_get_line_coding(struct usbh_ch34x *ch34x_class, struct cdc_line_coding *line_coding); +int usbh_ch34x_set_line_state(struct usbh_ch34x *ch34x_class, bool dtr, bool rts); + +int usbh_ch34x_bulk_in_transfer(struct usbh_ch34x *ch34x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout); +int usbh_ch34x_bulk_out_transfer(struct usbh_ch34x *ch34x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout); + +void usbh_ch34x_run(struct usbh_ch34x *ch34x_class); +void usbh_ch34x_stop(struct usbh_ch34x *ch34x_class); + +#ifdef __cplusplus +} +#endif + +#endif /* USBH_CH34X_H */ diff --git a/class/vendor/serial/usbh_cp210x.c b/class/vendor/serial/usbh_cp210x.c new file mode 100644 index 00000000..7dc45e64 --- /dev/null +++ b/class/vendor/serial/usbh_cp210x.c @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2024, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "usbh_core.h" +#include "usbh_cp210x.h" + +#define DEV_FORMAT "/dev/ttyUSB%d" + +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cp210x_buf[64]; + +#define CONFIG_USBHOST_MAX_CP210X_CLASS 4 + +static struct usbh_cp210x g_cp210x_class[CONFIG_USBHOST_MAX_CP210X_CLASS]; +static uint32_t g_devinuse = 0; + +static struct usbh_cp210x *usbh_cp210x_class_alloc(void) +{ + int devno; + + for (devno = 0; devno < CONFIG_USBHOST_MAX_CP210X_CLASS; devno++) { + if ((g_devinuse & (1 << devno)) == 0) { + g_devinuse |= (1 << devno); + memset(&g_cp210x_class[devno], 0, sizeof(struct usbh_cp210x)); + g_cp210x_class[devno].minor = devno; + return &g_cp210x_class[devno]; + } + } + return NULL; +} + +static void usbh_cp210x_class_free(struct usbh_cp210x *cp210x_class) +{ + int devno = cp210x_class->minor; + + if (devno >= 0 && devno < 32) { + g_devinuse &= ~(1 << devno); + } + memset(cp210x_class, 0, sizeof(struct usbh_cp210x)); +} + +static int usbh_cp210x_enable(struct usbh_cp210x *cp210x_class) +{ + struct usb_setup_packet *setup = cp210x_class->hport->setup; + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE; + setup->bRequest = CP210X_IFC_ENABLE; + setup->wValue = 1; + setup->wIndex = cp210x_class->intf; + setup->wLength = 0; + + return usbh_control_transfer(cp210x_class->hport, setup, NULL); +} + +static int usbh_cp210x_set_flow(struct usbh_cp210x *cp210x_class) +{ + struct usb_setup_packet *setup = cp210x_class->hport->setup; + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE; + setup->bRequest = CP210X_SET_FLOW; + setup->wValue = 0; + setup->wIndex = cp210x_class->intf; + setup->wLength = 16; + + memset(g_cp210x_buf, 0, 16); + g_cp210x_buf[13] = 0x20; + return usbh_control_transfer(cp210x_class->hport, setup, g_cp210x_buf); +} + +static int usbh_cp210x_set_chars(struct usbh_cp210x *cp210x_class) +{ + struct usb_setup_packet *setup = cp210x_class->hport->setup; + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE; + setup->bRequest = CP210X_SET_CHARS; + setup->wValue = 0; + setup->wIndex = cp210x_class->intf; + setup->wLength = 6; + + memset(g_cp210x_buf, 0, 6); + g_cp210x_buf[0] = 0x80; + g_cp210x_buf[4] = 0x88; + g_cp210x_buf[5] = 0x28; + return usbh_control_transfer(cp210x_class->hport, setup, g_cp210x_buf); +} + +static int usbh_cp210x_set_baudrate(struct usbh_cp210x *cp210x_class, uint32_t baudrate) +{ + struct usb_setup_packet *setup = cp210x_class->hport->setup; + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE; + setup->bRequest = CP210X_SET_BAUDRATE; + setup->wValue = 0; + setup->wIndex = cp210x_class->intf; + setup->wLength = 4; + + memcpy(g_cp210x_buf, (uint8_t *)&baudrate, 4); + return usbh_control_transfer(cp210x_class->hport, setup, g_cp210x_buf); +} + +static int usbh_cp210x_set_data_format(struct usbh_cp210x *cp210x_class, uint8_t databits, uint8_t parity, uint8_t stopbits) +{ + struct usb_setup_packet *setup = cp210x_class->hport->setup; + uint16_t value; + + value = ((databits & 0x0F) << 8) | ((parity & 0x0f) << 4) | ((stopbits & 0x03) << 0); + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE; + setup->bRequest = CP210X_SET_LINE_CTL; + setup->wValue = value; + setup->wIndex = cp210x_class->intf; + setup->wLength = 0; + + return usbh_control_transfer(cp210x_class->hport, setup, NULL); +} + +static int usbh_cp210x_set_mhs(struct usbh_cp210x *cp210x_class, uint8_t dtr, uint8_t rts, uint8_t dtr_mask, uint8_t rts_mask) +{ + struct usb_setup_packet *setup = cp210x_class->hport->setup; + uint16_t value; + + value = ((dtr & 0x01) << 0) | ((rts & 0x01) << 1) | ((dtr_mask & 0x01) << 8) | ((rts_mask & 0x01) << 9); + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE; + setup->bRequest = CP210X_SET_MHS; + setup->wValue = value; + setup->wIndex = cp210x_class->intf; + setup->wLength = 0; + + return usbh_control_transfer(cp210x_class->hport, setup, NULL); +} + +int usbh_cp210x_set_line_coding(struct usbh_cp210x *cp210x_class, struct cdc_line_coding *line_coding) +{ + memcpy((uint8_t *)&cp210x_class->line_coding, line_coding, sizeof(struct cdc_line_coding)); + usbh_cp210x_set_baudrate(cp210x_class, line_coding->dwDTERate); + return usbh_cp210x_set_data_format(cp210x_class, line_coding->bDataBits, line_coding->bParityType, line_coding->bCharFormat); +} + +int usbh_cp210x_get_line_coding(struct usbh_cp210x *cp210x_class, struct cdc_line_coding *line_coding) +{ + memcpy(line_coding, (uint8_t *)&cp210x_class->line_coding, sizeof(struct cdc_line_coding)); + return 0; +} + +int usbh_cp210x_set_line_state(struct usbh_cp210x *cp210x_class, bool dtr, bool rts) +{ + return usbh_cp210x_set_mhs(cp210x_class, dtr, rts, 1, 1); +} + +static int usbh_cp210x_connect(struct usbh_hubport *hport, uint8_t intf) +{ + struct usb_endpoint_descriptor *ep_desc; + int ret = 0; + + struct usbh_cp210x *cp210x_class = usbh_cp210x_class_alloc(); + if (cp210x_class == NULL) { + USB_LOG_ERR("Fail to alloc cp210x_class\r\n"); + return -USB_ERR_NOMEM; + } + + cp210x_class->hport = hport; + cp210x_class->intf = intf; + + hport->config.intf[intf].priv = cp210x_class; + + usbh_cp210x_enable(cp210x_class); + usbh_cp210x_set_flow(cp210x_class); + usbh_cp210x_set_chars(cp210x_class); + + for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) { + ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc; + + if (ep_desc->bEndpointAddress & 0x80) { + USBH_EP_INIT(cp210x_class->bulkin, ep_desc); + } else { + USBH_EP_INIT(cp210x_class->bulkout, ep_desc); + } + } + + snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, cp210x_class->minor); + + USB_LOG_INFO("Register CP210X Class:%s\r\n", hport->config.intf[intf].devname); + +#if 0 + USB_LOG_INFO("Test cp2102 rx and tx and rx for 5 times, baudrate is 115200\r\n"); + + struct cdc_line_coding linecoding; + uint8_t count = 5; + + linecoding.dwDTERate = 115200; + linecoding.bDataBits = 8; + linecoding.bParityType = 0; + linecoding.bCharFormat = 0; + usbh_cp210x_set_line_coding(cp210x_class, &linecoding); + usbh_cp210x_set_line_state(cp210x_class, true, false); + + memset(g_cp210x_buf, 'a', sizeof(g_cp210x_buf)); + ret = usbh_cp210x_bulk_out_transfer(cp210x_class, g_cp210x_buf, sizeof(g_cp210x_buf), 0xfffffff); + USB_LOG_RAW("out ret:%d\r\n", ret); + while (count--) { + ret = usbh_cp210x_bulk_in_transfer(cp210x_class, g_cp210x_buf, sizeof(g_cp210x_buf), 0xfffffff); + USB_LOG_RAW("in ret:%d\r\n", ret); + if (ret > 0) { + for (uint32_t i = 0; i < ret; i++) { + USB_LOG_RAW("%02x ", g_cp210x_buf[i]); + } + USB_LOG_RAW("\r\n"); + } + } +#endif + usbh_cp210x_run(cp210x_class); + return ret; +} + +static int usbh_cp210x_disconnect(struct usbh_hubport *hport, uint8_t intf) +{ + int ret = 0; + + struct usbh_cp210x *cp210x_class = (struct usbh_cp210x *)hport->config.intf[intf].priv; + + if (cp210x_class) { + if (cp210x_class->bulkin) { + usbh_kill_urb(&cp210x_class->bulkin_urb); + } + + if (cp210x_class->bulkout) { + usbh_kill_urb(&cp210x_class->bulkout_urb); + } + + if (hport->config.intf[intf].devname[0] != '\0') { + USB_LOG_INFO("Unregister CP210X Class:%s\r\n", hport->config.intf[intf].devname); + usbh_cp210x_stop(cp210x_class); + } + + usbh_cp210x_class_free(cp210x_class); + } + + return ret; +} + +int usbh_cp210x_bulk_in_transfer(struct usbh_cp210x *cp210x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout) +{ + int ret; + struct usbh_urb *urb = &cp210x_class->bulkin_urb; + + usbh_bulk_urb_fill(urb, cp210x_class->hport, cp210x_class->bulkin, buffer, buflen, timeout, NULL, NULL); + ret = usbh_submit_urb(urb); + if (ret == 0) { + ret = urb->actual_length; + } + return ret; +} + +int usbh_cp210x_bulk_out_transfer(struct usbh_cp210x *cp210x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout) +{ + int ret; + struct usbh_urb *urb = &cp210x_class->bulkout_urb; + + usbh_bulk_urb_fill(urb, cp210x_class->hport, cp210x_class->bulkout, buffer, buflen, timeout, NULL, NULL); + ret = usbh_submit_urb(urb); + if (ret == 0) { + ret = urb->actual_length; + } + return ret; +} + +__WEAK void usbh_cp210x_run(struct usbh_cp210x *cp210x_class) +{ +} + +__WEAK void usbh_cp210x_stop(struct usbh_cp210x *cp210x_class) +{ +} + +const struct usbh_class_driver cp210x_class_driver = { + .driver_name = "cp210x", + .connect = usbh_cp210x_connect, + .disconnect = usbh_cp210x_disconnect +}; + +CLASS_INFO_DEFINE const struct usbh_class_info cp210x_class_info = { + .match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS, + .class = 0xff, + .subclass = 0xff, + .protocol = 0xff, + .vid = 0x10C4, + .pid = 0xEA60, + .class_driver = &cp210x_class_driver +}; \ No newline at end of file diff --git a/class/vendor/serial/usbh_cp210x.h b/class/vendor/serial/usbh_cp210x.h new file mode 100644 index 00000000..597328ec --- /dev/null +++ b/class/vendor/serial/usbh_cp210x.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2024, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef USBH_CP210X_H +#define USBH_CP210X_H + +#include "usb_cdc.h" + +/* Requests */ +#define CP210X_IFC_ENABLE 0x00 +#define CP210X_SET_BAUDDIV 0x01 +#define CP210X_GET_BAUDDIV 0x02 +#define CP210X_SET_LINE_CTL 0x03 // Set parity, data bits, stop bits +#define CP210X_GET_LINE_CTL 0x04 +#define CP210X_SET_BREAK 0x05 +#define CP210X_IMM_CHAR 0x06 +#define CP210X_SET_MHS 0x07 // Set DTR, RTS +#define CP210X_GET_MDMSTS 0x08 +#define CP210X_SET_XON 0x09 +#define CP210X_SET_XOFF 0x0A +#define CP210X_SET_EVENTMASK 0x0B +#define CP210X_GET_EVENTMASK 0x0C +#define CP210X_SET_CHAR 0x0D +#define CP210X_GET_CHARS 0x0E +#define CP210X_GET_PROPS 0x0F +#define CP210X_GET_COMM_STATUS 0x10 +#define CP210X_RESET 0x11 +#define CP210X_PURGE 0x12 +#define CP210X_SET_FLOW 0x13 +#define CP210X_GET_FLOW 0x14 +#define CP210X_EMBED_EVENTS 0x15 +#define CP210X_GET_EVENTSTATE 0x16 +#define CP210X_SET_CHARS 0x19 +#define CP210X_GET_BAUDRATE 0x1D +#define CP210X_SET_BAUDRATE 0x1E // Set baudrate +#define CP210X_VENDOR_SPECIFIC 0xFF + +struct usbh_cp210x { + struct usbh_hubport *hport; + struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */ + struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */ + struct usbh_urb bulkout_urb; + struct usbh_urb bulkin_urb; + + struct cdc_line_coding line_coding; + + uint8_t intf; + uint8_t minor; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +int usbh_cp210x_set_line_coding(struct usbh_cp210x *ftdi_class, struct cdc_line_coding *line_coding); +int usbh_cp210x_get_line_coding(struct usbh_cp210x *ftdi_class, struct cdc_line_coding *line_coding); +int usbh_cp210x_set_line_state(struct usbh_cp210x *ftdi_class, bool dtr, bool rts); + +int usbh_cp210x_bulk_in_transfer(struct usbh_cp210x *cp210x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout); +int usbh_cp210x_bulk_out_transfer(struct usbh_cp210x *cp210x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout); + +void usbh_cp210x_run(struct usbh_cp210x *cp210x_class); +void usbh_cp210x_stop(struct usbh_cp210x *cp210x_class); + +#ifdef __cplusplus +} +#endif + +#endif /* USBH_CP210X_H */ diff --git a/class/vendor/serial/usbh_ftdi.c b/class/vendor/serial/usbh_ftdi.c new file mode 100644 index 00000000..48d1c1bd --- /dev/null +++ b/class/vendor/serial/usbh_ftdi.c @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2024, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "usbh_core.h" +#include "usbh_ftdi.h" + +#define DEV_FORMAT "/dev/ttyUSB%d" + +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_ftdi_buf[64]; + +#define CONFIG_USBHOST_MAX_FTDI_CLASS 4 + +static struct usbh_ftdi g_ftdi_class[CONFIG_USBHOST_MAX_FTDI_CLASS]; +static uint32_t g_devinuse = 0; + +static struct usbh_ftdi *usbh_ftdi_class_alloc(void) +{ + int devno; + + for (devno = 0; devno < CONFIG_USBHOST_MAX_FTDI_CLASS; devno++) { + if ((g_devinuse & (1 << devno)) == 0) { + g_devinuse |= (1 << devno); + memset(&g_ftdi_class[devno], 0, sizeof(struct usbh_ftdi)); + g_ftdi_class[devno].minor = devno; + return &g_ftdi_class[devno]; + } + } + return NULL; +} + +static void usbh_ftdi_class_free(struct usbh_ftdi *ftdi_class) +{ + int devno = ftdi_class->minor; + + if (devno >= 0 && devno < 32) { + g_devinuse &= ~(1 << devno); + } + memset(ftdi_class, 0, sizeof(struct usbh_ftdi)); +} + +static void usbh_ftdi_caculate_baudrate(uint32_t *itdf_divisor, uint32_t actual_baudrate) +{ +#define FTDI_USB_CLK 48000000 + int baudrate; + uint8_t frac[] = { 0, 8, 4, 2, 6, 10, 12, 14 }; + + if (actual_baudrate == 2000000) { + *itdf_divisor = 0x01; + } else if (actual_baudrate == 3000000) { + *itdf_divisor = 0x00; + } else { + baudrate = actual_baudrate; + if (baudrate > 100000 && baudrate < 12000000) { + baudrate = (baudrate / 100000) + 100000; + } + int divisor = FTDI_USB_CLK / baudrate; + int frac_bits = 0; + for (int i = 0; i < sizeof(frac) / sizeof(frac[0]); i++) { + if ((divisor & 0xF) == frac[i]) { + frac_bits = i; + break; + } + } + divisor >>= 4; + divisor &= 0x3FFF; + *itdf_divisor = (divisor << 14) | (frac_bits << 8); + } +} + +int usbh_ftdi_reset(struct usbh_ftdi *ftdi_class) +{ + struct usb_setup_packet *setup = ftdi_class->hport->setup; + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = SIO_RESET_REQUEST; + setup->wValue = 0; + setup->wIndex = ftdi_class->intf; + setup->wLength = 0; + + return usbh_control_transfer(ftdi_class->hport, setup, NULL); +} + +static int usbh_ftdi_set_modem(struct usbh_ftdi *ftdi_class, uint16_t value) +{ + struct usb_setup_packet *setup = ftdi_class->hport->setup; + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = SIO_SET_MODEM_CTRL_REQUEST; + setup->wValue = value; + setup->wIndex = ftdi_class->intf; + setup->wLength = 0; + + return usbh_control_transfer(ftdi_class->hport, setup, NULL); +} + +static int usbh_ftdi_set_baudrate(struct usbh_ftdi *ftdi_class, uint32_t baudrate) +{ + struct usb_setup_packet *setup = ftdi_class->hport->setup; + uint32_t itdf_divisor; + uint16_t value; + uint8_t baudrate_high; + + usbh_ftdi_caculate_baudrate(&itdf_divisor, baudrate); + value = itdf_divisor & 0xFFFF; + baudrate_high = (itdf_divisor >> 16) & 0xff; + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = SIO_SET_BAUDRATE_REQUEST; + setup->wValue = value; + setup->wIndex = (baudrate_high << 8) | ftdi_class->intf; + setup->wLength = 0; + + return usbh_control_transfer(ftdi_class->hport, setup, NULL); +} + +static int usbh_ftdi_set_data_format(struct usbh_ftdi *ftdi_class, uint8_t databits, uint8_t parity, uint8_t stopbits, uint8_t isbreak) +{ + /** + * D0-D7 databits BITS_7=7, BITS_8=8 + * D8-D10 parity NONE=0, ODD=1, EVEN=2, MARK=3, SPACE=4 + * D11-D12 STOP_BIT_1=0, STOP_BIT_15=1, STOP_BIT_2=2 + * D14 BREAK_OFF=0, BREAK_ON=1 + **/ + + uint16_t value = ((isbreak & 0x01) << 14) | ((stopbits & 0x03) << 11) | ((parity & 0x0f) << 8) | (databits & 0x0f); + + struct usb_setup_packet *setup = ftdi_class->hport->setup; + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = SIO_SET_DATA_REQUEST; + setup->wValue = value; + setup->wIndex = ftdi_class->intf; + setup->wLength = 0; + + return usbh_control_transfer(ftdi_class->hport, setup, NULL); +} + +static int usbh_ftdi_set_latency_timer(struct usbh_ftdi *ftdi_class, uint16_t value) +{ + struct usb_setup_packet *setup = ftdi_class->hport->setup; + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = SIO_SET_LATENCY_TIMER_REQUEST; + setup->wValue = value; + setup->wIndex = ftdi_class->intf; + setup->wLength = 0; + + return usbh_control_transfer(ftdi_class->hport, setup, NULL); +} + +static int usbh_ftdi_set_flow_ctrl(struct usbh_ftdi *ftdi_class, uint16_t value) +{ + struct usb_setup_packet *setup = ftdi_class->hport->setup; + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = SIO_SET_FLOW_CTRL_REQUEST; + setup->wValue = value; + setup->wIndex = ftdi_class->intf; + setup->wLength = 0; + + return usbh_control_transfer(ftdi_class->hport, setup, NULL); +} + +static int usbh_ftdi_read_modem_status(struct usbh_ftdi *ftdi_class) +{ + struct usb_setup_packet *setup = ftdi_class->hport->setup; + int ret; + + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = SIO_POLL_MODEM_STATUS_REQUEST; + setup->wValue = 0x0000; + setup->wIndex = ftdi_class->intf; + setup->wLength = 2; + + ret = usbh_control_transfer(ftdi_class->hport, setup, g_ftdi_buf); + if (ret < 0) { + return ret; + } + memcpy(ftdi_class->modem_status, g_ftdi_buf, 2); + return ret; +} + +int usbh_ftdi_set_line_coding(struct usbh_ftdi *ftdi_class, struct cdc_line_coding *line_coding) +{ + memcpy((uint8_t *)&ftdi_class->line_coding, line_coding, sizeof(struct cdc_line_coding)); + usbh_ftdi_set_baudrate(ftdi_class, line_coding->dwDTERate); + return usbh_ftdi_set_data_format(ftdi_class, line_coding->bDataBits, line_coding->bParityType, line_coding->bCharFormat, 0); +} + +int usbh_ftdi_get_line_coding(struct usbh_ftdi *ftdi_class, struct cdc_line_coding *line_coding) +{ + memcpy(line_coding, (uint8_t *)&ftdi_class->line_coding, sizeof(struct cdc_line_coding)); + return 0; +} + +int usbh_ftdi_set_line_state(struct usbh_ftdi *ftdi_class, bool dtr, bool rts) +{ + int ret; + + if (dtr) { + usbh_ftdi_set_modem(ftdi_class, SIO_SET_DTR_HIGH); + } else { + usbh_ftdi_set_modem(ftdi_class, SIO_SET_DTR_LOW); + } + + if (rts) { + ret = usbh_ftdi_set_modem(ftdi_class, SIO_SET_RTS_HIGH); + } else { + ret = usbh_ftdi_set_modem(ftdi_class, SIO_SET_RTS_LOW); + } + + return ret; +} + +static int usbh_ftdi_connect(struct usbh_hubport *hport, uint8_t intf) +{ + struct usb_endpoint_descriptor *ep_desc; + int ret = 0; + + struct usbh_ftdi *ftdi_class = usbh_ftdi_class_alloc(); + if (ftdi_class == NULL) { + USB_LOG_ERR("Fail to alloc ftdi_class\r\n"); + return -USB_ERR_NOMEM; + } + + ftdi_class->hport = hport; + ftdi_class->intf = intf; + + hport->config.intf[intf].priv = ftdi_class; + + usbh_ftdi_reset(ftdi_class); + usbh_ftdi_set_flow_ctrl(ftdi_class, SIO_DISABLE_FLOW_CTRL); + usbh_ftdi_set_latency_timer(ftdi_class, 0x10); + usbh_ftdi_read_modem_status(ftdi_class); + USB_LOG_INFO("modem status:%02x:%02x\r\n", ftdi_class->modem_status[0], ftdi_class->modem_status[1]); + + for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) { + ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc; + + if (ep_desc->bEndpointAddress & 0x80) { + USBH_EP_INIT(ftdi_class->bulkin, ep_desc); + } else { + USBH_EP_INIT(ftdi_class->bulkout, ep_desc); + } + } + + snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, ftdi_class->minor); + + USB_LOG_INFO("Register FTDI Class:%s\r\n", hport->config.intf[intf].devname); + +#if 0 + USB_LOG_INFO("Test ftdi rx and tx and rx for 5 times, baudrate is 115200\r\n"); + + struct cdc_line_coding linecoding; + uint8_t count = 5; + + linecoding.dwDTERate = 115200; + linecoding.bDataBits = 8; + linecoding.bParityType = 0; + linecoding.bCharFormat = 0; + usbh_ftdi_set_line_coding(ftdi_class, &linecoding); + usbh_ftdi_set_line_state(ftdi_class, true, false); + + memset(g_ftdi_buf, 'a', sizeof(g_ftdi_buf)); + ret = usbh_ftdi_bulk_out_transfer(ftdi_class, g_ftdi_buf, sizeof(g_ftdi_buf), 0xfffffff); + USB_LOG_RAW("out ret:%d\r\n", ret); + while (count--) { + ret = usbh_ftdi_bulk_in_transfer(ftdi_class, g_ftdi_buf, sizeof(g_ftdi_buf), 0xfffffff); + USB_LOG_RAW("in ret:%d\r\n", ret); + if (ret > 0) { + for (uint32_t i = 0; i < ret; i++) { + USB_LOG_RAW("%02x ", g_ftdi_buf[i]); + } + } + USB_LOG_RAW("\r\n"); + } +#endif + usbh_ftdi_run(ftdi_class); + return ret; +} + +static int usbh_ftdi_disconnect(struct usbh_hubport *hport, uint8_t intf) +{ + int ret = 0; + + struct usbh_ftdi *ftdi_class = (struct usbh_ftdi *)hport->config.intf[intf].priv; + + if (ftdi_class) { + if (ftdi_class->bulkin) { + usbh_kill_urb(&ftdi_class->bulkin_urb); + } + + if (ftdi_class->bulkout) { + usbh_kill_urb(&ftdi_class->bulkout_urb); + } + + if (hport->config.intf[intf].devname[0] != '\0') { + USB_LOG_INFO("Unregister FTDI Class:%s\r\n", hport->config.intf[intf].devname); + usbh_ftdi_stop(ftdi_class); + } + + usbh_ftdi_class_free(ftdi_class); + } + + return ret; +} + +int usbh_ftdi_bulk_in_transfer(struct usbh_ftdi *ftdi_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout) +{ + int ret; + struct usbh_urb *urb = &ftdi_class->bulkin_urb; + + usbh_bulk_urb_fill(urb, ftdi_class->hport, ftdi_class->bulkin, buffer, buflen, timeout, NULL, NULL); + ret = usbh_submit_urb(urb); + if (ret == 0) { + ret = urb->actual_length; + } + return ret; +} + +int usbh_ftdi_bulk_out_transfer(struct usbh_ftdi *ftdi_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout) +{ + int ret; + struct usbh_urb *urb = &ftdi_class->bulkout_urb; + + usbh_bulk_urb_fill(urb, ftdi_class->hport, ftdi_class->bulkout, buffer, buflen, timeout, NULL, NULL); + ret = usbh_submit_urb(urb); + if (ret == 0) { + ret = urb->actual_length; + } + return ret; +} + +__WEAK void usbh_ftdi_run(struct usbh_ftdi *ftdi_class) +{ +} + +__WEAK void usbh_ftdi_stop(struct usbh_ftdi *ftdi_class) +{ +} + +const struct usbh_class_driver ftdi_class_driver = { + .driver_name = "ftdi", + .connect = usbh_ftdi_connect, + .disconnect = usbh_ftdi_disconnect +}; + +CLASS_INFO_DEFINE const struct usbh_class_info ftdi1_class_info = { + .match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS, + .class = 0xff, + .subclass = 0xff, + .protocol = 0xff, + .vid = 0x0403, + .pid = 0x6001, + .class_driver = &ftdi_class_driver +}; + +CLASS_INFO_DEFINE const struct usbh_class_info ftdi2_class_info = { + .match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS, + .class = 0xff, + .subclass = 0xff, + .protocol = 0xff, + .vid = 0x0403, + .pid = 0x6010, + .class_driver = &ftdi_class_driver +}; \ No newline at end of file diff --git a/class/vendor/serial/usbh_ftdi.h b/class/vendor/serial/usbh_ftdi.h new file mode 100644 index 00000000..300ee6ab --- /dev/null +++ b/class/vendor/serial/usbh_ftdi.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2024, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef USBH_FTDI_H +#define USBH_FTDI_H + +#include "usb_cdc.h" + +/* Requests */ +#define SIO_RESET_REQUEST 0x00 /* Reset the port */ +#define SIO_SET_MODEM_CTRL_REQUEST 0x01 /* Set the modem control register */ +#define SIO_SET_FLOW_CTRL_REQUEST 0x02 /* Set flow control register */ +#define SIO_SET_BAUDRATE_REQUEST 0x03 /* Set baud rate */ +#define SIO_SET_DATA_REQUEST 0x04 /* Set the data characteristics of the port */ +#define SIO_POLL_MODEM_STATUS_REQUEST 0x05 +#define SIO_SET_EVENT_CHAR_REQUEST 0x06 +#define SIO_SET_ERROR_CHAR_REQUEST 0x07 +#define SIO_SET_LATENCY_TIMER_REQUEST 0x09 +#define SIO_GET_LATENCY_TIMER_REQUEST 0x0A +#define SIO_SET_BITMODE_REQUEST 0x0B +#define SIO_READ_PINS_REQUEST 0x0C +#define SIO_READ_EEPROM_REQUEST 0x90 +#define SIO_WRITE_EEPROM_REQUEST 0x91 +#define SIO_ERASE_EEPROM_REQUEST 0x92 + +#define SIO_DISABLE_FLOW_CTRL 0x0 +#define SIO_RTS_CTS_HS (0x1 << 8) +#define SIO_DTR_DSR_HS (0x2 << 8) +#define SIO_XON_XOFF_HS (0x4 << 8) + +#define SIO_SET_DTR_MASK 0x1 +#define SIO_SET_DTR_HIGH (1 | (SIO_SET_DTR_MASK << 8)) +#define SIO_SET_DTR_LOW (0 | (SIO_SET_DTR_MASK << 8)) +#define SIO_SET_RTS_MASK 0x2 +#define SIO_SET_RTS_HIGH (2 | (SIO_SET_RTS_MASK << 8)) +#define SIO_SET_RTS_LOW (0 | (SIO_SET_RTS_MASK << 8)) + +#define SIO_RTS_CTS_HS (0x1 << 8) + +struct usbh_ftdi { + struct usbh_hubport *hport; + struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */ + struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */ + struct usbh_urb bulkout_urb; + struct usbh_urb bulkin_urb; + + struct cdc_line_coding line_coding; + + uint8_t intf; + uint8_t minor; + uint8_t modem_status[2]; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +int usbh_ftdi_set_line_coding(struct usbh_ftdi *ftdi_class, struct cdc_line_coding *line_coding); +int usbh_ftdi_get_line_coding(struct usbh_ftdi *ftdi_class, struct cdc_line_coding *line_coding); +int usbh_ftdi_set_line_state(struct usbh_ftdi *ftdi_class, bool dtr, bool rts); + +int usbh_ftdi_bulk_in_transfer(struct usbh_ftdi *ftdi_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout); +int usbh_ftdi_bulk_out_transfer(struct usbh_ftdi *ftdi_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout); + +void usbh_ftdi_run(struct usbh_ftdi *ftdi_class); +void usbh_ftdi_stop(struct usbh_ftdi *ftdi_class); + +#ifdef __cplusplus +} +#endif + +#endif /* USBH_FTDI_H */ diff --git a/class/vendor/usbh_asix.c b/class/vendor/usbh_asix.c deleted file mode 100644 index d6c017bb..00000000 --- a/class/vendor/usbh_asix.c +++ /dev/null @@ -1,797 +0,0 @@ -/* - * Copyright (c) 2024, sakumisu - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "usbh_core.h" -#include "usbh_asix.h" -#include "usb_cdc.h" - -#undef USB_DBG_TAG -#define USB_DBG_TAG "asix" -#include "usb_log.h" - -#define DEV_FORMAT "/dev/asix" - -static struct usbh_asix g_asix_class; -#define CONFIG_USBHOST_ASIX_ETH_MAX_SEGSZE (1514U + 8) - -static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_rx_buffer[CONFIG_USBHOST_ASIX_ETH_MAX_SEGSZE]; -static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_tx_buffer[CONFIG_USBHOST_ASIX_ETH_MAX_SEGSZE]; -static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_inttx_buffer[16]; -USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_buf[32]; - -#define ETH_ALEN 6 - -#define PHY_MODE_MARVELL 0x0000 -#define MII_MARVELL_LED_CTRL 0x0018 -#define MII_MARVELL_STATUS 0x001b -#define MII_MARVELL_CTRL 0x0014 - -#define MARVELL_LED_MANUAL 0x0019 - -#define MARVELL_STATUS_HWCFG 0x0004 - -#define MARVELL_CTRL_TXDELAY 0x0002 -#define MARVELL_CTRL_RXDELAY 0x0080 - -#define PHY_MODE_RTL8211CL 0x000C - -#define AX88772A_PHY14H 0x14 -#define AX88772A_PHY14H_DEFAULT 0x442C - -#define AX88772A_PHY15H 0x15 -#define AX88772A_PHY15H_DEFAULT 0x03C8 - -#define AX88772A_PHY16H 0x16 -#define AX88772A_PHY16H_DEFAULT 0x4044 - -#define SPEED_100 0 -#define SPEED_10 1 - -static int usbh_asix_read_cmd(struct usbh_asix *asix_class, - uint8_t cmd, - uint16_t value, - uint16_t index, - void *data, - uint16_t size) -{ - struct usb_setup_packet *setup = asix_class->hport->setup; - int ret; - - setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; - setup->bRequest = cmd; - setup->wValue = value; - setup->wIndex = index; - setup->wLength = size; - - ret = usbh_control_transfer(asix_class->hport, setup, g_asix_buf); - if (ret < 0) { - return ret; - } - memcpy(data, g_asix_buf, ret - 8); - - return ret; -} - -static int usbh_asix_write_cmd(struct usbh_asix *asix_class, - uint8_t cmd, - uint16_t value, - uint16_t index, - void *data, - uint16_t size) -{ - struct usb_setup_packet *setup = asix_class->hport->setup; - - setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; - setup->bRequest = cmd; - setup->wValue = value; - setup->wIndex = index; - setup->wLength = size; - - memcpy(g_asix_buf, data, size); - - return usbh_control_transfer(asix_class->hport, setup, g_asix_buf); -} - -static int usbh_asix_mdio_write(struct usbh_asix *asix_class, int phy_id, int loc, int val) -{ - uint8_t smsr; - uint16_t res = (uint16_t)val; - int ret; - - for (uint8_t i = 0; i < 10; i++) { - ret = usbh_asix_write_cmd(asix_class, AX_CMD_SET_SW_MII, 0, 0, NULL, 0); - if (ret < 0) { - return ret; - } - usb_osal_msleep(1); - ret = usbh_asix_read_cmd(asix_class, AX_CMD_STATMNGSTS_REG, 0, 0, &smsr, 1); - if (ret < 0) { - return ret; - } - - if (smsr & AX_HOST_EN) { - break; - } - } - - ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_MII_REG, phy_id, loc, &res, 2); - if (ret < 0) { - return ret; - } - - ret = usbh_asix_write_cmd(asix_class, AX_CMD_SET_HW_MII, 0, 0, NULL, 0); - if (ret < 0) { - return ret; - } - return 0; -} - -static int usbh_asix_mdio_read(struct usbh_asix *asix_class, int phy_id, int loc) -{ - uint8_t smsr; - uint16_t res; - int ret; - - for (uint8_t i = 0; i < 10; i++) { - ret = usbh_asix_write_cmd(asix_class, AX_CMD_SET_SW_MII, 0, 0, NULL, 0); - if (ret < 0) { - return ret; - } - usb_osal_msleep(1); - ret = usbh_asix_read_cmd(asix_class, AX_CMD_STATMNGSTS_REG, 0, 0, &smsr, 1); - if (ret < 0) { - return ret; - } - - if (smsr & AX_HOST_EN) { - break; - } - } - - ret = usbh_asix_read_cmd(asix_class, AX_CMD_READ_MII_REG, phy_id, loc, &res, 2); - if (ret < 0) { - return ret; - } - - ret = usbh_asix_write_cmd(asix_class, AX_CMD_SET_HW_MII, 0, 0, NULL, 0); - if (ret < 0) { - return ret; - } - return res; -} - -static int usbh_asix_read_phy_addr(struct usbh_asix *asix_class, bool internal) -{ - int ret, offset; - uint8_t buf[2]; - - ret = usbh_asix_read_cmd(asix_class, AX_CMD_READ_PHY_ID, 0, 0, buf, 2); - if (ret < 0) { - return ret; - } - - offset = (internal ? 1 : 0); - ret = buf[offset]; - - USB_LOG_INFO("%s PHY address 0x%x\r\n", internal ? "internal" : "external", ret); - - return ret; -} - -static int usbh_asix_sw_reset(struct usbh_asix *asix_class, uint8_t flags) -{ - int ret; - - ret = usbh_asix_write_cmd(asix_class, AX_CMD_SW_RESET, flags, 0, NULL, 0); - if (ret < 0) - USB_LOG_ERR("Failed to send software reset: %d\r\n", ret); - - return ret; -} - -static uint16_t usbh_asix_read_rx_ctl(struct usbh_asix *asix_class) -{ - uint16_t v; - int ret = usbh_asix_read_cmd(asix_class, AX_CMD_READ_RX_CTL, 0, 0, &v, 2); - if (ret < 0) { - return ret; - } - return v; -} - -static int usbh_asix_write_rx_ctl(struct usbh_asix *asix_class, uint16_t mode) -{ - int ret; - - USB_LOG_DBG("asix_write_rx_ctl() - mode = 0x%04x\r\n", mode); - ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_RX_CTL, mode, 0, NULL, 0); - if (ret < 0) - USB_LOG_ERR("Failed to write RX_CTL mode to 0x%04x: %02x\r\n", - mode, ret); - - return ret; -} - -static uint16_t usbh_asix_read_medium_status(struct usbh_asix *asix_class) -{ - uint16_t v; - int ret = usbh_asix_read_cmd(asix_class, AX_CMD_READ_MEDIUM_STATUS, 0, 0, &v, 2); - - if (ret < 0) { - USB_LOG_ERR("Error reading Medium Status register: %02x\r\n", - ret); - return ret; /* TODO: callers not checking for error ret */ - } - - return v; -} - -static int usbh_asix_write_medium_mode(struct usbh_asix *asix_class, uint16_t mode) -{ - int ret; - - USB_LOG_DBG("asix_write_medium_mode() - mode = 0x%04x\r\n", mode); - ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, NULL, 0); - if (ret < 0) - USB_LOG_ERR("Failed to write Medium Mode mode to 0x%04x: %02x\r\n", - mode, ret); - - return ret; -} - -static int usbh_asix_write_gpio(struct usbh_asix *asix_class, uint16_t value, int sleep) -{ - int ret; - - USB_LOG_DBG("asix_write_gpio() - value = 0x%04x\r\n", value); - ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_GPIOS, value, 0, NULL, 0); - if (ret < 0) - USB_LOG_ERR("Failed to write GPIO value 0x%04x: %d\r\n", - value, ret); - - if (sleep) - usb_osal_msleep(sleep); - - return ret; -} - -/* - * AX88772 & AX88178 have a 16-bit RX_CTL value - */ -static void usbh_asix_set_multicast(struct usbh_asix *asix_class) -{ - uint16_t rx_ctl = AX_DEFAULT_RX_CTL | AX_RX_CTL_AM; - const uint8_t multi_filter[] = { 0x00, 0x00, 0x20, 0x80, 0x00, 0x00, 0x00, 0x40 }; - - usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_MULTI_FILTER, 0, 0, (uint8_t *)multi_filter, AX_MCAST_FILTER_SIZE); - usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, NULL, 0); -} - -static int usbh_ax88772_hw_reset(struct usbh_asix *asix_class) -{ - uint16_t rx_ctl; - int ret; - - ret = usbh_asix_write_gpio(asix_class, AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5); - if (ret < 0) - goto out; - - ret = usbh_asix_write_cmd(asix_class, AX_CMD_SW_PHY_SELECT, asix_class->embd_phy, - 0, NULL, 0); - if (ret < 0) { - USB_LOG_ERR("Select PHY #1 failed: %d\r\n", ret); - goto out; - } - - if (asix_class->embd_phy) { - ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_IPPD); - if (ret < 0) - goto out; - - usb_osal_msleep(10); - - ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_CLEAR); - if (ret < 0) - goto out; - - usb_osal_msleep(60); - - ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_IPRL | AX_SWRESET_PRL); - if (ret < 0) - goto out; - } else { - ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_IPPD | AX_SWRESET_PRL); - if (ret < 0) - goto out; - } - - usb_osal_msleep(150); - - ret = usbh_asix_write_rx_ctl(asix_class, AX_DEFAULT_RX_CTL); - if (ret < 0) - goto out; - - ret = usbh_asix_write_medium_mode(asix_class, AX88772_MEDIUM_DEFAULT); - if (ret < 0) - goto out; - - ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_IPG0, - AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT, - AX88772_IPG2_DEFAULT, NULL, 0); - if (ret < 0) { - USB_LOG_ERR("Write IPG,IPG1,IPG2 failed: %d\r\n", ret); - goto out; - } - - /* Rewrite MAC address */ - ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_NODE_ID, 0, 0, asix_class->mac, ETH_ALEN); - if (ret < 0) - goto out; - - /* Set RX_CTL to default values with 2k buffer, and enable cactus */ - ret = usbh_asix_write_rx_ctl(asix_class, AX_DEFAULT_RX_CTL); - if (ret < 0) - goto out; - - rx_ctl = usbh_asix_read_rx_ctl(asix_class); - USB_LOG_INFO("RX_CTL is 0x%04x after all initializations\r\n", - rx_ctl); - - rx_ctl = usbh_asix_read_medium_status(asix_class); - USB_LOG_INFO("Medium Status is 0x%04x after all initializations\r\n", - rx_ctl); - - return 0; - -out: - return ret; -} - -static int usbh_ax88772a_hw_reset(struct usbh_asix *asix_class) -{ - uint16_t rx_ctl, phy14h, phy15h, phy16h; - int ret; - - ret = usbh_asix_write_gpio(asix_class, AX_GPIO_RSE, 5); - if (ret < 0) - goto out; - - ret = usbh_asix_write_cmd(asix_class, AX_CMD_SW_PHY_SELECT, asix_class->embd_phy | AX_PHYSEL_SSEN, 0, 0, NULL); - if (ret < 0) { - USB_LOG_ERR("Select PHY #1 failed: %d\r\n", ret); - goto out; - } - usb_osal_msleep(10); - - ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_IPPD | AX_SWRESET_IPRL); - if (ret < 0) - goto out; - - usb_osal_msleep(10); - - ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_IPRL); - if (ret < 0) - goto out; - - usb_osal_msleep(160); - - ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_CLEAR); - if (ret < 0) - goto out; - - ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_IPRL); - if (ret < 0) - goto out; - - usb_osal_msleep(200); - - if (asix_class->chipcode == AX_AX88772B_CHIPCODE) { - ret = usbh_asix_write_cmd(asix_class, AX_QCTCTRL, 0x8000, 0x8001, NULL, 0); - if (ret < 0) { - USB_LOG_ERR("Write BQ setting failed: %d\r\n", ret); - goto out; - } - } else if (asix_class->chipcode == AX_AX88772A_CHIPCODE) { - /* Check if the PHY registers have default settings */ - phy14h = usbh_asix_mdio_read(asix_class, asix_class->phy_addr, - AX88772A_PHY14H); - phy15h = usbh_asix_mdio_read(asix_class, asix_class->phy_addr, - AX88772A_PHY15H); - phy16h = usbh_asix_mdio_read(asix_class, asix_class->phy_addr, - AX88772A_PHY16H); - - USB_LOG_DBG("772a_hw_reset: MR20=0x%x MR21=0x%x MR22=0x%x\r\n", - phy14h, phy15h, phy16h); - - /* Restore PHY registers default setting if not */ - if (phy14h != AX88772A_PHY14H_DEFAULT) - usbh_asix_mdio_write(asix_class, asix_class->phy_addr, - AX88772A_PHY14H, - AX88772A_PHY14H_DEFAULT); - if (phy15h != AX88772A_PHY15H_DEFAULT) - usbh_asix_mdio_write(asix_class, asix_class->phy_addr, - AX88772A_PHY15H, - AX88772A_PHY15H_DEFAULT); - if (phy16h != AX88772A_PHY16H_DEFAULT) - usbh_asix_mdio_write(asix_class, asix_class->phy_addr, - AX88772A_PHY16H, - AX88772A_PHY16H_DEFAULT); - } - - ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_IPG0, - AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT, - AX88772_IPG2_DEFAULT, 0, NULL); - if (ret < 0) { - USB_LOG_ERR("Write IPG,IPG1,IPG2 failed: %d\r\n", ret); - goto out; - } - - /* Rewrite MAC address */ - ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_NODE_ID, 0, 0, asix_class->mac, ETH_ALEN); - if (ret < 0) - goto out; - - /* Set RX_CTL to default values with 2k buffer, and enable cactus */ - ret = usbh_asix_write_rx_ctl(asix_class, AX_DEFAULT_RX_CTL); - if (ret < 0) - goto out; - - ret = usbh_asix_write_medium_mode(asix_class, AX88772_MEDIUM_DEFAULT); - if (ret < 0) - return ret; - - /* Set RX_CTL to default values with 2k buffer, and enable cactus */ - ret = usbh_asix_write_rx_ctl(asix_class, AX_DEFAULT_RX_CTL); - if (ret < 0) - goto out; - - rx_ctl = usbh_asix_read_rx_ctl(asix_class); - USB_LOG_INFO("RX_CTL is 0x%04x after all initializations\r\n", rx_ctl); - - rx_ctl = usbh_asix_read_medium_status(asix_class); - USB_LOG_INFO("Medium Status is 0x%04x after all initializations\r\n", rx_ctl); - - return 0; - -out: - return ret; -} - -static void usbh_ax88772_mac_link_down(struct usbh_asix *asix_class) -{ - usbh_asix_write_medium_mode(asix_class, 0); -} - -static void usbh_ax88772_mac_link_up(struct usbh_asix *asix_class, int speed, int duplex, bool tx_pause, bool rx_pause) -{ - uint16_t m = AX_MEDIUM_AC | AX_MEDIUM_RE; - - m |= duplex ? AX_MEDIUM_FD : 0; - - switch (speed) { - case SPEED_100: - m |= AX_MEDIUM_PS; - break; - case SPEED_10: - break; - default: - return; - } - - if (tx_pause) - m |= AX_MEDIUM_TFC; - - if (rx_pause) - m |= AX_MEDIUM_RFC; - - usbh_asix_write_medium_mode(asix_class, m); -} - -static int usbh_asix_connect(struct usbh_hubport *hport, uint8_t intf) -{ - struct usb_endpoint_descriptor *ep_desc; - int ret; - - struct usbh_asix *asix_class = &g_asix_class; - - memset(asix_class, 0, sizeof(struct usbh_asix)); - - asix_class->hport = hport; - asix_class->intf = intf; - - hport->config.intf[intf].priv = asix_class; - - if ((hport->device_desc.idVendor == 0x0b95) && (hport->device_desc.idProduct == 0x772b)) { - asix_class->name = "ASIX AX88772B"; - } else if ((hport->device_desc.idVendor == 0x0b95) && (hport->device_desc.idProduct == 0x7720)) { - asix_class->name = "ASIX AX88772"; - } else if ((hport->device_desc.idVendor == 0x0b95) && (hport->device_desc.idProduct == 0x1780)) { - asix_class->name = "ASIX AX88178"; - } - - for (uint8_t i = 0; i < (ETH_ALEN >> 1); i++) { - ret = usbh_asix_read_cmd(asix_class, AX_CMD_READ_EEPROM, - 0x04 + i, 0, &asix_class->mac[i * 2], 2); - if (ret < 0) { - return ret; - } - } - - USB_LOG_INFO("asix MAC address %02x:%02x:%02x:%02x:%02x:%02x\r\n", - asix_class->mac[0], - asix_class->mac[1], - asix_class->mac[2], - asix_class->mac[3], - asix_class->mac[4], - asix_class->mac[5]); - - ret = usbh_asix_read_phy_addr(asix_class, true); - if (ret < 0) { - USB_LOG_ERR("Failed to read phy addr: %d\r\n", ret); - return ret; - } - asix_class->phy_addr = ret; - asix_class->embd_phy = ((ret & 0x1f) == AX_EMBD_PHY_ADDR); - - ret = usbh_asix_read_cmd(asix_class, AX_CMD_STATMNGSTS_REG, 0, 0, &asix_class->chipcode, 1); - if (ret < 0) { - USB_LOG_ERR("Failed to read STATMNGSTS_REG: %d\r\n", ret); - return ret; - } - - asix_class->chipcode &= AX_CHIPCODE_MASK; - USB_LOG_INFO("asix chipcode 0x%x\r\n", asix_class->chipcode); - - if (asix_class->chipcode == AX_AX88772_CHIPCODE) { - usbh_ax88772_hw_reset(asix_class); - } else { - usbh_ax88772a_hw_reset(asix_class); - } - for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) { - ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc; - - if (USB_GET_ENDPOINT_TYPE(ep_desc->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) { - if (ep_desc->bEndpointAddress & 0x80) { - USBH_EP_INIT(asix_class->intin, ep_desc); - } else { - return -USB_ERR_NOTSUPP; - } - } else { - if (ep_desc->bEndpointAddress & 0x80) { - USBH_EP_INIT(asix_class->bulkin, ep_desc); - } else { - USBH_EP_INIT(asix_class->bulkout, ep_desc); - } - } - } - - if (asix_class->chipcode == AX_AX88772B_CHIPCODE) { - usbh_asix_mdio_write(asix_class, asix_class->phy_addr, 0, 0); - usbh_asix_mdio_read(asix_class, asix_class->phy_addr, 0); - - usbh_asix_mdio_write(asix_class, asix_class->phy_addr, 0, 0x8200); - usbh_asix_mdio_read(asix_class, asix_class->phy_addr, 0); - - usbh_asix_mdio_write(asix_class, asix_class->phy_addr, 0, 0x3900); - usbh_asix_mdio_read(asix_class, asix_class->phy_addr, 0); - - usbh_asix_mdio_write(asix_class, asix_class->phy_addr, 0, 0x3100); - usbh_asix_mdio_read(asix_class, asix_class->phy_addr, 4); - - usbh_asix_mdio_write(asix_class, asix_class->phy_addr, 4, 0x01e1); - usbh_asix_mdio_read(asix_class, asix_class->phy_addr, 1); - - usbh_asix_mdio_write(asix_class, asix_class->phy_addr, 0, 0x3300); - usbh_asix_mdio_read(asix_class, asix_class->phy_addr, 0); - } - - USB_LOG_INFO("Init %s done\r\n", asix_class->name); - - memcpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN); - - USB_LOG_INFO("Register ASIX Class:%s\r\n", hport->config.intf[intf].devname); - usbh_asix_run(asix_class); - return ret; -} - -static int usbh_asix_disconnect(struct usbh_hubport *hport, uint8_t intf) -{ - int ret = 0; - - struct usbh_asix *asix_class = (struct usbh_asix *)hport->config.intf[intf].priv; - - if (asix_class) { - if (asix_class->bulkin) { - usbh_kill_urb(&asix_class->bulkin_urb); - } - - if (asix_class->bulkout) { - usbh_kill_urb(&asix_class->bulkout_urb); - } - - if (asix_class->intin) { - usbh_kill_urb(&asix_class->intin_urb); - } - - if (hport->config.intf[intf].devname[0] != '\0') { - USB_LOG_INFO("Unregister ASIX Class:%s\r\n", hport->config.intf[intf].devname); - usbh_asix_stop(asix_class); - } - - memset(asix_class, 0, sizeof(struct usbh_asix)); - } - - return ret; -} - -int usbh_asix_get_connect_status(struct usbh_asix *asix_class) -{ - int ret; - - usbh_int_urb_fill(&asix_class->intin_urb, asix_class->hport, asix_class->intin, g_asix_inttx_buffer, 8, USB_OSAL_WAITING_FOREVER, NULL, NULL); - ret = usbh_submit_urb(&asix_class->intin_urb); - if (ret < 0) { - return ret; - } - - if (g_asix_inttx_buffer[1] == 0x00) { - if (g_asix_inttx_buffer[2] & 0x01) { - asix_class->connect_status = true; - usbh_ax88772_mac_link_up(asix_class, SPEED_100, 1, 1, 1); - usbh_asix_set_multicast(asix_class); - } else { - asix_class->connect_status = false; - usbh_ax88772_mac_link_down(asix_class); - } - } - return 0; -} - -void usbh_asix_rx_thread(void *argument) -{ - uint32_t g_asix_rx_length; - int ret; - err_t err; - uint16_t len; - uint16_t len_crc; - struct pbuf *p; - struct netif *netif = (struct netif *)argument; - - USB_LOG_INFO("Create asix rx thread\r\n"); - // clang-format off -find_class: - // clang-format on - g_asix_class.connect_status = false; - if (usbh_find_class_instance("/dev/asix") == NULL) { - goto delete; - } - - while (g_asix_class.connect_status == false) { - ret = usbh_asix_get_connect_status(&g_asix_class); - if (ret < 0) { - usb_osal_msleep(100); - goto find_class; - } - } - - g_asix_rx_length = 0; - while (1) { - usbh_bulk_urb_fill(&g_asix_class.bulkin_urb, g_asix_class.hport, g_asix_class.bulkin, &g_asix_rx_buffer[g_asix_rx_length], USB_GET_MAXPACKETSIZE(g_asix_class.bulkin->wMaxPacketSize), USB_OSAL_WAITING_FOREVER, NULL, NULL); - ret = usbh_submit_urb(&g_asix_class.bulkin_urb); - if (ret < 0) { - goto find_class; - } - - g_asix_rx_length += g_asix_class.bulkin_urb.actual_length; - - if (g_asix_rx_length % USB_GET_MAXPACKETSIZE(g_asix_class.bulkin->wMaxPacketSize)) { - len = ((uint16_t)g_asix_rx_buffer[0] | ((uint16_t)(g_asix_rx_buffer[1]) << 8)) & 0x7ff; - len_crc = g_asix_rx_buffer[2] | ((uint16_t)(g_asix_rx_buffer[3]) << 8); - - if (len != (~len_crc & 0x7ff)) { - USB_LOG_ERR("asix rx header error\r\n"); - continue; - } - - USB_LOG_DBG("rxlen:%d\r\n", g_asix_rx_length); - - p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); - if (p != NULL) { - memcpy(p->payload, (uint8_t *)&g_asix_rx_buffer[4], len); - g_asix_rx_length = 0; - - err = netif->input(p, netif); - if (err != ERR_OK) { - pbuf_free(p); - } - } else { - g_asix_rx_length = 0; - USB_LOG_ERR("No memory to alloc pbuf for asix rx\r\n"); - } - } else { - } - } - // clang-format off -delete: - USB_LOG_INFO("Delete asix rx thread\r\n"); - usb_osal_thread_delete(NULL); - // clang-format on -} - -err_t usbh_asix_linkoutput(struct netif *netif, struct pbuf *p) -{ - int ret; - struct pbuf *q; - uint16_t actual_len; - uint8_t *buffer = &g_asix_tx_buffer[4]; - - if (g_asix_class.connect_status == false) { - return ERR_BUF; - } - - for (q = p; q != NULL; q = q->next) { - memcpy(buffer, q->payload, q->len); - buffer += q->len; - } - - g_asix_tx_buffer[0] = p->tot_len & 0xff; - g_asix_tx_buffer[1] = (p->tot_len >> 8) & 0xff; - g_asix_tx_buffer[2] = ~g_asix_tx_buffer[0]; - g_asix_tx_buffer[3] = ~g_asix_tx_buffer[1]; - - if ((p->tot_len + 4) % USB_GET_MAXPACKETSIZE(g_asix_class.bulkout->wMaxPacketSize)) { - USB_LOG_DBG("txlen:%d\r\n", p->tot_len + 8); - g_asix_tx_buffer[p->tot_len + 4 + 0] = 0x00; - g_asix_tx_buffer[p->tot_len + 4 + 1] = 0x00; - g_asix_tx_buffer[p->tot_len + 4 + 2] = 0xff; - g_asix_tx_buffer[p->tot_len + 4 + 3] = 0xff; - actual_len = p->tot_len + 8; - } else { - USB_LOG_DBG("txlen:%d\r\n", p->tot_len + 4); - actual_len = p->tot_len + 4; - } - - usbh_bulk_urb_fill(&g_asix_class.bulkout_urb, g_asix_class.hport, g_asix_class.bulkout, g_asix_tx_buffer, actual_len, USB_OSAL_WAITING_FOREVER, NULL, NULL); - ret = usbh_submit_urb(&g_asix_class.bulkout_urb); - if (ret < 0) { - return ERR_BUF; - } - - return ERR_OK; -} - -__WEAK void usbh_asix_run(struct usbh_asix *asix_class) -{ -} - -__WEAK void usbh_asix_stop(struct usbh_asix *asix_class) -{ -} - -static const struct usbh_class_driver asix_class_driver = { - .driver_name = "asix", - .connect = usbh_asix_connect, - .disconnect = usbh_asix_disconnect -}; - -CLASS_INFO_DEFINE const struct usbh_class_info ax88772b_class_info = { - .match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS, - .class = 0xff, - .subclass = 0x00, - .protocol = 0x00, - .vid = 0x0B95, - .pid = 0x772B, - .class_driver = &asix_class_driver -}; - -CLASS_INFO_DEFINE const struct usbh_class_info ax88772_class_info = { - .match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS, - .class = 0xff, - .subclass = 0x00, - .protocol = 0x00, - .vid = 0x0B95, - .pid = 0x7720, - .class_driver = &asix_class_driver -}; diff --git a/class/vendor/usbh_asix.h b/class/vendor/usbh_asix.h deleted file mode 100644 index 8be79dfd..00000000 --- a/class/vendor/usbh_asix.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2024, sakumisu - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef USBH_ASIX_H -#define USBH_ASIX_H - -#include "lwip/netif.h" -#include "lwip/pbuf.h" - -/* ASIX AX8817X based USB 2.0 Ethernet Devices */ - -#define AX_CMD_SET_SW_MII 0x06 -#define AX_CMD_READ_MII_REG 0x07 -#define AX_CMD_WRITE_MII_REG 0x08 -#define AX_CMD_STATMNGSTS_REG 0x09 -#define AX_CMD_SET_HW_MII 0x0a -#define AX_CMD_READ_EEPROM 0x0b -#define AX_CMD_WRITE_EEPROM 0x0c -#define AX_CMD_WRITE_ENABLE 0x0d -#define AX_CMD_WRITE_DISABLE 0x0e -#define AX_CMD_READ_RX_CTL 0x0f -#define AX_CMD_WRITE_RX_CTL 0x10 -#define AX_CMD_READ_IPG012 0x11 -#define AX_CMD_WRITE_IPG0 0x12 -#define AX_CMD_WRITE_IPG1 0x13 -#define AX_CMD_READ_NODE_ID 0x13 -#define AX_CMD_WRITE_NODE_ID 0x14 -#define AX_CMD_WRITE_IPG2 0x14 -#define AX_CMD_WRITE_MULTI_FILTER 0x16 -#define AX88172_CMD_READ_NODE_ID 0x17 -#define AX_CMD_READ_PHY_ID 0x19 -#define AX_CMD_READ_MEDIUM_STATUS 0x1a -#define AX_CMD_WRITE_MEDIUM_MODE 0x1b -#define AX_CMD_READ_MONITOR_MODE 0x1c -#define AX_CMD_WRITE_MONITOR_MODE 0x1d -#define AX_CMD_READ_GPIOS 0x1e -#define AX_CMD_WRITE_GPIOS 0x1f -#define AX_CMD_SW_RESET 0x20 -#define AX_CMD_SW_PHY_STATUS 0x21 -#define AX_CMD_SW_PHY_SELECT 0x22 -#define AX_QCTCTRL 0x2A - -#define AX_CHIPCODE_MASK 0x70 -#define AX_AX88772_CHIPCODE 0x00 -#define AX_AX88772A_CHIPCODE 0x10 -#define AX_AX88772B_CHIPCODE 0x20 -#define AX_HOST_EN 0x01 - -#define AX_PHYSEL_PSEL 0x01 -#define AX_PHYSEL_SSMII 0 -#define AX_PHYSEL_SSEN 0x10 - -#define AX_PHY_SELECT_MASK (BIT(3) | BIT(2)) -#define AX_PHY_SELECT_INTERNAL 0 -#define AX_PHY_SELECT_EXTERNAL BIT(2) - -#define AX_MONITOR_MODE 0x01 -#define AX_MONITOR_LINK 0x02 -#define AX_MONITOR_MAGIC 0x04 -#define AX_MONITOR_HSFS 0x10 - -/* AX88172 Medium Status Register values */ -#define AX88172_MEDIUM_FD 0x02 -#define AX88172_MEDIUM_TX 0x04 -#define AX88172_MEDIUM_FC 0x10 -#define AX88172_MEDIUM_DEFAULT \ - (AX88172_MEDIUM_FD | AX88172_MEDIUM_TX | AX88172_MEDIUM_FC) - -#define AX_MCAST_FILTER_SIZE 8 -#define AX_MAX_MCAST 64 - -#define AX_SWRESET_CLEAR 0x00 -#define AX_SWRESET_RR 0x01 -#define AX_SWRESET_RT 0x02 -#define AX_SWRESET_PRTE 0x04 -#define AX_SWRESET_PRL 0x08 -#define AX_SWRESET_BZ 0x10 -#define AX_SWRESET_IPRL 0x20 -#define AX_SWRESET_IPPD 0x40 - -#define AX88772_IPG0_DEFAULT 0x15 -#define AX88772_IPG1_DEFAULT 0x0c -#define AX88772_IPG2_DEFAULT 0x12 - -/* AX88772 & AX88178 Medium Mode Register */ -#define AX_MEDIUM_PF 0x0080 -#define AX_MEDIUM_JFE 0x0040 -#define AX_MEDIUM_TFC 0x0020 -#define AX_MEDIUM_RFC 0x0010 -#define AX_MEDIUM_ENCK 0x0008 -#define AX_MEDIUM_AC 0x0004 -#define AX_MEDIUM_FD 0x0002 -#define AX_MEDIUM_GM 0x0001 -#define AX_MEDIUM_SM 0x1000 -#define AX_MEDIUM_SBP 0x0800 -#define AX_MEDIUM_PS 0x0200 -#define AX_MEDIUM_RE 0x0100 - -#define AX88178_MEDIUM_DEFAULT \ - (AX_MEDIUM_PS | AX_MEDIUM_FD | AX_MEDIUM_AC | \ - AX_MEDIUM_RFC | AX_MEDIUM_TFC | AX_MEDIUM_JFE | \ - AX_MEDIUM_RE) - -#define AX88772_MEDIUM_DEFAULT \ - (AX_MEDIUM_FD | AX_MEDIUM_PS | \ - AX_MEDIUM_AC | AX_MEDIUM_RE) - -/* AX88772 & AX88178 RX_CTL values */ -#define AX_RX_CTL_SO 0x0080 -#define AX_RX_CTL_AP 0x0020 -#define AX_RX_CTL_AM 0x0010 -#define AX_RX_CTL_AB 0x0008 -#define AX_RX_CTL_SEP 0x0004 -#define AX_RX_CTL_AMALL 0x0002 -#define AX_RX_CTL_PRO 0x0001 -#define AX_RX_CTL_MFB_2048 0x0000 -#define AX_RX_CTL_MFB_4096 0x0100 -#define AX_RX_CTL_MFB_8192 0x0200 -#define AX_RX_CTL_MFB_16384 0x0300 - -#define AX_DEFAULT_RX_CTL (AX_RX_CTL_SO | AX_RX_CTL_AB) - -/* GPIO 0 .. 2 toggles */ -#define AX_GPIO_GPO0EN 0x01 /* GPIO0 Output enable */ -#define AX_GPIO_GPO_0 0x02 /* GPIO0 Output value */ -#define AX_GPIO_GPO1EN 0x04 /* GPIO1 Output enable */ -#define AX_GPIO_GPO_1 0x08 /* GPIO1 Output value */ -#define AX_GPIO_GPO2EN 0x10 /* GPIO2 Output enable */ -#define AX_GPIO_GPO_2 0x20 /* GPIO2 Output value */ -#define AX_GPIO_RESERVED 0x40 /* Reserved */ -#define AX_GPIO_RSE 0x80 /* Reload serial EEPROM */ - -#define AX_EEPROM_MAGIC 0xdeadbeef -#define AX_EEPROM_LEN 0x200 - -#define AX_EMBD_PHY_ADDR 0x10 - -struct usbh_asix { - struct usbh_hubport *hport; - struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */ - struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */ - struct usb_endpoint_descriptor *intin; /* INTR IN endpoint */ - struct usbh_urb bulkout_urb; - struct usbh_urb bulkin_urb; - struct usbh_urb intin_urb; - - uint8_t intf; - char *name; - uint8_t phy_addr; - uint8_t embd_phy; - uint8_t chipcode; - uint16_t mac_capabilities; - - bool connect_status; - uint8_t mac[6]; - - ip_addr_t ipaddr; - ip_addr_t netmask; - ip_addr_t gateway; -}; - -#ifdef __cplusplus -extern "C" { -#endif - -int usbh_asix_get_connect_status(struct usbh_asix *asix_class); - -void usbh_asix_run(struct usbh_asix *asix_class); -void usbh_asix_stop(struct usbh_asix *asix_class); - -void usbh_asix_rx_thread(void *argument); -err_t usbh_asix_linkoutput(struct netif *netif, struct pbuf *p); - -#ifdef __cplusplus -} -#endif - -#endif /* USBH_ASIX_H */ \ No newline at end of file diff --git a/class/vendor/usbh_ch34x.c b/class/vendor/usbh_ch34x.c deleted file mode 100644 index 1effdba8..00000000 --- a/class/vendor/usbh_ch34x.c +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright (c) 2024, sakumisu - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "usbh_core.h" -#include "usbh_ch34x.h" - -#define DEV_FORMAT "/dev/ttyUSB%d" - -USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_ch34x_buf[64]; - -#define CONFIG_USBHOST_MAX_CP210X_CLASS 1 - -static struct usbh_ch34x g_ch34x_class[CONFIG_USBHOST_MAX_CP210X_CLASS]; -static uint32_t g_devinuse = 0; - -static struct usbh_ch34x *usbh_ch34x_class_alloc(void) -{ - int devno; - - for (devno = 0; devno < CONFIG_USBHOST_MAX_CP210X_CLASS; devno++) { - if ((g_devinuse & (1 << devno)) == 0) { - g_devinuse |= (1 << devno); - memset(&g_ch34x_class[devno], 0, sizeof(struct usbh_ch34x)); - g_ch34x_class[devno].minor = devno; - return &g_ch34x_class[devno]; - } - } - return NULL; -} - -static void usbh_ch34x_class_free(struct usbh_ch34x *ch34x_class) -{ - int devno = ch34x_class->minor; - - if (devno >= 0 && devno < 32) { - g_devinuse &= ~(1 << devno); - } - memset(ch34x_class, 0, sizeof(struct usbh_ch34x)); -} - -static int usbh_ch34x_get_baudrate_div(uint32_t baudrate, uint8_t *factor, uint8_t *divisor) -{ - uint8_t a; - uint8_t b; - uint32_t c; - - switch (baudrate) { - case 921600: - a = 0xf3; - b = 7; - break; - - case 307200: - a = 0xd9; - b = 7; - break; - - default: - if (baudrate > 6000000 / 255) { - b = 3; - c = 6000000; - } else if (baudrate > 750000 / 255) { - b = 2; - c = 750000; - } else if (baudrate > 93750 / 255) { - b = 1; - c = 93750; - } else { - b = 0; - c = 11719; - } - a = (uint8_t)(c / baudrate); - if (a == 0 || a == 0xFF) { - return -USB_ERR_INVAL; - } - if ((c / a - baudrate) > (baudrate - c / (a + 1))) { - a++; - } - a = (uint8_t)(256 - a); - break; - } - - *factor = a; - *divisor = b; - - return 0; -} - -static int usbh_ch34x_get_version(struct usbh_ch34x *ch34x_class) -{ - struct usb_setup_packet *setup = ch34x_class->hport->setup; - int ret; - - setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; - setup->bRequest = CH34X_READ_VERSION; - setup->wValue = 0; - setup->wIndex = 0; - setup->wLength = 2; - - ret = usbh_control_transfer(ch34x_class->hport, setup, g_ch34x_buf); - if (ret < 0) { - return ret; - } - - USB_LOG_INFO("Ch34x chip version %02x:%02x\r\n", g_ch34x_buf[0], g_ch34x_buf[1]); - return ret; -} - -static int usbh_ch34x_flow_ctrl(struct usbh_ch34x *ch34x_class) -{ - struct usb_setup_packet *setup = ch34x_class->hport->setup; - - setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; - setup->bRequest = CH34X_WRITE_REG; - setup->wValue = 0x2727; - setup->wIndex = 0; - setup->wLength = 0; - - return usbh_control_transfer(ch34x_class->hport, setup, NULL); -} - -int usbh_ch34x_set_line_coding(struct usbh_ch34x *ch34x_class, struct cdc_line_coding *line_coding) -{ - struct usb_setup_packet *setup = ch34x_class->hport->setup; - uint16_t reg_value = 0; - uint16_t value = 0; - uint8_t factor = 0; - uint8_t divisor = 0; - - memcpy((uint8_t *)&ch34x_class->line_coding, line_coding, sizeof(struct cdc_line_coding)); - - /* refer to https://github.com/WCHSoftGroup/ch341ser_linux/blob/main/driver/ch341.c */ - - switch (line_coding->bParityType) { - case 0: - break; - case 1: - reg_value |= CH341_L_PO; - break; - case 2: - reg_value |= CH341_L_PE; - break; - case 3: - reg_value |= CH341_L_PM; - break; - case 4: - reg_value |= CH341_L_PS; - break; - default: - return -USB_ERR_INVAL; - } - - switch (line_coding->bDataBits) { - case 5: - reg_value |= CH341_L_D5; - break; - case 6: - reg_value |= CH341_L_D6; - break; - case 7: - reg_value |= CH341_L_D7; - break; - case 8: - reg_value |= CH341_L_D8; - break; - default: - return -USB_ERR_INVAL; - } - - if (line_coding->bCharFormat == 2) { - reg_value |= CH341_L_SB; - } - - reg_value |= 0xC0; - - value |= 0x9c; - value |= reg_value << 8; - - usbh_ch34x_get_baudrate_div(line_coding->dwDTERate, &factor, &divisor); - - setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; - setup->bRequest = CH34X_SERIAL_INIT; - setup->wValue = value; - setup->wIndex = (factor << 8) | 0x80 | divisor; - setup->wLength = 0; - - return usbh_control_transfer(ch34x_class->hport, setup, NULL); -} - -int usbh_ch34x_get_line_coding(struct usbh_ch34x *ch34x_class, struct cdc_line_coding *line_coding) -{ - memcpy(line_coding, (uint8_t *)&ch34x_class->line_coding, sizeof(struct cdc_line_coding)); - return 0; -} - -int usbh_ch34x_set_line_state(struct usbh_ch34x *ch34x_class, bool dtr, bool rts) -{ - struct usb_setup_packet *setup = ch34x_class->hport->setup; - - setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; - setup->bRequest = CH34X_MODEM_CTRL; - setup->wValue = 0x0f | (dtr << 5) | (rts << 6); - setup->wIndex = 0; - setup->wLength = 0; - - return usbh_control_transfer(ch34x_class->hport, setup, NULL); -} - -static int usbh_ch34x_connect(struct usbh_hubport *hport, uint8_t intf) -{ - struct usb_endpoint_descriptor *ep_desc; - int ret = 0; - - struct usbh_ch34x *ch34x_class = usbh_ch34x_class_alloc(); - if (ch34x_class == NULL) { - USB_LOG_ERR("Fail to alloc ch34x_class\r\n"); - return -USB_ERR_NOMEM; - } - - ch34x_class->hport = hport; - ch34x_class->intf = intf; - - hport->config.intf[intf].priv = ch34x_class; - - usbh_ch34x_get_version(ch34x_class); - usbh_ch34x_flow_ctrl(ch34x_class); - - for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) { - ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc; - if (USB_GET_ENDPOINT_TYPE(ep_desc->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) { - continue; - } else { - if (ep_desc->bEndpointAddress & 0x80) { - USBH_EP_INIT(ch34x_class->bulkin, ep_desc); - } else { - USBH_EP_INIT(ch34x_class->bulkout, ep_desc); - } - } - } - - snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, ch34x_class->minor); - - USB_LOG_INFO("Register CH34X Class:%s\r\n", hport->config.intf[intf].devname); - -#if 0 - USB_LOG_INFO("Test ch34x rx and tx and rx for 5 times, baudrate is 115200\r\n"); - - struct cdc_line_coding linecoding; - uint8_t count = 5; - - linecoding.dwDTERate = 115200; - linecoding.bDataBits = 8; - linecoding.bParityType = 0; - linecoding.bCharFormat = 0; - usbh_ch34x_set_line_coding(ch34x_class, &linecoding); - usbh_ch34x_set_line_state(ch34x_class, true, false); - - memset(g_ch34x_buf, 'a', sizeof(g_ch34x_buf)); - ret = usbh_ch34x_bulk_out_transfer(ch34x_class, g_ch34x_buf, sizeof(g_ch34x_buf), 0xfffffff); - USB_LOG_RAW("out ret:%d\r\n", ret); - while (count--) { - ret = usbh_ch34x_bulk_in_transfer(ch34x_class, g_ch34x_buf, sizeof(g_ch34x_buf), 0xfffffff); - USB_LOG_RAW("in ret:%d\r\n", ret); - if (ret > 0) { - for (uint32_t i = 0; i < ret; i++) { - USB_LOG_RAW("%02x ", g_ch34x_buf[i]); - } - USB_LOG_RAW("\r\n"); - } - } -#endif - usbh_ch34x_run(ch34x_class); - return ret; -} - -static int usbh_ch34x_disconnect(struct usbh_hubport *hport, uint8_t intf) -{ - int ret = 0; - - struct usbh_ch34x *ch34x_class = (struct usbh_ch34x *)hport->config.intf[intf].priv; - - if (ch34x_class) { - if (ch34x_class->bulkin) { - usbh_kill_urb(&ch34x_class->bulkin_urb); - } - - if (ch34x_class->bulkout) { - usbh_kill_urb(&ch34x_class->bulkout_urb); - } - - if (hport->config.intf[intf].devname[0] != '\0') { - USB_LOG_INFO("Unregister CH34X Class:%s\r\n", hport->config.intf[intf].devname); - usbh_ch34x_stop(ch34x_class); - } - - usbh_ch34x_class_free(ch34x_class); - } - - return ret; -} - -int usbh_ch34x_bulk_in_transfer(struct usbh_ch34x *ch34x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout) -{ - int ret; - struct usbh_urb *urb = &ch34x_class->bulkin_urb; - - usbh_bulk_urb_fill(urb, ch34x_class->hport, ch34x_class->bulkin, buffer, buflen, timeout, NULL, NULL); - ret = usbh_submit_urb(urb); - if (ret == 0) { - ret = urb->actual_length; - } - return ret; -} - -int usbh_ch34x_bulk_out_transfer(struct usbh_ch34x *ch34x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout) -{ - int ret; - struct usbh_urb *urb = &ch34x_class->bulkout_urb; - - usbh_bulk_urb_fill(urb, ch34x_class->hport, ch34x_class->bulkout, buffer, buflen, timeout, NULL, NULL); - ret = usbh_submit_urb(urb); - if (ret == 0) { - ret = urb->actual_length; - } - return ret; -} - -__WEAK void usbh_ch34x_run(struct usbh_ch34x *ch34x_class) -{ -} - -__WEAK void usbh_ch34x_stop(struct usbh_ch34x *ch34x_class) -{ -} - -const struct usbh_class_driver ch34x_class_driver = { - .driver_name = "ch34x", - .connect = usbh_ch34x_connect, - .disconnect = usbh_ch34x_disconnect -}; - -CLASS_INFO_DEFINE const struct usbh_class_info ch34x_class_info = { - .match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS, - .class = 0xff, - .subclass = 0xff, - .protocol = 0xff, - .vid = 0x1A86, - .pid = 0x7523, - .class_driver = &ch34x_class_driver -}; \ No newline at end of file diff --git a/class/vendor/usbh_ch34x.h b/class/vendor/usbh_ch34x.h deleted file mode 100644 index 9918c3be..00000000 --- a/class/vendor/usbh_ch34x.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2024, sakumisu - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef USBH_CH34X_H -#define USBH_CH34X_H - -#include "usb_cdc.h" - -/* Requests */ -#define CH34X_READ_VERSION 0x5F -#define CH34X_WRITE_REG 0x9A -#define CH34X_READ_REG 0x95 -#define CH34X_SERIAL_INIT 0xA1 -#define CH34X_MODEM_CTRL 0xA4 - -// modem control bits -#define CH34X_BIT_RTS (1 << 6) -#define CH34X_BIT_DTR (1 << 5) - -#define CH341_CTO_O 0x10 -#define CH341_CTO_D 0x20 -#define CH341_CTO_R 0x40 -#define CH341_CTI_C 0x01 -#define CH341_CTI_DS 0x02 -#define CH341_CTRL_RI 0x04 -#define CH341_CTI_DC 0x08 -#define CH341_CTI_ST 0x0f - -#define CH341_L_ER 0x80 -#define CH341_L_ET 0x40 -#define CH341_L_PS 0x38 -#define CH341_L_PM 0x28 -#define CH341_L_PE 0x18 -#define CH341_L_PO 0x08 -#define CH341_L_SB 0x04 -#define CH341_L_D8 0x03 -#define CH341_L_D7 0x02 -#define CH341_L_D6 0x01 -#define CH341_L_D5 0x00 - -struct usbh_ch34x { - struct usbh_hubport *hport; - struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */ - struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */ - struct usbh_urb bulkout_urb; - struct usbh_urb bulkin_urb; - - struct cdc_line_coding line_coding; - - uint8_t intf; - uint8_t minor; -}; - -#ifdef __cplusplus -extern "C" { -#endif - -int usbh_ch34x_set_line_coding(struct usbh_ch34x *ch34x_class, struct cdc_line_coding *line_coding); -int usbh_ch34x_get_line_coding(struct usbh_ch34x *ch34x_class, struct cdc_line_coding *line_coding); -int usbh_ch34x_set_line_state(struct usbh_ch34x *ch34x_class, bool dtr, bool rts); - -int usbh_ch34x_bulk_in_transfer(struct usbh_ch34x *ch34x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout); -int usbh_ch34x_bulk_out_transfer(struct usbh_ch34x *ch34x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout); - -void usbh_ch34x_run(struct usbh_ch34x *ch34x_class); -void usbh_ch34x_stop(struct usbh_ch34x *ch34x_class); - -#ifdef __cplusplus -} -#endif - -#endif /* USBH_CH34X_H */ diff --git a/class/vendor/usbh_cp210x.c b/class/vendor/usbh_cp210x.c deleted file mode 100644 index 7dc45e64..00000000 --- a/class/vendor/usbh_cp210x.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright (c) 2024, sakumisu - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "usbh_core.h" -#include "usbh_cp210x.h" - -#define DEV_FORMAT "/dev/ttyUSB%d" - -USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cp210x_buf[64]; - -#define CONFIG_USBHOST_MAX_CP210X_CLASS 4 - -static struct usbh_cp210x g_cp210x_class[CONFIG_USBHOST_MAX_CP210X_CLASS]; -static uint32_t g_devinuse = 0; - -static struct usbh_cp210x *usbh_cp210x_class_alloc(void) -{ - int devno; - - for (devno = 0; devno < CONFIG_USBHOST_MAX_CP210X_CLASS; devno++) { - if ((g_devinuse & (1 << devno)) == 0) { - g_devinuse |= (1 << devno); - memset(&g_cp210x_class[devno], 0, sizeof(struct usbh_cp210x)); - g_cp210x_class[devno].minor = devno; - return &g_cp210x_class[devno]; - } - } - return NULL; -} - -static void usbh_cp210x_class_free(struct usbh_cp210x *cp210x_class) -{ - int devno = cp210x_class->minor; - - if (devno >= 0 && devno < 32) { - g_devinuse &= ~(1 << devno); - } - memset(cp210x_class, 0, sizeof(struct usbh_cp210x)); -} - -static int usbh_cp210x_enable(struct usbh_cp210x *cp210x_class) -{ - struct usb_setup_packet *setup = cp210x_class->hport->setup; - - setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE; - setup->bRequest = CP210X_IFC_ENABLE; - setup->wValue = 1; - setup->wIndex = cp210x_class->intf; - setup->wLength = 0; - - return usbh_control_transfer(cp210x_class->hport, setup, NULL); -} - -static int usbh_cp210x_set_flow(struct usbh_cp210x *cp210x_class) -{ - struct usb_setup_packet *setup = cp210x_class->hport->setup; - - setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE; - setup->bRequest = CP210X_SET_FLOW; - setup->wValue = 0; - setup->wIndex = cp210x_class->intf; - setup->wLength = 16; - - memset(g_cp210x_buf, 0, 16); - g_cp210x_buf[13] = 0x20; - return usbh_control_transfer(cp210x_class->hport, setup, g_cp210x_buf); -} - -static int usbh_cp210x_set_chars(struct usbh_cp210x *cp210x_class) -{ - struct usb_setup_packet *setup = cp210x_class->hport->setup; - - setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE; - setup->bRequest = CP210X_SET_CHARS; - setup->wValue = 0; - setup->wIndex = cp210x_class->intf; - setup->wLength = 6; - - memset(g_cp210x_buf, 0, 6); - g_cp210x_buf[0] = 0x80; - g_cp210x_buf[4] = 0x88; - g_cp210x_buf[5] = 0x28; - return usbh_control_transfer(cp210x_class->hport, setup, g_cp210x_buf); -} - -static int usbh_cp210x_set_baudrate(struct usbh_cp210x *cp210x_class, uint32_t baudrate) -{ - struct usb_setup_packet *setup = cp210x_class->hport->setup; - - setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE; - setup->bRequest = CP210X_SET_BAUDRATE; - setup->wValue = 0; - setup->wIndex = cp210x_class->intf; - setup->wLength = 4; - - memcpy(g_cp210x_buf, (uint8_t *)&baudrate, 4); - return usbh_control_transfer(cp210x_class->hport, setup, g_cp210x_buf); -} - -static int usbh_cp210x_set_data_format(struct usbh_cp210x *cp210x_class, uint8_t databits, uint8_t parity, uint8_t stopbits) -{ - struct usb_setup_packet *setup = cp210x_class->hport->setup; - uint16_t value; - - value = ((databits & 0x0F) << 8) | ((parity & 0x0f) << 4) | ((stopbits & 0x03) << 0); - - setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE; - setup->bRequest = CP210X_SET_LINE_CTL; - setup->wValue = value; - setup->wIndex = cp210x_class->intf; - setup->wLength = 0; - - return usbh_control_transfer(cp210x_class->hport, setup, NULL); -} - -static int usbh_cp210x_set_mhs(struct usbh_cp210x *cp210x_class, uint8_t dtr, uint8_t rts, uint8_t dtr_mask, uint8_t rts_mask) -{ - struct usb_setup_packet *setup = cp210x_class->hport->setup; - uint16_t value; - - value = ((dtr & 0x01) << 0) | ((rts & 0x01) << 1) | ((dtr_mask & 0x01) << 8) | ((rts_mask & 0x01) << 9); - - setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE; - setup->bRequest = CP210X_SET_MHS; - setup->wValue = value; - setup->wIndex = cp210x_class->intf; - setup->wLength = 0; - - return usbh_control_transfer(cp210x_class->hport, setup, NULL); -} - -int usbh_cp210x_set_line_coding(struct usbh_cp210x *cp210x_class, struct cdc_line_coding *line_coding) -{ - memcpy((uint8_t *)&cp210x_class->line_coding, line_coding, sizeof(struct cdc_line_coding)); - usbh_cp210x_set_baudrate(cp210x_class, line_coding->dwDTERate); - return usbh_cp210x_set_data_format(cp210x_class, line_coding->bDataBits, line_coding->bParityType, line_coding->bCharFormat); -} - -int usbh_cp210x_get_line_coding(struct usbh_cp210x *cp210x_class, struct cdc_line_coding *line_coding) -{ - memcpy(line_coding, (uint8_t *)&cp210x_class->line_coding, sizeof(struct cdc_line_coding)); - return 0; -} - -int usbh_cp210x_set_line_state(struct usbh_cp210x *cp210x_class, bool dtr, bool rts) -{ - return usbh_cp210x_set_mhs(cp210x_class, dtr, rts, 1, 1); -} - -static int usbh_cp210x_connect(struct usbh_hubport *hport, uint8_t intf) -{ - struct usb_endpoint_descriptor *ep_desc; - int ret = 0; - - struct usbh_cp210x *cp210x_class = usbh_cp210x_class_alloc(); - if (cp210x_class == NULL) { - USB_LOG_ERR("Fail to alloc cp210x_class\r\n"); - return -USB_ERR_NOMEM; - } - - cp210x_class->hport = hport; - cp210x_class->intf = intf; - - hport->config.intf[intf].priv = cp210x_class; - - usbh_cp210x_enable(cp210x_class); - usbh_cp210x_set_flow(cp210x_class); - usbh_cp210x_set_chars(cp210x_class); - - for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) { - ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc; - - if (ep_desc->bEndpointAddress & 0x80) { - USBH_EP_INIT(cp210x_class->bulkin, ep_desc); - } else { - USBH_EP_INIT(cp210x_class->bulkout, ep_desc); - } - } - - snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, cp210x_class->minor); - - USB_LOG_INFO("Register CP210X Class:%s\r\n", hport->config.intf[intf].devname); - -#if 0 - USB_LOG_INFO("Test cp2102 rx and tx and rx for 5 times, baudrate is 115200\r\n"); - - struct cdc_line_coding linecoding; - uint8_t count = 5; - - linecoding.dwDTERate = 115200; - linecoding.bDataBits = 8; - linecoding.bParityType = 0; - linecoding.bCharFormat = 0; - usbh_cp210x_set_line_coding(cp210x_class, &linecoding); - usbh_cp210x_set_line_state(cp210x_class, true, false); - - memset(g_cp210x_buf, 'a', sizeof(g_cp210x_buf)); - ret = usbh_cp210x_bulk_out_transfer(cp210x_class, g_cp210x_buf, sizeof(g_cp210x_buf), 0xfffffff); - USB_LOG_RAW("out ret:%d\r\n", ret); - while (count--) { - ret = usbh_cp210x_bulk_in_transfer(cp210x_class, g_cp210x_buf, sizeof(g_cp210x_buf), 0xfffffff); - USB_LOG_RAW("in ret:%d\r\n", ret); - if (ret > 0) { - for (uint32_t i = 0; i < ret; i++) { - USB_LOG_RAW("%02x ", g_cp210x_buf[i]); - } - USB_LOG_RAW("\r\n"); - } - } -#endif - usbh_cp210x_run(cp210x_class); - return ret; -} - -static int usbh_cp210x_disconnect(struct usbh_hubport *hport, uint8_t intf) -{ - int ret = 0; - - struct usbh_cp210x *cp210x_class = (struct usbh_cp210x *)hport->config.intf[intf].priv; - - if (cp210x_class) { - if (cp210x_class->bulkin) { - usbh_kill_urb(&cp210x_class->bulkin_urb); - } - - if (cp210x_class->bulkout) { - usbh_kill_urb(&cp210x_class->bulkout_urb); - } - - if (hport->config.intf[intf].devname[0] != '\0') { - USB_LOG_INFO("Unregister CP210X Class:%s\r\n", hport->config.intf[intf].devname); - usbh_cp210x_stop(cp210x_class); - } - - usbh_cp210x_class_free(cp210x_class); - } - - return ret; -} - -int usbh_cp210x_bulk_in_transfer(struct usbh_cp210x *cp210x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout) -{ - int ret; - struct usbh_urb *urb = &cp210x_class->bulkin_urb; - - usbh_bulk_urb_fill(urb, cp210x_class->hport, cp210x_class->bulkin, buffer, buflen, timeout, NULL, NULL); - ret = usbh_submit_urb(urb); - if (ret == 0) { - ret = urb->actual_length; - } - return ret; -} - -int usbh_cp210x_bulk_out_transfer(struct usbh_cp210x *cp210x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout) -{ - int ret; - struct usbh_urb *urb = &cp210x_class->bulkout_urb; - - usbh_bulk_urb_fill(urb, cp210x_class->hport, cp210x_class->bulkout, buffer, buflen, timeout, NULL, NULL); - ret = usbh_submit_urb(urb); - if (ret == 0) { - ret = urb->actual_length; - } - return ret; -} - -__WEAK void usbh_cp210x_run(struct usbh_cp210x *cp210x_class) -{ -} - -__WEAK void usbh_cp210x_stop(struct usbh_cp210x *cp210x_class) -{ -} - -const struct usbh_class_driver cp210x_class_driver = { - .driver_name = "cp210x", - .connect = usbh_cp210x_connect, - .disconnect = usbh_cp210x_disconnect -}; - -CLASS_INFO_DEFINE const struct usbh_class_info cp210x_class_info = { - .match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS, - .class = 0xff, - .subclass = 0xff, - .protocol = 0xff, - .vid = 0x10C4, - .pid = 0xEA60, - .class_driver = &cp210x_class_driver -}; \ No newline at end of file diff --git a/class/vendor/usbh_cp210x.h b/class/vendor/usbh_cp210x.h deleted file mode 100644 index 597328ec..00000000 --- a/class/vendor/usbh_cp210x.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2024, sakumisu - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef USBH_CP210X_H -#define USBH_CP210X_H - -#include "usb_cdc.h" - -/* Requests */ -#define CP210X_IFC_ENABLE 0x00 -#define CP210X_SET_BAUDDIV 0x01 -#define CP210X_GET_BAUDDIV 0x02 -#define CP210X_SET_LINE_CTL 0x03 // Set parity, data bits, stop bits -#define CP210X_GET_LINE_CTL 0x04 -#define CP210X_SET_BREAK 0x05 -#define CP210X_IMM_CHAR 0x06 -#define CP210X_SET_MHS 0x07 // Set DTR, RTS -#define CP210X_GET_MDMSTS 0x08 -#define CP210X_SET_XON 0x09 -#define CP210X_SET_XOFF 0x0A -#define CP210X_SET_EVENTMASK 0x0B -#define CP210X_GET_EVENTMASK 0x0C -#define CP210X_SET_CHAR 0x0D -#define CP210X_GET_CHARS 0x0E -#define CP210X_GET_PROPS 0x0F -#define CP210X_GET_COMM_STATUS 0x10 -#define CP210X_RESET 0x11 -#define CP210X_PURGE 0x12 -#define CP210X_SET_FLOW 0x13 -#define CP210X_GET_FLOW 0x14 -#define CP210X_EMBED_EVENTS 0x15 -#define CP210X_GET_EVENTSTATE 0x16 -#define CP210X_SET_CHARS 0x19 -#define CP210X_GET_BAUDRATE 0x1D -#define CP210X_SET_BAUDRATE 0x1E // Set baudrate -#define CP210X_VENDOR_SPECIFIC 0xFF - -struct usbh_cp210x { - struct usbh_hubport *hport; - struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */ - struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */ - struct usbh_urb bulkout_urb; - struct usbh_urb bulkin_urb; - - struct cdc_line_coding line_coding; - - uint8_t intf; - uint8_t minor; -}; - -#ifdef __cplusplus -extern "C" { -#endif - -int usbh_cp210x_set_line_coding(struct usbh_cp210x *ftdi_class, struct cdc_line_coding *line_coding); -int usbh_cp210x_get_line_coding(struct usbh_cp210x *ftdi_class, struct cdc_line_coding *line_coding); -int usbh_cp210x_set_line_state(struct usbh_cp210x *ftdi_class, bool dtr, bool rts); - -int usbh_cp210x_bulk_in_transfer(struct usbh_cp210x *cp210x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout); -int usbh_cp210x_bulk_out_transfer(struct usbh_cp210x *cp210x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout); - -void usbh_cp210x_run(struct usbh_cp210x *cp210x_class); -void usbh_cp210x_stop(struct usbh_cp210x *cp210x_class); - -#ifdef __cplusplus -} -#endif - -#endif /* USBH_CP210X_H */ diff --git a/class/vendor/usbh_ftdi.c b/class/vendor/usbh_ftdi.c deleted file mode 100644 index 48d1c1bd..00000000 --- a/class/vendor/usbh_ftdi.c +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Copyright (c) 2024, sakumisu - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "usbh_core.h" -#include "usbh_ftdi.h" - -#define DEV_FORMAT "/dev/ttyUSB%d" - -USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_ftdi_buf[64]; - -#define CONFIG_USBHOST_MAX_FTDI_CLASS 4 - -static struct usbh_ftdi g_ftdi_class[CONFIG_USBHOST_MAX_FTDI_CLASS]; -static uint32_t g_devinuse = 0; - -static struct usbh_ftdi *usbh_ftdi_class_alloc(void) -{ - int devno; - - for (devno = 0; devno < CONFIG_USBHOST_MAX_FTDI_CLASS; devno++) { - if ((g_devinuse & (1 << devno)) == 0) { - g_devinuse |= (1 << devno); - memset(&g_ftdi_class[devno], 0, sizeof(struct usbh_ftdi)); - g_ftdi_class[devno].minor = devno; - return &g_ftdi_class[devno]; - } - } - return NULL; -} - -static void usbh_ftdi_class_free(struct usbh_ftdi *ftdi_class) -{ - int devno = ftdi_class->minor; - - if (devno >= 0 && devno < 32) { - g_devinuse &= ~(1 << devno); - } - memset(ftdi_class, 0, sizeof(struct usbh_ftdi)); -} - -static void usbh_ftdi_caculate_baudrate(uint32_t *itdf_divisor, uint32_t actual_baudrate) -{ -#define FTDI_USB_CLK 48000000 - int baudrate; - uint8_t frac[] = { 0, 8, 4, 2, 6, 10, 12, 14 }; - - if (actual_baudrate == 2000000) { - *itdf_divisor = 0x01; - } else if (actual_baudrate == 3000000) { - *itdf_divisor = 0x00; - } else { - baudrate = actual_baudrate; - if (baudrate > 100000 && baudrate < 12000000) { - baudrate = (baudrate / 100000) + 100000; - } - int divisor = FTDI_USB_CLK / baudrate; - int frac_bits = 0; - for (int i = 0; i < sizeof(frac) / sizeof(frac[0]); i++) { - if ((divisor & 0xF) == frac[i]) { - frac_bits = i; - break; - } - } - divisor >>= 4; - divisor &= 0x3FFF; - *itdf_divisor = (divisor << 14) | (frac_bits << 8); - } -} - -int usbh_ftdi_reset(struct usbh_ftdi *ftdi_class) -{ - struct usb_setup_packet *setup = ftdi_class->hport->setup; - - setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; - setup->bRequest = SIO_RESET_REQUEST; - setup->wValue = 0; - setup->wIndex = ftdi_class->intf; - setup->wLength = 0; - - return usbh_control_transfer(ftdi_class->hport, setup, NULL); -} - -static int usbh_ftdi_set_modem(struct usbh_ftdi *ftdi_class, uint16_t value) -{ - struct usb_setup_packet *setup = ftdi_class->hport->setup; - - setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; - setup->bRequest = SIO_SET_MODEM_CTRL_REQUEST; - setup->wValue = value; - setup->wIndex = ftdi_class->intf; - setup->wLength = 0; - - return usbh_control_transfer(ftdi_class->hport, setup, NULL); -} - -static int usbh_ftdi_set_baudrate(struct usbh_ftdi *ftdi_class, uint32_t baudrate) -{ - struct usb_setup_packet *setup = ftdi_class->hport->setup; - uint32_t itdf_divisor; - uint16_t value; - uint8_t baudrate_high; - - usbh_ftdi_caculate_baudrate(&itdf_divisor, baudrate); - value = itdf_divisor & 0xFFFF; - baudrate_high = (itdf_divisor >> 16) & 0xff; - - setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; - setup->bRequest = SIO_SET_BAUDRATE_REQUEST; - setup->wValue = value; - setup->wIndex = (baudrate_high << 8) | ftdi_class->intf; - setup->wLength = 0; - - return usbh_control_transfer(ftdi_class->hport, setup, NULL); -} - -static int usbh_ftdi_set_data_format(struct usbh_ftdi *ftdi_class, uint8_t databits, uint8_t parity, uint8_t stopbits, uint8_t isbreak) -{ - /** - * D0-D7 databits BITS_7=7, BITS_8=8 - * D8-D10 parity NONE=0, ODD=1, EVEN=2, MARK=3, SPACE=4 - * D11-D12 STOP_BIT_1=0, STOP_BIT_15=1, STOP_BIT_2=2 - * D14 BREAK_OFF=0, BREAK_ON=1 - **/ - - uint16_t value = ((isbreak & 0x01) << 14) | ((stopbits & 0x03) << 11) | ((parity & 0x0f) << 8) | (databits & 0x0f); - - struct usb_setup_packet *setup = ftdi_class->hport->setup; - - setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; - setup->bRequest = SIO_SET_DATA_REQUEST; - setup->wValue = value; - setup->wIndex = ftdi_class->intf; - setup->wLength = 0; - - return usbh_control_transfer(ftdi_class->hport, setup, NULL); -} - -static int usbh_ftdi_set_latency_timer(struct usbh_ftdi *ftdi_class, uint16_t value) -{ - struct usb_setup_packet *setup = ftdi_class->hport->setup; - - setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; - setup->bRequest = SIO_SET_LATENCY_TIMER_REQUEST; - setup->wValue = value; - setup->wIndex = ftdi_class->intf; - setup->wLength = 0; - - return usbh_control_transfer(ftdi_class->hport, setup, NULL); -} - -static int usbh_ftdi_set_flow_ctrl(struct usbh_ftdi *ftdi_class, uint16_t value) -{ - struct usb_setup_packet *setup = ftdi_class->hport->setup; - - setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; - setup->bRequest = SIO_SET_FLOW_CTRL_REQUEST; - setup->wValue = value; - setup->wIndex = ftdi_class->intf; - setup->wLength = 0; - - return usbh_control_transfer(ftdi_class->hport, setup, NULL); -} - -static int usbh_ftdi_read_modem_status(struct usbh_ftdi *ftdi_class) -{ - struct usb_setup_packet *setup = ftdi_class->hport->setup; - int ret; - - setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; - setup->bRequest = SIO_POLL_MODEM_STATUS_REQUEST; - setup->wValue = 0x0000; - setup->wIndex = ftdi_class->intf; - setup->wLength = 2; - - ret = usbh_control_transfer(ftdi_class->hport, setup, g_ftdi_buf); - if (ret < 0) { - return ret; - } - memcpy(ftdi_class->modem_status, g_ftdi_buf, 2); - return ret; -} - -int usbh_ftdi_set_line_coding(struct usbh_ftdi *ftdi_class, struct cdc_line_coding *line_coding) -{ - memcpy((uint8_t *)&ftdi_class->line_coding, line_coding, sizeof(struct cdc_line_coding)); - usbh_ftdi_set_baudrate(ftdi_class, line_coding->dwDTERate); - return usbh_ftdi_set_data_format(ftdi_class, line_coding->bDataBits, line_coding->bParityType, line_coding->bCharFormat, 0); -} - -int usbh_ftdi_get_line_coding(struct usbh_ftdi *ftdi_class, struct cdc_line_coding *line_coding) -{ - memcpy(line_coding, (uint8_t *)&ftdi_class->line_coding, sizeof(struct cdc_line_coding)); - return 0; -} - -int usbh_ftdi_set_line_state(struct usbh_ftdi *ftdi_class, bool dtr, bool rts) -{ - int ret; - - if (dtr) { - usbh_ftdi_set_modem(ftdi_class, SIO_SET_DTR_HIGH); - } else { - usbh_ftdi_set_modem(ftdi_class, SIO_SET_DTR_LOW); - } - - if (rts) { - ret = usbh_ftdi_set_modem(ftdi_class, SIO_SET_RTS_HIGH); - } else { - ret = usbh_ftdi_set_modem(ftdi_class, SIO_SET_RTS_LOW); - } - - return ret; -} - -static int usbh_ftdi_connect(struct usbh_hubport *hport, uint8_t intf) -{ - struct usb_endpoint_descriptor *ep_desc; - int ret = 0; - - struct usbh_ftdi *ftdi_class = usbh_ftdi_class_alloc(); - if (ftdi_class == NULL) { - USB_LOG_ERR("Fail to alloc ftdi_class\r\n"); - return -USB_ERR_NOMEM; - } - - ftdi_class->hport = hport; - ftdi_class->intf = intf; - - hport->config.intf[intf].priv = ftdi_class; - - usbh_ftdi_reset(ftdi_class); - usbh_ftdi_set_flow_ctrl(ftdi_class, SIO_DISABLE_FLOW_CTRL); - usbh_ftdi_set_latency_timer(ftdi_class, 0x10); - usbh_ftdi_read_modem_status(ftdi_class); - USB_LOG_INFO("modem status:%02x:%02x\r\n", ftdi_class->modem_status[0], ftdi_class->modem_status[1]); - - for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) { - ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc; - - if (ep_desc->bEndpointAddress & 0x80) { - USBH_EP_INIT(ftdi_class->bulkin, ep_desc); - } else { - USBH_EP_INIT(ftdi_class->bulkout, ep_desc); - } - } - - snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, ftdi_class->minor); - - USB_LOG_INFO("Register FTDI Class:%s\r\n", hport->config.intf[intf].devname); - -#if 0 - USB_LOG_INFO("Test ftdi rx and tx and rx for 5 times, baudrate is 115200\r\n"); - - struct cdc_line_coding linecoding; - uint8_t count = 5; - - linecoding.dwDTERate = 115200; - linecoding.bDataBits = 8; - linecoding.bParityType = 0; - linecoding.bCharFormat = 0; - usbh_ftdi_set_line_coding(ftdi_class, &linecoding); - usbh_ftdi_set_line_state(ftdi_class, true, false); - - memset(g_ftdi_buf, 'a', sizeof(g_ftdi_buf)); - ret = usbh_ftdi_bulk_out_transfer(ftdi_class, g_ftdi_buf, sizeof(g_ftdi_buf), 0xfffffff); - USB_LOG_RAW("out ret:%d\r\n", ret); - while (count--) { - ret = usbh_ftdi_bulk_in_transfer(ftdi_class, g_ftdi_buf, sizeof(g_ftdi_buf), 0xfffffff); - USB_LOG_RAW("in ret:%d\r\n", ret); - if (ret > 0) { - for (uint32_t i = 0; i < ret; i++) { - USB_LOG_RAW("%02x ", g_ftdi_buf[i]); - } - } - USB_LOG_RAW("\r\n"); - } -#endif - usbh_ftdi_run(ftdi_class); - return ret; -} - -static int usbh_ftdi_disconnect(struct usbh_hubport *hport, uint8_t intf) -{ - int ret = 0; - - struct usbh_ftdi *ftdi_class = (struct usbh_ftdi *)hport->config.intf[intf].priv; - - if (ftdi_class) { - if (ftdi_class->bulkin) { - usbh_kill_urb(&ftdi_class->bulkin_urb); - } - - if (ftdi_class->bulkout) { - usbh_kill_urb(&ftdi_class->bulkout_urb); - } - - if (hport->config.intf[intf].devname[0] != '\0') { - USB_LOG_INFO("Unregister FTDI Class:%s\r\n", hport->config.intf[intf].devname); - usbh_ftdi_stop(ftdi_class); - } - - usbh_ftdi_class_free(ftdi_class); - } - - return ret; -} - -int usbh_ftdi_bulk_in_transfer(struct usbh_ftdi *ftdi_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout) -{ - int ret; - struct usbh_urb *urb = &ftdi_class->bulkin_urb; - - usbh_bulk_urb_fill(urb, ftdi_class->hport, ftdi_class->bulkin, buffer, buflen, timeout, NULL, NULL); - ret = usbh_submit_urb(urb); - if (ret == 0) { - ret = urb->actual_length; - } - return ret; -} - -int usbh_ftdi_bulk_out_transfer(struct usbh_ftdi *ftdi_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout) -{ - int ret; - struct usbh_urb *urb = &ftdi_class->bulkout_urb; - - usbh_bulk_urb_fill(urb, ftdi_class->hport, ftdi_class->bulkout, buffer, buflen, timeout, NULL, NULL); - ret = usbh_submit_urb(urb); - if (ret == 0) { - ret = urb->actual_length; - } - return ret; -} - -__WEAK void usbh_ftdi_run(struct usbh_ftdi *ftdi_class) -{ -} - -__WEAK void usbh_ftdi_stop(struct usbh_ftdi *ftdi_class) -{ -} - -const struct usbh_class_driver ftdi_class_driver = { - .driver_name = "ftdi", - .connect = usbh_ftdi_connect, - .disconnect = usbh_ftdi_disconnect -}; - -CLASS_INFO_DEFINE const struct usbh_class_info ftdi1_class_info = { - .match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS, - .class = 0xff, - .subclass = 0xff, - .protocol = 0xff, - .vid = 0x0403, - .pid = 0x6001, - .class_driver = &ftdi_class_driver -}; - -CLASS_INFO_DEFINE const struct usbh_class_info ftdi2_class_info = { - .match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS, - .class = 0xff, - .subclass = 0xff, - .protocol = 0xff, - .vid = 0x0403, - .pid = 0x6010, - .class_driver = &ftdi_class_driver -}; \ No newline at end of file diff --git a/class/vendor/usbh_ftdi.h b/class/vendor/usbh_ftdi.h deleted file mode 100644 index 300ee6ab..00000000 --- a/class/vendor/usbh_ftdi.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2024, sakumisu - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef USBH_FTDI_H -#define USBH_FTDI_H - -#include "usb_cdc.h" - -/* Requests */ -#define SIO_RESET_REQUEST 0x00 /* Reset the port */ -#define SIO_SET_MODEM_CTRL_REQUEST 0x01 /* Set the modem control register */ -#define SIO_SET_FLOW_CTRL_REQUEST 0x02 /* Set flow control register */ -#define SIO_SET_BAUDRATE_REQUEST 0x03 /* Set baud rate */ -#define SIO_SET_DATA_REQUEST 0x04 /* Set the data characteristics of the port */ -#define SIO_POLL_MODEM_STATUS_REQUEST 0x05 -#define SIO_SET_EVENT_CHAR_REQUEST 0x06 -#define SIO_SET_ERROR_CHAR_REQUEST 0x07 -#define SIO_SET_LATENCY_TIMER_REQUEST 0x09 -#define SIO_GET_LATENCY_TIMER_REQUEST 0x0A -#define SIO_SET_BITMODE_REQUEST 0x0B -#define SIO_READ_PINS_REQUEST 0x0C -#define SIO_READ_EEPROM_REQUEST 0x90 -#define SIO_WRITE_EEPROM_REQUEST 0x91 -#define SIO_ERASE_EEPROM_REQUEST 0x92 - -#define SIO_DISABLE_FLOW_CTRL 0x0 -#define SIO_RTS_CTS_HS (0x1 << 8) -#define SIO_DTR_DSR_HS (0x2 << 8) -#define SIO_XON_XOFF_HS (0x4 << 8) - -#define SIO_SET_DTR_MASK 0x1 -#define SIO_SET_DTR_HIGH (1 | (SIO_SET_DTR_MASK << 8)) -#define SIO_SET_DTR_LOW (0 | (SIO_SET_DTR_MASK << 8)) -#define SIO_SET_RTS_MASK 0x2 -#define SIO_SET_RTS_HIGH (2 | (SIO_SET_RTS_MASK << 8)) -#define SIO_SET_RTS_LOW (0 | (SIO_SET_RTS_MASK << 8)) - -#define SIO_RTS_CTS_HS (0x1 << 8) - -struct usbh_ftdi { - struct usbh_hubport *hport; - struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */ - struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */ - struct usbh_urb bulkout_urb; - struct usbh_urb bulkin_urb; - - struct cdc_line_coding line_coding; - - uint8_t intf; - uint8_t minor; - uint8_t modem_status[2]; -}; - -#ifdef __cplusplus -extern "C" { -#endif - -int usbh_ftdi_set_line_coding(struct usbh_ftdi *ftdi_class, struct cdc_line_coding *line_coding); -int usbh_ftdi_get_line_coding(struct usbh_ftdi *ftdi_class, struct cdc_line_coding *line_coding); -int usbh_ftdi_set_line_state(struct usbh_ftdi *ftdi_class, bool dtr, bool rts); - -int usbh_ftdi_bulk_in_transfer(struct usbh_ftdi *ftdi_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout); -int usbh_ftdi_bulk_out_transfer(struct usbh_ftdi *ftdi_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout); - -void usbh_ftdi_run(struct usbh_ftdi *ftdi_class); -void usbh_ftdi_stop(struct usbh_ftdi *ftdi_class); - -#ifdef __cplusplus -} -#endif - -#endif /* USBH_FTDI_H */ -- cgit v1.3.1