56 Commits

Author SHA1 Message Date
sakumisu
850e96577c fix missing bus in sunxi 2024-03-02 13:14:58 +08:00
sakumisu
384b11eb88 release v1.1.0 2024-02-25 21:07:13 +08:00
sakumisu
cfbe5615c4 disable device shell cmd 2024-02-25 21:06:03 +08:00
sakumisu
cbefa69715 disable net class 2024-02-24 16:41:37 +08:00
sakumisu
9e0cc8347c align for some buffers 2024-02-24 16:38:57 +08:00
sakumisu
8c72947794 fix bl glue 2024-02-24 16:34:43 +08:00
sakumisu
d5b4cdd4bd update img 2024-02-24 15:01:28 +08:00
sakumisu
3508879e1d fix asix output zlp 2024-02-24 14:57:01 +08:00
sakumisu
5c36affc3c classify vendor class 2024-02-24 13:35:41 +08:00
sakumisu
762c3cbb2f add get_connect_status api for rndis/cdc_ecm/asix 2024-02-24 10:49:11 +08:00
Zhihong Chen
b4e952b371 port: HPMicro: call suspend/connect/disconnect event
- call suspend/connect/disconnect event

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-02-23 16:55:58 +08:00
Zhihong Chen
756987050f class: msc: stage change should be before usbd_ep_start_write()
- stage change should be before usbd_ep_start_write()

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-02-23 10:42:53 +08:00
sakumisu
64773ab5e8 remove duplicate class info 2024-02-22 22:32:27 +08:00
Zhihong Chen
743669861e port: HPMicro: fix transfer_len not reset
- fix transfer_len not reset

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-02-20 22:10:56 +08:00
Zhihong Chen
0e3e9477cc port: HPMicro: decoupling the relationship between busid and usbid
- decoupling the relationship between busid and usbid

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-02-20 14:28:10 +08:00
sakumisu
56c90ab6f9 update rst 2024-02-19 20:31:19 +08:00
sakumisu
9c247f6e6b update asix phy config 2024-02-19 20:22:07 +08:00
Zhihong Chen
556fd6af63 HPMicro: port: fix _dcd_data align to 2048
- fix _dcd_data align to 2048

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-02-19 20:19:48 +08:00
Zhihong Chen
4803a6826b update endpoint number usage and fix busid check
Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-02-19 20:19:48 +08:00
sakumisu
e0551b3e7b config busid and regbase in usbh_initialize and usbd_initialize 2024-02-18 21:15:04 +08:00
sakumisu
31fa2b99c5 enable asix host driver 2024-02-15 22:54:14 +08:00
sakumisu
4313a2666e check if device is on extern hub 2024-02-09 12:35:44 +08:00
sakumisu
466d241c31 update doc 2024-02-09 12:21:40 +08:00
sakumisu
49116c6fbc format code 2024-02-09 12:08:08 +08:00
sakumisu
e7a57289ce update license year 2024-02-09 12:07:29 +08:00
sakumisu
e34ecc6cbb add volatile for HcEpType & ChannelEna 2024-02-07 21:37:17 +08:00
sakumisu
d1c7fa8c19 support multi port api for device 2024-02-06 19:52:22 +08:00
Zhihong Chen
920b02cb7c class: msc device: support multi lun
- support multi lun

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-02-06 18:31:47 +08:00
Zhihong Chen
3f89d1b003 usbd: change endpoint number from 8 to 16
- Because the maximum number of endpoints specified in the USB protocol is 16, and some vendors support 16 endpoints

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-02-06 18:31:47 +08:00
sakumisu
5897edffed make serial driver standard for cdc acm, ftdi, cp210x, ch34x 2024-02-03 22:20:58 +08:00
sakumisu
a01c08ddaa use cdc_linecoding and line state for ftdi 2024-02-02 23:37:46 +08:00
sakumisu
dcad369d06 add ftdi host 2024-02-02 22:53:54 +08:00
sakumisu
8232f64775 add nrf usbhci firmware 2024-02-01 20:49:31 +08:00
sakumisu
6fb3f31cbe add usbhci_h4 log and update bluetooth submodule 2024-01-31 20:52:01 +08:00
sakumisu
eeb304ae08 update log tag 2024-01-30 23:04:35 +08:00
sakumisu
fc80972284 add nimble submodule 2024-01-29 21:16:05 +08:00
sakumisu
feb69dcd95 add zephyr bluetooth submodule 2024-01-29 21:14:35 +08:00
sakumisu
cdfb7c3fb2 support hci usb h4 for usb bluetooth 2024-01-25 22:06:39 +08:00
sakumisu
24511c4d4b fix actual len position 2024-01-23 22:05:10 +08:00
sakumisu
c7cf09f6c3 update nimble porting with freertos 2024-01-22 19:49:23 +08:00
sakumisu
6b0a0135ac remove ununsed macro 2024-01-23 07:39:41 +08:00
sakumisu
04a300d803 remove ununsed header 2024-01-19 23:08:04 +08:00
sakumisu
0f5e05052f add usbd init and deinit event macro 2024-01-16 22:50:48 +08:00
sakumisu
b773cecd2e add ecm device write and read api 2024-01-14 18:49:41 +08:00
Zhihong Chen
c4a65146e8 port: hpmicro: fix usb_dc_deinit()
- fix usb_dc_deinit()

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-01-14 17:00:40 +08:00
Zhihong Chen
6bc6b06076 usbh_core: add iar risc-v support
- add iar risc-v support

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-01-14 17:00:40 +08:00
sakumisu
125aad65d6 dwc2 use fifo not dma as default because users may have problems in cache 2024-01-13 00:22:03 +08:00
sakumisu
07ced6d023 fix cdc ecm zlp check 2024-01-09 21:20:38 +08:00
sakumisu
45cca3930b update bluetooth rx callback, add zephyr bluetooth stack porting 2024-01-09 21:18:59 +08:00
sakumisu
eff338f8a7 add ehci hccr offset macro 2024-01-09 20:59:04 +08:00
sakumisu
1158fc3d8c support multi USB IP for host 2024-01-08 22:47:28 +08:00
sakumisu
d517f2594e fix macro name 2024-01-06 17:47:22 +08:00
sakumisu
b37f494304 support usb ble host 2024-01-06 12:53:22 +08:00
sakumisu
5fe66b4f0d dwc2: ctrl and bulk no need nak irq, when intr calls nak, retry by user 2024-01-06 01:09:55 +08:00
sakumisu
249e650c37 rename CONFIG_USBDEV_MSC_BLOCK_SIZE to CONFIG_USBDEV_MSC_MAX_BUFSIZE 2024-01-06 01:07:39 +08:00
sakumisu
cbfac7ec0c dwc2 low level deinit after usb register reset 2024-01-06 01:07:39 +08:00
155 changed files with 38974 additions and 2747 deletions

6
.gitmodules vendored Normal file
View File

@@ -0,0 +1,6 @@
[submodule "third_party/zephyr_bluetooth-2.7.5/zephyr_bluetooth"]
path = third_party/zephyr_bluetooth-2.7.5/zephyr_bluetooth
url = git@github.com:sakumisu/zephyr_bluetooth.git
[submodule "third_party/nimble-1.6.0/nimble"]
path = third_party/nimble-1.6.0/nimble
url = git@github.com:sakumisu/mynewt-nimble.git

View File

@@ -109,8 +109,10 @@ CherryUSB Host Stack has the following functions
- Support USB Video CLASS
- Support USB Audio CLASS
- Support Remote NDIS (RNDIS)
- Support USB Bluetooth class (support nimble and zephyr bluetooth stack, support **CLASS:0xE0** or vendor class like cdc acm)
- Support Vendor class
- Support USB modeswitch
- Support multi host with the same USB IP
The CherryUSB Host stack also provides the lsusb function, which allows you to view information about all mounted devices, including those on external hubs, with the help of a shell plugin.
@@ -127,6 +129,7 @@ CherryUSB Host Stack resource usage (GCC 10.2 with -O2):
|usbh_audio.c | ~3100 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|usbh_rndis.c | ~3900 | 4096 + 2 * 2048 | sizeof(struct usbh_rndis) * 1 | 0 |
|usbh_cdc_ecm.c | ~2500 | 2 * 1514 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|usbh_bluetooth.c | ~2300 | 2 * 2048(default) | sizeof(struct usbh_bluetooth) * 1 | 0 |
Among them, `sizeof(struct usbh_hub)` and `sizeof(struct usbh_hubport)` are affected by the following macros

View File

@@ -107,8 +107,10 @@ CherryUSB Host 协议栈当前实现以下功能:
- Support USB Video CLASS
- Support USB Audio CLASS
- 支持 Remote NDIS (RNDIS)
- 支持 USB Bluetooth (支持 nimble and zephyr bluetooth 协议栈,支持 **CLASS: 0xE0** 或者厂家自定义类,类似于 cdc acm 功能)
- 支持 Vendor 类 class
- 支持 USB modeswitch
- 支持相同 USB IP 的多主机
同时CherryUSB Host 协议栈还提供了 lsusb 的功能,借助 shell 插件可以查看所有挂载设备的信息,包括外部 hub 上的设备的信息。
@@ -125,6 +127,7 @@ CherryUSB Host 协议栈资源占用说明GCC 10.2 with -O2
|usbh_audio.c | ~3100 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|usbh_rndis.c | ~3900 | 4096 + 2 * 2048 | sizeof(struct usbh_rndis) * 1 | 0 |
|usbh_cdc_ecm.c | ~2500 | 2 * 1514 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|usbh_bluetooth.c | ~2300 | 2 * 2048(default) | sizeof(struct usbh_bluetooth) * 1 | 0 |
其中,`sizeof(struct usbh_hub)``sizeof(struct usbh_hubport)` 受以下宏影响:

View File

@@ -103,6 +103,8 @@ if GetDepend(['PKG_CHERRYUSB_HOST']):
src += Glob('class/wireless/usbh_rndis.c')
if GetDepend(['PKG_CHERRYUSB_HOST_CDC_ECM']):
src += Glob('class/cdc/usbh_cdc_ecm.c')
if GetDepend(['PKG_CHERRYUSB_HOST_BLUETOOTH']):
src += Glob('class/wireless/usbh_bluetooth.c')
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2']):
src += Glob('port/dwc2/usb_hc_dwc2.c')

View File

@@ -1,5 +1,5 @@
VERSION_MAJOR = 1
VERSION_MINOR = 0
VERSION_MINOR = 1
PATCHLEVEL = 99
VERSION_TWEAK = 0
EXTRAVERSION = 0

View File

@@ -6,8 +6,8 @@
#ifndef CHERRYUSB_CONFIG_H
#define CHERRYUSB_CONFIG_H
#define CHERRYUSB_VERSION 0x010000
#define CHERRYUSB_VERSION_STR "v1.0.0"
#define CHERRYUSB_VERSION 0x010100
#define CHERRYUSB_VERSION_STR "v1.1.0"
/* ================ USB common Configuration ================ */
@@ -33,6 +33,8 @@
/* ================= USB Device Stack Configuration ================ */
#define CONFIG_USBDEV_MAX_BUS 1 // for now, bus num must be 1 except hpm ip
/* Ep0 max transfer buffer, specially for receiving data from ep0 out */
#define CONFIG_USBDEV_REQUEST_BUFFER_LEN 256
@@ -45,8 +47,12 @@
/* Enable test mode */
// #define CONFIG_USBDEV_TEST_MODE
#ifndef CONFIG_USBDEV_MSC_BLOCK_SIZE
#define CONFIG_USBDEV_MSC_BLOCK_SIZE 512
#ifndef CONFIG_USBDEV_MSC_MAX_LUN
#define CONFIG_USBDEV_MSC_MAX_LUN 1
#endif
#ifndef CONFIG_USBDEV_MSC_MAX_BUFSIZE
#define CONFIG_USBDEV_MSC_MAX_BUFSIZE 512
#endif
#ifndef CONFIG_USBDEV_MSC_MANUFACTURER_STRING
@@ -91,6 +97,7 @@
/* ================ USB HOST Stack Configuration ================== */
#define CONFIG_USBHOST_MAX_BUS 1
#define CONFIG_USBHOST_MAX_RHPORTS 1
#define CONFIG_USBHOST_MAX_EXTHUBS 1
#define CONFIG_USBHOST_MAX_EHPORTS 4
@@ -129,26 +136,35 @@
#define CONFIG_USBHOST_MSC_TIMEOUT 5000
#endif
#define CONFIG_USBHOST_BLUETOOTH_HCI_H4
// #define CONFIG_USBHOST_BLUETOOTH_HCI_LOG
#ifndef CONFIG_USBHOST_BLUETOOTH_TX_SIZE
#define CONFIG_USBHOST_BLUETOOTH_TX_SIZE 2048
#endif
#ifndef CONFIG_USBHOST_BLUETOOTH_RX_SIZE
#define CONFIG_USBHOST_BLUETOOTH_RX_SIZE 2048
#endif
/* ================ USB Device Port Configuration ================*/
#define USBD_IRQHandler USBD_IRQHandler
#define USBD_BASE (0)
#define CONFIG_USBDEV_EP_NUM 4
#ifndef CONFIG_USBDEV_EP_NUM
#define CONFIG_USBDEV_EP_NUM 8
#endif
/* ================ USB Host Port Configuration ==================*/
// #define USBH_IRQHandler USBH_IRQHandler
// #define USBH_BASE (0)
// #define CONFIG_USBHOST_PIPE_NUM 10
/* ================ EHCI Configuration ================ */
#define CONFIG_USB_EHCI_HCCR_BASE (0x20072000)
#define CONFIG_USB_EHCI_HCOR_BASE (0x20072000 + 0x10)
#define CONFIG_USB_EHCI_HCCR_OFFSET (0x0)
#define CONFIG_USB_EHCI_HCOR_OFFSET (0x10)
#define CONFIG_USB_EHCI_FRAME_LIST_SIZE 1024
// #define CONFIG_USB_EHCI_INFO_ENABLE
// #define CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE
// #define CONFIG_USB_EHCI_CONFIGFLAG
// #define CONFIG_USB_EHCI_PORT_POWER
// #define CONFIG_USB_EHCI_PRINT_HW_PARAM
#endif

View File

@@ -17,9 +17,9 @@ struct usbd_audio_priv {
struct audio_entity_info *table;
uint8_t num;
uint16_t uac_version;
} g_usbd_audio;
} g_usbd_audio[CONFIG_USBDEV_MAX_BUS];
static int audio_class_endpoint_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
static int audio_class_endpoint_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
uint8_t control_selector;
uint32_t sampling_freq = 0;
@@ -34,13 +34,13 @@ static int audio_class_endpoint_request_handler(struct usb_setup_packet *setup,
case AUDIO_REQUEST_SET_CUR:
memcpy((uint8_t *)&sampling_freq, *data, *len);
USB_LOG_DBG("Set ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
usbd_audio_set_sampling_freq(ep, sampling_freq);
usbd_audio_set_sampling_freq(busid, ep, sampling_freq);
break;
case AUDIO_REQUEST_GET_CUR:
case AUDIO_REQUEST_GET_MIN:
case AUDIO_REQUEST_GET_MAX:
case AUDIO_REQUEST_GET_RES:
sampling_freq = usbd_audio_get_sampling_freq(ep);
sampling_freq = usbd_audio_get_sampling_freq(busid, ep);
memcpy(*data, &sampling_freq, 3);
USB_LOG_DBG("Get ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
*len = 3;
@@ -55,7 +55,7 @@ static int audio_class_endpoint_request_handler(struct usb_setup_packet *setup,
return 0;
}
static int audio_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_DBG("Audio Class request: "
"bRequest 0x%02x\r\n",
@@ -79,10 +79,10 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
ARG_UNUSED(mute_string);
for (uint8_t i = 0; i < g_usbd_audio.num; i++) {
if (g_usbd_audio.table[i].bEntityId == entity_id) {
subtype = g_usbd_audio.table[i].bDescriptorSubtype;
ep = g_usbd_audio.table[i].ep;
for (uint8_t i = 0; i < g_usbd_audio[busid].num; i++) {
if (g_usbd_audio[busid].table[i].bEntityId == entity_id) {
subtype = g_usbd_audio[busid].table[i].bDescriptorSubtype;
ep = g_usbd_audio[busid].table[i].ep;
break;
}
}
@@ -98,14 +98,14 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
case AUDIO_CONTROL_FEATURE_UNIT:
switch (control_selector) {
case AUDIO_FU_CONTROL_MUTE:
if (g_usbd_audio.uac_version < 0x0200) {
if (g_usbd_audio[busid].uac_version < 0x0200) {
switch (setup->bRequest) {
case AUDIO_REQUEST_SET_CUR:
mute = (*data)[0];
usbd_audio_set_mute(ep, ch, mute);
usbd_audio_set_mute(busid, ep, ch, mute);
break;
case AUDIO_REQUEST_GET_CUR:
(*data)[0] = usbd_audio_get_mute(ep, ch);
(*data)[0] = usbd_audio_get_mute(busid, ep, ch);
*len = 1;
break;
default:
@@ -116,11 +116,11 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
switch (setup->bRequest) {
case AUDIO_REQUEST_CUR:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
(*data)[0] = usbd_audio_get_mute(ep, ch);
(*data)[0] = usbd_audio_get_mute(busid, ep, ch);
*len = 1;
} else {
mute = (*data)[0];
usbd_audio_set_mute(ep, ch, mute);
usbd_audio_set_mute(busid, ep, ch, mute);
}
break;
default:
@@ -130,7 +130,7 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
}
break;
case AUDIO_FU_CONTROL_VOLUME:
if (g_usbd_audio.uac_version < 0x0200) {
if (g_usbd_audio[busid].uac_version < 0x0200) {
switch (setup->bRequest) {
case AUDIO_REQUEST_SET_CUR:
memcpy(&volume, *data, *len);
@@ -141,10 +141,10 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
}
volume_db += 128; /* 0 ~ 255 */
USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%04x\r\n", ep, ch, volume);
usbd_audio_set_volume(ep, ch, volume_db);
usbd_audio_set_volume(busid, ep, ch, volume_db);
break;
case AUDIO_REQUEST_GET_CUR:
volume_db = usbd_audio_get_volume(ep, ch);
volume_db = usbd_audio_get_volume(busid, ep, ch);
volume_db -= 128;
if (volume_db >= 0) {
volume = volume_db * 256;
@@ -177,7 +177,7 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
switch (setup->bRequest) {
case AUDIO_REQUEST_CUR:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
volume_db = usbd_audio_get_volume(ep, ch);
volume_db = usbd_audio_get_volume(busid, ep, ch);
volume = volume_db;
memcpy(*data, &volume, 2);
*len = 2;
@@ -185,7 +185,7 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
memcpy(&volume, *data, *len);
volume_db = volume;
USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%02x\r\n", ep, ch, volume);
usbd_audio_set_volume(ep, ch, volume_db);
usbd_audio_set_volume(busid, ep, ch, volume_db);
}
break;
case AUDIO_REQUEST_RANGE:
@@ -216,14 +216,14 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
switch (setup->bRequest) {
case AUDIO_REQUEST_CUR:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
sampling_freq = usbd_audio_get_sampling_freq(ep);
sampling_freq = usbd_audio_get_sampling_freq(busid, ep);
memcpy(*data, &sampling_freq, 4);
USB_LOG_DBG("Get ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
*len = 4;
} else {
memcpy(&sampling_freq, *data, setup->wLength);
USB_LOG_DBG("Set ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
usbd_audio_set_sampling_freq(ep, sampling_freq);
usbd_audio_set_sampling_freq(busid, ep, sampling_freq);
}
break;
case AUDIO_REQUEST_RANGE:
@@ -231,7 +231,7 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
uint8_t *sampling_freq_table = NULL;
uint16_t num;
usbd_audio_get_sampling_freq_table(ep, &sampling_freq_table);
usbd_audio_get_sampling_freq_table(busid, ep, &sampling_freq_table);
num = (uint16_t)((uint16_t)(sampling_freq_table[1] << 8) | ((uint16_t)sampling_freq_table[0]));
memcpy(*data, sampling_freq_table, (12 * num + 2));
*len = (12 * num + 2);
@@ -264,7 +264,7 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
return 0;
}
static void audio_notify_handler(uint8_t event, void *arg)
static void audio_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -274,9 +274,9 @@ static void audio_notify_handler(uint8_t event, void *arg)
case USBD_EVENT_SET_INTERFACE: {
struct usb_interface_descriptor *intf = (struct usb_interface_descriptor *)arg;
if (intf->bAlternateSetting) {
usbd_audio_open(intf->bInterfaceNumber);
usbd_audio_open(busid, intf->bInterfaceNumber);
} else {
usbd_audio_close(intf->bInterfaceNumber);
usbd_audio_close(busid, intf->bInterfaceNumber);
}
}
@@ -287,7 +287,8 @@ static void audio_notify_handler(uint8_t event, void *arg)
}
}
struct usbd_interface *usbd_audio_init_intf(struct usbd_interface *intf,
struct usbd_interface *usbd_audio_init_intf(uint8_t busid,
struct usbd_interface *intf,
uint16_t uac_version,
struct audio_entity_info *table,
uint8_t num)
@@ -304,40 +305,40 @@ struct usbd_interface *usbd_audio_init_intf(struct usbd_interface *intf,
intf->notify_handler = audio_notify_handler;
}
g_usbd_audio.uac_version = uac_version;
g_usbd_audio.table = table;
g_usbd_audio.num = num;
g_usbd_audio[busid].uac_version = uac_version;
g_usbd_audio[busid].table = table;
g_usbd_audio[busid].num = num;
return intf;
}
__WEAK void usbd_audio_set_volume(uint8_t ep, uint8_t ch, int volume)
__WEAK void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume)
{
}
__WEAK int usbd_audio_get_volume(uint8_t ep, uint8_t ch)
__WEAK int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch)
{
return 0;
}
__WEAK void usbd_audio_set_mute(uint8_t ep, uint8_t ch, bool mute)
__WEAK void usbd_audio_set_mute(uint8_t busid, uint8_t ep, uint8_t ch, bool mute)
{
}
__WEAK bool usbd_audio_get_mute(uint8_t ep, uint8_t ch)
__WEAK bool usbd_audio_get_mute(uint8_t busid, uint8_t ep, uint8_t ch)
{
return 0;
}
__WEAK void usbd_audio_set_sampling_freq(uint8_t ep, uint32_t sampling_freq)
__WEAK void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq)
{
}
__WEAK uint32_t usbd_audio_get_sampling_freq(uint8_t ep)
__WEAK uint32_t usbd_audio_get_sampling_freq(uint8_t busid, uint8_t ep)
{
return 0;
}
__WEAK void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
__WEAK void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table)
{
}

View File

@@ -19,22 +19,22 @@ struct audio_entity_info {
};
/* Init audio interface driver */
struct usbd_interface *usbd_audio_init_intf(struct usbd_interface *intf,
struct usbd_interface *usbd_audio_init_intf(uint8_t busid, struct usbd_interface *intf,
uint16_t uac_version,
struct audio_entity_info *table,
uint8_t num);
void usbd_audio_open(uint8_t intf);
void usbd_audio_close(uint8_t intf);
void usbd_audio_open(uint8_t busid, uint8_t intf);
void usbd_audio_close(uint8_t busid, uint8_t intf);
void usbd_audio_set_volume(uint8_t ep, uint8_t ch, int volume);
int usbd_audio_get_volume(uint8_t ep, uint8_t ch);
void usbd_audio_set_mute(uint8_t ep, uint8_t ch, bool mute);
bool usbd_audio_get_mute(uint8_t ep, uint8_t ch);
void usbd_audio_set_sampling_freq(uint8_t ep, uint32_t sampling_freq);
uint32_t usbd_audio_get_sampling_freq(uint8_t ep);
void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume);
int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch);
void usbd_audio_set_mute(uint8_t busid, uint8_t ep, uint8_t ch, bool mute);
bool usbd_audio_get_mute(uint8_t busid, uint8_t ep, uint8_t ch);
void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq);
uint32_t usbd_audio_get_sampling_freq(uint8_t busid, uint8_t ep);
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table);
void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table);
#ifdef __cplusplus
}

View File

@@ -6,6 +6,10 @@
#include "usbh_core.h"
#include "usbh_audio.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_audio"
#include "usb_log.h"
#define DEV_FORMAT "/dev/audio%d"
/* general descriptor field offsets */

View File

@@ -9,7 +9,7 @@
const char *stop_name[] = { "1", "1.5", "2" };
const char *parity_name[] = { "N", "O", "E", "M", "S" };
static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
static int cdc_acm_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_DBG("CDC Class request: "
"bRequest 0x%02x\r\n",
@@ -47,7 +47,7 @@ static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setu
parity_name[line_coding.bParityType],
stop_name[line_coding.bCharFormat]);
usbd_cdc_acm_set_line_coding(intf_num, &line_coding);
usbd_cdc_acm_set_line_coding(busid, intf_num, &line_coding);
break;
case CDC_REQUEST_SET_CONTROL_LINE_STATE:
@@ -57,12 +57,12 @@ static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setu
intf_num,
dtr,
rts);
usbd_cdc_acm_set_dtr(intf_num, dtr);
usbd_cdc_acm_set_rts(intf_num, rts);
usbd_cdc_acm_set_dtr(busid, intf_num, dtr);
usbd_cdc_acm_set_rts(busid, intf_num, rts);
break;
case CDC_REQUEST_GET_LINE_CODING:
usbd_cdc_acm_get_line_coding(intf_num, &line_coding);
usbd_cdc_acm_get_line_coding(busid, intf_num, &line_coding);
memcpy(*data, &line_coding, 7);
*len = 7;
USB_LOG_DBG("Get intf:%d linecoding %d %d %d %d\r\n",
@@ -73,7 +73,7 @@ static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setu
line_coding.bDataBits);
break;
case CDC_REQUEST_SEND_BREAK:
usbd_cdc_acm_send_break(intf_num);
usbd_cdc_acm_send_break(busid, intf_num);
break;
default:
USB_LOG_WRN("Unhandled CDC Class bRequest 0x%02x\r\n", setup->bRequest);
@@ -83,7 +83,7 @@ static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setu
return 0;
}
struct usbd_interface *usbd_cdc_acm_init_intf(struct usbd_interface *intf)
struct usbd_interface *usbd_cdc_acm_init_intf(uint8_t busid, struct usbd_interface *intf)
{
intf->class_interface_handler = cdc_acm_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
@@ -93,11 +93,11 @@ struct usbd_interface *usbd_cdc_acm_init_intf(struct usbd_interface *intf)
return intf;
}
__WEAK void usbd_cdc_acm_set_line_coding(uint8_t intf, struct cdc_line_coding *line_coding)
__WEAK void usbd_cdc_acm_set_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding)
{
}
__WEAK void usbd_cdc_acm_get_line_coding(uint8_t intf, struct cdc_line_coding *line_coding)
__WEAK void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding)
{
line_coding->dwDTERate = 2000000;
line_coding->bDataBits = 8;
@@ -105,14 +105,14 @@ __WEAK void usbd_cdc_acm_get_line_coding(uint8_t intf, struct cdc_line_coding *l
line_coding->bCharFormat = 0;
}
__WEAK void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
__WEAK void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
{
}
__WEAK void usbd_cdc_acm_set_rts(uint8_t intf, bool rts)
__WEAK void usbd_cdc_acm_set_rts(uint8_t busid, uint8_t intf, bool rts)
{
}
__WEAK void usbd_cdc_acm_send_break(uint8_t intf)
__WEAK void usbd_cdc_acm_send_break(uint8_t busid, uint8_t intf)
{
}

View File

@@ -13,14 +13,14 @@ extern "C" {
#endif
/* Init cdc acm interface driver */
struct usbd_interface *usbd_cdc_acm_init_intf(struct usbd_interface *intf);
struct usbd_interface *usbd_cdc_acm_init_intf(uint8_t busid, struct usbd_interface *intf);
/* Setup request command callback api */
void usbd_cdc_acm_set_line_coding(uint8_t intf, struct cdc_line_coding *line_coding);
void usbd_cdc_acm_get_line_coding(uint8_t intf, struct cdc_line_coding *line_coding);
void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr);
void usbd_cdc_acm_set_rts(uint8_t intf, bool rts);
void usbd_cdc_acm_send_break(uint8_t intf);
void usbd_cdc_acm_set_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding);
void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding);
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr);
void usbd_cdc_acm_set_rts(uint8_t busid, uint8_t intf, bool rts);
void usbd_cdc_acm_send_break(uint8_t busid, uint8_t intf);
#ifdef __cplusplus
}

View File

@@ -75,11 +75,11 @@ void usbd_cdc_ecm_send_notify(uint8_t notifycode, uint8_t value, uint32_t *speed
}
if (bytes2send) {
usbd_ep_start_write(cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr, g_cdc_ecm_notify_buf, bytes2send);
usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr, g_cdc_ecm_notify_buf, bytes2send);
}
}
static int cdc_ecm_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
static int cdc_ecm_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_DBG("CDC ECM Class request: "
"bRequest 0x%02x\r\n",
@@ -109,7 +109,7 @@ static int cdc_ecm_class_interface_request_handler(struct usb_setup_packet *setu
return 0;
}
void cdc_ecm_notify_handler(uint8_t event, void *arg)
void cdc_ecm_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -119,7 +119,7 @@ void cdc_ecm_notify_handler(uint8_t event, void *arg)
g_cdc_ecm_rx_data_buffer = NULL;
break;
case USBD_EVENT_CONFIGURED:
usbd_ep_start_read(cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], CDC_ECM_MAX_PACKET_SIZE);
usbd_ep_start_read(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], CDC_ECM_MAX_PACKET_SIZE);
break;
default:
@@ -127,29 +127,29 @@ void cdc_ecm_notify_handler(uint8_t event, void *arg)
}
}
void cdc_ecm_bulk_out(uint8_t ep, uint32_t nbytes)
void cdc_ecm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
g_cdc_ecm_rx_data_length += nbytes;
if (nbytes < CDC_ECM_MAX_PACKET_SIZE) {
g_cdc_ecm_rx_data_buffer = g_cdc_ecm_rx_buffer;
usbd_cdc_ecm_data_recv_done();
usbd_cdc_ecm_data_recv_done(g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length);
} else {
usbd_ep_start_read(ep, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], CDC_ECM_MAX_PACKET_SIZE);
usbd_ep_start_read(0, ep, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], CDC_ECM_MAX_PACKET_SIZE);
}
}
void cdc_ecm_bulk_in(uint8_t ep, uint32_t nbytes)
void cdc_ecm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
if ((nbytes % CDC_ECM_MAX_PACKET_SIZE) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(ep, NULL, 0);
usbd_ep_start_write(0, ep, NULL, 0);
} else {
g_cdc_ecm_tx_data_length = 0;
}
}
void cdc_ecm_int_in(uint8_t ep, uint32_t nbytes)
void cdc_ecm_int_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
if (g_current_net_status == 1) {
g_current_net_status = 2;
@@ -157,6 +157,25 @@ void cdc_ecm_int_in(uint8_t ep, uint32_t nbytes)
}
}
int usbd_cdc_ecm_start_write(uint8_t *buf, uint32_t len)
{
if (g_cdc_ecm_tx_data_length > 0) {
return -USB_ERR_BUSY;
}
g_cdc_ecm_tx_data_length = len;
USB_LOG_DBG("txlen:%d\r\n", g_cdc_ecm_tx_data_length);
return usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr, buf, g_cdc_ecm_tx_data_length);
}
void usbd_cdc_ecm_start_read_next(void)
{
g_cdc_ecm_rx_data_length = 0;
g_cdc_ecm_rx_data_buffer = NULL;
usbd_ep_start_read(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, g_cdc_ecm_rx_buffer, CDC_ECM_MAX_PACKET_SIZE);
}
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
struct pbuf *usbd_cdc_ecm_eth_rx(void)
{
@@ -167,16 +186,14 @@ struct pbuf *usbd_cdc_ecm_eth_rx(void)
}
p = pbuf_alloc(PBUF_RAW, g_cdc_ecm_rx_data_length, PBUF_POOL);
if (p == NULL) {
usbd_cdc_ecm_start_read_next();
return NULL;
}
memcpy(p->payload, (uint8_t *)g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length);
p->len = g_cdc_ecm_rx_data_length;
USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ecm_rx_data_length);
g_cdc_ecm_rx_data_length = 0;
g_cdc_ecm_rx_data_buffer = NULL;
usbd_ep_start_read(cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, g_cdc_ecm_rx_buffer, CDC_ECM_MAX_PACKET_SIZE);
usbd_cdc_ecm_start_read_next();
return p;
}
@@ -201,8 +218,7 @@ int usbd_cdc_ecm_eth_tx(struct pbuf *p)
g_cdc_ecm_tx_data_length = p->tot_len;
USB_LOG_DBG("txlen:%d\r\n", g_cdc_ecm_tx_data_length);
return usbd_ep_start_write(cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr, g_cdc_ecm_tx_buffer, g_cdc_ecm_tx_data_length);
return usbd_cdc_ecm_start_write(g_cdc_ecm_tx_buffer, g_cdc_ecm_tx_data_length);
}
#endif
@@ -220,9 +236,9 @@ struct usbd_interface *usbd_cdc_ecm_init_intf(struct usbd_interface *intf, const
cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr = int_ep;
cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_cb = cdc_ecm_int_in;
usbd_add_endpoint(&cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX]);
usbd_add_endpoint(&cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX]);
usbd_add_endpoint(&cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX]);
usbd_add_endpoint(0, &cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX]);
usbd_add_endpoint(0, &cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX]);
usbd_add_endpoint(0, &cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX]);
return intf;
}
@@ -232,6 +248,6 @@ void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2])
memcpy(g_connect_speed_table, speed, 8);
}
__WEAK void usbd_cdc_ecm_data_recv_done(void)
__WEAK void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len)
{
}

View File

@@ -14,17 +14,23 @@ extern "C" {
/* Ethernet Maximum Segment size, typically 1514 bytes */
#define CONFIG_CDC_ECM_ETH_MAX_SEGSZE 1514U
#define CONFIG_USBDEV_CDC_ECM_USING_LWIP
/* Init cdc ecm interface driver */
struct usbd_interface *usbd_cdc_ecm_init_intf(struct usbd_interface *intf, const uint8_t int_ep, const uint8_t out_ep, const uint8_t in_ep);
/* Setup request command callback api */
void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2]);
void usbd_cdc_ecm_data_recv_done(void);
/* Api for eth only without any net stack */
uint8_t *usbd_cdc_ecm_get_tx_buffer(void);
void usbd_cdc_ecm_send_done(void);
int usbd_cdc_ecm_start_write(uint8_t *buf, uint32_t len);
void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len);
void usbd_cdc_ecm_start_read_next(void);
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
#include <lwip/pbuf.h>
#include "lwip/netif.h"
#include "lwip/pbuf.h"
struct pbuf *usbd_cdc_ecm_eth_rx(void);
int usbd_cdc_ecm_eth_tx(struct pbuf *p);
#endif

View File

@@ -6,9 +6,13 @@
#include "usbh_core.h"
#include "usbh_cdc_acm.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_cdc_acm"
#include "usb_log.h"
#define DEV_FORMAT "/dev/ttyACM%d"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct cdc_line_coding g_cdc_line_coding;
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_acm_buf[64];
static struct usbh_cdc_acm g_cdc_acm_class[CONFIG_USBHOST_MAX_CDC_ACM_CLASS];
static uint32_t g_devinuse = 0;
@@ -45,12 +49,12 @@ int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CDC_REQUEST_SET_LINE_CODING;
setup->wValue = 0;
setup->wIndex = cdc_acm_class->ctrl_intf;
setup->wIndex = cdc_acm_class->intf;
setup->wLength = 7;
memcpy((uint8_t *)&g_cdc_line_coding, line_coding, sizeof(struct cdc_line_coding));
memcpy(g_cdc_acm_buf, line_coding, sizeof(struct cdc_line_coding));
return usbh_control_transfer(cdc_acm_class->hport, setup, (uint8_t *)&g_cdc_line_coding);
return usbh_control_transfer(cdc_acm_class->hport, setup, g_cdc_acm_buf);
}
int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding)
@@ -61,14 +65,14 @@ int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CDC_REQUEST_GET_LINE_CODING;
setup->wValue = 0;
setup->wIndex = cdc_acm_class->ctrl_intf;
setup->wIndex = cdc_acm_class->intf;
setup->wLength = 7;
ret = usbh_control_transfer(cdc_acm_class->hport, setup, (uint8_t *)&g_cdc_line_coding);
ret = usbh_control_transfer(cdc_acm_class->hport, setup, g_cdc_acm_buf);
if (ret < 0) {
return ret;
}
memcpy(line_coding, (uint8_t *)&g_cdc_line_coding, sizeof(struct cdc_line_coding));
memcpy(line_coding, g_cdc_acm_buf, sizeof(struct cdc_line_coding));
return ret;
}
@@ -79,19 +83,16 @@ int usbh_cdc_acm_set_line_state(struct usbh_cdc_acm *cdc_acm_class, bool dtr, bo
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE;
setup->wValue = (dtr << 0) | (rts << 1);
setup->wIndex = cdc_acm_class->ctrl_intf;
setup->wIndex = cdc_acm_class->intf;
setup->wLength = 0;
cdc_acm_class->dtr = dtr;
cdc_acm_class->rts = rts;
return usbh_control_transfer(cdc_acm_class->hport, setup, NULL);
}
static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
int ret;
int ret = 0;
struct usbh_cdc_acm *cdc_acm_class = usbh_cdc_acm_class_alloc();
if (cdc_acm_class == NULL) {
@@ -100,28 +101,11 @@ static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf)
}
cdc_acm_class->hport = hport;
cdc_acm_class->ctrl_intf = intf;
cdc_acm_class->data_intf = intf + 1;
cdc_acm_class->intf = intf;
hport->config.intf[intf].priv = cdc_acm_class;
hport->config.intf[intf + 1].priv = NULL;
cdc_acm_class->linecoding.dwDTERate = 115200;
cdc_acm_class->linecoding.bDataBits = 8;
cdc_acm_class->linecoding.bParityType = 0;
cdc_acm_class->linecoding.bCharFormat = 0;
ret = usbh_cdc_acm_set_line_coding(cdc_acm_class, &cdc_acm_class->linecoding);
if (ret < 0) {
USB_LOG_ERR("Fail to set linecoding\r\n");
return ret;
}
ret = usbh_cdc_acm_set_line_state(cdc_acm_class, true, true);
if (ret < 0) {
USB_LOG_ERR("Fail to set line state\r\n");
return ret;
}
#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
USBH_EP_INIT(cdc_acm_class->intin, ep_desc);
@@ -140,6 +124,34 @@ static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf)
USB_LOG_INFO("Register CDC ACM Class:%s\r\n", hport->config.intf[intf].devname);
#if 0
USB_LOG_INFO("Test cdc acm 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_cdc_acm_set_line_coding(cdc_acm_class, &linecoding);
usbh_cdc_acm_set_line_state(cdc_acm_class, true, false);
memset(g_cdc_acm_buf, 'a', sizeof(g_cdc_acm_buf));
ret = usbh_cdc_acm_bulk_out_transfer(cdc_acm_class, g_cdc_acm_buf, sizeof(g_cdc_acm_buf), 0xfffffff);
USB_LOG_RAW("out ret:%d\r\n", ret);
while (count--) {
ret = usbh_cdc_acm_bulk_in_transfer(cdc_acm_class, g_cdc_acm_buf, sizeof(g_cdc_acm_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_cdc_acm_buf[i]);
}
}
USB_LOG_RAW("\r\n");
}
#endif
usbh_cdc_acm_run(cdc_acm_class);
return ret;
}

View File

@@ -12,16 +12,18 @@ struct usbh_cdc_acm {
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 (optional) */
#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
struct usb_endpoint_descriptor *intin; /* INTR IN endpoint (optional) */
#endif
struct usbh_urb bulkout_urb;
struct usbh_urb bulkin_urb;
#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
struct usbh_urb intin_urb;
#endif
struct cdc_line_coding linecoding;
uint8_t ctrl_intf; /* Control interface number */
uint8_t data_intf; /* Data interface number */
bool dtr;
bool rts;
uint8_t intf;
uint8_t minor;
};

View File

@@ -6,6 +6,10 @@
#include "usbh_core.h"
#include "usbh_cdc_ecm.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_cdc_ecm"
#include "usb_log.h"
#define DEV_FORMAT "/dev/cdc_ether"
/* general descriptor field offsets */
@@ -39,7 +43,7 @@ static int usbh_cdc_ecm_set_eth_packet_filter(struct usbh_cdc_ecm *cdc_ecm_class
return usbh_control_transfer(cdc_ecm_class->hport, setup, NULL);
}
int usbh_cdc_ecm_get_notification(struct usbh_cdc_ecm *cdc_ecm_class)
int usbh_cdc_ecm_get_connect_status(struct usbh_cdc_ecm *cdc_ecm_class)
{
int ret;
@@ -240,7 +244,7 @@ find_class:
}
while (g_cdc_ecm_class.connect_status == false) {
ret = usbh_cdc_ecm_get_notification(&g_cdc_ecm_class);
ret = usbh_cdc_ecm_get_connect_status(&g_cdc_ecm_class);
if (ret < 0) {
usb_osal_msleep(100);
goto find_class;
@@ -257,7 +261,7 @@ find_class:
g_cdc_ecm_rx_length += g_cdc_ecm_class.bulkin_urb.actual_length;
if (g_cdc_ecm_rx_length % USB_GET_MAXPACKETSIZE(g_cdc_ecm_class.bulkin->wMaxPacketSize)) {
if (g_cdc_ecm_class.bulkin_urb.actual_length != USB_GET_MAXPACKETSIZE(g_cdc_ecm_class.bulkin->wMaxPacketSize)) {
USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ecm_rx_length);
p = pbuf_alloc(PBUF_RAW, g_cdc_ecm_rx_length, PBUF_POOL);
@@ -274,6 +278,7 @@ find_class:
USB_LOG_ERR("No memory to alloc pbuf for cdc ecm rx\r\n");
}
} else {
/* read continue util read short packet */
}
}
// clang-format off

View File

@@ -38,6 +38,8 @@ struct usbh_cdc_ecm {
extern "C" {
#endif
int usbh_cdc_ecm_get_connect_status(struct usbh_cdc_ecm *cdc_ecm_class);
void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class);
void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class);

View File

@@ -428,7 +428,7 @@ void dfu_request_abort(void)
}
}
static int dfu_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
static int dfu_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_DBG("DFU Class request: "
"bRequest 0x%02x\r\n",
@@ -464,7 +464,7 @@ static int dfu_class_interface_request_handler(struct usb_setup_packet *setup, u
return 0;
}
static void dfu_notify_handler(uint8_t event, void *arg)
static void dfu_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:

View File

@@ -6,7 +6,7 @@
#include "usbd_core.h"
#include "usbd_hid.h"
static int hid_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
static int hid_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_DBG("HID Class request: "
"bRequest 0x%02x\r\n",
@@ -17,27 +17,27 @@ static int hid_class_interface_request_handler(struct usb_setup_packet *setup, u
switch (setup->bRequest) {
case HID_REQUEST_GET_REPORT:
/* report id ,report type */
usbd_hid_get_report(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), data, len);
usbd_hid_get_report(busid, intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), data, len);
break;
case HID_REQUEST_GET_IDLE:
(*data)[0] = usbd_hid_get_idle(intf_num, LO_BYTE(setup->wValue));
(*data)[0] = usbd_hid_get_idle(busid, intf_num, LO_BYTE(setup->wValue));
*len = 1;
break;
case HID_REQUEST_GET_PROTOCOL:
(*data)[0] = usbd_hid_get_protocol(intf_num);
(*data)[0] = usbd_hid_get_protocol(busid, intf_num);
*len = 1;
break;
case HID_REQUEST_SET_REPORT:
/* report id ,report type, report, report len */
usbd_hid_set_report(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), *data, *len);
usbd_hid_set_report(busid, intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), *data, *len);
break;
case HID_REQUEST_SET_IDLE:
/* report id, duration */
usbd_hid_set_idle(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue));
usbd_hid_set_idle(busid, intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue));
break;
case HID_REQUEST_SET_PROTOCOL:
/* protocol */
usbd_hid_set_protocol(intf_num, LO_BYTE(setup->wValue));
usbd_hid_set_protocol(busid, intf_num, LO_BYTE(setup->wValue));
break;
default:
@@ -48,7 +48,7 @@ static int hid_class_interface_request_handler(struct usb_setup_packet *setup, u
return 0;
}
struct usbd_interface *usbd_hid_init_intf(struct usbd_interface *intf, const uint8_t *desc, uint32_t desc_len)
struct usbd_interface *usbd_hid_init_intf(uint8_t busid, struct usbd_interface *intf, const uint8_t *desc, uint32_t desc_len)
{
intf->class_interface_handler = hid_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
@@ -60,30 +60,30 @@ struct usbd_interface *usbd_hid_init_intf(struct usbd_interface *intf, const uin
return intf;
}
__WEAK void usbd_hid_get_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t **data, uint32_t *len)
__WEAK void usbd_hid_get_report(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t **data, uint32_t *len)
{
(*data[0]) = 0;
*len = 1;
}
__WEAK uint8_t usbd_hid_get_idle(uint8_t intf, uint8_t report_id)
__WEAK uint8_t usbd_hid_get_idle(uint8_t busid, uint8_t intf, uint8_t report_id)
{
return 0;
}
__WEAK uint8_t usbd_hid_get_protocol(uint8_t intf)
__WEAK uint8_t usbd_hid_get_protocol(uint8_t busid, uint8_t intf)
{
return 0;
}
__WEAK void usbd_hid_set_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t *report, uint32_t report_len)
__WEAK void usbd_hid_set_report(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t *report, uint32_t report_len)
{
}
__WEAK void usbd_hid_set_idle(uint8_t intf, uint8_t report_id, uint8_t duration)
__WEAK void usbd_hid_set_idle(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t duration)
{
}
__WEAK void usbd_hid_set_protocol(uint8_t intf, uint8_t protocol)
__WEAK void usbd_hid_set_protocol(uint8_t busid, uint8_t intf, uint8_t protocol)
{
}

View File

@@ -13,19 +13,19 @@ extern "C" {
#endif
/* Init hid interface driver */
struct usbd_interface *usbd_hid_init_intf(struct usbd_interface *intf, const uint8_t *desc, uint32_t desc_len);
struct usbd_interface *usbd_hid_init_intf(uint8_t busid, struct usbd_interface *intf, const uint8_t *desc, uint32_t desc_len);
/* Register desc api */
void usbd_hid_descriptor_register(uint8_t intf_num, const uint8_t *desc);
void usbd_hid_report_descriptor_register(uint8_t intf_num, const uint8_t *desc, uint32_t desc_len);
void usbd_hid_descriptor_register(uint8_t busid, uint8_t intf_num, const uint8_t *desc);
void usbd_hid_report_descriptor_register(uint8_t busid, uint8_t intf_num, const uint8_t *desc, uint32_t desc_len);
/* Setup request command callback api */
void usbd_hid_get_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t **data, uint32_t *len);
uint8_t usbd_hid_get_idle(uint8_t intf, uint8_t report_id);
uint8_t usbd_hid_get_protocol(uint8_t intf);
void usbd_hid_set_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t *report, uint32_t report_len);
void usbd_hid_set_idle(uint8_t intf, uint8_t report_id, uint8_t duration);
void usbd_hid_set_protocol(uint8_t intf, uint8_t protocol);
void usbd_hid_get_report(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t **data, uint32_t *len);
uint8_t usbd_hid_get_idle(uint8_t busid, uint8_t intf, uint8_t report_id);
uint8_t usbd_hid_get_protocol(uint8_t busid, uint8_t intf);
void usbd_hid_set_report(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t *report, uint32_t report_len);
void usbd_hid_set_idle(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t duration);
void usbd_hid_set_protocol(uint8_t busid, uint8_t intf, uint8_t protocol);
#ifdef __cplusplus
}

View File

@@ -6,6 +6,10 @@
#include "usbh_core.h"
#include "usbh_hid.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_hid"
#include "usb_log.h"
#define DEV_FORMAT "/dev/input%d"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hid_buf[128];

View File

@@ -6,24 +6,21 @@
#include "usbh_core.h"
#include "usbh_hub.h"
#define DEV_FORMAT "/dev/hub%d"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_hub"
#include "usb_log.h"
#define DEV_FORMAT "/dev/hub%d"
#define HUB_DEBOUNCE_TIMEOUT 1500
#define HUB_DEBOUNCE_STEP 25
#define HUB_DEBOUNCE_STABLE 100
#define DELAY_TIME_AFTER_RESET 200
#define EXTHUB_FIRST_INDEX 2
#define EXTHUB_FIRST_INDEX 2
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_buf[32];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_intbuf[CONFIG_USBHOST_MAX_EXTHUBS + 1][CONFIG_USB_ALIGN_SIZE];
usb_slist_t hub_class_head = USB_SLIST_OBJECT_INIT(hub_class_head);
usb_osal_thread_t hub_thread;
usb_osal_mq_t hub_mq;
struct usbh_hub roothub;
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_buf[CONFIG_USBHOST_MAX_BUS][USB_ALIGN_UP(32, CONFIG_USB_ALIGN_SIZE)];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_intbuf[CONFIG_USBHOST_MAX_BUS][CONFIG_USBHOST_MAX_EXTHUBS + 1][USB_ALIGN_UP(1, CONFIG_USB_ALIGN_SIZE)];
extern int usbh_free_devaddr(struct usbh_hubport *hport);
extern int usbh_enumerate(struct usbh_hubport *hport);
@@ -67,17 +64,7 @@ static void usbh_hub_class_free(struct usbh_hub *hub_class)
}
#endif
static void usbh_hub_register(struct usbh_hub *hub)
{
usb_slist_add_tail(&hub_class_head, &hub->list);
}
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
static void usbh_hub_unregister(struct usbh_hub *hub)
{
usb_slist_remove(&hub_class_head, &hub->list);
}
static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
{
struct usb_setup_packet *setup;
@@ -100,7 +87,7 @@ static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
setup->wIndex = 0;
setup->wLength = USB_SIZEOF_HUB_DESC;
ret = usbh_control_transfer(hub->parent, setup, g_hub_buf);
ret = usbh_control_transfer(hub->parent, setup, g_hub_buf[hub->bus->busid]);
if (ret < 0) {
return ret;
}
@@ -144,11 +131,11 @@ static int _usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct h
setup->wIndex = port;
setup->wLength = 4;
ret = usbh_control_transfer(hub->parent, setup, g_hub_buf);
ret = usbh_control_transfer(hub->parent, setup, g_hub_buf[hub->bus->busid]);
if (ret < 0) {
return ret;
}
memcpy(port_status, g_hub_buf, 4);
memcpy(port_status, g_hub_buf[hub->bus->busid], 4);
return ret;
}
@@ -233,7 +220,7 @@ static int usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hu
setup->wValue = 0;
setup->wIndex = port;
setup->wLength = 4;
return usbh_roothub_control(&roothub_setup, (uint8_t *)port_status);
return usbh_roothub_control(hub->bus, &roothub_setup, (uint8_t *)port_status);
} else {
return _usbh_hub_get_portstatus(hub, port, port_status);
}
@@ -251,7 +238,7 @@ int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
setup->wValue = feature;
setup->wIndex = port;
setup->wLength = 0;
return usbh_roothub_control(setup, NULL);
return usbh_roothub_control(hub->bus, setup, NULL);
} else {
return _usbh_hub_set_feature(hub, port, feature);
}
@@ -269,7 +256,7 @@ int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
setup->wValue = feature;
setup->wIndex = port;
setup->wLength = 0;
return usbh_roothub_control(setup, NULL);
return usbh_roothub_control(hub->bus, setup, NULL);
} else {
return _usbh_hub_clear_feature(hub, port, feature);
}
@@ -287,17 +274,12 @@ static int usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
setup->wValue = depth;
setup->wIndex = 0;
setup->wLength = 0;
return usbh_roothub_control(setup, NULL);
return usbh_roothub_control(hub->bus, setup, NULL);
} else {
return _usbh_hub_set_depth(hub, depth);
}
}
static void usbh_hub_thread_wakeup(struct usbh_hub *hub)
{
usb_osal_mq_send(hub_mq, (uintptr_t)hub);
}
static void usbh_hubport_release(struct usbh_hubport *child)
{
if (child->connected) {
@@ -321,6 +303,9 @@ static void hub_int_complete_callback(void *arg, int nbytes)
if (nbytes > 0) {
usbh_hub_thread_wakeup(hub);
} else if (nbytes == -USB_ERR_NAK) {
usbh_submit_urb(&hub->intin_urb);
} else {
}
}
@@ -338,6 +323,7 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
hub->hub_addr = hport->dev_addr;
hub->parent = hport;
hub->bus = hport->bus;
hport->config.intf[intf].priv = hub;
@@ -351,6 +337,7 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
hub->child[port].port = port + 1;
hub->child[port].parent = hub;
hub->child[port].bus = hport->bus;
}
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
@@ -391,10 +378,12 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
hub->connected = true;
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, hub->index);
usbh_hub_register(hub);
usb_slist_add_tail(&hub->bus->hub_list, &hub->list);
USB_LOG_INFO("Register HUB Class:%s\r\n", hport->config.intf[intf].devname);
hub->int_buffer = g_hub_intbuf[hub->index - 1];
hub->int_buffer = g_hub_intbuf[hub->bus->busid][hub->index - 1];
usbh_int_urb_fill(&hub->intin_urb, hub->parent, hub->intin, hub->int_buffer, 1, 0, hub_int_complete_callback, hub);
usbh_submit_urb(&hub->intin_urb);
return 0;
@@ -420,7 +409,7 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister HUB Class:%s\r\n", hport->config.intf[intf].devname);
usbh_hub_unregister(hub);
usb_slist_remove(&hub->bus->hub_list, &hub->list);
}
usbh_hub_class_free(hub);
@@ -458,7 +447,7 @@ static void usbh_hub_events(struct usbh_hub *hub)
}
portchange_index = hub->int_buffer[0];
hub->int_buffer[0] = 0;
hub->int_buffer[0] &= ~portchange_index;
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
USB_LOG_DBG("Port change:0x%02x\r\n", portchange_index);
@@ -599,9 +588,10 @@ static void usbh_hub_events(struct usbh_hub *hub)
child->connected = true;
child->port = port + 1;
child->speed = speed;
child->bus = hub->bus;
child->mutex = usb_osal_mutex_create();
USB_LOG_INFO("New %s device on Hub %u, Port %u connected\r\n", speed_table[speed], hub->index, port + 1);
USB_LOG_INFO("New %s device on Bus %u, Hub %u, Port %u connected\r\n", speed_table[speed], hub->bus->busid, hub->index, port + 1);
/* create disposable thread to enumerate device on current hport, do not block hub thread */
usb_osal_thread_create("usbh_enum", CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO + 1, usbh_hubport_enumerate_thread, (void *)child);
@@ -619,7 +609,7 @@ static void usbh_hub_events(struct usbh_hub *hub)
child = &hub->child[port];
/** release child sources */
usbh_hubport_release(child);
USB_LOG_INFO("Device on Hub %u, Port %u disconnected\r\n", hub->index, port + 1);
USB_LOG_INFO("Device on Bus %u, Hub %u, Port %u disconnected\r\n", hub->bus->busid, hub->index, port + 1);
}
}
}
@@ -635,9 +625,11 @@ static void usbh_hub_thread(void *argument)
struct usbh_hub *hub;
int ret = 0;
usb_hc_init();
struct usbh_bus *bus = (struct usbh_bus *)argument;
usb_hc_init(bus);
while (1) {
ret = usb_osal_mq_recv(hub_mq, (uintptr_t *)&hub, USB_OSAL_WAITING_FOREVER);
ret = usb_osal_mq_recv(bus->hub_mq, (uintptr_t *)&hub, USB_OSAL_WAITING_FOREVER);
if (ret < 0) {
continue;
}
@@ -645,55 +637,41 @@ static void usbh_hub_thread(void *argument)
}
}
static void usbh_roothub_register(void)
void usbh_hub_thread_wakeup(struct usbh_hub *hub)
{
usb_slist_init(&hub_class_head);
memset(&roothub, 0, sizeof(struct usbh_hub));
roothub.connected = true;
roothub.index = 1;
roothub.is_roothub = true;
roothub.parent = NULL;
roothub.hub_addr = 1;
roothub.hub_desc.bNbrPorts = CONFIG_USBHOST_MAX_RHPORTS;
usbh_hub_register(&roothub);
usb_osal_mq_send(hub->bus->hub_mq, (uintptr_t)hub);
}
void usbh_roothub_thread_wakeup(uint8_t port)
int usbh_hub_initialize(struct usbh_bus *bus)
{
roothub.int_buffer = g_hub_intbuf[roothub.index - 1];
roothub.int_buffer[0] |= (1 << port);
usbh_hub_thread_wakeup(&roothub);
}
char thread_name[32] = { 0 };
int usbh_hub_initialize(void)
{
usbh_roothub_register();
hub_mq = usb_osal_mq_create(7);
if (hub_mq == NULL) {
bus->hub_mq = usb_osal_mq_create(7);
if (bus->hub_mq == NULL) {
USB_LOG_ERR("Failed to create hub mq\r\n");
return -1;
}
hub_thread = usb_osal_thread_create("usbh_hub", CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO, usbh_hub_thread, NULL);
if (hub_thread == NULL) {
snprintf(thread_name, 32, "usbh_hub%u", bus->busid);
bus->hub_thread = usb_osal_thread_create(thread_name, CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO, usbh_hub_thread, bus);
if (bus->hub_thread == NULL) {
USB_LOG_ERR("Failed to create hub thread\r\n");
return -1;
}
return 0;
}
int usbh_hub_deinitialize(void)
int usbh_hub_deinitialize(struct usbh_bus *bus)
{
usb_slist_t *i;
usb_slist_t *hub_list;
struct usbh_hubport *hport;
size_t flags;
flags = usb_osal_enter_critical_section();
usb_slist_for_each(i, &hub_class_head)
usb_slist_for_each(hub_list, &bus->hub_list)
{
struct usbh_hub *hub = usb_slist_entry(i, struct usbh_hub, list);
struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list);
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
hport = &hub->child[port];
@@ -702,12 +680,12 @@ int usbh_hub_deinitialize(void)
}
}
usb_hc_deinit();
usb_hc_deinit(bus);
usb_osal_leave_critical_section(flags);
usb_osal_mq_delete(hub_mq);
usb_osal_thread_delete(hub_thread);
usb_osal_mq_delete(bus->hub_mq);
usb_osal_thread_delete(bus->hub_thread);
return 0;
}

View File

@@ -8,13 +8,12 @@
#include "usb_hub.h"
struct usbh_hub;
#define USBH_HUB_MAX_PORTS 4
/* Maximum size of an interrupt IN transfer */
#define USBH_HUB_INTIN_BUFSIZE ((USBH_HUB_MAX_PORTS + 8) >> 3)
extern usb_slist_t hub_class_head;
extern struct usbh_hub roothub;
#ifdef __cplusplus
extern "C" {
#endif
@@ -22,10 +21,10 @@ extern "C" {
int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature);
int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature);
void usbh_roothub_thread_wakeup(uint8_t port);
void usbh_hub_thread_wakeup(struct usbh_hub *hub);
int usbh_hub_initialize(void);
int usbh_hub_deinitialize(void);
int usbh_hub_initialize(struct usbh_bus *bus);
int usbh_hub_deinitialize(struct usbh_bus *bus);
#ifdef __cplusplus
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2022, sakumisu
* Copyright (c) 2024, zhihong chen
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -13,16 +14,16 @@ extern "C" {
#endif
/* Init msc interface driver */
struct usbd_interface *usbd_msc_init_intf(struct usbd_interface *intf,
struct usbd_interface *usbd_msc_init_intf(uint8_t busid, struct usbd_interface *intf,
const uint8_t out_ep,
const uint8_t in_ep);
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size);
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length);
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length);
void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size);
int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length);
int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length);
void usbd_msc_set_readonly(bool readonly);
bool usbd_msc_set_popup(void);
void usbd_msc_set_readonly(uint8_t busid, bool readonly);
bool usbd_msc_set_popup(uint8_t busid);
#ifdef __cplusplus
}

View File

@@ -7,6 +7,10 @@
#include "usbh_msc.h"
#include "usb_scsi.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_msc"
#include "usb_log.h"
#define DEV_FORMAT "/dev/sd%c"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_msc_buf[32];

View File

@@ -1,7 +1,7 @@
#include "usbd_core.h"
#include "usbd_xxx.h"
static int xxx_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
static int xxx_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_WRN("XXX Class request: "
"bRequest 0x%02x\r\n",
@@ -16,7 +16,7 @@ static int xxx_class_interface_request_handler(struct usb_setup_packet *setup, u
return 0;
}
static void xxx_notify_handler(uint8_t event, void *arg)
static void xxx_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -28,7 +28,7 @@ static void xxx_notify_handler(uint8_t event, void *arg)
}
}
struct usbd_interface *usbd_xxx_init_intf(struct usbd_interface *intf)
struct usbd_interface *usbd_xxx_init_intf(uint8_t busid, struct usbd_interface *intf)
{
intf->class_interface_handler = xxx_class_interface_request_handler;
intf->class_endpoint_handler = NULL;

View File

@@ -7,7 +7,7 @@
extern "C" {
#endif
struct usbd_interface *usbd_xxx_init_intf(struct usbd_interface *intf);
struct usbd_interface *usbd_xxx_init_intf(uint8_t busid, struct usbd_interface *intf);
#ifdef __cplusplus
}

797
class/vendor/net/usbh_asix.c vendored Normal file
View File

@@ -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
};

180
class/vendor/net/usbh_asix.h vendored Normal file
View File

@@ -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 */

352
class/vendor/serial/usbh_ch34x.c vendored Normal file
View File

@@ -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
};

74
class/vendor/serial/usbh_ch34x.h vendored Normal file
View File

@@ -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 */

291
class/vendor/serial/usbh_cp210x.c vendored Normal file
View File

@@ -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
};

71
class/vendor/serial/usbh_cp210x.h vendored Normal file
View File

@@ -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 */

368
class/vendor/serial/usbh_ftdi.c vendored Normal file
View File

@@ -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
};

74
class/vendor/serial/usbh_ftdi.h vendored Normal file
View File

@@ -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 */

View File

@@ -18,9 +18,9 @@ struct usbd_video_priv {
uint8_t power_mode;
uint8_t error_code;
struct video_entity_info info[3];
} g_usbd_video;
} g_usbd_video[CONFIG_USBDEV_MAX_BUS];
static int usbd_video_control_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
static int usbd_video_control_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
@@ -60,13 +60,13 @@ static int usbd_video_control_request_handler(struct usb_setup_packet *setup, ui
return 0;
}
static int usbd_video_control_unit_terminal_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
uint8_t entity_id = (uint8_t)(setup->wIndex >> 8);
uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
for (uint8_t i = 0; i < 3; i++) {
struct video_entity_info *entity_info = &g_usbd_video.info[i];
struct video_entity_info *entity_info = &g_usbd_video[busid].info[i];
if (entity_info->bEntityId == entity_id) {
switch (entity_info->bDescriptorSubtype) {
case VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE:
@@ -546,7 +546,7 @@ static int usbd_video_control_unit_terminal_request_handler(struct usb_setup_pac
}
break;
default:
g_usbd_video.error_code = 0x06;
g_usbd_video[busid].error_code = 0x06;
USB_LOG_WRN("Unhandled Video Class control selector 0x%02x\r\n", control_selector);
return -1;
}
@@ -564,7 +564,7 @@ static int usbd_video_control_unit_terminal_request_handler(struct usb_setup_pac
return 0;
}
static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
static int usbd_video_stream_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
@@ -572,10 +572,10 @@ static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uin
case VIDEO_VS_PROBE_CONTROL:
switch (setup->bRequest) {
case VIDEO_REQUEST_SET_CUR:
//memcpy((uint8_t *)&g_usbd_video.probe, *data, setup->wLength);
//memcpy((uint8_t *)&g_usbd_video[busid].probe, *data, setup->wLength);
break;
case VIDEO_REQUEST_GET_CUR:
memcpy(*data, (uint8_t *)&g_usbd_video.probe, setup->wLength);
memcpy(*data, (uint8_t *)&g_usbd_video[busid].probe, setup->wLength);
*len = sizeof(struct video_probe_and_commit_controls);
break;
@@ -583,7 +583,7 @@ static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uin
case VIDEO_REQUEST_GET_MAX:
case VIDEO_REQUEST_GET_RES:
case VIDEO_REQUEST_GET_DEF:
memcpy(*data, (uint8_t *)&g_usbd_video.probe, setup->wLength);
memcpy(*data, (uint8_t *)&g_usbd_video[busid].probe, setup->wLength);
*len = sizeof(struct video_probe_and_commit_controls);
break;
case VIDEO_REQUEST_GET_LEN:
@@ -604,17 +604,17 @@ static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uin
case VIDEO_VS_COMMIT_CONTROL:
switch (setup->bRequest) {
case VIDEO_REQUEST_SET_CUR:
//memcpy((uint8_t *)&g_usbd_video.commit, *data, setup->wLength);
//memcpy((uint8_t *)&g_usbd_video[busid].commit, *data, setup->wLength);
break;
case VIDEO_REQUEST_GET_CUR:
memcpy(*data, (uint8_t *)&g_usbd_video.commit, setup->wLength);
memcpy(*data, (uint8_t *)&g_usbd_video[busid].commit, setup->wLength);
*len = sizeof(struct video_probe_and_commit_controls);
break;
case VIDEO_REQUEST_GET_MIN:
case VIDEO_REQUEST_GET_MAX:
case VIDEO_REQUEST_GET_RES:
case VIDEO_REQUEST_GET_DEF:
memcpy(*data, (uint8_t *)&g_usbd_video.commit, setup->wLength);
memcpy(*data, (uint8_t *)&g_usbd_video[busid].commit, setup->wLength);
*len = sizeof(struct video_probe_and_commit_controls);
break;
@@ -636,7 +636,7 @@ static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uin
case VIDEO_VS_STREAM_ERROR_CODE_CONTROL:
switch (setup->bRequest) {
case VIDEO_REQUEST_GET_CUR:
(*data)[0] = g_usbd_video.error_code;
(*data)[0] = g_usbd_video[busid].error_code;
*len = 1;
break;
case VIDEO_REQUEST_GET_INFO:
@@ -655,7 +655,7 @@ static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uin
return 0;
}
static int video_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
static int video_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_DBG("Video Class request: "
"bRequest 0x%02x\r\n",
@@ -666,30 +666,30 @@ static int video_class_interface_request_handler(struct usb_setup_packet *setup,
if (intf_num == 0) { /* Video Control Interface */
if (entity_id == 0) {
return usbd_video_control_request_handler(setup, data, len); /* Interface Control Requests */
return usbd_video_control_request_handler(busid, setup, data, len); /* Interface Control Requests */
} else {
return usbd_video_control_unit_terminal_request_handler(setup, data, len); /* Unit and Terminal Requests */
return usbd_video_control_unit_terminal_request_handler(busid, setup, data, len); /* Unit and Terminal Requests */
}
} else if (intf_num == 1) { /* Video Stream Inteface */
return usbd_video_stream_request_handler(setup, data, len); /* Interface Stream Requests */
return usbd_video_stream_request_handler(busid, setup, data, len); /* Interface Stream Requests */
}
return -1;
}
static void video_notify_handler(uint8_t event, void *arg)
static void video_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:
g_usbd_video.error_code = 0;
g_usbd_video.power_mode = 0;
g_usbd_video[busid].error_code = 0;
g_usbd_video[busid].power_mode = 0;
break;
case USBD_EVENT_SET_INTERFACE: {
struct usb_interface_descriptor *intf = (struct usb_interface_descriptor *)arg;
if (intf->bAlternateSetting == 1) {
usbd_video_open(intf->bInterfaceNumber);
usbd_video_open(busid, intf->bInterfaceNumber);
} else {
usbd_video_close(intf->bInterfaceNumber);
usbd_video_close(busid, intf->bInterfaceNumber);
}
}
@@ -699,46 +699,46 @@ static void video_notify_handler(uint8_t event, void *arg)
}
}
void usbd_video_probe_and_commit_controls_init(uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
void usbd_video_probe_and_commit_controls_init(uint8_t busid, uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
{
g_usbd_video.probe.hintUnion.bmHint = 0x01;
g_usbd_video.probe.hintUnion1.bmHint = 0;
g_usbd_video.probe.bFormatIndex = 1;
g_usbd_video.probe.bFrameIndex = 1;
g_usbd_video.probe.dwFrameInterval = dwFrameInterval;
g_usbd_video.probe.wKeyFrameRate = 0;
g_usbd_video.probe.wPFrameRate = 0;
g_usbd_video.probe.wCompQuality = 0;
g_usbd_video.probe.wCompWindowSize = 0;
g_usbd_video.probe.wDelay = 0;
g_usbd_video.probe.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
g_usbd_video.probe.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
g_usbd_video.probe.dwClockFrequency = 0;
g_usbd_video.probe.bmFramingInfo = 0;
g_usbd_video.probe.bPreferedVersion = 0;
g_usbd_video.probe.bMinVersion = 0;
g_usbd_video.probe.bMaxVersion = 0;
g_usbd_video[busid].probe.hintUnion.bmHint = 0x01;
g_usbd_video[busid].probe.hintUnion1.bmHint = 0;
g_usbd_video[busid].probe.bFormatIndex = 1;
g_usbd_video[busid].probe.bFrameIndex = 1;
g_usbd_video[busid].probe.dwFrameInterval = dwFrameInterval;
g_usbd_video[busid].probe.wKeyFrameRate = 0;
g_usbd_video[busid].probe.wPFrameRate = 0;
g_usbd_video[busid].probe.wCompQuality = 0;
g_usbd_video[busid].probe.wCompWindowSize = 0;
g_usbd_video[busid].probe.wDelay = 0;
g_usbd_video[busid].probe.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
g_usbd_video[busid].probe.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
g_usbd_video[busid].probe.dwClockFrequency = 0;
g_usbd_video[busid].probe.bmFramingInfo = 0;
g_usbd_video[busid].probe.bPreferedVersion = 0;
g_usbd_video[busid].probe.bMinVersion = 0;
g_usbd_video[busid].probe.bMaxVersion = 0;
g_usbd_video.commit.hintUnion.bmHint = 0x01;
g_usbd_video.commit.hintUnion1.bmHint = 0;
g_usbd_video.commit.bFormatIndex = 1;
g_usbd_video.commit.bFrameIndex = 1;
g_usbd_video.commit.dwFrameInterval = dwFrameInterval;
g_usbd_video.commit.wKeyFrameRate = 0;
g_usbd_video.commit.wPFrameRate = 0;
g_usbd_video.commit.wCompQuality = 0;
g_usbd_video.commit.wCompWindowSize = 0;
g_usbd_video.commit.wDelay = 0;
g_usbd_video.commit.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
g_usbd_video.commit.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
g_usbd_video.commit.dwClockFrequency = 0;
g_usbd_video.commit.bmFramingInfo = 0;
g_usbd_video.commit.bPreferedVersion = 0;
g_usbd_video.commit.bMinVersion = 0;
g_usbd_video.commit.bMaxVersion = 0;
g_usbd_video[busid].commit.hintUnion.bmHint = 0x01;
g_usbd_video[busid].commit.hintUnion1.bmHint = 0;
g_usbd_video[busid].commit.bFormatIndex = 1;
g_usbd_video[busid].commit.bFrameIndex = 1;
g_usbd_video[busid].commit.dwFrameInterval = dwFrameInterval;
g_usbd_video[busid].commit.wKeyFrameRate = 0;
g_usbd_video[busid].commit.wPFrameRate = 0;
g_usbd_video[busid].commit.wCompQuality = 0;
g_usbd_video[busid].commit.wCompWindowSize = 0;
g_usbd_video[busid].commit.wDelay = 0;
g_usbd_video[busid].commit.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
g_usbd_video[busid].commit.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
g_usbd_video[busid].commit.dwClockFrequency = 0;
g_usbd_video[busid].commit.bmFramingInfo = 0;
g_usbd_video[busid].commit.bPreferedVersion = 0;
g_usbd_video[busid].commit.bMinVersion = 0;
g_usbd_video[busid].commit.bMaxVersion = 0;
}
struct usbd_interface *usbd_video_init_intf(struct usbd_interface *intf,
struct usbd_interface *usbd_video_init_intf(uint8_t busid, struct usbd_interface *intf,
uint32_t dwFrameInterval,
uint32_t dwMaxVideoFrameSize,
uint32_t dwMaxPayloadTransferSize)
@@ -748,39 +748,39 @@ struct usbd_interface *usbd_video_init_intf(struct usbd_interface *intf,
intf->vendor_handler = NULL;
intf->notify_handler = video_notify_handler;
g_usbd_video.info[0].bDescriptorSubtype = VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE;
g_usbd_video.info[0].bEntityId = 0x01;
g_usbd_video.info[0].wTerminalType = VIDEO_ITT_CAMERA;
g_usbd_video.info[1].bDescriptorSubtype = VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE;
g_usbd_video.info[1].bEntityId = 0x03;
g_usbd_video.info[1].wTerminalType = 0x00;
g_usbd_video.info[2].bDescriptorSubtype = VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE;
g_usbd_video.info[2].bEntityId = 0x02;
g_usbd_video.info[2].wTerminalType = 0x00;
g_usbd_video[busid].info[0].bDescriptorSubtype = VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE;
g_usbd_video[busid].info[0].bEntityId = 0x01;
g_usbd_video[busid].info[0].wTerminalType = VIDEO_ITT_CAMERA;
g_usbd_video[busid].info[1].bDescriptorSubtype = VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE;
g_usbd_video[busid].info[1].bEntityId = 0x03;
g_usbd_video[busid].info[1].wTerminalType = 0x00;
g_usbd_video[busid].info[2].bDescriptorSubtype = VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE;
g_usbd_video[busid].info[2].bEntityId = 0x02;
g_usbd_video[busid].info[2].wTerminalType = 0x00;
usbd_video_probe_and_commit_controls_init(dwFrameInterval, dwMaxVideoFrameSize, dwMaxPayloadTransferSize);
usbd_video_probe_and_commit_controls_init(busid, dwFrameInterval, dwMaxVideoFrameSize, dwMaxPayloadTransferSize);
return intf;
}
uint32_t usbd_video_mjpeg_payload_fill(uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len)
uint32_t usbd_video_mjpeg_payload_fill(uint8_t busid, uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len)
{
uint32_t packets;
uint32_t last_packet_size;
uint32_t picture_pos = 0;
static uint8_t uvc_header[2] = { 0x02, 0x80 };
packets = (input_len + (g_usbd_video.probe.dwMaxPayloadTransferSize - 2) ) / (g_usbd_video.probe.dwMaxPayloadTransferSize - 2);
last_packet_size = input_len - ((packets - 1) * (g_usbd_video.probe.dwMaxPayloadTransferSize - 2));
packets = (input_len + (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2) ) / (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2);
last_packet_size = input_len - ((packets - 1) * (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2));
for (size_t i = 0; i < packets; i++) {
output[g_usbd_video.probe.dwMaxPayloadTransferSize * i] = uvc_header[0];
output[g_usbd_video.probe.dwMaxPayloadTransferSize * i + 1] = uvc_header[1];
output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i] = uvc_header[0];
output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i + 1] = uvc_header[1];
if (i == (packets - 1)) {
memcpy(&output[2 + g_usbd_video.probe.dwMaxPayloadTransferSize * i], &input[picture_pos], last_packet_size);
output[g_usbd_video.probe.dwMaxPayloadTransferSize * i + 1] |= (1 << 1);
memcpy(&output[2 + g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i], &input[picture_pos], last_packet_size);
output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i + 1] |= (1 << 1);
} else {
memcpy(&output[2 + g_usbd_video.probe.dwMaxPayloadTransferSize * i], &input[picture_pos], g_usbd_video.probe.dwMaxPayloadTransferSize - 2);
picture_pos += g_usbd_video.probe.dwMaxPayloadTransferSize - 2;
memcpy(&output[2 + g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i], &input[picture_pos], g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2);
picture_pos += g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2;
}
}
uvc_header[1] ^= 1;

View File

@@ -13,14 +13,14 @@ extern "C" {
#endif
/* Init video interface driver */
struct usbd_interface *usbd_video_init_intf(struct usbd_interface *intf,
struct usbd_interface *usbd_video_init_intf(uint8_t busid, struct usbd_interface *intf,
uint32_t dwFrameInterval,
uint32_t dwMaxVideoFrameSize,
uint32_t dwMaxPayloadTransferSize);
void usbd_video_open(uint8_t intf);
void usbd_video_close(uint8_t intf);
uint32_t usbd_video_mjpeg_payload_fill(uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len);
void usbd_video_open(uint8_t busid, uint8_t intf);
void usbd_video_close(uint8_t busid, uint8_t intf);
uint32_t usbd_video_mjpeg_payload_fill(uint8_t busid, uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len);
#ifdef __cplusplus
}

View File

@@ -6,6 +6,10 @@
#include "usbh_core.h"
#include "usbh_video.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_video"
#include "usb_log.h"
#define DEV_FORMAT "/dev/video%d"
/* general descriptor field offsets */

View File

@@ -105,10 +105,10 @@ static void rndis_notify_rsp(void)
{
memset(NOTIFY_RESPONSE_AVAILABLE, 0, 8);
NOTIFY_RESPONSE_AVAILABLE[0] = 0x01;
usbd_ep_start_write(rndis_ep_data[RNDIS_INT_EP_IDX].ep_addr, NOTIFY_RESPONSE_AVAILABLE, 8);
usbd_ep_start_write(0, rndis_ep_data[RNDIS_INT_EP_IDX].ep_addr, NOTIFY_RESPONSE_AVAILABLE, 8);
}
static int rndis_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
static int rndis_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
switch (setup->bRequest) {
case CDC_REQUEST_SEND_ENCAPSULATED_COMMAND:
@@ -426,7 +426,7 @@ static int rndis_keepalive_cmd_handler(uint8_t *data, uint32_t len)
return 0;
}
static void rndis_notify_handler(uint8_t event, void *arg)
static void rndis_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -436,7 +436,7 @@ static void rndis_notify_handler(uint8_t event, void *arg)
g_rndis_rx_data_length = 0;
g_rndis_tx_data_length = 0;
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_CONNECTED;
usbd_ep_start_read(rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
break;
default:
@@ -444,14 +444,14 @@ static void rndis_notify_handler(uint8_t event, void *arg)
}
}
void rndis_bulk_out(uint8_t ep, uint32_t nbytes)
void rndis_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
rndis_data_packet_t *hdr;
hdr = (rndis_data_packet_t *)g_rndis_rx_buffer;
g_rndis_rx_data_buffer = g_rndis_rx_buffer;
if ((hdr->MessageType != NDIS_PACKET_TYPE_DIRECTED) || (nbytes != hdr->MessageLength)) {
usbd_ep_start_read(rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
return;
}
@@ -462,17 +462,17 @@ void rndis_bulk_out(uint8_t ep, uint32_t nbytes)
usbd_rndis_data_recv_done();
}
void rndis_bulk_in(uint8_t ep, uint32_t nbytes)
void rndis_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
if ((nbytes % RNDIS_MAX_PACKET_SIZE) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(ep, NULL, 0);
usbd_ep_start_write(0, ep, NULL, 0);
} else {
g_rndis_tx_data_length = 0;
}
}
void rndis_int_in(uint8_t ep, uint32_t nbytes)
void rndis_int_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
//USB_LOG_DBG("len:%d\r\n", nbytes);
}
@@ -496,7 +496,7 @@ struct pbuf *usbd_rndis_eth_rx(void)
USB_LOG_DBG("rxlen:%d\r\n", g_rndis_rx_data_length);
g_rndis_rx_data_length = 0;
usbd_ep_start_read(rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
return p;
}
@@ -536,7 +536,7 @@ int usbd_rndis_eth_tx(struct pbuf *p)
g_rndis_tx_data_length = sizeof(rndis_data_packet_t) + p->tot_len;
USB_LOG_DBG("txlen:%d\r\n", g_rndis_tx_data_length);
return usbd_ep_start_write(rndis_ep_data[RNDIS_IN_EP_IDX].ep_addr, g_rndis_tx_buffer, g_rndis_tx_data_length);
return usbd_ep_start_write(0, rndis_ep_data[RNDIS_IN_EP_IDX].ep_addr, g_rndis_tx_buffer, g_rndis_tx_data_length);
}
#endif
struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
@@ -557,9 +557,9 @@ struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
rndis_ep_data[RNDIS_INT_EP_IDX].ep_addr = int_ep;
rndis_ep_data[RNDIS_INT_EP_IDX].ep_cb = rndis_int_in;
usbd_add_endpoint(&rndis_ep_data[RNDIS_OUT_EP_IDX]);
usbd_add_endpoint(&rndis_ep_data[RNDIS_IN_EP_IDX]);
usbd_add_endpoint(&rndis_ep_data[RNDIS_INT_EP_IDX]);
usbd_add_endpoint(0, &rndis_ep_data[RNDIS_OUT_EP_IDX]);
usbd_add_endpoint(0, &rndis_ep_data[RNDIS_IN_EP_IDX]);
usbd_add_endpoint(0, &rndis_ep_data[RNDIS_INT_EP_IDX]);
intf->class_interface_handler = rndis_class_interface_request_handler;
intf->class_endpoint_handler = NULL;

View File

@@ -0,0 +1,399 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_bluetooth.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_bluetooth"
#include "usb_log.h"
#define DEV_FORMAT "/dev/bluetooth"
static struct usbh_bluetooth g_bluetooth_class;
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_tx_buf[1 + CONFIG_USBHOST_BLUETOOTH_TX_SIZE];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_rx_buf[1 + CONFIG_USBHOST_BLUETOOTH_RX_SIZE];
#else
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_cmd_buf[1 + 256];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_evt_buf[1 + 256];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_tx_buf[1 + CONFIG_USBHOST_BLUETOOTH_TX_SIZE];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_rx_buf[1 + CONFIG_USBHOST_BLUETOOTH_RX_SIZE];
#endif
static int usbh_bluetooth_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
int ret = 0;
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
uint8_t mult;
uint16_t mps;
#endif
struct usbh_bluetooth *bluetooth_class = &g_bluetooth_class;
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
if (intf != 0) {
return 0;
}
#endif
memset(bluetooth_class, 0, sizeof(struct usbh_bluetooth));
bluetooth_class->hport = hport;
bluetooth_class->intf = intf;
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
bluetooth_class->num_of_intf_altsettings = hport->config.intf[intf + 1].altsetting_num;
#endif
hport->config.intf[intf].priv = bluetooth_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;
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
if (USB_GET_ENDPOINT_TYPE(ep_desc->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) {
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(bluetooth_class->intin, ep_desc);
} else {
return -USB_ERR_NOTSUPP;
}
} else {
#endif
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(bluetooth_class->bulkin, ep_desc);
} else {
USBH_EP_INIT(bluetooth_class->bulkout, ep_desc);
}
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
}
#endif
}
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
USB_LOG_INFO("Num of altsettings:%u\r\n", bluetooth_class->num_of_intf_altsettings);
for (uint8_t i = 0; i < bluetooth_class->num_of_intf_altsettings; i++) {
USB_LOG_INFO("Altsetting:%u\r\n", i);
for (uint8_t j = 0; j < hport->config.intf[intf + 1].altsetting[i].intf_desc.bNumEndpoints; j++) {
ep_desc = &bluetooth_class->hport->config.intf[intf + 1].altsetting[i].ep[j].ep_desc;
mult = USB_GET_MULT(ep_desc->wMaxPacketSize);
mps = USB_GET_MAXPACKETSIZE(ep_desc->wMaxPacketSize);
USB_LOG_INFO("\tEp=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n",
ep_desc->bEndpointAddress,
ep_desc->bmAttributes,
mps,
ep_desc->bInterval,
mult);
}
}
ret = usbh_set_interface(hport, intf, 0);
if (ret < 0) {
return ret;
}
USB_LOG_INFO("Bluetooth select altsetting 0\r\n");
#endif
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT);
USB_LOG_INFO("Register Bluetooth Class:%s\r\n", hport->config.intf[intf].devname);
usbh_bluetooth_run(bluetooth_class);
return ret;
}
static int usbh_bluetooth_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_bluetooth *bluetooth_class = (struct usbh_bluetooth *)hport->config.intf[intf].priv;
if (hport->config.config_desc.bNumInterfaces == (intf + 1)) {
return 0;
}
if (bluetooth_class) {
if (bluetooth_class->bulkin) {
usbh_kill_urb(&bluetooth_class->bulkin_urb);
}
if (bluetooth_class->bulkout) {
usbh_kill_urb(&bluetooth_class->bulkout_urb);
}
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
if (bluetooth_class->intin) {
usbh_kill_urb(&bluetooth_class->intin_urb);
}
// if (bluetooth_class->isoin) {
// usbh_kill_urb(&bluetooth_class->isoin_urb);
// }
// if (bluetooth_class->isoin) {
// usbh_kill_urb(&bluetooth_class->isoinin_urb);
// }
#endif
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister Bluetooth Class:%s\r\n", hport->config.intf[intf].devname);
usbh_bluetooth_stop(bluetooth_class);
}
memset(bluetooth_class, 0, sizeof(struct usbh_bluetooth));
}
return ret;
}
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_LOG
static void usbh_bluetooth_hci_dump(uint8_t *data, uint32_t len)
{
uint32_t i = 0;
for (i = 0; i < len; i++) {
if (i % 16 == 0) {
USB_LOG_RAW("\r\n");
}
USB_LOG_RAW("%02x ", data[i]);
}
USB_LOG_RAW("\r\n");
}
#else
#define usbh_bluetooth_hci_dump(data, len)
#endif
static int usbh_bluetooth_hci_bulk_out(uint8_t *buffer, uint32_t buflen)
{
struct usbh_bluetooth *bluetooth_class = &g_bluetooth_class;
struct usbh_urb *urb = &bluetooth_class->bulkout_urb;
int ret;
usbh_bulk_urb_fill(urb, bluetooth_class->hport, bluetooth_class->bulkout, buffer, buflen, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
return ret;
}
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4
int usbh_bluetooth_hci_write(uint8_t hci_type, uint8_t *buffer, uint32_t buflen)
{
int ret;
g_bluetooth_tx_buf[0] = hci_type;
memcpy(&g_bluetooth_tx_buf[1], buffer, buflen);
usbh_bluetooth_hci_dump(g_bluetooth_tx_buf, buflen + 1);
ret = usbh_bluetooth_hci_bulk_out(g_bluetooth_tx_buf, buflen + 1);
return ret;
}
void usbh_bluetooth_hci_rx_thread(void *argument)
{
int ret;
uint32_t ep_mps;
uint8_t retry = 0;
uint16_t actual_len = 0;
ep_mps = USB_GET_MAXPACKETSIZE(g_bluetooth_class.bulkin->wMaxPacketSize);
USB_LOG_INFO("Create hc rx thread\r\n");
while (1) {
usbh_bulk_urb_fill(&g_bluetooth_class.bulkin_urb, g_bluetooth_class.hport, g_bluetooth_class.bulkin, &g_bluetooth_rx_buf[actual_len], ep_mps, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_bluetooth_class.bulkin_urb);
if (ret < 0) {
if (ret == -USB_ERR_SHUTDOWN) {
goto delete;
} else {
retry++;
if (retry == 3) {
retry = 0;
goto delete;
}
continue;
}
}
actual_len += g_bluetooth_class.bulkin_urb.actual_length;
if (g_bluetooth_class.bulkin_urb.actual_length != ep_mps) {
usbh_bluetooth_hci_dump(g_bluetooth_rx_buf, actual_len);
usbh_bluetooth_hci_read_callback(g_bluetooth_rx_buf, actual_len);
actual_len = 0;
} else {
/* read continue util read short packet */
}
}
// clang-format off
delete :
USB_LOG_INFO("Delete hc acl rx thread\r\n");
usb_osal_thread_delete(NULL);
// clang-format on
}
#else
static int usbh_bluetooth_hci_cmd(uint8_t *buffer, uint32_t buflen)
{
struct usbh_bluetooth *bluetooth_class = &g_bluetooth_class;
struct usb_setup_packet *setup = bluetooth_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = 0x00;
setup->wValue = 0;
setup->wIndex = bluetooth_class->intf;
setup->wLength = buflen;
return usbh_control_transfer(bluetooth_class->hport, setup, buffer);
}
int usbh_bluetooth_hci_write(uint8_t hci_type, uint8_t *buffer, uint32_t buflen)
{
int ret;
if (hci_type == USB_BLUETOOTH_HCI_CMD) {
g_bluetooth_cmd_buf[0] = USB_BLUETOOTH_HCI_CMD;
memcpy(&g_bluetooth_cmd_buf[1], buffer, buflen);
usbh_bluetooth_hci_dump(g_bluetooth_cmd_buf, buflen + 1);
ret = usbh_bluetooth_hci_cmd(&g_bluetooth_cmd_buf[1], buflen);
} else if (hci_type == USB_BLUETOOTH_HCI_ACL) {
g_bluetooth_tx_buf[0] = USB_BLUETOOTH_HCI_ACL;
memcpy(&g_bluetooth_tx_buf[1], buffer, buflen);
usbh_bluetooth_hci_dump(g_bluetooth_tx_buf, buflen + 1);
ret = usbh_bluetooth_hci_bulk_out(&g_bluetooth_tx_buf[1], buflen);
} else {
ret = -1;
}
return ret;
}
void usbh_bluetooth_hci_evt_rx_thread(void *argument)
{
int ret;
uint32_t ep_mps;
uint32_t interval;
uint8_t retry = 0;
uint16_t actual_len = 0;
ep_mps = USB_GET_MAXPACKETSIZE(g_bluetooth_class.intin->wMaxPacketSize);
interval = g_bluetooth_class.intin->bInterval;
USB_LOG_INFO("Create hc event rx thread\r\n");
while (1) {
usbh_int_urb_fill(&g_bluetooth_class.intin_urb, g_bluetooth_class.hport, g_bluetooth_class.intin, &g_bluetooth_evt_buf[1 + actual_len], ep_mps, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_bluetooth_class.intin_urb);
if (ret < 0) {
if (ret == -USB_ERR_SHUTDOWN) {
goto delete;
} else if (ret == -USB_ERR_NAK) {
usb_osal_msleep(interval);
continue;
} else {
retry++;
if (retry == 3) {
retry = 0;
goto delete;
}
usb_osal_msleep(interval);
continue;
}
}
actual_len += g_bluetooth_class.intin_urb.actual_length;
if (g_bluetooth_class.intin_urb.actual_length != ep_mps) {
g_bluetooth_evt_buf[0] = USB_BLUETOOTH_HCI_EVT;
usbh_bluetooth_hci_dump(g_bluetooth_evt_buf, actual_len + 1);
usbh_bluetooth_hci_read_callback(g_bluetooth_evt_buf, actual_len + 1);
actual_len = 0;
} else {
/* read continue util read short packet */
}
usb_osal_msleep(interval);
}
// clang-format off
delete :
USB_LOG_INFO("Delete hc event rx thread\r\n");
usb_osal_thread_delete(NULL);
// clang-format on
}
void usbh_bluetooth_hci_acl_rx_thread(void *argument)
{
int ret;
uint32_t ep_mps;
uint8_t retry = 0;
uint16_t actual_len = 0;
ep_mps = USB_GET_MAXPACKETSIZE(g_bluetooth_class.bulkin->wMaxPacketSize);
USB_LOG_INFO("Create hc acl rx thread\r\n");
while (1) {
usbh_bulk_urb_fill(&g_bluetooth_class.bulkin_urb, g_bluetooth_class.hport, g_bluetooth_class.bulkin, &g_bluetooth_rx_buf[1 + actual_len], ep_mps, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_bluetooth_class.bulkin_urb);
if (ret < 0) {
if (ret == -USB_ERR_SHUTDOWN) {
goto delete;
} else {
retry++;
if (retry == 3) {
retry = 0;
goto delete;
}
continue;
}
}
actual_len += g_bluetooth_class.bulkin_urb.actual_length;
if (g_bluetooth_class.bulkin_urb.actual_length != ep_mps) {
g_bluetooth_rx_buf[0] = USB_BLUETOOTH_HCI_ACL;
usbh_bluetooth_hci_dump(g_bluetooth_rx_buf, actual_len + 1);
usbh_bluetooth_hci_read_callback(g_bluetooth_rx_buf, actual_len + 1);
actual_len = 0;
} else {
/* read continue util read short packet */
}
}
// clang-format off
delete :
USB_LOG_INFO("Delete hc acl rx thread\r\n");
usb_osal_thread_delete(NULL);
// clang-format on
}
#endif
__WEAK void usbh_bluetooth_hci_read_callback(uint8_t *data, uint32_t len)
{
}
__WEAK void usbh_bluetooth_run(struct usbh_bluetooth *bluetooth_class)
{
}
__WEAK void usbh_bluetooth_stop(struct usbh_bluetooth *bluetooth_class)
{
}
static const struct usbh_class_driver bluetooth_class_driver = {
.driver_name = "bluetooth",
.connect = usbh_bluetooth_connect,
.disconnect = usbh_bluetooth_disconnect
};
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4
CLASS_INFO_DEFINE const struct usbh_class_info bluetooth_h4_nrf_class_info = {
.match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS,
.class = 0xff,
.subclass = 0x00,
.protocol = 0x00,
.vid = 0x2fe3,
.pid = 0x000c,
.class_driver = &bluetooth_class_driver
};
#else
CLASS_INFO_DEFINE const struct usbh_class_info bluetooth_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.class = USB_DEVICE_CLASS_WIRELESS,
.subclass = 0x01,
.protocol = 0x01,
.vid = 0x00,
.pid = 0x00,
.class_driver = &bluetooth_class_driver
};
#endif

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_BLUETOOTH_H
#define USBH_BLUETOOTH_H
#define USB_BLUETOOTH_HCI_NONE 0x00
#define USB_BLUETOOTH_HCI_CMD 0x01
#define USB_BLUETOOTH_HCI_ACL 0x02
#define USB_BLUETOOTH_HCI_SCO 0x03
#define USB_BLUETOOTH_HCI_EVT 0x04
#define USB_BLUETOOTH_HCI_ISO 0x05
struct usbh_bluetooth {
struct usbh_hubport *hport;
uint8_t intf;
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
struct usbh_urb bulkin_urb; /* Bulk IN urb */
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
struct usb_endpoint_descriptor *intin; /* INTR endpoint */
struct usb_endpoint_descriptor *isoin; /* Bulk IN endpoint */
struct usb_endpoint_descriptor *isoout; /* Bulk OUT endpoint */
struct usbh_urb intin_urb; /* INTR IN urb */
struct usbh_urb *isoin_urb; /* Bulk IN urb */
struct usbh_urb *isoout_urb; /* Bulk OUT urb */
uint8_t num_of_intf_altsettings;
#endif
};
#ifdef __cplusplus
extern "C" {
#endif
int usbh_bluetooth_hci_write(uint8_t hci_type, uint8_t *buffer, uint32_t buflen);
void usbh_bluetooth_hci_read_callback(uint8_t *data, uint32_t len);
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4
void usbh_bluetooth_hci_rx_thread(void *argument);
#else
void usbh_bluetooth_hci_evt_rx_thread(void *argument);
void usbh_bluetooth_hci_acl_rx_thread(void *argument);
#endif
void usbh_bluetooth_run(struct usbh_bluetooth *bluetooth_class);
void usbh_bluetooth_stop(struct usbh_bluetooth *bluetooth_class);
#ifdef __cplusplus
}
#endif
#endif /* USBH_BLUETOOTH_H */

View File

@@ -7,6 +7,10 @@
#include "usbh_rndis.h"
#include "rndis_protocol.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_rndis"
#include "usb_log.h"
#define DEV_FORMAT "/dev/rndis"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_buf[4096];
@@ -185,7 +189,7 @@ static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t
return ret;
}
static int usbh_rndis_get_connect_status(struct usbh_rndis *rndis_class)
int usbh_rndis_get_connect_status(struct usbh_rndis *rndis_class)
{
int ret;
uint8_t data[32];
@@ -196,9 +200,9 @@ static int usbh_rndis_get_connect_status(struct usbh_rndis *rndis_class)
return ret;
}
if (NDIS_MEDIA_STATE_CONNECTED == data[0]) {
rndis_class->link_status = true;
rndis_class->connect_status = true;
} else {
rndis_class->link_status = false;
rndis_class->connect_status = false;
}
return 0;
}
@@ -326,9 +330,9 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
goto query_errorout;
}
if (NDIS_MEDIA_STATE_CONNECTED == data[0]) {
rndis_class->link_status = true;
rndis_class->connect_status = true;
} else {
rndis_class->link_status = false;
rndis_class->connect_status = false;
}
break;
case OID_802_3_MAXIMUM_LIST_SIZE:
@@ -438,12 +442,12 @@ void usbh_rndis_rx_thread(void *argument)
// clang-format off
find_class:
// clang-format on
g_rndis_class.link_status = false;
g_rndis_class.connect_status = false;
if (usbh_find_class_instance("/dev/rndis") == NULL) {
goto delete;
}
while (g_rndis_class.link_status == false) {
while (g_rndis_class.connect_status == false) {
ret = usbh_rndis_get_connect_status(&g_rndis_class);
if (ret < 0) {
usb_osal_msleep(100);
@@ -513,7 +517,7 @@ err_t usbh_rndis_linkoutput(struct netif *netif, struct pbuf *p)
uint8_t *buffer;
rndis_data_packet_t *hdr;
if (g_rndis_class.link_status == false) {
if (g_rndis_class.connect_status == false) {
return ERR_BUF;
}

View File

@@ -27,7 +27,7 @@ struct usbh_rndis {
uint32_t request_id;
uint32_t link_speed;
bool link_status;
bool connect_status;
uint8_t mac[6];
ip_addr_t ipaddr;
@@ -39,6 +39,7 @@ struct usbh_rndis {
extern "C" {
#endif
int usbh_rndis_get_connect_status(struct usbh_rndis *rndis_class);
int usbh_rndis_keepalive(struct usbh_rndis *rndis_class);
void usbh_rndis_run(struct usbh_rndis *rndis_class);

View File

@@ -16,13 +16,13 @@ extern "C" {
* @brief init device controller registers.
* @return On success will return 0, and others indicate fail.
*/
int usb_dc_init(void);
int usb_dc_init(uint8_t busid);
/**
* @brief deinit device controller registers.
* @return On success will return 0, and others indicate fail.
*/
int usb_dc_deinit(void);
int usb_dc_deinit(uint8_t busid);
/**
* @brief Set USB device address
@@ -31,7 +31,7 @@ int usb_dc_deinit(void);
*
* @return On success will return 0, and others indicate fail.
*/
int usbd_set_address(const uint8_t addr);
int usbd_set_address(uint8_t busid, const uint8_t addr);
/**
* @brief Get USB device speed
@@ -40,7 +40,7 @@ int usbd_set_address(const uint8_t addr);
*
* @return port speed, USB_SPEED_LOW or USB_SPEED_FULL or USB_SPEED_HIGH
*/
uint8_t usbd_get_port_speed(const uint8_t port);
uint8_t usbd_get_port_speed(uint8_t busid, const uint8_t port);
/**
* @brief configure and enable endpoint.
@@ -49,7 +49,7 @@ uint8_t usbd_get_port_speed(const uint8_t port);
*
* @return On success will return 0, and others indicate fail.
*/
int usbd_ep_open(const struct usb_endpoint_descriptor *ep);
int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep);
/**
* @brief Disable the selected endpoint
@@ -58,7 +58,7 @@ int usbd_ep_open(const struct usb_endpoint_descriptor *ep);
*
* @return On success will return 0, and others indicate fail.
*/
int usbd_ep_close(const uint8_t ep);
int usbd_ep_close(uint8_t busid, const uint8_t ep);
/**
* @brief Set stall condition for the selected endpoint
@@ -68,7 +68,7 @@ int usbd_ep_close(const uint8_t ep);
*
* @return On success will return 0, and others indicate fail.
*/
int usbd_ep_set_stall(const uint8_t ep);
int usbd_ep_set_stall(uint8_t busid, const uint8_t ep);
/**
* @brief Clear stall condition for the selected endpoint
@@ -78,7 +78,7 @@ int usbd_ep_set_stall(const uint8_t ep);
*
* @return On success will return 0, and others indicate fail.
*/
int usbd_ep_clear_stall(const uint8_t ep);
int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep);
/**
* @brief Check if the selected endpoint is stalled
@@ -89,7 +89,7 @@ int usbd_ep_clear_stall(const uint8_t ep);
*
* @return On success will return 0, and others indicate fail.
*/
int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled);
int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled);
/**
* @brief Setup in ep transfer setting and start transfer.
@@ -108,7 +108,7 @@ int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled);
* be zero for a zero length status packet.
* @return 0 on success, negative errno code on fail.
*/
int usbd_ep_start_write(const uint8_t ep, const uint8_t *data, uint32_t data_len);
int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len);
/**
* @brief Setup out ep transfer setting and start transfer.
@@ -127,40 +127,40 @@ int usbd_ep_start_write(const uint8_t ep, const uint8_t *data, uint32_t data_len
*
* @return 0 on success, negative errno code on fail.
*/
int usbd_ep_start_read(const uint8_t ep, uint8_t *data, uint32_t data_len);
int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len);
/* usb dcd irq callback */
/**
* @brief Usb connect irq callback.
*/
void usbd_event_connect_handler(void);
void usbd_event_connect_handler(uint8_t busid);
/**
* @brief Usb disconnect irq callback.
*/
void usbd_event_disconnect_handler(void);
void usbd_event_disconnect_handler(uint8_t busid);
/**
* @brief Usb resume irq callback.
*/
void usbd_event_resume_handler(void);
void usbd_event_resume_handler(uint8_t busid);
/**
* @brief Usb suspend irq callback.
*/
void usbd_event_suspend_handler(void);
void usbd_event_suspend_handler(uint8_t busid);
/**
* @brief Usb reset irq callback.
*/
void usbd_event_reset_handler(void);
void usbd_event_reset_handler(uint8_t busid);
/**
* @brief Usb setup packet recv irq callback.
* @param[in] psetup setup packet.
*/
void usbd_event_ep0_setup_complete_handler(uint8_t *psetup);
void usbd_event_ep0_setup_complete_handler(uint8_t busid, uint8_t *psetup);
/**
* @brief In ep transfer complete irq callback.
@@ -168,7 +168,7 @@ void usbd_event_ep0_setup_complete_handler(uint8_t *psetup);
* listed in the device configuration table
* @param[in] nbytes How many nbytes have transferred.
*/
void usbd_event_ep_in_complete_handler(uint8_t ep, uint32_t nbytes);
void usbd_event_ep_in_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbytes);
/**
* @brief Out ep transfer complete irq callback.
@@ -176,7 +176,7 @@ void usbd_event_ep_in_complete_handler(uint8_t ep, uint32_t nbytes);
* listed in the device configuration table
* @param[in] nbytes How many nbytes have transferred.
*/
void usbd_event_ep_out_complete_handler(uint8_t ep, uint32_t nbytes);
void usbd_event_ep_out_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbytes);
#ifdef __cplusplus
}

View File

@@ -14,6 +14,8 @@ extern "C" {
typedef void (*usbh_complete_callback_t)(void *arg, int nbytes);
struct usbh_bus;
/**
* @brief USB Iso Configuration.
*
@@ -59,21 +61,21 @@ struct usbh_urb {
*
* @return On success will return 0, and others indicate fail.
*/
int usb_hc_init(void);
int usb_hc_init(struct usbh_bus *bus);
/**
* @brief usb host controller hardware deinit.
*
* @return On success will return 0, and others indicate fail.
*/
int usb_hc_deinit(void);
int usb_hc_deinit(struct usbh_bus *bus);
/**
* @brief Get frame number.
*
* @return frame number.
*/
uint16_t usbh_get_frame_number(void);
uint16_t usbh_get_frame_number(struct usbh_bus *bus);
/**
* @brief control roothub.
*
@@ -81,7 +83,7 @@ uint16_t usbh_get_frame_number(void);
* @param buf buf for reading response or write data.
* @return On success will return 0, and others indicate fail.
*/
int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf);
int usbh_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, uint8_t *buf);
/**
* @brief Submit a usb transfer request to an endpoint.

View File

@@ -46,7 +46,7 @@
#endif
#elif defined(__ICCARM__) || defined(__ICCRX__) || defined(__ICCRISCV__)
#ifndef __USED
#if defined(__ICCARM_V8) || defined (__ICCRISCV__)
#if defined(__ICCARM_V8) || defined(__ICCRISCV__)
#define __USED __attribute__((used))
#else
#define __USED __root
@@ -54,7 +54,7 @@
#endif
#ifndef __WEAK
#if defined(__ICCARM_V8) || defined (__ICCRISCV__)
#if defined(__ICCARM_V8) || defined(__ICCRISCV__)
#define __WEAK __attribute__((weak))
#else
#define __WEAK _Pragma("__weak")
@@ -62,7 +62,7 @@
#endif
#ifndef __PACKED
#if defined(__ICCARM_V8) || defined (__ICCRISCV__)
#if defined(__ICCARM_V8) || defined(__ICCRISCV__)
#define __PACKED __attribute__((packed, aligned(1)))
#else
/* Needs IAR language extensions */
@@ -71,7 +71,7 @@
#endif
#ifndef __PACKED_STRUCT
#if defined(__ICCARM_V8) || defined (__ICCRISCV__)
#if defined(__ICCARM_V8) || defined(__ICCRISCV__)
#define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
#else
/* Needs IAR language extensions */
@@ -80,7 +80,7 @@
#endif
#ifndef __PACKED_UNION
#if defined(__ICCARM_V8) || defined (__ICCRISCV__)
#if defined(__ICCARM_V8) || defined(__ICCRISCV__)
#define __PACKED_UNION union __attribute__((packed, aligned(1)))
#else
/* Needs IAR language extensions */
@@ -89,7 +89,7 @@
#endif
#ifndef __ALIGNED
#if defined(__ICCARM_V8) || defined (__ICCRISCV__)
#if defined(__ICCARM_V8) || defined(__ICCRISCV__)
#define __ALIGNED(x) __attribute__((aligned(x)))
#elif (__VER__ >= 7080000)
/* Needs IAR language extensions */
@@ -205,4 +205,6 @@
#define USB_MEM_ALIGNX __attribute__((aligned(CONFIG_USB_ALIGN_SIZE)))
#define USB_ALIGN_UP(size, align) (((size) + (align)-1) & ~((align)-1))
#endif /* USB_UTIL_H */

File diff suppressed because it is too large Load Diff

View File

@@ -38,12 +38,14 @@ enum usbd_event_type {
USBD_EVENT_SET_INTERFACE, /** USB interface selected */
USBD_EVENT_SET_REMOTE_WAKEUP, /** USB set remote wakeup */
USBD_EVENT_CLR_REMOTE_WAKEUP, /** USB clear remote wakeup */
USBD_EVENT_INIT, /** USB init done when call usbd_initialize */
USBD_EVENT_DEINIT, /** USB deinit done when call usbd_deinitialize */
USBD_EVENT_UNKNOWN
};
typedef int (*usbd_request_handler)(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len);
typedef void (*usbd_endpoint_callback)(uint8_t ep, uint32_t nbytes);
typedef void (*usbd_notify_handler)(uint8_t event, void *arg);
typedef int (*usbd_request_handler)(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len);
typedef void (*usbd_endpoint_callback)(uint8_t busid, uint8_t ep, uint32_t nbytes);
typedef void (*usbd_notify_handler)(uint8_t busid, uint8_t event, void *arg);
struct usbd_endpoint {
uint8_t ep_addr;
@@ -72,23 +74,32 @@ struct usb_descriptor {
const struct usb_bos_descriptor *bos_descriptor;
};
#ifdef CONFIG_USBDEV_ADVANCE_DESC
void usbd_desc_register(const struct usb_descriptor *desc);
#else
void usbd_desc_register(const uint8_t *desc);
void usbd_msosv1_desc_register(struct usb_msosv1_descriptor *desc);
void usbd_msosv2_desc_register(struct usb_msosv2_descriptor *desc);
void usbd_bos_desc_register(struct usb_bos_descriptor *desc);
struct usbd_bus {
uint8_t busid;
uint32_t reg_base;
};
extern struct usbd_bus g_usbdev_bus[];
#ifdef USBD_IRQHandler
#error USBD_IRQHandler is obsolete, please call USBD_IRQHandler(xxx) in your irq
#endif
void usbd_add_interface(struct usbd_interface *intf);
void usbd_add_endpoint(struct usbd_endpoint *ep);
#ifdef CONFIG_USBDEV_ADVANCE_DESC
void usbd_desc_register(uint8_t busid, const struct usb_descriptor *desc);
#else
void usbd_desc_register(uint8_t busid, const uint8_t *desc);
void usbd_msosv1_desc_register(uint8_t busid, struct usb_msosv1_descriptor *desc);
void usbd_msosv2_desc_register(uint8_t busid, struct usb_msosv2_descriptor *desc);
void usbd_bos_desc_register(uint8_t busid, struct usb_bos_descriptor *desc);
#endif
bool usb_device_is_configured(void);
int usbd_initialize(void);
int usbd_deinitialize(void);
void usbd_add_interface(uint8_t busid, struct usbd_interface *intf);
void usbd_add_endpoint(uint8_t busid, struct usbd_endpoint *ep);
void usbd_event_handler(uint8_t event);
bool usb_device_is_configured(uint8_t busid);
int usbd_initialize(uint8_t busid, uint32_t reg_base, void (*event_handler)(uint8_t busid, uint8_t event));
int usbd_deinitialize(uint8_t busid);
#ifdef __cplusplus
}

View File

@@ -5,36 +5,28 @@
*/
#include "usbh_core.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_core"
#include "usb_log.h"
struct usbh_class_info *usbh_class_info_table_begin = NULL;
struct usbh_class_info *usbh_class_info_table_end = NULL;
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t ep0_request_buffer[CONFIG_USBHOST_REQUEST_BUFFER_LEN];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct usb_setup_packet g_setup[CONFIG_USBHOST_MAX_EXTHUBS + 1][CONFIG_USBHOST_MAX_EHPORTS];
usb_slist_t g_bus_head = USB_SLIST_OBJECT_INIT(g_bus_head);
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t ep0_request_buffer[CONFIG_USBHOST_MAX_BUS][USB_ALIGN_UP(CONFIG_USBHOST_REQUEST_BUFFER_LEN, CONFIG_USB_ALIGN_SIZE)];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct usb_setup_packet g_setup_buffer[CONFIG_USBHOST_MAX_BUS][CONFIG_USBHOST_MAX_EXTHUBS + 1][CONFIG_USBHOST_MAX_EHPORTS];
struct usbh_bus g_usbhost_bus[CONFIG_USBHOST_MAX_BUS];
/* general descriptor field offsets */
#define DESC_bLength 0 /** Length offset */
#define DESC_bDescriptorType 1 /** Descriptor type offset */
#define DESC_bLength 0 /** Length offset */
#define DESC_bDescriptorType 1 /** Descriptor type offset */
#define USB_DEV_ADDR_MAX 0x7f
#define USB_DEV_ADDR_MARK_OFFSET 5
#define USB_DEV_ADDR_MARK_MASK 0x1f
struct usbh_devaddr_map {
/**
* alloctab[0]:addr from 0~31
* alloctab[1]:addr from 32~63
* alloctab[2]:addr from 64~95
* alloctab[3]:addr from 96~127
*
*/
uint8_t next; /* Next device address */
uint32_t alloctab[4]; /* Bit allocation table */
};
struct usbh_bus {
struct usbh_devaddr_map devgen;
} g_usbh_bus;
static int usbh_allocate_devaddr(struct usbh_devaddr_map *devgen)
{
uint8_t startaddr = devgen->next;
@@ -227,15 +219,18 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
cur_ep = 0;
if (cur_iface > (CONFIG_USBHOST_MAX_INTERFACES - 1)) {
USB_LOG_ERR("Interface num overflow\r\n");
return -USB_ERR_NOMEM;
while (1) {
}
}
if (cur_alt_setting > (CONFIG_USBHOST_MAX_INTF_ALTSETTINGS - 1)) {
USB_LOG_ERR("Interface altsetting num overflow\r\n");
return -USB_ERR_NOMEM;
while (1) {
}
}
if (cur_ep_num > CONFIG_USBHOST_MAX_ENDPOINTS) {
USB_LOG_ERR("Endpoint num overflow\r\n");
return -USB_ERR_NOMEM;
while (1) {
}
}
#if 0
USB_LOG_DBG("Interface Descriptor:\r\n");
@@ -343,7 +338,7 @@ int usbh_free_devaddr(struct usbh_hubport *hport)
{
#ifndef CONFIG_USBHOST_XHCI
if (hport->dev_addr > 0) {
__usbh_free_devaddr(&g_usbh_bus.devgen, hport->dev_addr);
__usbh_free_devaddr(&hport->bus->devgen, hport->dev_addr);
}
#endif
@@ -368,12 +363,12 @@ int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *out
setup->wIndex = 0x0409;
setup->wLength = 255;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
if (ret < 0) {
return ret;
}
src = ep0_request_buffer;
src = ep0_request_buffer[hport->bus->busid];
dst = output;
len = src[0];
@@ -409,7 +404,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
uint16_t ep_mps;
int ret;
hport->setup = &g_setup[hport->parent->index - 1][hport->port - 1];
hport->setup = &g_setup_buffer[hport->bus->busid][hport->parent->index - 1][hport->port - 1];
setup = hport->setup;
ep = &hport->ep0;
@@ -431,16 +426,16 @@ int usbh_enumerate(struct usbh_hubport *hport)
setup->wIndex = 0;
setup->wLength = 8;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
if (ret < 0) {
USB_LOG_ERR("Failed to get device descriptor,errorcode:%d\r\n", ret);
goto errout;
}
parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer, 8);
parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid], 8);
/* Extract the correct max packetsize from the device descriptor */
dev_desc = (struct usb_device_descriptor *)ep0_request_buffer;
dev_desc = (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid];
if (dev_desc->bcdUSB >= USB_3_0) {
ep_mps = 1 << dev_desc->bMaxPacketSize0;
} else {
@@ -465,7 +460,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
}
#else
/* Assign a function address to the device connected to this port */
dev_addr = usbh_allocate_devaddr(&g_usbh_bus.devgen);
dev_addr = usbh_allocate_devaddr(&hport->bus->devgen);
if (dev_addr < 0) {
USB_LOG_ERR("Failed to allocate devaddr,errorcode:%d\r\n", ret);
goto errout;
@@ -498,17 +493,17 @@ int usbh_enumerate(struct usbh_hubport *hport)
setup->wIndex = 0;
setup->wLength = USB_SIZEOF_DEVICE_DESC;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
if (ret < 0) {
USB_LOG_ERR("Failed to get full device descriptor,errorcode:%d\r\n", ret);
goto errout;
}
parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer, USB_SIZEOF_DEVICE_DESC);
parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid], USB_SIZEOF_DEVICE_DESC);
USB_LOG_INFO("New device found,idVendor:%04x,idProduct:%04x,bcdDevice:%04x\r\n",
((struct usb_device_descriptor *)ep0_request_buffer)->idVendor,
((struct usb_device_descriptor *)ep0_request_buffer)->idProduct,
((struct usb_device_descriptor *)ep0_request_buffer)->bcdDevice);
((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->idVendor,
((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->idProduct,
((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->bcdDevice);
/* Read the first 9 bytes of the config descriptor */
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
@@ -517,7 +512,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
setup->wIndex = 0;
setup->wLength = USB_SIZEOF_CONFIG_DESC;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
if (ret < 0) {
USB_LOG_ERR("Failed to get config descriptor,errorcode:%d\r\n", ret);
goto errout;
@@ -534,18 +529,18 @@ int usbh_enumerate(struct usbh_hubport *hport)
setup->wIndex = 0;
setup->wLength = wTotalLength;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
if (ret < 0) {
USB_LOG_ERR("Failed to get full config descriptor,errorcode:%d\r\n", ret);
goto errout;
}
ret = parse_config_descriptor(hport, (struct usb_configuration_descriptor *)ep0_request_buffer, wTotalLength);
ret = parse_config_descriptor(hport, (struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid], wTotalLength);
if (ret < 0) {
USB_LOG_ERR("Parse config fail\r\n");
goto errout;
}
USB_LOG_INFO("The device has %d interfaces\r\n", ((struct usb_configuration_descriptor *)ep0_request_buffer)->bNumInterfaces);
USB_LOG_INFO("The device has %d interfaces\r\n", ((struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid])->bNumInterfaces);
hport->raw_config_desc = usb_malloc(wTotalLength);
if (hport->raw_config_desc == NULL) {
ret = -USB_ERR_NOMEM;
@@ -640,9 +635,48 @@ errout:
return ret;
}
int usbh_initialize(void)
static void usbh_bus_init(struct usbh_bus *bus, uint8_t busid, uint32_t reg_base)
{
memset(&g_usbh_bus, 0, sizeof(struct usbh_bus));
struct usbh_hub *hub;
memset(bus, 0, sizeof(struct usbh_bus));
bus->busid = busid;
bus->hcd.hcd_id = busid;
bus->hcd.reg_base = reg_base;
/* devaddr 1 is for roothub */
bus->devgen.next = 2;
usb_slist_init(&bus->hub_list);
hub = &bus->hcd.roothub;
hub->connected = true;
hub->index = 1;
hub->is_roothub = true;
hub->parent = NULL;
hub->hub_addr = 1;
hub->hub_desc.bNbrPorts = CONFIG_USBHOST_MAX_RHPORTS;
hub->int_buffer = bus->hcd.roothub_intbuf;
hub->bus = bus;
usb_slist_init(&bus->hub_list);
usb_slist_add_tail(&bus->hub_list, &hub->list);
usb_slist_add_tail(&g_bus_head, &bus->list);
}
int usbh_initialize(uint8_t busid, uint32_t reg_base)
{
struct usbh_bus *bus;
if (busid >= CONFIG_USBHOST_MAX_BUS) {
USB_LOG_ERR("bus overflow\r\n");
while (1) {
}
}
bus = &g_usbhost_bus[busid];
usbh_bus_init(bus, busid, reg_base);
#ifdef __ARMCC_VERSION /* ARM C Compiler */
extern const int usbh_class_info$$Base;
@@ -654,21 +688,26 @@ int usbh_initialize(void)
extern uint32_t __usbh_class_info_end__;
usbh_class_info_table_begin = (struct usbh_class_info *)&__usbh_class_info_start__;
usbh_class_info_table_end = (struct usbh_class_info *)&__usbh_class_info_end__;
#elif defined(__ICCARM__) || defined(__ICCRX__)
#elif defined(__ICCARM__) || defined(__ICCRX__) || defined(__ICCRISCV__)
usbh_class_info_table_begin = (struct usbh_class_info *)__section_begin("usbh_class_info");
usbh_class_info_table_end = (struct usbh_class_info *)__section_end("usbh_class_info");
#endif
/* devaddr 1 is for roothub */
g_usbh_bus.devgen.next = 2;
usbh_hub_initialize();
usbh_hub_initialize(bus);
return 0;
}
int usbh_deinitialize(void)
int usbh_deinitialize(uint8_t busid)
{
return usbh_hub_deinitialize();
struct usbh_bus *bus;
bus = &g_usbhost_bus[busid];
usbh_hub_deinitialize(bus);
usb_slist_init(&bus->hub_list);
usb_slist_remove(&g_bus_head, &bus->list);
return 0;
}
int usbh_control_transfer(struct usbh_hubport *hport, struct usb_setup_packet *setup, uint8_t *buffer)
@@ -695,16 +734,21 @@ void *usbh_find_class_instance(const char *devname)
{
struct usbh_hubport *hport;
usb_slist_t *hub_list;
usb_slist_t *bus_list;
usb_slist_for_each(hub_list, &hub_class_head)
usb_slist_for_each(bus_list, &g_bus_head)
{
struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list);
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
hport = &hub->child[port];
if (hport->connected) {
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
if ((strncmp(hport->config.intf[itf].devname, devname, CONFIG_USBHOST_DEV_NAMELEN) == 0) && hport->config.intf[itf].priv)
return hport->config.intf[itf].priv;
struct usbh_bus *bus = usb_slist_entry(bus_list, struct usbh_bus, list);
usb_slist_for_each(hub_list, &bus->hub_list)
{
struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list);
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
hport = &hub->child[port];
if (hport->connected) {
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
if ((strncmp(hport->config.intf[itf].devname, devname, CONFIG_USBHOST_DEV_NAMELEN) == 0) && hport->config.intf[itf].priv)
return hport->config.intf[itf].priv;
}
}
}
}
@@ -714,7 +758,8 @@ void *usbh_find_class_instance(const char *devname)
int lsusb(int argc, char **argv)
{
usb_slist_t *i;
usb_slist_t *hub_list;
usb_slist_t *bus_list;
struct usbh_hubport *hport;
if (argc < 2) {
@@ -739,30 +784,38 @@ int lsusb(int argc, char **argv)
}
if (strcmp(argv[1], "-t") == 0) {
usb_slist_for_each(i, &hub_class_head)
usb_slist_for_each(bus_list, &g_bus_head)
{
struct usbh_hub *hub = usb_slist_entry(i, struct usbh_hub, list);
struct usbh_bus *bus = usb_slist_entry(bus_list, struct usbh_bus, list);
usb_slist_for_each(hub_list, &bus->hub_list)
{
struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list);
if (hub->is_roothub) {
USB_LOG_RAW("/: Hub %02u, ports=%u, is roothub\r\n", hub->index, hub->hub_desc.bNbrPorts);
} else {
USB_LOG_RAW("/: Hub %02u, ports=%u, mounted on Hub %02u:Port %u\r\n",
hub->index,
hub->hub_desc.bNbrPorts,
hub->parent->parent->index,
hub->parent->port);
}
if (hub->is_roothub) {
USB_LOG_RAW("/: Bus %u, Hub %u, ports=%u, is roothub\r\n",
bus->busid,
hub->index,
hub->hub_desc.bNbrPorts);
} else {
USB_LOG_RAW("/: Bus %u, Hub %u, ports=%u, mounted on Hub %02u:Port %u\r\n",
bus->busid,
hub->index,
hub->hub_desc.bNbrPorts,
hub->parent->parent->index,
hub->parent->port);
}
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
hport = &hub->child[port];
if (hport->connected) {
for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
if (hport->config.intf[i].class_driver->driver_name) {
USB_LOG_RAW(" |__Port %u,Port addr:0x%02x,If %u,ClassDriver=%s\r\n",
hport->port,
hport->dev_addr,
i,
hport->config.intf[i].class_driver->driver_name);
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
hport = &hub->child[port];
if (hport->connected) {
for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
if (hport->config.intf[i].class_driver->driver_name) {
USB_LOG_RAW("\t|__Port %u, dev addr:0x%02x, If %u, ClassDriver=%s\r\n",
hport->port,
hport->dev_addr,
i,
hport->config.intf[i].class_driver->driver_name);
}
}
}
}
@@ -771,19 +824,24 @@ int lsusb(int argc, char **argv)
}
if (strcmp(argv[1], "-v") == 0) {
usb_slist_for_each(i, &hub_class_head)
usb_slist_for_each(bus_list, &g_bus_head)
{
struct usbh_hub *hub = usb_slist_entry(i, struct usbh_hub, list);
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
hport = &hub->child[port];
if (hport->connected) {
USB_LOG_RAW("Hub %02u,Port %u,Port addr:0x%02x,VID:PID 0x%04x:0x%04x\r\n",
hub->index,
hport->port,
hport->dev_addr,
hport->device_desc.idVendor,
hport->device_desc.idProduct);
usbh_print_hubport_info(hport);
struct usbh_bus *bus = usb_slist_entry(bus_list, struct usbh_bus, list);
usb_slist_for_each(hub_list, &bus->hub_list)
{
struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list);
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
hport = &hub->child[port];
if (hport->connected) {
USB_LOG_RAW("Bus %u, Hub %02u, Port %u, dev addr:0x%02x, VID:PID 0x%04x:0x%04x\r\n",
bus->busid,
hub->index,
hport->port,
hport->dev_addr,
hport->device_desc.idVendor,
hport->device_desc.idProduct);
usbh_print_hubport_info(hport);
}
}
}
}

View File

@@ -31,14 +31,14 @@ extern "C" {
#define USB_CLASS_MATCH_INTF_SUBCLASS 0x0008
#define USB_CLASS_MATCH_INTF_PROTOCOL 0x0010
#define CLASS_CONNECT(hport, i) ((hport)->config.intf[i].class_driver->connect(hport, i))
#define CLASS_DISCONNECT(hport, i) ((hport)->config.intf[i].class_driver->disconnect(hport, i))
#define CLASS_CONNECT(hport, i) ((hport)->config.intf[i].class_driver->connect(hport, i))
#define CLASS_DISCONNECT(hport, i) ((hport)->config.intf[i].class_driver->disconnect(hport, i))
#ifdef __ARMCC_VERSION /* ARM C Compiler */
#define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1)
#elif defined(__GNUC__)
#define CLASS_INFO_DEFINE __attribute__((section(".usbh_class_info"))) __USED __ALIGNED(1)
#elif defined(__ICCARM__) || defined(__ICCRX__)
#elif defined(__ICCARM__) || defined(__ICCRX__) || defined(__ICCRISCV__)
#pragma section = "usbh_class_info"
#define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1)
#endif
@@ -106,6 +106,7 @@ struct usbh_hubport {
uint8_t *raw_config_desc;
struct usb_setup_packet *setup;
struct usbh_hub *parent;
struct usbh_bus *bus;
#ifdef CONFIG_USBHOST_XHCI
uint32_t protocol; /* port protocol, for xhci, some ports are USB2.0, others are USB3.0 */
#endif
@@ -123,11 +124,41 @@ struct usbh_hub {
struct usb_hub_descriptor hub_desc;
struct usbh_hubport child[CONFIG_USBHOST_MAX_EHPORTS];
struct usbh_hubport *parent;
struct usbh_bus *bus;
struct usb_endpoint_descriptor *intin;
struct usbh_urb intin_urb;
uint8_t *int_buffer;
};
struct usbh_devaddr_map {
/**
* alloctab[0]:addr from 0~31
* alloctab[1]:addr from 32~63
* alloctab[2]:addr from 64~95
* alloctab[3]:addr from 96~127
*
*/
uint8_t next; /* Next device address */
uint32_t alloctab[4]; /* Bit allocation table */
};
struct usbh_hcd {
uint32_t reg_base;
uint8_t hcd_id;
uint8_t roothub_intbuf[1];
struct usbh_hub roothub;
};
struct usbh_bus {
usb_slist_t list;
uint8_t busid;
struct usbh_hcd hcd;
struct usbh_devaddr_map devgen;
usb_osal_thread_t hub_thread;
usb_osal_mq_t hub_mq;
usb_slist_t hub_list;
};
static inline void usbh_control_urb_fill(struct usbh_urb *urb,
struct usbh_hubport *hport,
struct usb_setup_packet *setup,
@@ -185,6 +216,11 @@ static inline void usbh_int_urb_fill(struct usbh_urb *urb,
urb->arg = arg;
}
extern struct usbh_bus g_usbhost_bus[];
#ifdef USBH_IRQHandler
#error USBH_IRQHandler is obsolete, please call USBH_IRQHandler(xxx) in your irq
#endif
/**
* @brief Submit an control transfer to an endpoint.
* This is a blocking method; this method will not return until the transfer has completed.
@@ -225,8 +261,8 @@ int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *out
*/
int usbh_set_interface(struct usbh_hubport *hport, uint8_t intf, uint8_t altsetting);
int usbh_initialize(void);
int usbh_deinitialize(void);
int usbh_initialize(uint8_t busid, uint32_t reg_base);
int usbh_deinitialize(uint8_t busid);
void *usbh_find_class_instance(const char *devname);
int lsusb(int argc, char **argv);

View File

@@ -148,7 +148,7 @@ const uint8_t audio_v1_descriptor[] = {
volatile bool tx_flag = 0;
volatile bool ep_tx_busy_flag = false;
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -173,19 +173,19 @@ void usbd_event_handler(uint8_t event)
}
}
void usbd_audio_open(uint8_t intf)
void usbd_audio_open(uint8_t busid, uint8_t intf)
{
tx_flag = 1;
USB_LOG_RAW("OPEN\r\n");
}
void usbd_audio_close(uint8_t intf)
void usbd_audio_close(uint8_t busid, uint8_t intf)
{
USB_LOG_RAW("CLOSE\r\n");
tx_flag = 0;
}
void usbd_audio_iso_callback(uint8_t ep, uint32_t nbytes)
void usbd_audio_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
ep_tx_busy_flag = false;
@@ -205,25 +205,25 @@ struct audio_entity_info audio_entity_table[] = {
.ep = AUDIO_IN_EP },
};
void audio_v1_init(void)
void audio_v1_init(uint8_t busid, uint32_t reg_base)
{
usbd_desc_register(audio_v1_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0100, audio_entity_table, 1));
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0100, audio_entity_table, 1));
usbd_add_endpoint(&audio_in_ep);
usbd_desc_register(busid, audio_v1_descriptor);
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0100, audio_entity_table, 1));
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0100, audio_entity_table, 1));
usbd_add_endpoint(busid, &audio_in_ep);
usbd_initialize();
usbd_initialize(busid, reg_base, usbd_event_handler);
}
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[AUDIO_IN_PACKET];
void audio_test()
void audio_test(uint8_t busid)
{
while (1) {
if (tx_flag) {
memset(write_buffer, 'a', AUDIO_IN_PACKET);
ep_tx_busy_flag = true;
usbd_ep_start_write(AUDIO_IN_EP, write_buffer, AUDIO_IN_PACKET);
usbd_ep_start_write(busid, AUDIO_IN_EP, write_buffer, AUDIO_IN_PACKET);
while (ep_tx_busy_flag) {
if (tx_flag == false) {
break;

View File

@@ -147,7 +147,7 @@ volatile bool tx_flag = 0;
volatile bool rx_flag = 0;
volatile bool ep_tx_busy_flag = false;
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -172,12 +172,12 @@ void usbd_event_handler(uint8_t event)
}
}
void usbd_audio_open(uint8_t intf)
void usbd_audio_open(uint8_t busid, uint8_t intf)
{
if (intf == 1) {
rx_flag = 1;
/* setup first out ep read transfer */
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
printf("OPEN1\r\n");
} else {
tx_flag = 1;
@@ -185,7 +185,7 @@ void usbd_audio_open(uint8_t intf)
}
}
void usbd_audio_close(uint8_t intf)
void usbd_audio_close(uint8_t busid, uint8_t intf)
{
if (intf == 1) {
rx_flag = 1;
@@ -196,13 +196,13 @@ void usbd_audio_close(uint8_t intf)
}
}
void usbd_audio_out_callback(uint8_t ep, uint32_t nbytes)
void usbd_audio_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
}
void usbd_audio_in_callback(uint8_t ep, uint32_t nbytes)
void usbd_audio_in_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
ep_tx_busy_flag = false;
@@ -231,24 +231,24 @@ struct audio_entity_info audio_entity_table[] = {
.ep = AUDIO_OUT_EP },
};
void audio_v1_init(void)
void audio_v1_init(uint8_t busid, uint32_t reg_base)
{
usbd_desc_register(audio_v1_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0100, audio_entity_table, 2));
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0100, audio_entity_table, 2));
usbd_add_interface(usbd_audio_init_intf(&intf2, 0x0100, audio_entity_table, 2));
usbd_add_endpoint(&audio_in_ep);
usbd_add_endpoint(&audio_out_ep);
usbd_desc_register(busid, audio_v1_descriptor);
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0100, audio_entity_table, 2));
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0100, audio_entity_table, 2));
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf2, 0x0100, audio_entity_table, 2));
usbd_add_endpoint(busid, &audio_in_ep);
usbd_add_endpoint(busid, &audio_out_ep);
usbd_initialize();
usbd_initialize(busid, reg_base, usbd_event_handler);
}
void audio_v1_test(void)
void audio_v1_test(uint8_t busid)
{
if (tx_flag) {
memset(write_buffer, 'a', AUDIO_IN_PACKET);
ep_tx_busy_flag = true;
usbd_ep_start_write(AUDIO_IN_EP, write_buffer, AUDIO_IN_PACKET);
usbd_ep_start_write(busid, AUDIO_IN_EP, write_buffer, AUDIO_IN_PACKET);
while (ep_tx_busy_flag) {
if (tx_flag == false) {
break;

View File

@@ -159,7 +159,7 @@ static const uint8_t mic_default_sampling_freq_table[] = {
volatile bool tx_flag = 0;
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -184,26 +184,26 @@ void usbd_event_handler(uint8_t event)
}
}
void usbd_audio_open(uint8_t intf)
void usbd_audio_open(uint8_t busid, uint8_t intf)
{
tx_flag = 1;
USB_LOG_RAW("OPEN\r\n");
}
void usbd_audio_close(uint8_t intf)
void usbd_audio_close(uint8_t busid, uint8_t intf)
{
USB_LOG_RAW("CLOSE\r\n");
tx_flag = 0;
}
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table)
{
if (ep == AUDIO_IN_EP) {
*sampling_freq_table = (uint8_t *)mic_default_sampling_freq_table;
}
}
void usbd_audio_iso_in_callback(uint8_t ep, uint32_t nbytes)
void usbd_audio_iso_in_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
}
@@ -224,17 +224,17 @@ struct audio_entity_info audio_entity_table[] = {
.ep = AUDIO_IN_EP },
};
void audio_v2_init(void)
void audio_v2_init(uint8_t busid, uint32_t reg_base)
{
usbd_desc_register(audio_v2_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0200, audio_entity_table, 2));
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0200, audio_entity_table, 2));
usbd_add_endpoint(&audio_in_ep);
usbd_desc_register(busid, audio_v2_descriptor);
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 2));
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0200, audio_entity_table, 2));
usbd_add_endpoint(busid, &audio_in_ep);
usbd_initialize();
usbd_initialize(busid, reg_base, usbd_event_handler);
}
void audio_v2_test(void)
void audio_v2_test(uint8_t busid)
{
if (tx_flag) {
}

View File

@@ -229,7 +229,7 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[AUDIO_IN_PACKET];
volatile bool tx_flag = 0;
volatile bool rx_flag = 0;
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -254,12 +254,12 @@ void usbd_event_handler(uint8_t event)
}
}
void usbd_audio_open(uint8_t intf)
void usbd_audio_open(uint8_t busid, uint8_t intf)
{
if (intf == 1) {
rx_flag = 1;
/* setup first out ep read transfer */
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
USB_LOG_RAW("OPEN1\r\n");
} else {
tx_flag = 1;
@@ -267,7 +267,7 @@ void usbd_audio_open(uint8_t intf)
}
}
void usbd_audio_close(uint8_t intf)
void usbd_audio_close(uint8_t busid, uint8_t intf)
{
if (intf == 1) {
rx_flag = 1;
@@ -278,7 +278,7 @@ void usbd_audio_close(uint8_t intf)
}
}
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table)
{
if (ep == AUDIO_OUT_EP) {
*sampling_freq_table = (uint8_t *)speaker_default_sampling_freq_table;
@@ -288,7 +288,7 @@ void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_tabl
}
}
void usbd_audio_set_sampling_freq(uint8_t ep, uint32_t sampling_freq)
void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq)
{
uint16_t packet_size = 0;
if (ep == AUDIO_OUT_EP) {
@@ -302,13 +302,13 @@ void usbd_audio_set_sampling_freq(uint8_t ep, uint32_t sampling_freq)
}
}
void usbd_audio_iso_out_callback(uint8_t ep, uint32_t nbytes)
void usbd_audio_iso_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
}
void usbd_audio_iso_in_callback(uint8_t ep, uint32_t nbytes)
void usbd_audio_iso_in_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
}
@@ -341,19 +341,19 @@ struct audio_entity_info audio_entity_table[] = {
.ep = AUDIO_IN_EP },
};
void audio_v2_init(void)
void audio_v2_init(uint8_t busid, uint32_t reg_base)
{
usbd_desc_register(audio_v2_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0200, audio_entity_table, 4));
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0200, audio_entity_table, 4));
usbd_add_interface(usbd_audio_init_intf(&intf2, 0x0200, audio_entity_table, 4));
usbd_add_endpoint(&audio_in_ep);
usbd_add_endpoint(&audio_out_ep);
usbd_desc_register(busid, audio_v2_descriptor);
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 4));
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0200, audio_entity_table, 4));
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf2, 0x0200, audio_entity_table, 4));
usbd_add_endpoint(busid, &audio_in_ep);
usbd_add_endpoint(busid, &audio_out_ep);
usbd_initialize();
usbd_initialize(busid, reg_base, usbd_event_handler);
}
void audio_v2_test(void)
void audio_v2_test(uint8_t busid)
{
if (tx_flag) {
}

View File

@@ -173,7 +173,7 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[AUDIO_OUT_PACKET];
volatile bool rx_flag = 0;
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -198,31 +198,31 @@ void usbd_event_handler(uint8_t event)
}
}
void usbd_audio_open(uint8_t intf)
void usbd_audio_open(uint8_t busid, uint8_t intf)
{
rx_flag = 1;
/* setup first out ep read transfer */
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
USB_LOG_RAW("OPEN\r\n");
}
void usbd_audio_close(uint8_t intf)
void usbd_audio_close(uint8_t busid, uint8_t intf)
{
USB_LOG_RAW("CLOSE\r\n");
rx_flag = 0;
}
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table)
{
if (ep == AUDIO_OUT_EP) {
*sampling_freq_table = (uint8_t *)default_sampling_freq_table;
}
}
void usbd_audio_iso_out_callback(uint8_t ep, uint32_t nbytes)
void usbd_audio_iso_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
}
static struct usbd_endpoint audio_out_ep = {
@@ -242,17 +242,17 @@ struct audio_entity_info audio_entity_table[] = {
.ep = AUDIO_OUT_EP },
};
void audio_v2_init(void)
void audio_v2_init(uint8_t busid, uint32_t reg_base)
{
usbd_desc_register(audio_v2_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0200, audio_entity_table, 2));
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0200, audio_entity_table, 2));
usbd_add_endpoint(&audio_out_ep);
usbd_desc_register(busid, audio_v2_descriptor);
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 2));
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0200, audio_entity_table, 2));
usbd_add_endpoint(busid, &audio_out_ep);
usbd_initialize();
usbd_initialize(busid, reg_base, usbd_event_handler);
}
void audio_v2_test(void)
void audio_v2_test(uint8_t busid)
{
if (rx_flag) {
}

View File

@@ -216,7 +216,7 @@ static struct hid_mouse mouse_cfg;
static volatile uint8_t hid_state = HID_STATE_IDLE;
/* function ------------------------------------------------------------------*/
static void usbd_hid_int_callback(uint8_t ep, uint32_t nbytes)
static void usbd_hid_int_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
hid_state = HID_STATE_IDLE;
}
@@ -238,7 +238,7 @@ volatile bool ep_tx_busy_flag = false;
#define CDC_MAX_MPS 64
#endif
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -253,7 +253,7 @@ void usbd_event_handler(uint8_t event)
break;
case USBD_EVENT_CONFIGURED:
/* setup first out ep read transfer */
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
@@ -265,20 +265,20 @@ void usbd_event_handler(uint8_t event)
}
}
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
/* setup next out ep read transfer */
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
}
void usbd_cdc_acm_bulk_in(uint8_t ep, uint32_t nbytes)
void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(CDC_IN_EP, NULL, 0);
usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);
} else {
ep_tx_busy_flag = false;
}
@@ -300,19 +300,19 @@ struct usbd_interface intf1;
struct usbd_interface intf2;
struct usbd_interface intf3;
void cdc_acm_hid_msc_descriptor_init(void)
void cdc_acm_hid_msc_descriptor_init(uint8_t busid, uint32_t reg_base)
{
usbd_desc_register(cdc_acm_hid_msc_descriptor);
usbd_desc_register(busid, cdc_acm_hid_msc_descriptor);
usbd_add_interface(usbd_cdc_acm_init_intf(&intf0));
usbd_add_interface(usbd_cdc_acm_init_intf(&intf1));
usbd_add_endpoint(&cdc_out_ep);
usbd_add_endpoint(&cdc_in_ep);
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0));
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
usbd_add_endpoint(busid, &cdc_out_ep);
usbd_add_endpoint(busid, &cdc_in_ep);
usbd_add_interface(usbd_msc_init_intf(&intf2, MSC_OUT_EP, MSC_IN_EP));
usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf2, MSC_OUT_EP, MSC_IN_EP));
usbd_add_interface(usbd_hid_init_intf(&intf3, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE));
usbd_add_endpoint(&hid_in_ep);
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf3, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE));
usbd_add_endpoint(busid, &hid_in_ep);
/*!< init mouse report data */
mouse_cfg.buttons = 0;
@@ -320,7 +320,7 @@ void cdc_acm_hid_msc_descriptor_init(void)
mouse_cfg.x = 0;
mouse_cfg.y = 0;
usbd_initialize();
usbd_initialize(busid, reg_base, usbd_event_handler);
}
/**
@@ -329,12 +329,12 @@ void cdc_acm_hid_msc_descriptor_init(void)
* @param[in] none
* @retval none
*/
void hid_mouse_test(void)
void hid_mouse_test(uint8_t busid)
{
/*!< move mouse pointer */
mouse_cfg.x += 10;
mouse_cfg.y = 0;
int ret = usbd_ep_start_write(HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
int ret = usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
if (ret < 0) {
return;
}
@@ -345,7 +345,7 @@ void hid_mouse_test(void)
volatile uint8_t dtr_enable = 0;
void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
{
if (dtr) {
dtr_enable = 1;
@@ -354,12 +354,12 @@ void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
}
}
void cdc_acm_data_send_with_dtr_test(void)
void cdc_acm_data_send_with_dtr_test(uint8_t busid)
{
if (dtr_enable) {
memset(&write_buffer[10], 'a', 2038);
ep_tx_busy_flag = true;
usbd_ep_start_write(CDC_IN_EP, write_buffer, 2048);
usbd_ep_start_write(busid, CDC_IN_EP, write_buffer, 2048);
while (ep_tx_busy_flag) {
}
}
@@ -375,19 +375,19 @@ typedef struct
BLOCK_TYPE mass_block[BLOCK_COUNT];
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size)
{
*block_num = 1000; //Pretend having so many buffer,not has actually.
*block_size = BLOCK_SIZE;
}
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length)
int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
{
if (sector < 10)
memcpy(buffer, mass_block[sector].BlockSpace, length);
return 0;
}
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length)
int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
{
if (sector < 10)
memcpy(mass_block[sector].BlockSpace, buffer, length);

View File

@@ -249,7 +249,7 @@ volatile bool ep_tx_busy_flag = false;
#define CDC_MAX_MPS 64
#endif
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -264,7 +264,7 @@ void usbd_event_handler(uint8_t event)
break;
case USBD_EVENT_CONFIGURED:
/* setup first out ep read transfer */
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
@@ -276,20 +276,20 @@ void usbd_event_handler(uint8_t event)
}
}
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
/* setup next out ep read transfer */
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
}
void usbd_cdc_acm_bulk_in(uint8_t ep, uint32_t nbytes)
void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(CDC_IN_EP, NULL, 0);
usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);
} else {
ep_tx_busy_flag = false;
}
@@ -310,25 +310,25 @@ struct usbd_interface intf0;
struct usbd_interface intf1;
struct usbd_interface intf2;
void cdc_acm_msc_init(void)
void cdc_acm_msc_init(uint8_t busid, uint32_t reg_base)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(&cdc_msc_descriptor);
usbd_desc_register(busid, &cdc_msc_descriptor);
#else
usbd_desc_register(cdc_msc_descriptor);
usbd_desc_register(busid, cdc_msc_descriptor);
#endif
usbd_add_interface(usbd_cdc_acm_init_intf(&intf0));
usbd_add_interface(usbd_cdc_acm_init_intf(&intf1));
usbd_add_endpoint(&cdc_out_ep);
usbd_add_endpoint(&cdc_in_ep);
usbd_add_interface(usbd_msc_init_intf(&intf2, MSC_OUT_EP, MSC_IN_EP));
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0));
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
usbd_add_endpoint(busid, &cdc_out_ep);
usbd_add_endpoint(busid, &cdc_in_ep);
usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf2, MSC_OUT_EP, MSC_IN_EP));
usbd_initialize();
usbd_initialize(busid, reg_base, usbd_event_handler);
}
volatile uint8_t dtr_enable = 0;
void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
{
if (dtr) {
dtr_enable = 1;
@@ -337,12 +337,12 @@ void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
}
}
void cdc_acm_data_send_with_dtr_test(void)
void cdc_acm_data_send_with_dtr_test(uint8_t busid)
{
if (dtr_enable) {
memset(&write_buffer[10], 'a', 2038);
ep_tx_busy_flag = true;
usbd_ep_start_write(CDC_IN_EP, write_buffer, 2048);
usbd_ep_start_write(busid, CDC_IN_EP, write_buffer, 2048);
while (ep_tx_busy_flag) {
}
}
@@ -358,19 +358,19 @@ typedef struct
BLOCK_TYPE mass_block[BLOCK_COUNT];
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size)
{
*block_num = 1000; //Pretend having so many buffer,not has actually.
*block_size = BLOCK_SIZE;
}
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length)
int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
{
if (sector < 10)
memcpy(buffer, mass_block[sector].BlockSpace, length);
return 0;
}
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length)
int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
{
if (sector < 10)
memcpy(mass_block[sector].BlockSpace, buffer, length);

View File

@@ -125,7 +125,7 @@ volatile bool ep_tx_busy_flag = false;
#define CDC_MAX_MPS 64
#endif
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -140,10 +140,10 @@ void usbd_event_handler(uint8_t event)
break;
case USBD_EVENT_CONFIGURED:
/* setup first out ep read transfer */
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
usbd_ep_start_read(CDC_OUT_EP2, read_buffer, 2048);
usbd_ep_start_read(CDC_OUT_EP3, read_buffer, 2048);
usbd_ep_start_read(CDC_OUT_EP4, read_buffer, 2048);
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
usbd_ep_start_read(busid, CDC_OUT_EP2, read_buffer, 2048);
usbd_ep_start_read(busid, CDC_OUT_EP3, read_buffer, 2048);
usbd_ep_start_read(busid, CDC_OUT_EP4, read_buffer, 2048);
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
@@ -155,14 +155,14 @@ void usbd_event_handler(uint8_t event)
}
}
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
/* setup next out ep read transfer */
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
}
void usbd_cdc_acm_bulk_in(uint8_t ep, uint32_t nbytes)
void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
@@ -223,29 +223,29 @@ struct usbd_interface intf5;
struct usbd_interface intf6;
struct usbd_interface intf7;
void cdc_acm_multi_init(void)
void cdc_acm_multi_init(uint8_t busid, uint32_t reg_base)
{
usbd_desc_register(cdc_descriptor);
usbd_desc_register(busid, cdc_descriptor);
usbd_add_interface(usbd_cdc_acm_init_intf(&intf0));
usbd_add_interface(usbd_cdc_acm_init_intf(&intf1));
usbd_add_endpoint(&cdc_out_ep1);
usbd_add_endpoint(&cdc_in_ep1);
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0));
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
usbd_add_endpoint(busid, &cdc_out_ep1);
usbd_add_endpoint(busid, &cdc_in_ep1);
usbd_add_interface(usbd_cdc_acm_init_intf(&intf2));
usbd_add_interface(usbd_cdc_acm_init_intf(&intf3));
usbd_add_endpoint(&cdc_out_ep2);
usbd_add_endpoint(&cdc_in_ep2);
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf2));
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf3));
usbd_add_endpoint(busid, &cdc_out_ep2);
usbd_add_endpoint(busid, &cdc_in_ep2);
usbd_add_interface(usbd_cdc_acm_init_intf(&intf4));
usbd_add_interface(usbd_cdc_acm_init_intf(&intf5));
usbd_add_endpoint(&cdc_out_ep3);
usbd_add_endpoint(&cdc_in_ep3);
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf4));
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf5));
usbd_add_endpoint(busid, &cdc_out_ep3);
usbd_add_endpoint(busid, &cdc_in_ep3);
usbd_add_interface(usbd_cdc_acm_init_intf(&intf6));
usbd_add_interface(usbd_cdc_acm_init_intf(&intf7));
usbd_add_endpoint(&cdc_out_ep4);
usbd_add_endpoint(&cdc_in_ep4);
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf6));
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf7));
usbd_add_endpoint(busid, &cdc_out_ep4);
usbd_add_endpoint(busid, &cdc_in_ep4);
usbd_initialize();
usbd_initialize(busid, reg_base, usbd_event_handler);
}

View File

@@ -110,7 +110,7 @@ volatile bool ep_tx_busy_flag = false;
#define CDC_MAX_MPS 64
#endif
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -125,7 +125,7 @@ void usbd_event_handler(uint8_t event)
break;
case USBD_EVENT_CONFIGURED:
/* setup first out ep read transfer */
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
@@ -137,7 +137,7 @@ void usbd_event_handler(uint8_t event)
}
}
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
// for (int i = 0; i < 100; i++) {
@@ -145,16 +145,16 @@ void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
// }
// printf("\r\n");
/* setup next out ep read transfer */
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
}
void usbd_cdc_acm_bulk_in(uint8_t ep, uint32_t nbytes)
void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(CDC_IN_EP, NULL, 0);
usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);
} else {
ep_tx_busy_flag = false;
}
@@ -174,24 +174,24 @@ struct usbd_endpoint cdc_in_ep = {
static struct usbd_interface intf0;
static struct usbd_interface intf1;
void cdc_acm_init(void)
void cdc_acm_init(uint8_t busid, uint32_t reg_base)
{
const uint8_t data[10] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30 };
memcpy(&write_buffer[0], data, 10);
memset(&write_buffer[10], 'a', 2038);
usbd_desc_register(cdc_descriptor);
usbd_add_interface(usbd_cdc_acm_init_intf(&intf0));
usbd_add_interface(usbd_cdc_acm_init_intf(&intf1));
usbd_add_endpoint(&cdc_out_ep);
usbd_add_endpoint(&cdc_in_ep);
usbd_initialize();
usbd_desc_register(busid, cdc_descriptor);
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0));
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
usbd_add_endpoint(busid, &cdc_out_ep);
usbd_add_endpoint(busid, &cdc_in_ep);
usbd_initialize(busid, reg_base, usbd_event_handler);
}
volatile uint8_t dtr_enable = 0;
void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
{
if (dtr) {
dtr_enable = 1;
@@ -200,11 +200,11 @@ void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
}
}
void cdc_acm_data_send_with_dtr_test(void)
void cdc_acm_data_send_with_dtr_test(uint8_t busid)
{
if (dtr_enable) {
ep_tx_busy_flag = true;
usbd_ep_start_write(CDC_IN_EP, write_buffer, 2048);
usbd_ep_start_write(busid, CDC_IN_EP, write_buffer, 2048);
while (ep_tx_busy_flag) {
}
}

View File

@@ -221,7 +221,7 @@ void cdc_ecm_lwip_init(void)
// while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {}
}
void usbd_cdc_ecm_data_recv_done(void)
void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len)
{
}
@@ -230,7 +230,7 @@ void cdc_ecm_input_poll(void)
cdc_ecm_if_input(&cdc_ecm_netif);
}
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -263,12 +263,12 @@ struct usbd_interface intf1;
* sudo ifconfig enxaabbccddeeff up
* sudo dhcpclient enxaabbccddeeff
*/
void cdc_ecm_init(void)
void cdc_ecm_init(uint8_t busid, uint32_t reg_base)
{
cdc_ecm_lwip_init();
usbd_desc_register(cdc_ecm_descriptor);
usbd_add_interface(usbd_cdc_ecm_init_intf(&intf0, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP));
usbd_add_interface(usbd_cdc_ecm_init_intf(&intf1, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP));
usbd_initialize();
usbd_desc_register(busid, cdc_ecm_descriptor);
usbd_add_interface(busid, usbd_cdc_ecm_init_intf(&intf0, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP));
usbd_add_interface(busid, usbd_cdc_ecm_init_intf(&intf1, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP));
usbd_initialize(busid, reg_base, usbd_event_handler);
}

View File

@@ -263,7 +263,7 @@ void rndis_input_poll(void)
}
#endif /* RT_USING_LWIP */
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -294,15 +294,15 @@ void usbd_event_handler(uint8_t event)
struct usbd_interface intf0;
struct usbd_interface intf1;
void cdc_rndis_init(void)
void cdc_rndis_init(uint8_t busid, uint32_t reg_base)
{
#ifdef RT_USING_LWIP
rt_usbd_rndis_init();
#else
rndis_lwip_init();
#endif
usbd_desc_register(cdc_descriptor);
usbd_add_interface(usbd_rndis_init_intf(&intf0, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, mac));
usbd_add_interface(usbd_rndis_init_intf(&intf1, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, mac));
usbd_initialize();
usbd_desc_register(busid, cdc_descriptor);
usbd_add_interface(busid, usbd_rndis_init_intf(&intf0, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, mac));
usbd_add_interface(busid, usbd_rndis_init_intf(&intf1, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, mac));
usbd_initialize(busid, reg_base, usbd_event_handler);
}

View File

@@ -137,7 +137,7 @@ const uint8_t dfu_flash_descriptor[] = {
0x00
};
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -164,9 +164,9 @@ void usbd_event_handler(uint8_t event)
struct usbd_interface intf0;
void dfu_flash_init(void)
void dfu_flash_init(uint8_t busid, uint32_t reg_base)
{
usbd_desc_register(dfu_flash_descriptor);
usbd_add_interface(usbd_dfu_init_intf(&intf0));
usbd_initialize();
usbd_desc_register(busid, dfu_flash_descriptor);
usbd_add_interface(busid, usbd_dfu_init_intf(&intf0));
usbd_initialize(busid, reg_base, usbd_event_handler);
}

View File

@@ -169,7 +169,7 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t send_buffer[HIDRAW_IN_EP_SIZE];
/*!< hid state ! Data can be sent only when state is idle */
static volatile uint8_t custom_state;
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -184,7 +184,7 @@ void usbd_event_handler(uint8_t event)
break;
case USBD_EVENT_CONFIGURED:
/* setup first out ep read transfer */
usbd_ep_start_read(HIDRAW_OUT_EP, read_buffer, HIDRAW_OUT_EP_SIZE);
usbd_ep_start_read(busid, HIDRAW_OUT_EP, read_buffer, HIDRAW_OUT_EP_SIZE);
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
@@ -196,18 +196,18 @@ void usbd_event_handler(uint8_t event)
}
}
static void usbd_hid_custom_in_callback(uint8_t ep, uint32_t nbytes)
static void usbd_hid_custom_in_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
custom_state = HID_STATE_IDLE;
}
static void usbd_hid_custom_out_callback(uint8_t ep, uint32_t nbytes)
static void usbd_hid_custom_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
usbd_ep_start_read(HIDRAW_OUT_EP, read_buffer, 64);
usbd_ep_start_read(busid, HIDRAW_OUT_EP, read_buffer, 64);
read_buffer[0] = 0x02; /* IN: report id */
usbd_ep_start_write(HIDRAW_IN_EP, read_buffer, nbytes);
usbd_ep_start_write(busid, HIDRAW_IN_EP, read_buffer, nbytes);
}
static struct usbd_endpoint custom_in_ep = {
@@ -229,12 +229,12 @@ static struct usbd_endpoint custom_out_ep = {
*/
struct usbd_interface intf0;
void hid_custom_init(void)
void hid_custom_init(uint8_t busid, uint32_t reg_base)
{
usbd_desc_register(hid_descriptor);
usbd_add_interface(usbd_hid_init_intf(&intf0, hid_custom_report_desc, HID_CUSTOM_REPORT_DESC_SIZE));
usbd_add_endpoint(&custom_in_ep);
usbd_add_endpoint(&custom_out_ep);
usbd_desc_register(busid, hid_descriptor);
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_custom_report_desc, HID_CUSTOM_REPORT_DESC_SIZE));
usbd_add_endpoint(busid, &custom_in_ep);
usbd_add_endpoint(busid, &custom_out_ep);
usbd_initialize();
usbd_initialize(busid, usbd_event_handler);
}

View File

@@ -172,7 +172,7 @@ static const uint8_t hid_keyboard_report_desc[HID_KEYBOARD_REPORT_DESC_SIZE] = {
0xc0 // END_COLLECTION
};
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -203,7 +203,7 @@ void usbd_event_handler(uint8_t event)
/*!< hid state ! Data can be sent only when state is idle */
static volatile uint8_t hid_state = HID_STATE_IDLE;
void usbd_hid_int_callback(uint8_t ep, uint32_t nbytes)
void usbd_hid_int_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
hid_state = HID_STATE_IDLE;
}
@@ -215,23 +215,23 @@ static struct usbd_endpoint hid_in_ep = {
struct usbd_interface intf0;
void hid_keyboard_init(void)
void hid_keyboard_init(uint8_t busid, uint32_t reg_base)
{
usbd_desc_register(hid_descriptor);
usbd_add_interface(usbd_hid_init_intf(&intf0, hid_keyboard_report_desc, HID_KEYBOARD_REPORT_DESC_SIZE));
usbd_add_endpoint(&hid_in_ep);
usbd_desc_register(busid, hid_descriptor);
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_keyboard_report_desc, HID_KEYBOARD_REPORT_DESC_SIZE));
usbd_add_endpoint(busid, &hid_in_ep);
usbd_initialize();
usbd_initialize(busid, reg_base, usbd_event_handler);
}
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[64];
void hid_keyboard_test(void)
void hid_keyboard_test(uint8_t busid)
{
const uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 };
memcpy(write_buffer, sendbuffer, 8);
int ret = usbd_ep_start_write(HID_INT_EP, write_buffer, 8);
int ret = usbd_ep_start_write(busid, HID_INT_EP, write_buffer, 8);
if (ret < 0) {
return;
}

View File

@@ -194,7 +194,7 @@ static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct hid_mouse mouse_cfg;
/*!< hid state ! Data can be sent only when state is idle */
static volatile uint8_t hid_state = HID_STATE_IDLE;
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -220,7 +220,7 @@ void usbd_event_handler(uint8_t event)
}
/* function ------------------------------------------------------------------*/
static void usbd_hid_int_callback(uint8_t ep, uint32_t nbytes)
static void usbd_hid_int_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
hid_state = HID_STATE_IDLE;
}
@@ -233,13 +233,13 @@ static struct usbd_endpoint hid_in_ep = {
struct usbd_interface intf0;
void hid_mouse_init(void)
void hid_mouse_init(uint8_t busid, uint32_t reg_base)
{
usbd_desc_register(hid_descriptor);
usbd_add_interface(usbd_hid_init_intf(&intf0, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE));
usbd_add_endpoint(&hid_in_ep);
usbd_desc_register(busid, hid_descriptor);
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE));
usbd_add_endpoint(busid, &hid_in_ep);
usbd_initialize();
usbd_initialize(busid, reg_base, usbd_event_handler);
/*!< init mouse report data */
mouse_cfg.buttons = 0;
@@ -254,7 +254,7 @@ void hid_mouse_init(void)
* @param[in] none
* @retval none
*/
void hid_mouse_test(void)
void hid_mouse_test(uint8_t busid)
{
int counter = 0;
while (counter < 1000) {
@@ -262,7 +262,7 @@ void hid_mouse_test(void)
mouse_cfg.x += 40;
mouse_cfg.y += 0;
int ret = usbd_ep_start_write(HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
int ret = usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
if (ret < 0) {
return;
}

View File

@@ -146,7 +146,7 @@ const uint8_t midi_descriptor[] = {
0x00
};
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -171,11 +171,11 @@ void usbd_event_handler(uint8_t event)
}
}
void usbd_midi_bulk_out(uint8_t ep, uint32_t nbytes)
void usbd_midi_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
}
void usbd_midi_bulk_in(uint8_t ep, uint32_t nbytes)
void usbd_midi_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
}
@@ -192,13 +192,13 @@ struct usbd_endpoint midi_in_ep = {
.ep_cb = usbd_midi_bulk_in
};
void midi_init(void)
void midi_init(uint8_t busid, uint32_t reg_base)
{
usbd_desc_register(midi_descriptor);
usbd_add_interface(&intf0);
usbd_add_interface(&intf1);
usbd_add_endpoint(&midi_out_ep);
usbd_add_endpoint(&midi_in_ep);
usbd_desc_register(busid, midi_descriptor);
usbd_add_interface(busid, &intf0);
usbd_add_interface(busid, &intf1);
usbd_add_endpoint(busid, &midi_out_ep);
usbd_add_endpoint(busid, &midi_in_ep);
usbd_initialize();
usbd_initialize(busid, reg_base, usbd_event_handler);
}

View File

@@ -95,7 +95,7 @@ const uint8_t msc_ram_descriptor[] = {
0x00
};
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -130,19 +130,19 @@ typedef struct
BLOCK_TYPE mass_block[BLOCK_COUNT];
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size)
{
*block_num = 1000; //Pretend having so many buffer,not has actually.
*block_size = BLOCK_SIZE;
}
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length)
int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
{
if (sector < BLOCK_COUNT)
memcpy(buffer, mass_block[sector].BlockSpace, length);
return 0;
}
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length)
int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
{
if (sector < BLOCK_COUNT)
memcpy(mass_block[sector].BlockSpace, buffer, length);
@@ -151,10 +151,10 @@ int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length)
struct usbd_interface intf0;
void msc_ram_init(void)
void msc_ram_init(uint8_t busid, uint32_t reg_base)
{
usbd_desc_register(msc_ram_descriptor);
usbd_add_interface(usbd_msc_init_intf(&intf0, MSC_OUT_EP, MSC_IN_EP));
usbd_desc_register(busid, msc_ram_descriptor);
usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf0, MSC_OUT_EP, MSC_IN_EP));
usbd_initialize();
usbd_initialize(busid, reg_base, usbd_event_handler);
}

View File

@@ -106,7 +106,7 @@ struct usbd_interface intf0;
#define BLOCK_COUNT 0x1024U * 0x1024U
static rt_device_t blk_dev = RT_NULL;
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -131,25 +131,25 @@ void usbd_event_handler(uint8_t event)
}
}
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size)
{
*block_num = BLOCK_COUNT;
*block_size = BLOCK_SIZE;
}
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length)
int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
{
rt_device_read(blk_dev, sector, buffer, length / BLOCK_SIZE);
return 0;
}
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length)
int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
{
rt_device_write(blk_dev, sector, buffer, length / BLOCK_SIZE);
return 0;
}
void msc_storage_init(void)
void msc_storage_init(uint8_t busid, uint32_t reg_base)
{
rt_err_t res;
@@ -159,9 +159,9 @@ void msc_storage_init(void)
res = rt_device_open(blk_dev, RT_DEVICE_OFLAG_RDWR);
RT_ASSERT(res == RT_EOK);
usbd_desc_register(msc_storage_descriptor);
usbd_add_interface(usbd_msc_init_intf(&intf0, MSC_OUT_EP, MSC_IN_EP));
usbd_desc_register(busid, msc_storage_descriptor);
usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf0, MSC_OUT_EP, MSC_IN_EP));
usbd_initialize();
usbd_initialize(busid, reg_base, usbd_event_handler);
}
#endif

View File

@@ -1,193 +0,0 @@
#include "usbd_core.h"
#include "usbd_mtp.h"
#define WCID_VENDOR_CODE 0x01
__ALIGN_BEGIN const uint8_t WCID_StringDescriptor_MSOS[18] __ALIGN_END = {
///////////////////////////////////////
/// MS OS string descriptor
///////////////////////////////////////
0x12, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
/* MSFT100 */
'M', 0x00, 'S', 0x00, 'F', 0x00, 'T', 0x00, /* wcChar_7 */
'1', 0x00, '0', 0x00, '0', 0x00, /* wcChar_7 */
WCID_VENDOR_CODE, /* bVendorCode */
0x00, /* bReserved */
};
__ALIGN_BEGIN const uint8_t WINUSB_WCIDDescriptor[40] __ALIGN_END = {
///////////////////////////////////////
/// WCID descriptor
///////////////////////////////////////
0x28, 0x00, 0x00, 0x00, /* dwLength */
0x00, 0x01, /* bcdVersion */
0x04, 0x00, /* wIndex */
0x01, /* bCount */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_7 */
///////////////////////////////////////
/// WCID function descriptor
///////////////////////////////////////
0x00, /* bFirstInterfaceNumber */
0x01, /* bReserved */
/* MTP */
'M', 'T', 'P', 0x00, 0x00, 0x00, 0x00, 0x00, /* cCID_8 */
/* */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* cSubCID_8 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_6 */
};
struct usb_msosv1_descriptor msosv1_desc = {
.string = (uint8_t *)WCID_StringDescriptor_MSOS,
.string_len = 18,
.vendor_code = WCID_VENDOR_CODE,
.compat_id = (uint8_t *)WINUSB_WCIDDescriptor,
.compat_id_len = sizeof(WINUSB_WCIDDescriptor),
.comp_id_property = NULL,
.comp_id_property_len = 0,
};
/*!< endpoint address */
#define CDC_IN_EP 0x81
#define CDC_OUT_EP 0x02
#define CDC_INT_EP 0x83
#define USBD_VID 0xFFFE
#define USBD_PID 0xFFFF
#define USBD_MAX_POWER 100
#define USBD_LANGID_STRING 1033
/*!< config descriptor size */
#define USB_CONFIG_SIZE (9 + MTP_DESCRIPTOR_LEN)
#ifdef CONFIG_USB_HS
#define MTP_MAX_MPS 512
#else
#define MTP_MAX_MPS 64
#endif
const uint8_t mtp_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0201, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
MTP_DESCRIPTOR_INIT(0x00, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, MTP_MAX_MPS, 0x02),
///////////////////////////////////////
/// string0 descriptor
///////////////////////////////////////
USB_LANGID_INIT(USBD_LANGID_STRING),
///////////////////////////////////////
/// string1 descriptor
///////////////////////////////////////
0x14, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'C', 0x00, /* wcChar0 */
'h', 0x00, /* wcChar1 */
'e', 0x00, /* wcChar2 */
'r', 0x00, /* wcChar3 */
'r', 0x00, /* wcChar4 */
'y', 0x00, /* wcChar5 */
'U', 0x00, /* wcChar6 */
'S', 0x00, /* wcChar7 */
'B', 0x00, /* wcChar8 */
///////////////////////////////////////
/// string2 descriptor
///////////////////////////////////////
0x26, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'C', 0x00, /* wcChar0 */
'h', 0x00, /* wcChar1 */
'e', 0x00, /* wcChar2 */
'r', 0x00, /* wcChar3 */
'r', 0x00, /* wcChar4 */
'y', 0x00, /* wcChar5 */
'U', 0x00, /* wcChar6 */
'S', 0x00, /* wcChar7 */
'B', 0x00, /* wcChar8 */
' ', 0x00, /* wcChar9 */
'M', 0x00, /* wcChar10 */
'T', 0x00, /* wcChar11 */
'P', 0x00, /* wcChar12 */
' ', 0x00, /* wcChar13 */
'D', 0x00, /* wcChar14 */
'E', 0x00, /* wcChar15 */
'M', 0x00, /* wcChar16 */
'O', 0x00, /* wcChar17 */
///////////////////////////////////////
/// string3 descriptor
///////////////////////////////////////
0x16, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'2', 0x00, /* wcChar0 */
'0', 0x00, /* wcChar1 */
'2', 0x00, /* wcChar2 */
'1', 0x00, /* wcChar3 */
'0', 0x00, /* wcChar4 */
'3', 0x00, /* wcChar5 */
'1', 0x00, /* wcChar6 */
'0', 0x00, /* wcChar7 */
'0', 0x00, /* wcChar8 */
'0', 0x00, /* wcChar9 */
#ifdef CONFIG_USB_HS
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x02,
0x02,
0x01,
0x40,
0x01,
0x00,
#endif
0x00
};
const uint8_t bos_descriptor[] = {
0x05, 0x0f, 0x16, 0x00, 0x02,
0x07, 0x10, 0x02, 0x06, 0x00, 0x00, 0x00,
0x0a, 0x10, 0x03, 0x00, 0x0f, 0x00, 0x01, 0x01, 0xf4, 0x01
};
void usbd_event_handler(uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
break;
case USBD_EVENT_CONNECTED:
break;
case USBD_EVENT_DISCONNECTED:
break;
case USBD_EVENT_RESUME:
break;
case USBD_EVENT_SUSPEND:
break;
case USBD_EVENT_CONFIGURED:
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
case USBD_EVENT_CLR_REMOTE_WAKEUP:
break;
default:
break;
}
}
struct usbd_interface intf0;
struct usb_bos_descriptor bos_desc = {
.string = bos_descriptor,
.string_len = 22
};
void mtp_init(void)
{
usbd_desc_register(mtp_descriptor);
usbd_msosv1_desc_register(&msosv1_desc);
usbd_bos_desc_register(&bos_desc);
usbd_add_interface(usbd_mtp_init_intf(&intf0, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP));
usbd_initialize();
}

View File

@@ -1,184 +0,0 @@
#include "usbd_core.h"
#include "usb_printer.h"
/*!< endpoint address */
#define PRINTER_IN_EP 0x81
#define PRINTER_IN_EP_SIZE 0x40
#define PRINTER_OUT_EP 0x02
#define PRINTER_OUT_EP_SIZE 0x40
#define USBD_VID 0x5A5A
#define USBD_PID 0xA5A5
#define USBD_MAX_POWER 100
#define USBD_LANGID_STRING 0x0409
/*!< config descriptor size */
#define USB_CONFIG_SIZE (32)
/*!< global descriptor */
static const uint8_t printer_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0000, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_SELF_POWERED, USBD_MAX_POWER),
USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0x07, 0x01, 0x02, 0x00),
USB_ENDPOINT_DESCRIPTOR_INIT(PRINTER_IN_EP, 0x02, PRINTER_IN_EP_SIZE, 0x00),
USB_ENDPOINT_DESCRIPTOR_INIT(PRINTER_OUT_EP, 0x02, PRINTER_OUT_EP_SIZE, 0x00),
///////////////////////////////////////
/// string0 descriptor
///////////////////////////////////////
USB_LANGID_INIT(USBD_LANGID_STRING),
///////////////////////////////////////
/// string1 descriptor
///////////////////////////////////////
0x14, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'C', 0x00, /* wcChar0 */
'h', 0x00, /* wcChar1 */
'e', 0x00, /* wcChar2 */
'r', 0x00, /* wcChar3 */
'r', 0x00, /* wcChar4 */
'y', 0x00, /* wcChar5 */
'U', 0x00, /* wcChar6 */
'S', 0x00, /* wcChar7 */
'B', 0x00, /* wcChar8 */
///////////////////////////////////////
/// string2 descriptor
///////////////////////////////////////
0x2A, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'C', 0x00, /* wcChar0 */
'h', 0x00, /* wcChar1 */
'e', 0x00, /* wcChar2 */
'r', 0x00, /* wcChar3 */
'r', 0x00, /* wcChar4 */
'y', 0x00, /* wcChar5 */
'U', 0x00, /* wcChar6 */
'S', 0x00, /* wcChar7 */
'B', 0x00, /* wcChar8 */
' ', 0x00, /* wcChar9 */
'P', 0x00, /* wcChar10 */
'R', 0x00, /* wcChar11 */
'I', 0x00, /* wcChar12 */
'N', 0x00, /* wcChar13 */
'T', 0x00, /* wcChar14 */
' ', 0x00, /* wcChar15 */
'D', 0x00, /* wcChar16 */
'E', 0x00, /* wcChar17 */
'M', 0x00, /* wcChar18 */
'O', 0x00, /* wcChar19 */
///////////////////////////////////////
/// string3 descriptor
///////////////////////////////////////
0x16, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'2', 0x00, /* wcChar0 */
'0', 0x00, /* wcChar1 */
'2', 0x00, /* wcChar2 */
'2', 0x00, /* wcChar3 */
'1', 0x00, /* wcChar4 */
'2', 0x00, /* wcChar5 */
'3', 0x00, /* wcChar6 */
'4', 0x00, /* wcChar7 */
'5', 0x00, /* wcChar8 */
'6', 0x00, /* wcChar9 */
#ifdef CONFIG_USB_HS
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x02,
0x02,
0x01,
0x40,
0x01,
0x00,
#endif
0x00
};
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[PRINTER_OUT_EP_SIZE];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[PRINTER_IN_EP_SIZE];
void usbd_event_handler(uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
break;
case USBD_EVENT_CONNECTED:
break;
case USBD_EVENT_DISCONNECTED:
break;
case USBD_EVENT_RESUME:
break;
case USBD_EVENT_SUSPEND:
break;
case USBD_EVENT_CONFIGURED:
/* setup first out ep read transfer */
usbd_ep_start_read(PRINTER_OUT_EP, read_buffer, PRINTER_OUT_EP_SIZE);
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
case USBD_EVENT_CLR_REMOTE_WAKEUP:
break;
default:
break;
}
}
void usbd_printer_bulk_out(uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
// for (int i = 0; i < 100; i++) {
// printf("%02x ", read_buffer[i]);
// }
// printf("\r\n");
/* setup next out ep read transfer */
usbd_ep_start_read(PRINTER_OUT_EP, read_buffer, PRINTER_OUT_EP_SIZE);
}
void usbd_printer_bulk_in(uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
if ((nbytes % PRINTER_IN_EP_SIZE) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(PRINTER_IN_EP, NULL, 0);
} else {
}
}
/*!< endpoint call back */
struct usbd_endpoint printer_out_ep = {
.ep_addr = PRINTER_OUT_EP,
.ep_cb = usbd_printer_bulk_out
};
struct usbd_endpoint printer_in_ep = {
.ep_addr = PRINTER_IN_EP,
.ep_cb = usbd_printer_bulk_in
};
struct usbd_interface intf0;
static const uint8_t printer_device_id[] =
{
0x00, 51,
'M','F','G',':','C','B','M',';',
'C','M','D',':','G','D','I',';',
'M','D','L',':','C','B','M','1','0','0','0',';',
'C','L','S',':','P','R','I','N','T','E','R',';',
'M','O','D','E',':','G','D','I',';'
};
void printer_init(void)
{
usbd_desc_register(printer_descriptor);
usbd_add_interface(usbd_printer_init_intf(&intf0, printer_device_id, sizeof(printer_device_id)));
usbd_add_endpoint(&printer_out_ep);
usbd_add_endpoint(&printer_in_ep);
usbd_initialize();
}

View File

@@ -11,14 +11,9 @@
#define TEST_USBH_MSC_FATFS 0
#define TEST_USBH_AUDIO 0
#define TEST_USBH_VIDEO 0
#if __has_include("lwip/pbuf.h")
#define TEST_USBH_CDC_ECM 1
#define TEST_USBH_RNDIS 1
#else
#define TEST_USBH_CDC_ECM 0
#define TEST_USBH_RNDIS 0
#endif
#define TEST_USBH_CDC_ECM 0
#define TEST_USBH_RNDIS 0
#define TEST_USBH_ASIX 0
#if TEST_USBH_CDC_ACM
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t cdc_buffer[512];
@@ -87,6 +82,9 @@ void usbh_hid_callback(void *arg, int nbytes)
}
USB_LOG_RAW("nbytes:%d\r\n", nbytes);
usbh_submit_urb(&hid_class->intin_urb);
} else if (nbytes == -USB_ERR_NAK) { /* for dwc2 */
usbh_submit_urb(&hid_class->intin_urb);
} else {
}
}
@@ -346,7 +344,7 @@ void usbh_videostreaming_parse_yuyv2(struct usbh_urb *urb, struct usbh_videostre
}
#endif
#if TEST_USBH_CDC_ECM || TEST_USBH_RNDIS
#if TEST_USBH_CDC_ECM || TEST_USBH_RNDIS || TEST_USBH_ASIX
#include "netif/etharp.h"
#include "lwip/netif.h"
#include "lwip/pbuf.h"
@@ -670,6 +668,118 @@ void usbh_rndis_stop(struct usbh_rndis *rndis_class)
}
#endif
#if TEST_USBH_ASIX
#include "usbh_asix.h"
struct netif g_asix_netif;
#ifdef __RTTHREAD__
static struct eth_device asix_dev;
static rt_err_t rt_usbh_asix_control(rt_device_t dev, int cmd, void *args)
{
struct usbh_asix *asix_class = (struct usbh_asix *)dev->user_data;
switch (cmd) {
case NIOCTL_GADDR:
/* get mac address */
if (args)
rt_memcpy(args, asix_class->mac, 6);
else
return -RT_ERROR;
break;
default:
break;
}
return RT_EOK;
}
static rt_err_t rt_usbh_asix_eth_tx(rt_device_t dev, struct pbuf *p)
{
return usbh_asix_linkoutput(NULL, p);
}
#endif
static err_t usbh_asix_if_init(struct netif *netif)
{
LWIP_ASSERT("netif != NULL", (netif != NULL));
netif->mtu = 1500;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
netif->state = NULL;
netif->name[0] = 'E';
netif->name[1] = 'X';
netif->output = etharp_output;
netif->linkoutput = usbh_asix_linkoutput;
return ERR_OK;
}
void usbh_asix_run(struct usbh_asix *asix_class)
{
#ifdef __RTTHREAD__
struct netdev *netdev;
memset(&asix_dev, 0, sizeof(struct eth_device));
asix_dev.parent.control = rt_usbh_asix_control;
asix_dev.eth_rx = NULL;
asix_dev.eth_tx = rt_usbh_asix_eth_tx;
asix_dev.parent.user_data = asix_class;
eth_device_init(&asix_dev, "u2");
eth_device_linkchange(&asix_dev, RT_TRUE);
usb_osal_thread_create("usbh_asix_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_asix_rx_thread, asix_dev.netif);
#else
struct netif *netif = &g_asix_netif;
netif->hwaddr_len = 6;
memcpy(netif->hwaddr, asix_class->mac, 6);
IP4_ADDR(&asix_class->ipaddr, 0, 0, 0, 0);
IP4_ADDR(&asix_class->netmask, 0, 0, 0, 0);
IP4_ADDR(&asix_class->gateway, 0, 0, 0, 0);
netif = netif_add(netif, &asix_class->ipaddr, &asix_class->netmask, &asix_class->gateway, NULL, usbh_asix_if_init, tcpip_input);
netif_set_default(netif);
while (!netif_is_up(netif)) {
}
dhcp_handle1 = xTimerCreate((const char *)"dhcp1", (TickType_t)200, (UBaseType_t)pdTRUE, (void *const)netif, (TimerCallbackFunction_t)dhcp_timeout);
if (dhcp_handle1 == NULL) {
USB_LOG_ERR("timer creation failed! \r\n");
while (1) {
}
}
usb_osal_thread_create("usbh_asix_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_asix_rx_thread, netif);
#if LWIP_DHCP
dhcp_start(netif);
xTimerStart(dhcp_handle1, 0);
#endif
#endif
}
void usbh_asix_stop(struct usbh_asix *asix_class)
{
#ifdef __RTTHREAD__
eth_device_deinit(&asix_dev);
#else
struct netif *netif = &g_asix_netif;
#if LWIP_DHCP
dhcp_stop(netif);
dhcp_cleanup(netif);
#endif
netif_set_down(netif);
netif_remove(netif);
#endif
}
#endif
void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class)
{
#if TEST_USBH_CDC_ACM
@@ -734,7 +844,7 @@ void usbh_class_test(void)
#ifdef __RTTHREAD__
/* do nothing */
#else
#if TEST_USBH_CDC_ECM || TEST_USBH_RNDIS
#if TEST_USBH_CDC_ECM || TEST_USBH_RNDIS || TEST_USBH_ASIX
/* Initialize the LwIP stack */
tcpip_init(NULL, NULL);
#endif

View File

@@ -141,7 +141,7 @@ const uint8_t video_descriptor[] = {
0x00
};
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -169,20 +169,20 @@ void usbd_event_handler(uint8_t event)
volatile bool tx_flag = 0;
volatile bool iso_tx_busy = false;
void usbd_video_open(uint8_t intf)
void usbd_video_open(uint8_t busid, uint8_t intf)
{
tx_flag = 1;
USB_LOG_RAW("OPEN\r\n");
iso_tx_busy = false;
}
void usbd_video_close(uint8_t intf)
void usbd_video_close(uint8_t busid, uint8_t intf)
{
USB_LOG_RAW("CLOSE\r\n");
tx_flag = 0;
iso_tx_busy = false;
}
void usbd_video_iso_callback(uint8_t ep, uint32_t nbytes)
void usbd_video_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
iso_tx_busy = false;
@@ -196,29 +196,29 @@ static struct usbd_endpoint video_in_ep = {
struct usbd_interface intf0;
struct usbd_interface intf1;
void video_init()
void video_init(uint8_t busid, uint32_t reg_base)
{
usbd_desc_register(video_descriptor);
usbd_add_interface(usbd_video_init_intf(&intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
usbd_add_interface(usbd_video_init_intf(&intf1, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
usbd_add_endpoint(&video_in_ep);
usbd_desc_register(busid, video_descriptor);
usbd_add_interface(busid, usbd_video_init_intf(busid, &intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
usbd_add_interface(busid, usbd_video_init_intf(busid, &intf1, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
usbd_add_endpoint(busid, &video_in_ep);
usbd_initialize();
usbd_initialize(busid, reg_base, usbd_event_handler);
}
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[10 * 1024];
void video_test()
void video_test(uint8_t busid)
{
uint32_t out_len;
uint32_t packets;
memset(packet_buffer, 0, 10 * 1024);
while (1) {
if (tx_flag) {
packets = usbd_video_mjpeg_payload_fill((uint8_t *)jpeg_data, sizeof(jpeg_data), packet_buffer, &out_len);
packets = usbd_video_mjpeg_payload_fill(busid, (uint8_t *)jpeg_data, sizeof(jpeg_data), packet_buffer, &out_len);
#if 0
iso_tx_busy = true;
usbd_ep_start_write(VIDEO_IN_EP, packet_buffer, out_len);
usbd_ep_start_write(busid, VIDEO_IN_EP, packet_buffer, out_len);
while (iso_tx_busy) {
if (tx_flag == 0) {
break;
@@ -229,7 +229,7 @@ void video_test()
for (uint32_t i = 0; i < packets; i++) {
if (i == (packets - 1)) {
iso_tx_busy = true;
usbd_ep_start_write(VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], out_len - (packets - 1) * MAX_PAYLOAD_SIZE);
usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], out_len - (packets - 1) * MAX_PAYLOAD_SIZE);
while (iso_tx_busy) {
if (tx_flag == 0) {
break;
@@ -237,7 +237,7 @@ void video_test()
}
} else {
iso_tx_busy = true;
usbd_ep_start_write(VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], MAX_PAYLOAD_SIZE);
usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], MAX_PAYLOAD_SIZE);
while (iso_tx_busy) {
if (tx_flag == 0) {
break;

View File

@@ -334,7 +334,7 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
volatile bool ep_tx_busy_flag = false;
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -349,9 +349,9 @@ void usbd_event_handler(uint8_t event)
break;
case USBD_EVENT_CONFIGURED:
/* setup first out ep read transfer */
usbd_ep_start_read(WINUSB_OUT_EP, read_buffer, 2048);
usbd_ep_start_read(busid, WINUSB_OUT_EP, read_buffer, 2048);
#if DOUBLE_WINUSB == 1
usbd_ep_start_read(WINUSB_OUT_EP2, read_buffer, 2048);
usbd_ep_start_read(busid, WINUSB_OUT_EP2, read_buffer, 2048);
#endif
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
@@ -364,25 +364,25 @@ void usbd_event_handler(uint8_t event)
}
}
void usbd_winusb_out(uint8_t ep, uint32_t nbytes)
void usbd_winusb_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
// for (int i = 0; i < 100; i++) {
// printf("%02x ", read_buffer[i]);
// }
// printf("\r\n");
usbd_ep_start_write(WINUSB_IN_EP, read_buffer, nbytes);
usbd_ep_start_write(busid, WINUSB_IN_EP, read_buffer, nbytes);
/* setup next out ep read transfer */
usbd_ep_start_read(WINUSB_OUT_EP, read_buffer, 2048);
usbd_ep_start_read(busid, WINUSB_OUT_EP, read_buffer, 2048);
}
void usbd_winusb_in(uint8_t ep, uint32_t nbytes)
void usbd_winusb_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
if ((nbytes % WINUSB_EP_MPS) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(WINUSB_IN_EP, NULL, 0);
usbd_ep_start_write(busid, WINUSB_IN_EP, NULL, 0);
} else {
ep_tx_busy_flag = false;
}
@@ -402,25 +402,25 @@ struct usbd_interface intf0;
#if DOUBLE_WINUSB == 1
void usbd_winusb_out2(uint8_t ep, uint32_t nbytes)
void usbd_winusb_out2(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
// for (int i = 0; i < 100; i++) {
// printf("%02x ", read_buffer[i]);
// }
// printf("\r\n");
usbd_ep_start_write(WINUSB_IN_EP2, read_buffer, nbytes);
usbd_ep_start_write(busid, WINUSB_IN_EP2, read_buffer, nbytes);
/* setup next out ep read transfer */
usbd_ep_start_read(WINUSB_OUT_EP2, read_buffer, 2048);
usbd_ep_start_read(busid, WINUSB_OUT_EP2, read_buffer, 2048);
}
void usbd_winusb_in2(uint8_t ep, uint32_t nbytes)
void usbd_winusb_in2(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
if ((nbytes % WINUSB_EP_MPS) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(WINUSB_IN_EP2, NULL, 0);
usbd_ep_start_write(busid, WINUSB_IN_EP2, NULL, 0);
} else {
ep_tx_busy_flag = false;
}
@@ -440,17 +440,17 @@ struct usbd_interface intf1;
#endif
void winusb_init(void)
void winusb_init(uint8_t busid, uint32_t reg_base)
{
usbd_desc_register(winusb_descriptor);
usbd_msosv1_desc_register(&msosv1_desc);
usbd_add_interface(&intf0);
usbd_add_endpoint(&winusb_out_ep1);
usbd_add_endpoint(&winusb_in_ep1);
usbd_desc_register(busid, winusb_descriptor);
usbd_msosv1_desc_register(busid, &msosv1_desc);
usbd_add_interface(busid, &intf0);
usbd_add_endpoint(busid, &winusb_out_ep1);
usbd_add_endpoint(busid, &winusb_in_ep1);
#if DOUBLE_WINUSB == 1
usbd_add_interface(&intf1);
usbd_add_endpoint(&winusb_out_ep2);
usbd_add_endpoint(&winusb_in_ep2);
usbd_add_interface(busid, &intf1);
usbd_add_endpoint(busid, &winusb_out_ep2);
usbd_add_endpoint(busid, &winusb_in_ep2);
#endif
usbd_initialize();
usbd_initialize(busid, reg_base, usbd_event_handler);
}

View File

@@ -51,12 +51,11 @@ CONFIG_USBDEV_TEST_MODE
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
使能或者关闭 usb test mode
CONFIG_USBDEV_MSC_BLOCK_SIZE
CONFIG_USBDEV_MSC_MAX_BUFSIZE
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
msc 临时缓存的大小,缓存越大,msc 的速度越高,默认等于 1个内存介质的扇区大小例如 sd卡 512flash 4K更改时需要是内存介质扇区的倍数
虽然名字叫 block size但是跟内存介质的 block size不是一个意思。
msc 缓存的最大长度,缓存越大,USB 的速度越高,因为介质一般多个 block 读写速度比单个 block 高很多,比如 sd 卡
默认 512 ,如果是 flash 需要改成 4K, 缓存的大小需要是 介质的一个 block size 的整数倍。
CONFIG_USBDEV_MSC_MANUFACTURER_STRING
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@@ -10,6 +10,8 @@
CORE
-----------------
.. note:: 请注意v1.1 版本开始增加 busid 形参,其余保持不变,所以 API 说明不做更新
端点结构体
""""""""""""""""""""""""""""""""""""

View File

@@ -111,6 +111,19 @@ hub 结构体
uint8_t *int_buffer;
};
usbh_alloc_bus
""""""""""""""""""""""""""""""""""""
``usbh_alloc_bus`` 用于创建一个 bus并且根据 reg_base 分配一个 hcd
.. code-block:: C
struct usbh_bus *usbh_alloc_bus(uint8_t busid, uint32_t reg_base);
- **busid** bus id从 0开始不能超过 `CONFIG_USBHOST_MAX_BUS`
- **reg_base** hcd 寄存器基地址
- 返回 bus 句柄
usbh_initialize
""""""""""""""""""""""""""""""""""""
@@ -118,7 +131,9 @@ usbh_initialize
.. code-block:: C
int usbh_initialize(void);
int usbh_initialize(struct usbh_bus *bus);
- **bus** bus 句柄
usbh_find_class_instance
""""""""""""""""""""""""""""""""""""

View File

@@ -1,6 +1,8 @@
Porting
=========================
.. note:: 请注意v1.1 版本开始增加 busid 形参,其余保持不变,所以 API 说明不做更新
device controller(dcd)
-------------------------

View File

@@ -3,11 +3,11 @@
# -- Project information
project = 'CherryUSB'
copyright = '2022, sakumisu'
copyright = '2024, sakumisu'
author = 'sakumisu'
release = '1.0.0'
version = '1.0.0'
release = '1.1.0'
version = '1.1.0'
# -- General configuration

View File

@@ -35,7 +35,7 @@ USB 模拟 U 盘
}
- 实现三个接口即可使用 msc读写操作如果没有 os 则是在中断中
- `CONFIG_USBDEV_MSC_BLOCK_SIZE` 可以为 512 的整数倍,更改此项,可以增加 msc 的读写速度,当然,也会消耗更多的 ram
- `CONFIG_USBDEV_MSC_MAX_BUFSIZE` 可以为 512 的整数倍,更改此项,可以增加 msc 的读写速度,当然,也会消耗更多的 ram
.. note:: MSC 一般配合 rtos 使用,因为读写操作是阻塞的,放中断是不合适的, `CONFIG_USBDEV_MSC_THREAD` 则是使能 os 管理

View File

@@ -216,17 +216,17 @@ EHCI 是 intel 制定的标准主机控制器接口,任何厂家都必须实
.. code-block:: C
//Host Controller Capability Register BASE
#define CONFIG_USB_EHCI_HCCR_BASE (0xxx)
//Host Controller Operational Register BASE
#define CONFIG_USB_EHCI_HCOR_BASE (0xxx)
//Host Controller Operational Register BASE 距离基地址的偏移
#define CONFIG_USB_EHCI_HCOR_OFFSET (0x14)
//是否打印 ehci 配置信息
#define CONFIG_USB_EHCI_INFO_ENABLE
//是否关闭保留寄存器的占位,默认保留 9 个双字的占位
#define CONFIG_USB_ECHI_HCOR_RESERVED_DISABLE
#define CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE
//是否使能 configflag 寄存器中的 bit0
#define CONFIG_USB_EHCI_CONFIGFLAG
//是否使能 port power bit
#define CONFIG_USB_EHCI_PORT_POWER
//是否查看 ehci 配置信息
#define CONFIG_USB_EHCI_PRINT_HW_PARAM
同时由于 EHCI 只是主机控制器并且只支持高速,一般配合一个 otg 控制器和一个低速全速兼容控制单元,而速度的获取一般是在 otg 寄存器中,所以需要用户实现 `usbh_get_port_speed` 函数。

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -4,7 +4,6 @@
在学习 USB 或者是学习 CherryUSB 代码之前,我们需要先基于现有的 demo 进行快速验证,为什么?是为了提升对 USB 的兴趣,能有信心进行下一步的动作,如果 demo 都跑不起来,或者自己摸索写代码,或者先看 USB 基本概念,结果看到最后,
发现一点都看不懂,概念好多,根本记不住,从而丧失对 USB 的兴趣。因此,先跑 demo 非常重要。下面我将给大家罗列目前支持的 demo 仓库。
基于 bouffalolab 系列芯片
---------------------------
@@ -100,23 +99,31 @@ USB Device 移植要点
.. code-block:: C
// 以下细节如有出入,请对照 stm32xxx.h 文件修改
#define USBD_IRQHandler OTG_HS_IRQHandler // pa11/pa12 引脚使用 OTG_FS_IRQHandler
#define USBD_BASE (0x40040000UL) // pa11/pa12 引脚一般使用 50000000ULSTM32F7/H7 使用 0x40080000UL
#define CONFIG_USBDEV_EP_NUM 6 // pa11/pa12 引脚使用 4
#define CONFIG_USB_DWC2_RAM_SIZE 4096 // pa11/pa12 引脚使用 1280
- 如果使用 fsdev ip`usb_config.h` 中实现以下宏:
.. code-block:: C
#define CONFIG_USBDEV_EP_NUM 8
#define CONFIG_USBDEV_FSDEV_PMA_ACCESS 2
- 编译器推荐使用 **AC6**。勾选 **Microlib**,并实现 **printf** ,方便后续查看 log。
.. figure:: img/stm32_10.png
.. figure:: img/stm32_11.png
- 拷贝 **xxx_msp.c** 中的 **HAL_PCD_MspInit** 函数中的内容到 **usb_dc_low_level_init** 函数中,屏蔽 st 生成的 usb 中断函数和 usb 初始化
- 拷贝 **xxx_msp.c** 中的 **HAL_PCD_MspInit** 函数中的内容到 **usb_dc_low_level_init** 函数中,屏蔽 st 生成的 usb 初始化
.. figure:: img/stm32_12.png
.. figure:: img/stm32_13.png
.. figure:: img/stm32_14.png
- 调用 template 的内容初始化,就可以使用了
- 在中断函数中调用 `USBD_IRQHandler`,并传入 `busid`
.. figure:: img/stm32_13.png
- 调用 template 的内容初始化,并填入 `busid` 和 USB IP 的 `reg base` `busid` 从 0 开始,不能超过 `CONFIG_USBDEV_MAX_BUS`
.. figure:: img/stm32_15.png
@@ -134,12 +141,6 @@ USB Host 移植要点
.. figure:: img/stm32_10.png
.. figure:: img/stm32_11.png
- 拷贝 **xxx_msp.c** 中的 **HAL_HCD_MspInit** 函数中的内容到 **usb_hc_low_level_init** 函数中,屏蔽 st 生成的 usb 中断函数和 usb 初始化
.. figure:: img/stm32_18.png
.. figure:: img/stm32_13.png
.. figure:: img/stm32_19.png
- 复制一份 **cherryusb_config_template.h**,放到 `Core/Inc` 目录下,并命名为 `usb_config.h`
- 增加 **usb_glue_st.c** 文件,并在 `usb_config.h` 中实现以下宏:
@@ -147,13 +148,15 @@ USB Host 移植要点
.. code-block:: C
// 以下细节如有出入,请对照 stm32xxx.h 文件修改
#define USBH_BASE (0x40040000UL)
#define USBH_IRQHandler OTG_HS_IRQHandler
#define CONFIG_USBHOST_PIPE_NUM 12
- 调用 **usbh_initialize** 以及 os 需要的启动线程的函数即可使用
- 拷贝 **xxx_msp.c** 中的 `HAL_HCD_MspInit` 函数中的内容到 `usb_hc_low_level_init` 函数中,屏蔽 st 生成的 usb 初始化
- 在中断函数中调用 `USBH_IRQHandler`,并传入 `busid`
- 调用 `usbh_initialize` 并填入 `busid` 和 USB IP 的 `reg base` `busid` 从 0 开始,不能超过 `CONFIG_USBHOST_MAX_BUS`
- 启动线程
.. figure:: img/stm32_20.png
.. figure:: img/stm32_18.png
.. figure:: img/stm32_19.png
- 如果使用 **msc**,并且带文件系统,需要自行添加文件系统文件了,对应的 porting 编写参考 **fatfs_usbh.c** 文件。

View File

@@ -8,13 +8,11 @@ USB Device 移植要点
- 拷贝 CherryUSB 源码到工程目录下,并按需添加源文件和头文件路径,其中 `usbd_core.c``usb_dc_xxx.c` 为必须添加项。而 `usb_dc_xxx.c` 是芯片所对应的 USB IP dcd 部分驱动,如果不知道自己芯片属于那个 USB IP参考 **port** 目录下的不同 USB IP 的 readme。如果使用的 USB IP 没有支持,只能自己实现了
- 拷贝 `cherryusb_config_template.h` 文件到自己工程目录下,命名为 `usb_config.h`,并添加相应的目录头文件路径
-`usb_config.h` 中添加 `USBD_IRQHandler=xxxx``CONFIG_USBDEV_EP_NUM=x` 以及 `USBD_BASE=0xxxxx` 三个常规 porting 需要的宏
.. note:: 上述三个宏仅对 fsdev、musb、dwc2 有效,因为这 3 个是通用 IP
- 实现 `usb_dc_low_level_init` 函数(该函数主要负责 USB 时钟、引脚、中断的初始化)。该函数可以放在你想要放的任何参与编译的 c 文件中。如何进行 USB 的时钟、引脚、中断等初始化,请自行根据你使用的芯片原厂提供的源码中进行添加。
- 描述符的注册、class的注册、接口的注册、端点中断的注册。不会的参考 demo 下的 template
- 调用 `usbd_initialize` 初始化 usb 硬件
- 调用 `usbd_initialize` 并填入 `busid` 和 USB IP 的 `reg base` `busid` 从 0 开始,不能超过 `CONFIG_USBDEV_MAX_BUS`
- 在中断函数中调用 `USBD_IRQHandler`,并传入 `busid`, 如果你的 SDK 中中断入口已经存在 `USBD_IRQHandler` ,请更改 USB 协议栈中的名称
- 编译使用。各个 class 如何使用,参考 demo 下的 template
USB Host 移植要点
@@ -22,12 +20,9 @@ USB Host 移植要点
- 拷贝 CherryUSB 源码到工程目录下,并按需添加源文件和头文件路径,其中 `usbh_core.c``usb_hc_xxx.c` 以及 **osal** 目录下源文件(根据不同的 os 选择对应的源文件)为必须添加项。而 `usb_hc_xxx.c` 是芯片所对应的 USB IP dcd 部分驱动,如果不知道自己芯片属于那个 USB IP参考 **port** 目录下的不同 USB IP 的 readme。如果使用的 USB IP 没有支持,只能自己实现了
- 拷贝 `cherryusb_config_template.h` 文件到自己工程目录下,命名为 `usb_config.h`,并添加相应的目录头文件路径
-`usb_config.h` 中添加 `USBH_IRQHandler=xxxx``CONFIG_USBHOST_PIPE_NUM=x` 以及 `USBH_BASE=0xxxxx` 三个常规 porting 需要的宏
.. note:: 上述三个宏仅对 musb、dwc2 有效,因为这 2 个是通用 IP
- 实现 `usb_hc_low_level_init` 函数(该函数主要负责 USB 时钟、引脚、中断的初始化)。该函数可以放在你想要放的任何参与编译的 c 文件中。如何进行 USB 的时钟、引脚、中断等初始化,请自行根据你使用的芯片原厂提供的源码中进行添加。
- 调用 `usbh_initialize` 初始化 usb 硬件
- 调用 `usbh_initialize` 并填入 `busid` 和 USB IP 的 `reg base` `busid` 从 0 开始,不能超过 `CONFIG_USBHOST_MAX_BUS`
- 在中断函数中调用 `USBH_IRQHandler`,并传入 `busid`, 如果你的 SDK 中中断入口已经存在 `USBH_IRQHandler` ,请更改 USB 协议栈中的名称
- 如果使用的是 GCC ,需要在链接脚本(ld)中添加如下代码:
.. code-block:: C
@@ -52,8 +47,6 @@ USB Host 移植要点
- 编译使用。各个 class 如何使用,参考 demo 下的 `usb_host.c` 文件
.. caution:: 如果主从 ip 共用一个中断,设置 `USBD_IRQHandler=USBD_IRQHandler``USBH_IRQHandler=USBH_IRQHandler` ,然后由真正的中断函数根据主从模式调用这两个函数。
带 cache 功能的芯片使用注意
-------------------------------

View File

@@ -35,7 +35,9 @@
.. figure:: img/config_file.png
* 使用 `scons --target=mdk` 或者 `scons` 进行编译
- `usb_config.h` 中添加 `USBD_IRQHandler=xxxx``CONFIG_USBDEV_EP_NUM=x` 以及 `USBD_BASE=0xxxxx` 三个常规 porting 需要的宏
* 使用 `scons --target=mdk5` 或者 `scons` 进行编译
主机配置
--------------------------
@@ -48,15 +50,33 @@
.. figure:: img/env8.png
* 默认使能除了 hub 之外的所有 class 驱动
* 设置 psc 线程的线程栈以及线程优先级。
* 根据需要勾选 class 驱动
* 最后退出保存即可。
* 退出以后不急着编译,需要在代码中实现 `usb_hc_low_level_init` 函数。
* 复制一份 `usb_config.h` 到自己的目录中,并实现以下内容, 禁止包含 `"rtthread.h"`
.. figure:: img/config_file.png
* 使用 `scons --target=mdk` 或者 `scons` 进行编译
* 在代码中实现 `usb_hc_low_level_init` 函数USB 中断中调用 `USBH_IRQHandler`
* 调用 `usbh_initialize`
* 以上内容我们推荐放在 **board.c** 中,如下代码:
.. code-block:: C
void OTG_HS_IRQHandler(void)
{
extern void USBH_IRQHandler(uint8_t busid);
USBH_IRQHandler(0);
}
int usbh_init(void)
{
usbh_initialize(0, USB_OTG_HS_PERIPH_BASE);
return 0;
}
INIT_APP_EXPORT(usbh_init);
* 使用 `scons --target=mdk5` 或者 `scons` 进行编译,需要使用 AC6 编译器
* 如果使用的是 GCC ,需要在链接脚本(ld)中添加如下代码:
.. code-block:: C
@@ -71,17 +91,17 @@
借助 STM32CubeMX 生成 USB 初始化
----------------------------------
使用 STM32CubeMX 主要是用来生成 usb 时钟、引脚、中断的配置。我们需要点击如图所示文件,并配置好 USB 的时钟、中断,点击 `Generate Code`生成的时钟配置在 `main.c` 中的 `SystemClock_Config` 文件,将其拷贝到 `board.c` 中。
使用 STM32CubeMX 主要是用来生成 usb 时钟、引脚、中断的配置。我们需要点击如图所示文件,并配置好 USB 的时钟、中断,点击 `Generate Code`
.. figure:: img/stm32cubemx0.png
.. figure:: img/stm32cubemx1.png
.. figure:: img/stm32cubemx2.png
.. figure:: img/stm32cubemx_clk.png
然后将 `stm32xxxx_hal_msp.c` 中的 `HAL_PCD_MspInit` 或者是 `HAL_HCD_MspInit` 中的内容复制到 `usb_dc_low_level_init``usb_hc_low_level_init` 函数中,举例如下:
-`main.c` 中的 `SystemClock_Config` 替换掉 `board.c` 中的配置
.. figure:: img/stm32_init2.png
-`stm32xxxx_hal_msp.c` 中的 `HAL_PCD_MspInit` 或者是 `HAL_HCD_MspInit` 中的内容复制到 `usb_dc_low_level_init``usb_hc_low_level_init` 函数中,举例如下:
.. figure:: img/stm32_init.png
其次将 `main.c` 中的 `SystemClock_Config` 替换掉 `board.c` 中的配置
.. figure:: img/stm32_init2.png

View File

@@ -3,10 +3,3 @@
## Support Chip List
- CH32V30x
## Before Use
Your should implement `usb_dc_low_level_init` and `usb_dc_low_level_deinit`.
- Enable or disable USB clock and set USB clock for 48M.
- Enable or disable gpio and gpio clk for usb dp and dm.
- Enable or disable usb irq

View File

@@ -1,4 +1,3 @@
#include "usb_dc.h"
#include "usbd_core.h"
#include "usb_ch58x_usbfs_reg.h"
@@ -121,249 +120,13 @@ __WEAK void usb_dc_low_level_deinit(void)
{
}
/**
* @brief Set address
* @pre None
* @param[in] address 8-bit valid address
* @retval >=0 success otherwise failure
*/
int usbd_set_address(const uint8_t address)
{
if (address == 0) {
CH58x_USBFS_DEV->USB_DEV_AD = (CH58x_USBFS_DEV->USB_DEV_AD & 0x80) | address;
}
usb_dc_cfg.address = address;
return 0;
}
uint8_t usbd_get_port_speed(const uint8_t port)
{
return USB_SPEED_FULL;
}
/**
* @brief Open endpoint
* @pre None
* @param[in] ep_cfg : Endpoint configuration structure pointer
* @retval >=0 success otherwise failure
*/
int usbd_ep_open(const struct usb_endpoint_descriptor *ep)
{
/*!< ep id */
uint8_t epid = USB_EP_GET_IDX(ep->bEndpointAddress);
if (epid > (USB_NUM_BIDIR_ENDPOINTS - 1)) {
/**
* If you use ch58x, you can change the EP_NUMS set to 8
*/
USB_LOG_ERR("Ep addr %02x overflow\r\n", ep->bEndpointAddress);
return -1;
}
/*!< ep max packet length */
uint8_t mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
/*!< update ep max packet length */
if (USB_EP_DIR_IS_IN(ep->bEndpointAddress)) {
/*!< in */
usb_dc_cfg.ep_in[epid].ep_enable = true;
usb_dc_cfg.ep_in[epid].mps = mps;
usb_dc_cfg.ep_in[epid].eptype = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
} else if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
/*!< out */
usb_dc_cfg.ep_out[epid].ep_enable = true;
usb_dc_cfg.ep_out[epid].mps = mps;
usb_dc_cfg.ep_out[epid].eptype = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
}
return 0;
}
/**
* @brief Close endpoint
* @pre None
* @param[in] ep Endpoint address
* @retval >=0 success otherwise failure
*/
int usbd_ep_close(const uint8_t ep)
{
/*!< ep id */
uint8_t epid = USB_EP_GET_IDX(ep);
if (USB_EP_DIR_IS_IN(ep)) {
/*!< in */
usb_dc_cfg.ep_in[epid].ep_enable = false;
} else if (USB_EP_DIR_IS_OUT(ep)) {
/*!< out */
usb_dc_cfg.ep_out[epid].ep_enable = false;
}
return 0;
}
/**
* @brief Setup in ep transfer setting and start transfer.
*
* This function is asynchronous.
* This function is similar to uart with tx dma.
*
* This function is called to write data to the specified endpoint. The
* supplied usbd_endpoint_callback function will be called when data is transmitted
* out.
*
* @param[in] ep Endpoint address corresponding to the one
* listed in the device configuration table
* @param[in] data Pointer to data to write
* @param[in] data_len Length of the data requested to write. This may
* be zero for a zero length status packet.
* @return 0 on success, negative errno code on fail.
*/
int usbd_ep_start_write(const uint8_t ep, const uint8_t *data, uint32_t data_len)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
if (!data && data_len) {
return -1;
}
if (!usb_dc_cfg.ep_in[ep_idx].ep_enable) {
return -2;
}
if ((uint32_t)data & 0x03) {
return -3;
}
usb_dc_cfg.ep_in[ep_idx].xfer_buf = (uint8_t *)data;
usb_dc_cfg.ep_in[ep_idx].xfer_len = data_len;
usb_dc_cfg.ep_in[ep_idx].actual_xfer_len = 0;
if (data_len == 0) {
/*!< write 0 len data */
EPn_SET_TX_LEN(ep_idx, 0);
/*!< enable tx */
if (usb_dc_cfg.ep_in[ep_idx].eptype != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
EPn_SET_TX_VALID(ep_idx);
} else {
EPn_SET_TX_ISO_VALID(ep_idx);
}
/*!< return */
return 0;
} else {
/*!< Not zlp */
data_len = MIN(data_len, usb_dc_cfg.ep_in[ep_idx].mps);
/*!< write buff */
memcpy(usb_dc_cfg.ep_in[ep_idx].ep_ram_addr, data, data_len);
/*!< write real_wt_nums len data */
EPn_SET_TX_LEN(ep_idx, data_len);
/*!< enable tx */
if (usb_dc_cfg.ep_in[ep_idx].eptype != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
EPn_SET_TX_VALID(ep_idx);
} else {
EPn_SET_TX_ISO_VALID(ep_idx);
}
}
return 0;
}
/**
* @brief Setup out ep transfer setting and start transfer.
*
* This function is asynchronous.
* This function is similar to uart with rx dma.
*
* This function is called to read data to the specified endpoint. The
* supplied usbd_endpoint_callback function will be called when data is received
* in.
*
* @param[in] ep Endpoint address corresponding to the one
* listed in the device configuration table
* @param[in] data Pointer to data to read
* @param[in] data_len Max length of the data requested to read.
*
* @return 0 on success, negative errno code on fail.
*/
int usbd_ep_start_read(const uint8_t ep, uint8_t *data, uint32_t data_len)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
if (!data && data_len) {
return -1;
}
if (!usb_dc_cfg.ep_out[ep_idx].ep_enable) {
return -2;
}
if ((uint32_t)data & 0x03) {
return -3;
}
usb_dc_cfg.ep_out[ep_idx].xfer_buf = (uint8_t *)data;
usb_dc_cfg.ep_out[ep_idx].xfer_len = data_len;
usb_dc_cfg.ep_out[ep_idx].actual_xfer_len = 0;
if (data_len == 0) {
} else {
data_len = MIN(data_len, usb_dc_cfg.ep_out[ep_idx].mps);
}
if (usb_dc_cfg.ep_out[ep_idx].eptype != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
EPn_SET_RX_VALID(ep_idx);
} else {
EPn_SET_RX_ISO_VALID(ep_idx);
}
return 0;
}
/**
* @brief Endpoint setting stall
* @pre None
* @param[in] ep Endpoint address
* @retval >=0 success otherwise failure
*/
int usbd_ep_set_stall(const uint8_t ep)
{
/*!< ep id */
uint8_t epid = USB_EP_GET_IDX(ep);
if (USB_EP_DIR_IS_OUT(ep)) {
EPn_SET_RX_STALL(epid);
} else {
EPn_SET_TX_STALL(epid);
}
return 0;
}
/**
* @brief Endpoint clear stall
* @pre None
* @param[in] ep Endpoint address
* @retval >=0 success otherwise failure
*/
int usbd_ep_clear_stall(const uint8_t ep)
{
uint8_t epid = USB_EP_GET_IDX(ep);
if (USB_EP_DIR_IS_OUT(ep)) {
EPn_CLR_RX_STALL(epid);
} else {
EPn_CLR_TX_STALL(epid);
}
return 0;
}
/**
* @brief Check endpoint status
* @pre None
* @param[in] ep Endpoint address
* @param[out] stalled Outgoing endpoint status
* @retval >=0 success otherwise failure
*/
int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled)
{
if (USB_EP_DIR_IS_OUT(ep)) {
} else {
}
return 0;
}
/**
* @brief USB initialization
* @pre None
* @param[in] None
* @retval >=0 success otherwise failure
*/
int usb_dc_init(void)
int usb_dc_init(uint8_t busid)
{
usb_dc_cfg.ep_in[0].ep_ram_addr = ep0_data_buff;
usb_dc_cfg.ep_out[0].ep_ram_addr = ep0_data_buff;
@@ -435,6 +198,248 @@ int usb_dc_init(void)
return 0;
}
int usb_dc_deinit(uint8_t busid)
{
return 0;
}
/**
* @brief Set address
* @pre None
* @param[in] address 8-bit valid address
* @retval >=0 success otherwise failure
*/
int usbd_set_address(uint8_t busid, const uint8_t address)
{
if (address == 0) {
CH58x_USBFS_DEV->USB_DEV_AD = (CH58x_USBFS_DEV->USB_DEV_AD & 0x80) | address;
}
usb_dc_cfg.address = address;
return 0;
}
uint8_t usbd_get_port_speed(uint8_t busid, const uint8_t port)
{
return USB_SPEED_FULL;
}
/**
* @brief Open endpoint
* @pre None
* @param[in] ep_cfg : Endpoint configuration structure pointer
* @retval >=0 success otherwise failure
*/
int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
{
/*!< ep id */
uint8_t epid = USB_EP_GET_IDX(ep->bEndpointAddress);
if (epid > (USB_NUM_BIDIR_ENDPOINTS - 1)) {
/**
* If you use ch58x, you can change the EP_NUMS set to 8
*/
USB_LOG_ERR("Ep addr %02x overflow\r\n", ep->bEndpointAddress);
return -1;
}
/*!< ep max packet length */
uint8_t mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
/*!< update ep max packet length */
if (USB_EP_DIR_IS_IN(ep->bEndpointAddress)) {
/*!< in */
usb_dc_cfg.ep_in[epid].ep_enable = true;
usb_dc_cfg.ep_in[epid].mps = mps;
usb_dc_cfg.ep_in[epid].eptype = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
} else if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
/*!< out */
usb_dc_cfg.ep_out[epid].ep_enable = true;
usb_dc_cfg.ep_out[epid].mps = mps;
usb_dc_cfg.ep_out[epid].eptype = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
}
return 0;
}
/**
* @brief Close endpoint
* @pre None
* @param[in] ep Endpoint address
* @retval >=0 success otherwise failure
*/
int usbd_ep_close(uint8_t busid, const uint8_t ep)
{
/*!< ep id */
uint8_t epid = USB_EP_GET_IDX(ep);
if (USB_EP_DIR_IS_IN(ep)) {
/*!< in */
usb_dc_cfg.ep_in[epid].ep_enable = false;
} else if (USB_EP_DIR_IS_OUT(ep)) {
/*!< out */
usb_dc_cfg.ep_out[epid].ep_enable = false;
}
return 0;
}
/**
* @brief Endpoint setting stall
* @pre None
* @param[in] ep Endpoint address
* @retval >=0 success otherwise failure
*/
int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
{
/*!< ep id */
uint8_t epid = USB_EP_GET_IDX(ep);
if (USB_EP_DIR_IS_OUT(ep)) {
EPn_SET_RX_STALL(epid);
} else {
EPn_SET_TX_STALL(epid);
}
return 0;
}
/**
* @brief Endpoint clear stall
* @pre None
* @param[in] ep Endpoint address
* @retval >=0 success otherwise failure
*/
int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep)
{
uint8_t epid = USB_EP_GET_IDX(ep);
if (USB_EP_DIR_IS_OUT(ep)) {
EPn_CLR_RX_STALL(epid);
} else {
EPn_CLR_TX_STALL(epid);
}
return 0;
}
/**
* @brief Check endpoint status
* @pre None
* @param[in] ep Endpoint address
* @param[out] stalled Outgoing endpoint status
* @retval >=0 success otherwise failure
*/
int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled)
{
if (USB_EP_DIR_IS_OUT(ep)) {
} else {
}
return 0;
}
/**
* @brief Setup in ep transfer setting and start transfer.
*
* This function is asynchronous.
* This function is similar to uart with tx dma.
*
* This function is called to write data to the specified endpoint. The
* supplied usbd_endpoint_callback function will be called when data is transmitted
* out.
*
* @param[in] ep Endpoint address corresponding to the one
* listed in the device configuration table
* @param[in] data Pointer to data to write
* @param[in] data_len Length of the data requested to write. This may
* be zero for a zero length status packet.
* @return 0 on success, negative errno code on fail.
*/
int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
if (!data && data_len) {
return -1;
}
if (!usb_dc_cfg.ep_in[ep_idx].ep_enable) {
return -2;
}
if ((uint32_t)data & 0x03) {
return -3;
}
usb_dc_cfg.ep_in[ep_idx].xfer_buf = (uint8_t *)data;
usb_dc_cfg.ep_in[ep_idx].xfer_len = data_len;
usb_dc_cfg.ep_in[ep_idx].actual_xfer_len = 0;
if (data_len == 0) {
/*!< write 0 len data */
EPn_SET_TX_LEN(ep_idx, 0);
/*!< enable tx */
if (usb_dc_cfg.ep_in[ep_idx].eptype != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
EPn_SET_TX_VALID(ep_idx);
} else {
EPn_SET_TX_ISO_VALID(ep_idx);
}
/*!< return */
return 0;
} else {
/*!< Not zlp */
data_len = MIN(data_len, usb_dc_cfg.ep_in[ep_idx].mps);
/*!< write buff */
memcpy(usb_dc_cfg.ep_in[ep_idx].ep_ram_addr, data, data_len);
/*!< write real_wt_nums len data */
EPn_SET_TX_LEN(ep_idx, data_len);
/*!< enable tx */
if (usb_dc_cfg.ep_in[ep_idx].eptype != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
EPn_SET_TX_VALID(ep_idx);
} else {
EPn_SET_TX_ISO_VALID(ep_idx);
}
}
return 0;
}
/**
* @brief Setup out ep transfer setting and start transfer.
*
* This function is asynchronous.
* This function is similar to uart with rx dma.
*
* This function is called to read data to the specified endpoint. The
* supplied usbd_endpoint_callback function will be called when data is received
* in.
*
* @param[in] ep Endpoint address corresponding to the one
* listed in the device configuration table
* @param[in] data Pointer to data to read
* @param[in] data_len Max length of the data requested to read.
*
* @return 0 on success, negative errno code on fail.
*/
int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
if (!data && data_len) {
return -1;
}
if (!usb_dc_cfg.ep_out[ep_idx].ep_enable) {
return -2;
}
if ((uint32_t)data & 0x03) {
return -3;
}
usb_dc_cfg.ep_out[ep_idx].xfer_buf = (uint8_t *)data;
usb_dc_cfg.ep_out[ep_idx].xfer_len = data_len;
usb_dc_cfg.ep_out[ep_idx].actual_xfer_len = 0;
if (data_len == 0) {
} else {
data_len = MIN(data_len, usb_dc_cfg.ep_out[ep_idx].mps);
}
if (usb_dc_cfg.ep_out[ep_idx].eptype != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
EPn_SET_RX_VALID(ep_idx);
} else {
EPn_SET_RX_ISO_VALID(ep_idx);
}
return 0;
}
/**
* @brief USB interrupt processing function
* @pre None
@@ -472,11 +477,11 @@ USBD_IRQHandler(void)
if (usb_dc_cfg.ep_in[0].xfer_len > usb_dc_cfg.ep_in[0].mps) {
usb_dc_cfg.ep_in[0].xfer_len -= usb_dc_cfg.ep_in[0].mps;
usb_dc_cfg.ep_in[0].actual_xfer_len += usb_dc_cfg.ep_in[0].mps;
usbd_event_ep_in_complete_handler(0 | 0x80, usb_dc_cfg.ep_in[0].actual_xfer_len);
usbd_event_ep_in_complete_handler(0, 0 | 0x80, usb_dc_cfg.ep_in[0].actual_xfer_len);
} else {
usb_dc_cfg.ep_in[0].actual_xfer_len += usb_dc_cfg.ep_in[0].xfer_len;
usb_dc_cfg.ep_in[0].xfer_len = 0;
usbd_event_ep_in_complete_handler(0 | 0x80, usb_dc_cfg.ep_in[0].actual_xfer_len);
usbd_event_ep_in_complete_handler(0, 0 | 0x80, usb_dc_cfg.ep_in[0].actual_xfer_len);
}
break;
case 0:
@@ -527,7 +532,7 @@ USBD_IRQHandler(void)
} else {
usb_dc_cfg.ep_in[epid].actual_xfer_len += usb_dc_cfg.ep_in[epid].xfer_len;
usb_dc_cfg.ep_in[epid].xfer_len = 0;
usbd_event_ep_in_complete_handler(epid | 0x80, usb_dc_cfg.ep_in[epid].actual_xfer_len);
usbd_event_ep_in_complete_handler(0, epid | 0x80, usb_dc_cfg.ep_in[epid].actual_xfer_len);
}
}
break;
@@ -540,7 +545,7 @@ USBD_IRQHandler(void)
usb_dc_cfg.ep_out[0].actual_xfer_len += read_count;
usb_dc_cfg.ep_out[0].xfer_len -= read_count;
usbd_event_ep_out_complete_handler(0x00, usb_dc_cfg.ep_out[0].actual_xfer_len);
usbd_event_ep_out_complete_handler(0, 0x00, usb_dc_cfg.ep_out[0].actual_xfer_len);
if (read_count == 0) {
/*!< Out status, start reading setup */
EPn_SET_RX_VALID(0);
@@ -557,7 +562,7 @@ USBD_IRQHandler(void)
usb_dc_cfg.ep_out[epid].xfer_len -= read_count;
if ((read_count < usb_dc_cfg.ep_out[epid].mps) || (usb_dc_cfg.ep_out[epid].xfer_len == 0)) {
usbd_event_ep_out_complete_handler(((epid)&0x7f), usb_dc_cfg.ep_out[epid].actual_xfer_len);
usbd_event_ep_out_complete_handler(0, ((epid)&0x7f), usb_dc_cfg.ep_out[epid].actual_xfer_len);
} else {
if (usb_dc_cfg.ep_out[epid].eptype != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
EPn_SET_RX_VALID(epid);
@@ -597,13 +602,13 @@ USBD_IRQHandler(void)
EPn_SET_TX_VALID(0);
}
EPn_SET_RX_NAK(0);
usbd_event_ep0_setup_complete_handler((uint8_t *)&(usb_dc_cfg.setup));
usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&(usb_dc_cfg.setup));
CH58x_USBFS_DEV->USB_INT_FG = RB_UIF_TRANSFER;
}
} else if (intflag & RB_UIF_BUS_RST) {
/*!< Reset */
CH58x_USBFS_DEV->USB_DEV_AD = 0;
usbd_event_reset_handler();
usbd_event_reset_handler(0);
/*!< Set ep0 rx vaild to start receive setup packet */
EPn_SET_RX_VALID(0);
CH58x_USBFS_DEV->USB_INT_FG = RB_UIF_BUS_RST;

View File

@@ -54,7 +54,7 @@ __WEAK void usb_dc_low_level_deinit(void)
{
}
int usb_dc_init(void)
int usb_dc_init(uint8_t busid)
{
usb_dc_low_level_init();
@@ -82,12 +82,12 @@ int usb_dc_init(void)
return 0;
}
int usb_dc_deinit(void)
int usb_dc_deinit(uint8_t busid)
{
return 0;
}
int usbd_set_address(const uint8_t addr)
int usbd_set_address(uint8_t busid, const uint8_t addr)
{
if (addr == 0) {
USBFS_DEVICE->DEV_ADDR = (USBFS_DEVICE->DEV_ADDR & USBFS_UDA_GP_BIT) | 0;
@@ -96,12 +96,12 @@ int usbd_set_address(const uint8_t addr)
return 0;
}
uint8_t usbd_get_port_speed(const uint8_t port)
uint8_t usbd_get_port_speed(uint8_t busid, const uint8_t port)
{
return USB_SPEED_FULL;
}
int usbd_ep_open(const struct usb_endpoint_descriptor *ep)
int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
@@ -118,11 +118,11 @@ int usbd_ep_open(const struct usb_endpoint_descriptor *ep)
}
return 0;
}
int usbd_ep_close(const uint8_t ep)
int usbd_ep_close(uint8_t busid, const uint8_t ep)
{
return 0;
}
int usbd_ep_set_stall(const uint8_t ep)
int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
@@ -147,7 +147,7 @@ int usbd_ep_set_stall(const uint8_t ep)
return 0;
}
int usbd_ep_clear_stall(const uint8_t ep)
int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
@@ -163,12 +163,12 @@ int usbd_ep_clear_stall(const uint8_t ep)
return 0;
}
int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled)
int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled)
{
return 0;
}
int usbd_ep_start_write(const uint8_t ep, const uint8_t *data, uint32_t data_len)
int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
@@ -215,7 +215,7 @@ int usbd_ep_start_write(const uint8_t ep, const uint8_t *data, uint32_t data_len
return 0;
}
int usbd_ep_start_read(const uint8_t ep, uint8_t *data, uint32_t data_len)
int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
@@ -265,7 +265,7 @@ void USBD_IRQHandler(void)
switch (token) {
case USBFS_UIS_TOKEN_SETUP:
USB_SET_RX_CTRL(ep_idx, USBFS_UEP_R_RES_NAK);
usbd_event_ep0_setup_complete_handler((uint8_t *)&g_ch32_usbfs_udc.setup);
usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&g_ch32_usbfs_udc.setup);
break;
case USBFS_UIS_TOKEN_IN:
@@ -280,7 +280,7 @@ void USBD_IRQHandler(void)
ep0_tx_data_toggle = true;
}
usbd_event_ep_in_complete_handler(ep_idx | 0x80, g_ch32_usbfs_udc.in_ep[ep_idx].actual_xfer_len);
usbd_event_ep_in_complete_handler(0, ep_idx | 0x80, g_ch32_usbfs_udc.in_ep[ep_idx].actual_xfer_len);
if (g_ch32_usbfs_udc.dev_addr > 0) {
USBFS_DEVICE->DEV_ADDR = (USBFS_DEVICE->DEV_ADDR & USBFS_UDA_GP_BIT) | g_ch32_usbfs_udc.dev_addr;
@@ -315,7 +315,7 @@ void USBD_IRQHandler(void)
} else {
g_ch32_usbfs_udc.in_ep[ep_idx].actual_xfer_len += g_ch32_usbfs_udc.in_ep[ep_idx].xfer_len;
g_ch32_usbfs_udc.in_ep[ep_idx].xfer_len = 0;
usbd_event_ep_in_complete_handler(ep_idx | 0x80, g_ch32_usbfs_udc.in_ep[ep_idx].actual_xfer_len);
usbd_event_ep_in_complete_handler(0, ep_idx | 0x80, g_ch32_usbfs_udc.in_ep[ep_idx].actual_xfer_len);
}
}
break;
@@ -328,7 +328,7 @@ void USBD_IRQHandler(void)
g_ch32_usbfs_udc.out_ep[ep_idx].actual_xfer_len += read_count;
g_ch32_usbfs_udc.out_ep[ep_idx].xfer_len -= read_count;
usbd_event_ep_out_complete_handler(0x00, g_ch32_usbfs_udc.out_ep[ep_idx].actual_xfer_len);
usbd_event_ep_out_complete_handler(0, 0x00, g_ch32_usbfs_udc.out_ep[ep_idx].actual_xfer_len);
if (read_count == 0) {
/* Out status, start reading setup */
@@ -351,7 +351,7 @@ void USBD_IRQHandler(void)
g_ch32_usbfs_udc.out_ep[ep_idx].xfer_len -= read_count;
if ((read_count < g_ch32_usbfs_udc.out_ep[ep_idx].ep_mps) || (g_ch32_usbfs_udc.out_ep[ep_idx].xfer_len == 0)) {
usbd_event_ep_out_complete_handler(ep_idx, g_ch32_usbfs_udc.out_ep[ep_idx].actual_xfer_len);
usbd_event_ep_out_complete_handler(0, ep_idx, g_ch32_usbfs_udc.out_ep[ep_idx].actual_xfer_len);
} else {
USB_SET_RX_CTRL(ep_idx, (USB_GET_RX_CTRL(ep_idx) & ~USBFS_UEP_R_RES_MASK) | USBFS_UEP_R_RES_ACK);
}
@@ -383,7 +383,7 @@ void USBD_IRQHandler(void)
ep0_rx_data_toggle = true;
memset(&g_ch32_usbfs_udc, 0, sizeof(struct ch32_usbfs_udc));
usbd_event_reset_handler();
usbd_event_reset_handler(0);
USB_SET_DMA(ep_idx, (uint32_t)&g_ch32_usbfs_udc.setup);
USB_SET_RX_CTRL(ep_idx, USBFS_UEP_R_RES_ACK);

View File

@@ -53,7 +53,7 @@ __WEAK void usb_dc_low_level_deinit(void)
{
}
int usb_dc_init(void)
int usb_dc_init(uint8_t busid)
{
usb_dc_low_level_init();
@@ -82,12 +82,12 @@ int usb_dc_init(void)
return 0;
}
int usb_dc_deinit(void)
int usb_dc_deinit(uint8_t busid)
{
return 0;
}
int usbd_set_address(const uint8_t addr)
int usbd_set_address(uint8_t busid, const uint8_t addr)
{
if (addr == 0) {
USBHS_DEVICE->DEV_AD = addr & 0xff;
@@ -96,12 +96,12 @@ int usbd_set_address(const uint8_t addr)
return 0;
}
uint8_t usbd_get_port_speed(const uint8_t port)
uint8_t usbd_get_port_speed(uint8_t busid, const uint8_t port)
{
return USB_SPEED_HIGH;
}
int usbd_ep_open(const struct usb_endpoint_descriptor *ep)
int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
@@ -122,12 +122,12 @@ int usbd_ep_open(const struct usb_endpoint_descriptor *ep)
return 0;
}
int usbd_ep_close(const uint8_t ep)
int usbd_ep_close(uint8_t busid, const uint8_t ep)
{
return 0;
}
int usbd_ep_set_stall(const uint8_t ep)
int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
@@ -148,7 +148,7 @@ int usbd_ep_set_stall(const uint8_t ep)
return 0;
}
int usbd_ep_clear_stall(const uint8_t ep)
int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
@@ -160,12 +160,12 @@ int usbd_ep_clear_stall(const uint8_t ep)
return 0;
}
int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled)
int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled)
{
return 0;
}
int usbd_ep_start_write(const uint8_t ep, const uint8_t *data, uint32_t data_len)
int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
uint32_t tmp;
@@ -211,7 +211,7 @@ int usbd_ep_start_write(const uint8_t ep, const uint8_t *data, uint32_t data_len
return 0;
}
int usbd_ep_start_read(const uint8_t ep, uint8_t *data, uint32_t data_len)
int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
@@ -268,7 +268,7 @@ void USBD_IRQHandler(void)
ep0_tx_data_toggle = true;
}
usbd_event_ep_in_complete_handler(ep_idx | 0x80, g_ch32_usbhs_udc.in_ep[ep_idx].actual_xfer_len);
usbd_event_ep_in_complete_handler(0, ep_idx | 0x80, g_ch32_usbhs_udc.in_ep[ep_idx].actual_xfer_len);
if (g_ch32_usbhs_udc.dev_addr > 0) {
USBHS_DEVICE->DEV_AD = g_ch32_usbhs_udc.dev_addr & 0xff;
@@ -309,7 +309,7 @@ void USBD_IRQHandler(void)
g_ch32_usbhs_udc.in_ep[ep_idx].actual_xfer_len += g_ch32_usbhs_udc.in_ep[ep_idx].xfer_len;
g_ch32_usbhs_udc.in_ep[ep_idx].xfer_len = 0;
epx_tx_data_toggle[ep_idx - 1] ^= 1;
usbd_event_ep_in_complete_handler(ep_idx | 0x80, g_ch32_usbhs_udc.in_ep[ep_idx].actual_xfer_len);
usbd_event_ep_in_complete_handler(0, ep_idx | 0x80, g_ch32_usbhs_udc.in_ep[ep_idx].actual_xfer_len);
}
}
} else if (token == PID_OUT) {
@@ -319,7 +319,7 @@ void USBD_IRQHandler(void)
g_ch32_usbhs_udc.out_ep[ep_idx].actual_xfer_len += read_count;
g_ch32_usbhs_udc.out_ep[ep_idx].xfer_len -= read_count;
usbd_event_ep_out_complete_handler(0x00, g_ch32_usbhs_udc.out_ep[ep_idx].actual_xfer_len);
usbd_event_ep_out_complete_handler(0, 0x00, g_ch32_usbhs_udc.out_ep[ep_idx].actual_xfer_len);
if (read_count == 0) {
/* Out status, start reading setup */
@@ -340,7 +340,7 @@ void USBD_IRQHandler(void)
g_ch32_usbhs_udc.out_ep[ep_idx].xfer_len -= read_count;
if ((read_count < g_ch32_usbhs_udc.out_ep[ep_idx].ep_mps) || (g_ch32_usbhs_udc.out_ep[ep_idx].xfer_len == 0)) {
usbd_event_ep_out_complete_handler(ep_idx, g_ch32_usbhs_udc.out_ep[ep_idx].actual_xfer_len);
usbd_event_ep_out_complete_handler(0, ep_idx, g_ch32_usbhs_udc.out_ep[ep_idx].actual_xfer_len);
} else {
USB_SET_RX_DMA(ep_idx, (uint32_t)g_ch32_usbhs_udc.out_ep[ep_idx].xfer_buf);
USB_SET_RX_CTRL(ep_idx, (USB_GET_RX_CTRL(ep_idx) & ~USBHS_EP_R_RES_MASK) | USBHS_EP_R_RES_ACK);
@@ -350,7 +350,7 @@ void USBD_IRQHandler(void)
}
USBHS_DEVICE->INT_FG = USBHS_TRANSFER_FLAG;
} else if (intflag & USBHS_SETUP_FLAG) {
usbd_event_ep0_setup_complete_handler((uint8_t *)&g_ch32_usbhs_udc.setup);
usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&g_ch32_usbhs_udc.setup);
USBHS_DEVICE->INT_FG = USBHS_SETUP_FLAG;
} else if (intflag & USBHS_DETECT_FLAG) {
USBHS_DEVICE->ENDP_CONFIG = USBHS_EP0_T_EN | USBHS_EP0_R_EN;
@@ -369,7 +369,7 @@ void USBD_IRQHandler(void)
}
memset(&g_ch32_usbhs_udc, 0, sizeof(struct ch32_usbhs_udc));
usbd_event_reset_handler();
usbd_event_reset_handler(0);
USBHS_DEVICE->UEP0_DMA = (uint32_t)&g_ch32_usbhs_udc.setup;
USBHS_DEVICE->UEP0_RX_CTRL = USBHS_EP_R_RES_ACK;
USBHS_DEVICE->INT_FG = USBHS_DETECT_FLAG;

View File

@@ -29,10 +29,3 @@
## Espressif
- ESP32S2、ESP32S3
## Before Use
Your should implement `usb_dc_low_level_init` and `usb_dc_low_level_deinit`.
- Enable or disable USB clock and set USB clock for 48M.
- Enable or disable gpio and gpio clk for usb dp and dm.
- Enable or disable usb irq

View File

@@ -51,14 +51,6 @@
#endif
// clang-format on
#ifndef USBD_IRQHandler
#error "please define USBD_IRQHandler in usb_config.h"
#endif
#ifndef USBD_BASE
#error "please define USBD_BASE in usb_config.h"
#endif
#ifndef CONFIG_USB_DWC2_RAM_SIZE
#error "please define CONFIG_USB_DWC2_RAM_SIZE in usb_config.h, only support 1280 or 4096"
#endif
@@ -99,7 +91,7 @@
#elif CONFIG_USB_DWC2_RAM_SIZE == 4096
#define CONFIG_USB_DWC2_DMA_ENABLE
//#define CONFIG_USB_DWC2_DMA_ENABLE
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
#warning "if you enable dcache,please add .nocacheble section in your sct or ld or icf"
@@ -142,6 +134,8 @@
#error "Unsupported CONFIG_USB_DWC2_RAM_SIZE value"
#endif
#define USBD_BASE (g_usbdev_bus[0].reg_base)
#define USB_OTG_GLB ((USB_OTG_GlobalTypeDef *)(USBD_BASE))
#define USB_OTG_DEV ((USB_OTG_DeviceTypeDef *)(USBD_BASE + USB_OTG_DEVICE_BASE))
#define USB_OTG_PCGCCTL *(__IO uint32_t *)((uint32_t)USBD_BASE + USB_OTG_PCGCCTL_BASE)
@@ -515,7 +509,7 @@ __WEAK void usb_dc_low_level_deinit(void)
{
}
int usb_dc_init(void)
int usb_dc_init(uint8_t busid)
{
int ret;
uint8_t fsphy_type;
@@ -581,7 +575,7 @@ int usb_dc_init(void)
USB_OTG_GLB->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT;
/* This is vendor register */
USB_OTG_GLB->GCCFG = usbd_get_dwc2_gccfg_conf();
USB_OTG_GLB->GCCFG = usbd_get_dwc2_gccfg_conf(USBD_BASE);
ret = dwc2_core_init();
@@ -676,9 +670,8 @@ int usb_dc_init(void)
return ret;
}
int usb_dc_deinit(void)
int usb_dc_deinit(uint8_t busid)
{
usb_dc_low_level_deinit();
/* Clear Pending interrupt */
for (uint8_t i = 0U; i < 15U; i++) {
USB_OTG_INEP(i)->DIEPINT = 0xFB7FU;
@@ -696,17 +689,18 @@ int usb_dc_deinit(void)
USB_OTG_DEV->DCTL |= USB_OTG_DCTL_SDIS;
usb_dc_low_level_deinit();
return 0;
}
int usbd_set_address(const uint8_t addr)
int usbd_set_address(uint8_t busid, const uint8_t addr)
{
USB_OTG_DEV->DCFG &= ~(USB_OTG_DCFG_DAD);
USB_OTG_DEV->DCFG |= ((uint32_t)addr << 4) & USB_OTG_DCFG_DAD;
return 0;
}
uint8_t usbd_get_port_speed(const uint8_t port)
uint8_t usbd_get_port_speed(uint8_t busid, const uint8_t port)
{
uint8_t speed;
uint32_t DevEnumSpeed = USB_OTG_DEV->DSTS & USB_OTG_DSTS_ENUMSPD;
@@ -723,7 +717,7 @@ uint8_t usbd_get_port_speed(const uint8_t port)
return speed;
}
int usbd_ep_open(const struct usb_endpoint_descriptor *ep)
int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
@@ -761,7 +755,7 @@ int usbd_ep_open(const struct usb_endpoint_descriptor *ep)
return 0;
}
int usbd_ep_close(const uint8_t ep)
int usbd_ep_close(uint8_t busid, const uint8_t ep)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
volatile uint32_t count = 0U;
@@ -810,7 +804,7 @@ int usbd_ep_close(const uint8_t ep)
return 0;
}
int usbd_ep_set_stall(const uint8_t ep)
int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
@@ -833,7 +827,7 @@ int usbd_ep_set_stall(const uint8_t ep)
return 0;
}
int usbd_ep_clear_stall(const uint8_t ep)
int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
@@ -853,7 +847,7 @@ int usbd_ep_clear_stall(const uint8_t ep)
return 0;
}
int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled)
int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled)
{
if (USB_EP_DIR_IS_OUT(ep)) {
} else {
@@ -861,7 +855,7 @@ int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled)
return 0;
}
int usbd_ep_start_write(const uint8_t ep, const uint8_t *data, uint32_t data_len)
int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
uint32_t pktcnt = 0;
@@ -934,7 +928,7 @@ int usbd_ep_start_write(const uint8_t ep, const uint8_t *data, uint32_t data_len
return 0;
}
int usbd_ep_start_read(const uint8_t ep, uint8_t *data, uint32_t data_len)
int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
uint32_t pktcnt = 0;
@@ -997,7 +991,7 @@ int usbd_ep_start_read(const uint8_t ep, uint8_t *data, uint32_t data_len)
return 0;
}
void USBD_IRQHandler(void)
void USBD_IRQHandler(uint8_t busid)
{
uint32_t gint_status, temp, ep_idx, ep_intr, epint, read_count, daintmask;
gint_status = dwc2_get_glb_intstatus();
@@ -1048,17 +1042,17 @@ void USBD_IRQHandler(void)
} else {
g_dwc2_udc.out_ep[ep_idx].actual_xfer_len = g_dwc2_udc.out_ep[ep_idx].xfer_len - ((USB_OTG_OUTEP(ep_idx)->DOEPTSIZ) & USB_OTG_DOEPTSIZ_XFRSIZ);
g_dwc2_udc.out_ep[ep_idx].xfer_len = 0;
usbd_event_ep_out_complete_handler(0x00, g_dwc2_udc.out_ep[ep_idx].actual_xfer_len);
usbd_event_ep_out_complete_handler(0, 0x00, g_dwc2_udc.out_ep[ep_idx].actual_xfer_len);
}
} else {
g_dwc2_udc.out_ep[ep_idx].actual_xfer_len = g_dwc2_udc.out_ep[ep_idx].xfer_len - ((USB_OTG_OUTEP(ep_idx)->DOEPTSIZ) & USB_OTG_DOEPTSIZ_XFRSIZ);
g_dwc2_udc.out_ep[ep_idx].xfer_len = 0;
usbd_event_ep_out_complete_handler(ep_idx, g_dwc2_udc.out_ep[ep_idx].actual_xfer_len);
usbd_event_ep_out_complete_handler(0, ep_idx, g_dwc2_udc.out_ep[ep_idx].actual_xfer_len);
}
}
if ((epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP) {
usbd_event_ep0_setup_complete_handler((uint8_t *)&g_dwc2_udc.setup);
usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&g_dwc2_udc.setup);
}
}
ep_intr >>= 1U;
@@ -1078,7 +1072,7 @@ void USBD_IRQHandler(void)
if (ep_idx == 0) {
g_dwc2_udc.in_ep[ep_idx].actual_xfer_len = g_dwc2_udc.in_ep[ep_idx].xfer_len - ((USB_OTG_INEP(ep_idx)->DIEPTSIZ) & USB_OTG_DIEPTSIZ_XFRSIZ);
g_dwc2_udc.in_ep[ep_idx].xfer_len = 0;
usbd_event_ep_in_complete_handler(0x80, g_dwc2_udc.in_ep[ep_idx].actual_xfer_len);
usbd_event_ep_in_complete_handler(0, 0x80, g_dwc2_udc.in_ep[ep_idx].actual_xfer_len);
if (g_dwc2_udc.setup.wLength && ((g_dwc2_udc.setup.bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_OUT)) {
/* In status, start reading setup */
@@ -1090,7 +1084,7 @@ void USBD_IRQHandler(void)
} else {
g_dwc2_udc.in_ep[ep_idx].actual_xfer_len = g_dwc2_udc.in_ep[ep_idx].xfer_len - ((USB_OTG_INEP(ep_idx)->DIEPTSIZ) & USB_OTG_DIEPTSIZ_XFRSIZ);
g_dwc2_udc.in_ep[ep_idx].xfer_len = 0;
usbd_event_ep_in_complete_handler(ep_idx | 0x80, g_dwc2_udc.in_ep[ep_idx].actual_xfer_len);
usbd_event_ep_in_complete_handler(0, ep_idx | 0x80, g_dwc2_udc.in_ep[ep_idx].actual_xfer_len);
}
}
if ((epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE) {
@@ -1138,7 +1132,7 @@ void USBD_IRQHandler(void)
USB_OTG_DEV->DIEPMSK = USB_OTG_DIEPMSK_XFRCM;
memset(&g_dwc2_udc, 0, sizeof(struct dwc2_udc));
usbd_event_reset_handler();
usbd_event_reset_handler(0);
/* Start reading setup */
dwc2_ep0_start_read_setup((uint8_t *)&g_dwc2_udc.setup);
}

View File

@@ -1706,6 +1706,6 @@ typedef struct
#define USB_UNMASK_HALT_HC_INT(chnum) (USB_OTG_HC(chnum)->HCINTMSK |= USB_OTG_HCINTMSK_CHHM)
#define CLEAR_HC_INT(chnum, __INTERRUPT__) (USB_OTG_HC(chnum)->HCINT = (__INTERRUPT__))
uint32_t usbd_get_dwc2_gccfg_conf(void);
uint32_t usbh_get_dwc2_gccfg_conf(void);
uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base);
uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base);
#endif

View File

@@ -10,7 +10,7 @@
*
*/
uint32_t usbd_get_dwc2_gccfg_conf(void)
uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base)
{
#ifdef CONFIG_USB_HS
return ((1 << 16) | (1 << 21));
@@ -28,7 +28,7 @@ uint32_t usbd_get_dwc2_gccfg_conf(void)
#endif
}
uint32_t usbh_get_dwc2_gccfg_conf(void)
uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
{
#ifdef CONFIG_USB_DWC2_ULPI_PHY
return ((1 << 16) | (1 << 21));

View File

@@ -8,7 +8,7 @@
*
*/
uint32_t usbd_get_dwc2_gccfg_conf(void)
uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base)
{
#ifdef CONFIG_USB_HS
return 0;
@@ -17,7 +17,7 @@ uint32_t usbd_get_dwc2_gccfg_conf(void)
#endif
}
uint32_t usbh_get_dwc2_gccfg_conf(void)
uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
{
#ifdef CONFIG_USB_DWC2_ULPI_PHY
return 0;

View File

@@ -11,13 +11,13 @@
*
*/
uint32_t usbd_get_dwc2_gccfg_conf(void)
uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base)
{
#ifdef CONFIG_USB_HS
return 0;
#else
#if __has_include("stm32h7xx.h") || __has_include("stm32f7xx.h") || __has_include("stm32l4xx.h")
#define USB_OTG_GLB ((USB_OTG_GlobalTypeDef *)(USBD_BASE))
#define USB_OTG_GLB ((USB_OTG_GlobalTypeDef *)(reg_base))
/* B-peripheral session valid override enable */
USB_OTG_GLB->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN;
USB_OTG_GLB->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL;
@@ -28,13 +28,13 @@ uint32_t usbd_get_dwc2_gccfg_conf(void)
#endif
}
uint32_t usbh_get_dwc2_gccfg_conf(void)
uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
{
#ifdef CONFIG_USB_DWC2_ULPI_PHY
return 0;
#else
#if __has_include("stm32h7xx.h") || __has_include("stm32f7xx.h") || __has_include("stm32l4xx.h")
#define USB_OTG_GLB ((USB_OTG_GlobalTypeDef *)(USBD_BASE))
#define USB_OTG_GLB ((USB_OTG_GlobalTypeDef *)(reg_base))
/* B-peripheral session valid override enable */
USB_OTG_GLB->GOTGCTL &= ~USB_OTG_GOTGCTL_BVALOEN;
USB_OTG_GLB->GOTGCTL &= ~USB_OTG_GOTGCTL_BVALOVAL;

View File

@@ -7,24 +7,16 @@
#include "usbh_hub.h"
#include "usb_dwc2_reg.h"
#ifndef USBH_IRQHandler
#error "please define USBH_IRQHandler in usb_config.h"
#endif
#ifndef USBH_BASE
#error "please define USBH_BASE in usb_config.h"
#endif
#ifndef CONFIG_USBHOST_PIPE_NUM
#define CONFIG_USBHOST_PIPE_NUM 12
#endif
#define USB_OTG_GLB ((USB_OTG_GlobalTypeDef *)(USBH_BASE))
#define USB_OTG_PCGCCTL *(__IO uint32_t *)((uint32_t)USBH_BASE + USB_OTG_PCGCCTL_BASE)
#define USB_OTG_HPRT *(__IO uint32_t *)((uint32_t)USBH_BASE + USB_OTG_HOST_PORT_BASE)
#define USB_OTG_HOST ((USB_OTG_HostTypeDef *)(USBH_BASE + USB_OTG_HOST_BASE))
#define USB_OTG_HC(i) ((USB_OTG_HostChannelTypeDef *)(USBH_BASE + USB_OTG_HOST_CHANNEL_BASE + ((i)*USB_OTG_HOST_CHANNEL_SIZE)))
#define USB_OTG_FIFO(i) *(__IO uint32_t *)(USBH_BASE + USB_OTG_FIFO_BASE + ((i)*USB_OTG_FIFO_SIZE))
#define USB_OTG_GLB ((USB_OTG_GlobalTypeDef *)(bus->hcd.reg_base))
#define USB_OTG_PCGCCTL *(__IO uint32_t *)((uint32_t)bus->hcd.reg_base + USB_OTG_PCGCCTL_BASE)
#define USB_OTG_HPRT *(__IO uint32_t *)((uint32_t)bus->hcd.reg_base + USB_OTG_HOST_PORT_BASE)
#define USB_OTG_HOST ((USB_OTG_HostTypeDef *)(bus->hcd.reg_base + USB_OTG_HOST_BASE))
#define USB_OTG_HC(i) ((USB_OTG_HostChannelTypeDef *)(bus->hcd.reg_base + USB_OTG_HOST_CHANNEL_BASE + ((i)*USB_OTG_HOST_CHANNEL_SIZE)))
#define USB_OTG_FIFO(i) *(__IO uint32_t *)(bus->hcd.reg_base + USB_OTG_FIFO_BASE + ((i)*USB_OTG_FIFO_SIZE))
struct dwc2_chan {
uint8_t ep0_state;
@@ -42,7 +34,7 @@ struct dwc2_hcd {
volatile bool port_pec;
volatile bool port_occ;
struct dwc2_chan chan_pool[CONFIG_USBHOST_PIPE_NUM];
} g_dwc2_hcd;
} g_dwc2_hcd[CONFIG_USBHOST_MAX_BUS];
#define DWC2_EP0_STATE_SETUP 0
#define DWC2_EP0_STATE_INDATA 1
@@ -50,7 +42,7 @@ struct dwc2_hcd {
#define DWC2_EP0_STATE_INSTATUS 3
#define DWC2_EP0_STATE_OUTSTATUS 4
static inline int dwc2_reset(void)
static inline int dwc2_reset(struct usbh_bus *bus)
{
volatile uint32_t count = 0U;
@@ -74,7 +66,7 @@ static inline int dwc2_reset(void)
return 0;
}
static inline int dwc2_core_init(void)
static inline int dwc2_core_init(struct usbh_bus *bus)
{
int ret;
#if defined(CONFIG_USB_DWC2_ULPI_PHY)
@@ -86,17 +78,17 @@ static inline int dwc2_core_init(void)
//USB_OTG_GLB->GUSBCFG |= USB_OTG_GUSBCFG_ULPIEVBUSD;
/* Reset after a PHY select */
ret = dwc2_reset();
ret = dwc2_reset(bus);
#else
/* Select FS Embedded PHY */
USB_OTG_GLB->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;
/* Reset after a PHY select */
ret = dwc2_reset();
ret = dwc2_reset(bus);
#endif
return ret;
}
static inline void dwc2_set_mode(uint8_t mode)
static inline void dwc2_set_mode(struct usbh_bus *bus, uint8_t mode)
{
USB_OTG_GLB->GUSBCFG &= ~(USB_OTG_GUSBCFG_FHMOD | USB_OTG_GUSBCFG_FDMOD);
@@ -107,7 +99,7 @@ static inline void dwc2_set_mode(uint8_t mode)
}
}
static inline int dwc2_flush_rxfifo(void)
static inline int dwc2_flush_rxfifo(struct usbh_bus *bus)
{
volatile uint32_t count = 0;
@@ -122,7 +114,7 @@ static inline int dwc2_flush_rxfifo(void)
return 0;
}
static inline int dwc2_flush_txfifo(uint32_t num)
static inline int dwc2_flush_txfifo(struct usbh_bus *bus, uint32_t num)
{
volatile uint32_t count = 0U;
@@ -137,7 +129,7 @@ static inline int dwc2_flush_txfifo(uint32_t num)
return 0;
}
static inline void dwc2_drivebus(uint8_t state)
static inline void dwc2_drivebus(struct usbh_bus *bus, uint8_t state)
{
__IO uint32_t hprt0 = 0U;
@@ -154,7 +146,27 @@ static inline void dwc2_drivebus(uint8_t state)
}
}
static void dwc2_chan_init(uint8_t ch_num, uint8_t devaddr, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps, uint8_t speed)
static uint8_t usbh_get_port_speed(struct usbh_bus *bus, const uint8_t port)
{
__IO uint32_t hprt0 = 0U;
uint8_t speed;
hprt0 = USB_OTG_HPRT;
speed = (hprt0 & USB_OTG_HPRT_PSPD) >> 17;
if (speed == HPRT0_PRTSPD_HIGH_SPEED) {
return USB_SPEED_HIGH;
} else if (speed == HPRT0_PRTSPD_FULL_SPEED) {
return USB_SPEED_FULL;
} else if (speed == HPRT0_PRTSPD_LOW_SPEED) {
return USB_SPEED_LOW;
} else {
return USB_SPEED_UNKNOWN;
}
}
static void dwc2_chan_init(struct usbh_bus *bus, uint8_t ch_num, uint8_t devaddr, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps, uint8_t speed)
{
uint32_t regval;
@@ -174,7 +186,7 @@ static void dwc2_chan_init(uint8_t ch_num, uint8_t devaddr, uint8_t ep_addr, uin
switch (ep_type) {
case USB_ENDPOINT_TYPE_CONTROL:
regval |= USB_OTG_HCINTMSK_NAKM;
//regval |= USB_OTG_HCINTMSK_NAKM;
case USB_ENDPOINT_TYPE_BULK:
//regval |= USB_OTG_HCINTMSK_NAKM;
break;
@@ -205,7 +217,7 @@ static void dwc2_chan_init(uint8_t ch_num, uint8_t devaddr, uint8_t ep_addr, uin
}
/* LS device plugged to HUB */
if (speed == USB_SPEED_LOW) {
if ((speed == USB_SPEED_LOW) && (usbh_get_port_speed(bus, 0) != USB_SPEED_LOW)) {
regval |= USB_OTG_HCCHAR_LSDEV;
}
@@ -217,7 +229,7 @@ static void dwc2_chan_init(uint8_t ch_num, uint8_t devaddr, uint8_t ep_addr, uin
}
/* For IN channel HCTSIZ.XferSize is expected to be an integer multiple of ep_mps size.*/
static inline void dwc2_chan_transfer(uint8_t ch_num, uint8_t ep_addr, uint32_t *buf, uint32_t size, uint8_t num_packets, uint8_t pid)
static inline void dwc2_chan_transfer(struct usbh_bus *bus, uint8_t ch_num, uint8_t ep_addr, uint32_t *buf, uint32_t size, uint8_t num_packets, uint8_t pid)
{
__IO uint32_t tmpreg;
uint8_t is_oddframe;
@@ -241,11 +253,11 @@ static inline void dwc2_chan_transfer(uint8_t ch_num, uint8_t ep_addr, uint32_t
USB_OTG_HC(ch_num)->HCCHAR = tmpreg;
}
static void dwc2_halt(uint8_t ch_num)
static void dwc2_halt(struct usbh_bus *bus, uint8_t ch_num)
{
volatile uint32_t count = 0U;
uint32_t HcEpType = (USB_OTG_HC(ch_num)->HCCHAR & USB_OTG_HCCHAR_EPTYP) >> 18;
uint32_t ChannelEna = (USB_OTG_HC(ch_num)->HCCHAR & USB_OTG_HCCHAR_CHENA) >> 31;
volatile uint32_t HcEpType = (USB_OTG_HC(ch_num)->HCCHAR & USB_OTG_HCCHAR_EPTYP) >> 18;
volatile uint32_t ChannelEna = (USB_OTG_HC(ch_num)->HCCHAR & USB_OTG_HCCHAR_CHENA) >> 31;
if (((USB_OTG_GLB->GAHBCFG & USB_OTG_GAHBCFG_DMAEN) == USB_OTG_GAHBCFG_DMAEN) &&
(ChannelEna == 0U)) {
@@ -288,7 +300,7 @@ static void dwc2_halt(uint8_t ch_num)
}
}
static int usbh_reset_port(const uint8_t port)
static int usbh_reset_port(struct usbh_bus *bus, const uint8_t port)
{
__IO uint32_t hprt0 = 0U;
@@ -308,31 +320,11 @@ static int usbh_reset_port(const uint8_t port)
return 0;
}
static uint8_t usbh_get_port_speed(const uint8_t port)
{
__IO uint32_t hprt0 = 0U;
uint8_t speed;
hprt0 = USB_OTG_HPRT;
speed = (hprt0 & USB_OTG_HPRT_PSPD) >> 17;
if (speed == HPRT0_PRTSPD_HIGH_SPEED) {
return USB_SPEED_HIGH;
} else if (speed == HPRT0_PRTSPD_FULL_SPEED) {
return USB_SPEED_FULL;
} else if (speed == HPRT0_PRTSPD_LOW_SPEED) {
return USB_SPEED_LOW;
} else {
return USB_SPEED_UNKNOWN;
}
}
/**
* @brief dwc2_get_glb_intstatus: return the global USB interrupt status
* @retval status
*/
static inline uint32_t dwc2_get_glb_intstatus(void)
static inline uint32_t dwc2_get_glb_intstatus(struct usbh_bus *bus)
{
uint32_t tmpreg;
@@ -342,13 +334,13 @@ static inline uint32_t dwc2_get_glb_intstatus(void)
return tmpreg;
}
static int dwc2_chan_alloc(void)
static int dwc2_chan_alloc(struct usbh_bus *bus)
{
int chidx;
for (chidx = 0; chidx < CONFIG_USBHOST_PIPE_NUM; chidx++) {
if (!g_dwc2_hcd.chan_pool[chidx].inuse) {
g_dwc2_hcd.chan_pool[chidx].inuse = true;
if (!g_dwc2_hcd[bus->hcd.hcd_id].chan_pool[chidx].inuse) {
g_dwc2_hcd[bus->hcd.hcd_id].chan_pool[chidx].inuse = true;
return chidx;
}
}
@@ -358,7 +350,11 @@ static int dwc2_chan_alloc(void)
static void dwc2_chan_free(struct dwc2_chan *chan)
{
size_t flags;
flags = usb_osal_enter_critical_section();
chan->inuse = false;
usb_osal_leave_critical_section(flags);
}
static uint8_t dwc2_calculate_packet_num(uint32_t input_size, uint8_t ep_addr, uint16_t ep_mps, uint32_t *output_size)
@@ -384,77 +380,77 @@ static uint8_t dwc2_calculate_packet_num(uint32_t input_size, uint8_t ep_addr, u
return num_packets;
}
static void dwc2_control_urb_init(uint8_t chidx, struct usbh_urb *urb, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen)
static void dwc2_control_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *urb, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen)
{
struct dwc2_chan *chan;
chan = &g_dwc2_hcd.chan_pool[chidx];
chan = &g_dwc2_hcd[bus->hcd.hcd_id].chan_pool[chidx];
if (chan->ep0_state == DWC2_EP0_STATE_SETUP) /* fill setup */
{
chan->num_packets = dwc2_calculate_packet_num(8, 0x00, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
dwc2_chan_init(chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
dwc2_chan_transfer(chidx, 0x00, (uint32_t *)setup, chan->xferlen, chan->num_packets, HC_PID_SETUP);
dwc2_chan_init(bus, chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
dwc2_chan_transfer(bus, chidx, 0x00, (uint32_t *)setup, chan->xferlen, chan->num_packets, HC_PID_SETUP);
} else if (chan->ep0_state == DWC2_EP0_STATE_INDATA) /* fill in data */
{
chan->num_packets = dwc2_calculate_packet_num(setup->wLength, 0x80, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
dwc2_chan_init(chidx, urb->hport->dev_addr, 0x80, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
dwc2_chan_transfer(chidx, 0x80, (uint32_t *)buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1);
dwc2_chan_init(bus, chidx, urb->hport->dev_addr, 0x80, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
dwc2_chan_transfer(bus, chidx, 0x80, (uint32_t *)buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1);
} else if (chan->ep0_state == DWC2_EP0_STATE_OUTDATA) /* fill out data */
{
chan->num_packets = dwc2_calculate_packet_num(setup->wLength, 0x00, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
dwc2_chan_init(chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
dwc2_chan_transfer(chidx, 0x00, (uint32_t *)buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1);
dwc2_chan_init(bus, chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
dwc2_chan_transfer(bus, chidx, 0x00, (uint32_t *)buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1);
} else if (chan->ep0_state == DWC2_EP0_STATE_INSTATUS) /* fill in status */
{
chan->num_packets = dwc2_calculate_packet_num(0, 0x80, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
dwc2_chan_init(chidx, urb->hport->dev_addr, 0x80, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
dwc2_chan_transfer(chidx, 0x80, NULL, chan->xferlen, chan->num_packets, HC_PID_DATA1);
dwc2_chan_init(bus, chidx, urb->hport->dev_addr, 0x80, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
dwc2_chan_transfer(bus, chidx, 0x80, NULL, chan->xferlen, chan->num_packets, HC_PID_DATA1);
} else if (chan->ep0_state == DWC2_EP0_STATE_OUTSTATUS) /* fill out status */
{
chan->num_packets = dwc2_calculate_packet_num(0, 0x00, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
dwc2_chan_init(chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
dwc2_chan_transfer(chidx, 0x00, NULL, chan->xferlen, chan->num_packets, HC_PID_DATA1);
dwc2_chan_init(bus, chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
dwc2_chan_transfer(bus, chidx, 0x00, NULL, chan->xferlen, chan->num_packets, HC_PID_DATA1);
}
}
static void dwc2_bulk_intr_urb_init(uint8_t chidx, struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen)
static void dwc2_bulk_intr_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen)
{
struct dwc2_chan *chan;
chan = &g_dwc2_hcd.chan_pool[chidx];
chan = &g_dwc2_hcd[bus->hcd.hcd_id].chan_pool[chidx];
chan->num_packets = dwc2_calculate_packet_num(buflen, urb->ep->bEndpointAddress, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
dwc2_chan_init(chidx, urb->hport->dev_addr, urb->ep->bEndpointAddress, USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes), USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
dwc2_chan_transfer(chidx, urb->ep->bEndpointAddress, (uint32_t *)buffer, chan->xferlen, chan->num_packets, urb->data_toggle);
dwc2_chan_init(bus, chidx, urb->hport->dev_addr, urb->ep->bEndpointAddress, USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes), USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
dwc2_chan_transfer(bus, chidx, urb->ep->bEndpointAddress, (uint32_t *)buffer, chan->xferlen, chan->num_packets, urb->data_toggle);
}
static void dwc2_iso_urb_init(uint8_t chidx, struct usbh_urb *urb, struct usbh_iso_frame_packet *iso_packet)
static void dwc2_iso_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *urb, struct usbh_iso_frame_packet *iso_packet)
{
struct dwc2_chan *chan;
chan = &g_dwc2_hcd.chan_pool[chidx];
chan = &g_dwc2_hcd[bus->hcd.hcd_id].chan_pool[chidx];
chan->num_packets = dwc2_calculate_packet_num(iso_packet->transfer_buffer_length, urb->ep->bEndpointAddress, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
dwc2_chan_init(chidx, urb->hport->dev_addr, urb->ep->bEndpointAddress, USB_ENDPOINT_TYPE_ISOCHRONOUS, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
dwc2_chan_transfer(chidx, urb->ep->bEndpointAddress, (uint32_t *)iso_packet->transfer_buffer, chan->xferlen, chan->num_packets, HC_PID_DATA0);
dwc2_chan_init(bus, chidx, urb->hport->dev_addr, urb->ep->bEndpointAddress, USB_ENDPOINT_TYPE_ISOCHRONOUS, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
dwc2_chan_transfer(bus, chidx, urb->ep->bEndpointAddress, (uint32_t *)iso_packet->transfer_buffer, chan->xferlen, chan->num_packets, HC_PID_DATA0);
}
__WEAK void usb_hc_low_level_init(void)
__WEAK void usb_hc_low_level_init(struct usbh_bus *bus)
{
}
int usb_hc_init(void)
int usb_hc_init(struct usbh_bus *bus)
{
int ret;
memset(&g_dwc2_hcd, 0, sizeof(struct dwc2_hcd));
memset(&g_dwc2_hcd[bus->hcd.hcd_id], 0, sizeof(struct dwc2_hcd));
for (uint8_t chidx = 0; chidx < CONFIG_USBHOST_PIPE_NUM; chidx++) {
g_dwc2_hcd.chan_pool[chidx].waitsem = usb_osal_sem_create(0);
g_dwc2_hcd[bus->hcd.hcd_id].chan_pool[chidx].waitsem = usb_osal_sem_create(0);
}
usb_hc_low_level_init();
usb_hc_low_level_init(bus);
USB_LOG_INFO("========== dwc2 hcd params ==========\r\n");
USB_LOG_INFO("GCCFG:%08x\r\n", USB_OTG_GLB->GCCFG);
@@ -476,12 +472,12 @@ int usb_hc_init(void)
USB_OTG_GLB->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT;
/* This is vendor register */
USB_OTG_GLB->GCCFG = usbh_get_dwc2_gccfg_conf();
USB_OTG_GLB->GCCFG = usbh_get_dwc2_gccfg_conf(bus->hcd.reg_base);
ret = dwc2_core_init();
ret = dwc2_core_init(bus);
/* Force Host Mode*/
dwc2_set_mode(USB_OTG_MODE_HOST);
dwc2_set_mode(bus, USB_OTG_MODE_HOST);
usb_osal_msleep(50);
/* Restart the Phy Clock */
@@ -490,8 +486,8 @@ int usb_hc_init(void)
/* Set default Max speed support */
USB_OTG_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSS);
ret = dwc2_flush_txfifo(0x10U);
ret = dwc2_flush_rxfifo();
ret = dwc2_flush_txfifo(bus, 0x10U);
ret = dwc2_flush_rxfifo(bus);
/* Clear all pending HC Interrupts */
for (uint8_t i = 0U; i < CONFIG_USBHOST_PIPE_NUM; i++) {
@@ -499,7 +495,7 @@ int usb_hc_init(void)
USB_OTG_HC(i)->HCINTMSK = 0U;
}
dwc2_drivebus(1);
dwc2_drivebus(bus, 1);
usb_osal_msleep(200);
/* Disable all interrupts. */
@@ -525,15 +521,15 @@ int usb_hc_init(void)
return 0;
}
int usb_hc_deinit(void)
int usb_hc_deinit(struct usbh_bus *bus)
{
volatile uint32_t count = 0U;
uint32_t value;
USB_OTG_GLB->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT;
dwc2_flush_txfifo(0x10U);
dwc2_flush_rxfifo();
dwc2_flush_txfifo(bus, 0x10U);
dwc2_flush_rxfifo(bus);
/* Flush out any leftover queued requests. */
for (uint32_t i = 0U; i <= 15U; i++) {
@@ -566,22 +562,22 @@ int usb_hc_deinit(void)
USB_OTG_HOST->HAINT = 0xFFFFFFFFU;
USB_OTG_GLB->GINTSTS = 0xFFFFFFFFU;
dwc2_drivebus(0);
dwc2_drivebus(bus, 0);
usb_osal_msleep(200);
for (uint8_t chidx = 0; chidx < CONFIG_USBHOST_PIPE_NUM; chidx++) {
usb_osal_sem_delete(g_dwc2_hcd.chan_pool[chidx].waitsem);
usb_osal_sem_delete(g_dwc2_hcd[bus->hcd.hcd_id].chan_pool[chidx].waitsem);
}
return 0;
}
uint16_t usbh_get_frame_number(void)
uint16_t usbh_get_frame_number(struct usbh_bus *bus)
{
return (USB_OTG_HOST->HFNUM & USB_OTG_HFNUM_FRNUM);
}
int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
int usbh_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, uint8_t *buf)
{
__IO uint32_t hprt0;
uint8_t nports;
@@ -637,13 +633,13 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
case HUB_PORT_FEATURE_POWER:
break;
case HUB_PORT_FEATURE_C_CONNECTION:
g_dwc2_hcd.port_csc = 0;
g_dwc2_hcd[bus->hcd.hcd_id].port_csc = 0;
break;
case HUB_PORT_FEATURE_C_ENABLE:
g_dwc2_hcd.port_pec = 0;
g_dwc2_hcd[bus->hcd.hcd_id].port_pec = 0;
break;
case HUB_PORT_FEATURE_C_OVER_CURREN:
g_dwc2_hcd.port_occ = 0;
g_dwc2_hcd[bus->hcd.hcd_id].port_occ = 0;
break;
case HUB_PORT_FEATURE_C_RESET:
break;
@@ -663,7 +659,7 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
USB_OTG_HPRT &= ~USB_OTG_HPRT_PPWR;
break;
case HUB_PORT_FEATURE_RESET:
usbh_reset_port(port);
usbh_reset_port(bus, port);
break;
default:
@@ -677,13 +673,13 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
hprt0 = USB_OTG_HPRT;
status = 0;
if (g_dwc2_hcd.port_csc) {
if (g_dwc2_hcd[bus->hcd.hcd_id].port_csc) {
status |= (1 << HUB_PORT_FEATURE_C_CONNECTION);
}
if (g_dwc2_hcd.port_pec) {
if (g_dwc2_hcd[bus->hcd.hcd_id].port_pec) {
status |= (1 << HUB_PORT_FEATURE_C_ENABLE);
}
if (g_dwc2_hcd.port_occ) {
if (g_dwc2_hcd[bus->hcd.hcd_id].port_occ) {
status |= (1 << HUB_PORT_FEATURE_C_OVER_CURREN);
}
@@ -692,9 +688,9 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
}
if (hprt0 & USB_OTG_HPRT_PENA) {
status |= (1 << HUB_PORT_FEATURE_ENABLE);
if (usbh_get_port_speed(port) == USB_SPEED_LOW) {
if (usbh_get_port_speed(bus, port) == USB_SPEED_LOW) {
status |= (1 << HUB_PORT_FEATURE_LOWSPEED);
} else if (usbh_get_port_speed(port) == USB_SPEED_HIGH) {
} else if (usbh_get_port_speed(bus, port) == USB_SPEED_HIGH) {
status |= (1 << HUB_PORT_FEATURE_HIGHSPEED);
}
}
@@ -720,11 +716,12 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
int usbh_submit_urb(struct usbh_urb *urb)
{
struct dwc2_chan *chan;
struct usbh_bus *bus;
size_t flags;
int ret = 0;
int chidx;
if (!urb || !urb->hport || !urb->ep) {
if (!urb || !urb->hport || !urb->ep || !urb->hport->bus) {
return -USB_ERR_INVAL;
}
@@ -733,6 +730,8 @@ int usbh_submit_urb(struct usbh_urb *urb)
return -USB_ERR_INVAL;
}
bus = urb->hport->bus;
if (!(USB_OTG_HPRT & USB_OTG_HPRT_PCSTS) || !urb->hport->connected) {
return -USB_ERR_NOTCONN;
}
@@ -743,13 +742,13 @@ int usbh_submit_urb(struct usbh_urb *urb)
flags = usb_osal_enter_critical_section();
chidx = dwc2_chan_alloc();
chidx = dwc2_chan_alloc(bus);
if (chidx == -1) {
usb_osal_leave_critical_section(flags);
return -USB_ERR_NOMEM;
}
chan = &g_dwc2_hcd.chan_pool[chidx];
chan = &g_dwc2_hcd[bus->hcd.hcd_id].chan_pool[chidx];
chan->chidx = chidx;
chan->urb = urb;
@@ -762,11 +761,11 @@ int usbh_submit_urb(struct usbh_urb *urb)
switch (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes)) {
case USB_ENDPOINT_TYPE_CONTROL:
chan->ep0_state = DWC2_EP0_STATE_SETUP;
dwc2_control_urb_init(chidx, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
dwc2_control_urb_init(bus, chidx, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
break;
case USB_ENDPOINT_TYPE_BULK:
case USB_ENDPOINT_TYPE_INTERRUPT:
dwc2_bulk_intr_urb_init(chidx, urb, urb->transfer_buffer, urb->transfer_buffer_length);
dwc2_bulk_intr_urb_init(bus, chidx, urb, urb->transfer_buffer, urb->transfer_buffer_length);
break;
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
break;
@@ -795,17 +794,20 @@ errout_timeout:
int usbh_kill_urb(struct usbh_urb *urb)
{
struct dwc2_chan *chan;
struct usbh_bus *bus;
size_t flags;
if (!urb || !urb->hcpriv) {
if (!urb || !urb->hcpriv || !urb->hport->bus) {
return -USB_ERR_INVAL;
}
bus = urb->hport->bus;
flags = usb_osal_enter_critical_section();
chan = (struct dwc2_chan *)urb->hcpriv;
dwc2_halt(chan->chidx);
dwc2_halt(bus, chan->chidx);
CLEAR_HC_INT(chan->chidx, USB_OTG_HCINT_CHH);
chan->urb = NULL;
@@ -848,7 +850,7 @@ static inline void dwc2_urb_waitup(struct usbh_urb *urb)
}
}
static void dwc2_inchan_irq_handler(uint8_t ch_num)
static void dwc2_inchan_irq_handler(struct usbh_bus *bus, uint8_t ch_num)
{
uint32_t chan_intstatus;
struct dwc2_chan *chan;
@@ -856,66 +858,65 @@ static void dwc2_inchan_irq_handler(uint8_t ch_num)
chan_intstatus = (USB_OTG_HC(ch_num)->HCINT) & (USB_OTG_HC((uint32_t)ch_num)->HCINTMSK);
chan = &g_dwc2_hcd.chan_pool[ch_num];
chan = &g_dwc2_hcd[bus->hcd.hcd_id].chan_pool[ch_num];
urb = chan->urb;
//printf("s1:%08x\r\n", chan_intstatus);
if ((chan_intstatus & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC) {
urb->errorcode = 0;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(bus, ch_num);
} else if ((chan_intstatus & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR) {
urb->errorcode = -USB_ERR_IO;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
dwc2_halt(bus, ch_num);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR);
} else if ((chan_intstatus & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL) {
urb->errorcode = -USB_ERR_STALL;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(bus, ch_num);
} else if ((chan_intstatus & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK) {
urb->errorcode = -USB_ERR_NAK;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(bus, ch_num);
} else if ((chan_intstatus & USB_OTG_HCINT_ACK) == USB_OTG_HCINT_ACK) {
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK);
} else if ((chan_intstatus & USB_OTG_HCINT_NYET) == USB_OTG_HCINT_NYET) {
urb->errorcode = -USB_ERR_NAK;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET);
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(bus, ch_num);
} else if ((chan_intstatus & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR) {
urb->errorcode = -USB_ERR_IO;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR);
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(bus, ch_num);
} else if ((chan_intstatus & USB_OTG_HCINT_BBERR) == USB_OTG_HCINT_BBERR) {
urb->errorcode = -USB_ERR_BABBLE;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_BBERR);
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(bus, ch_num);
} else if ((chan_intstatus & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR) {
urb->errorcode = -USB_ERR_IO;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR);
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(bus, ch_num);
} else if ((chan_intstatus & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR) {
urb->errorcode = -USB_ERR_DT;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(bus, ch_num);
} else if ((chan_intstatus & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH) {
USB_MASK_HALT_HC_INT(ch_num);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH);
if (urb->errorcode == 0) {
uint32_t count = chan->xferlen - (USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ); /* how many size has received */
uint32_t count = chan->xferlen - (USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ); /* how many size has received */
uint32_t has_used_packets = chan->num_packets - ((USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) >> 19); /* how many packets have used */
urb->actual_length += count;
@@ -932,7 +933,7 @@ static void dwc2_inchan_irq_handler(uint8_t ch_num)
if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_CONTROL) {
if (chan->ep0_state == DWC2_EP0_STATE_INDATA) {
chan->ep0_state = DWC2_EP0_STATE_OUTSTATUS;
dwc2_control_urb_init(ch_num, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
dwc2_control_urb_init(bus, ch_num, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
} else if (chan->ep0_state == DWC2_EP0_STATE_INSTATUS) {
chan->ep0_state = DWC2_EP0_STATE_SETUP;
dwc2_urb_waitup(urb);
@@ -941,21 +942,13 @@ static void dwc2_inchan_irq_handler(uint8_t ch_num)
} else {
dwc2_urb_waitup(urb);
}
} else if (urb->errorcode == -USB_ERR_NAK) {
/* re-activate the channel */
if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_CONTROL) {
dwc2_control_urb_init(ch_num, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
} else if ((USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_BULK) || (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT)) {
dwc2_bulk_intr_urb_init(ch_num, urb, urb->transfer_buffer, urb->transfer_buffer_length);
} else {
}
} else {
dwc2_urb_waitup(urb);
}
}
}
static void dwc2_outchan_irq_handler(uint8_t ch_num)
static void dwc2_outchan_irq_handler(struct usbh_bus *bus, uint8_t ch_num)
{
uint32_t chan_intstatus;
struct dwc2_chan *chan;
@@ -964,68 +957,66 @@ static void dwc2_outchan_irq_handler(uint8_t ch_num)
chan_intstatus = (USB_OTG_HC(ch_num)->HCINT) & (USB_OTG_HC((uint32_t)ch_num)->HCINTMSK);
chan = &g_dwc2_hcd.chan_pool[ch_num];
chan = &g_dwc2_hcd[bus->hcd.hcd_id].chan_pool[ch_num];
urb = chan->urb;
//printf("s2:%08x\r\n", chan_intstatus);
if ((chan_intstatus & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC) {
urb->errorcode = 0;
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC);
dwc2_halt(ch_num);
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(bus, ch_num);
} else if ((chan_intstatus & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR) {
urb->errorcode = -USB_ERR_IO;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR);
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(bus, ch_num);
} else if ((chan_intstatus & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL) {
urb->errorcode = -USB_ERR_STALL;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL);
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(bus, ch_num);
} else if ((chan_intstatus & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK) {
urb->errorcode = -USB_ERR_NAK;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
} else if ((chan_intstatus & USB_OTG_HCINT_ACK) == USB_OTG_HCINT_ACK) {
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK);
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(bus, ch_num);
} else if ((chan_intstatus & USB_OTG_HCINT_NYET) == USB_OTG_HCINT_NYET) {
urb->errorcode = -USB_ERR_NAK;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET);
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(bus, ch_num);
} else if ((chan_intstatus & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR) {
urb->errorcode = -USB_ERR_IO;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR);
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(bus, ch_num);
} else if ((chan_intstatus & USB_OTG_HCINT_BBERR) == USB_OTG_HCINT_BBERR) {
urb->errorcode = -USB_ERR_BABBLE;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
dwc2_halt(bus, ch_num);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_BBERR);
} else if ((chan_intstatus & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR) {
urb->errorcode = -USB_ERR_IO;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR);
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(bus, ch_num);
} else if ((chan_intstatus & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR) {
urb->errorcode = -USB_ERR_DT;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(bus, ch_num);
} else if ((chan_intstatus & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH) {
USB_MASK_HALT_HC_INT(ch_num);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH);
if (urb->errorcode == 0) {
uint32_t count = USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ; /* last packet size */
uint32_t count = USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ; /* last packet size */
uint32_t has_used_packets = chan->num_packets - ((USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) >> 19); /* how many packets have used */
urb->actual_length += (has_used_packets - 1) * USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize) + count; //the same with urb->actual_length += chan->xferlen;
urb->actual_length += (has_used_packets - 1) * USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize) + count; //the same with urb->actual_length += chan->xferlen;
if (has_used_packets % 2) /* toggle in odd numbers */
{
if (urb->data_toggle == HC_PID_DATA0) {
@@ -1046,10 +1037,10 @@ static void dwc2_outchan_irq_handler(uint8_t ch_num)
} else {
chan->ep0_state = DWC2_EP0_STATE_INSTATUS;
}
dwc2_control_urb_init(ch_num, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
dwc2_control_urb_init(bus, ch_num, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
} else if (chan->ep0_state == DWC2_EP0_STATE_OUTDATA) {
chan->ep0_state = DWC2_EP0_STATE_INSTATUS;
dwc2_control_urb_init(ch_num, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
dwc2_control_urb_init(bus, ch_num, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
} else if (chan->ep0_state == DWC2_EP0_STATE_OUTSTATUS) {
chan->ep0_state = DWC2_EP0_STATE_SETUP;
dwc2_urb_waitup(urb);
@@ -1058,21 +1049,13 @@ static void dwc2_outchan_irq_handler(uint8_t ch_num)
} else {
dwc2_urb_waitup(urb);
}
} else if (urb->errorcode == -USB_ERR_NAK) {
/* re-activate the channel */
if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_CONTROL) {
dwc2_control_urb_init(ch_num, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
} else if ((USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_BULK) || (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT)) {
dwc2_bulk_intr_urb_init(ch_num, urb, urb->transfer_buffer, urb->transfer_buffer_length);
} else {
}
} else {
dwc2_urb_waitup(urb);
}
}
}
static void dwc2_port_irq_handler(void)
static void dwc2_port_irq_handler(struct usbh_bus *bus)
{
__IO uint32_t hprt0, hprt0_dup, regval;
@@ -1086,16 +1069,17 @@ static void dwc2_port_irq_handler(void)
/* Check whether Port Connect detected */
if ((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET) {
if ((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS) {
usbh_roothub_thread_wakeup(1);
bus->hcd.roothub.int_buffer[0] = (1 << 1);
usbh_hub_thread_wakeup(&bus->hcd.roothub);
}
hprt0_dup |= USB_OTG_HPRT_PCDET;
g_dwc2_hcd.port_csc = 1;
g_dwc2_hcd[bus->hcd.hcd_id].port_csc = 1;
}
/* Check whether Port Enable Changed */
if ((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG) {
hprt0_dup |= USB_OTG_HPRT_PENCHNG;
g_dwc2_hcd.port_pec = 1;
g_dwc2_hcd[bus->hcd.hcd_id].port_pec = 1;
if ((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA) {
#if defined(CONFIG_USB_DWC2_ULPI_PHY)
@@ -1125,16 +1109,19 @@ static void dwc2_port_irq_handler(void)
/* Check for an overcurrent */
if ((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG) {
hprt0_dup |= USB_OTG_HPRT_POCCHNG;
g_dwc2_hcd.port_occ = 1;
g_dwc2_hcd[bus->hcd.hcd_id].port_occ = 1;
}
/* Clear Port Interrupts */
USB_OTG_HPRT = hprt0_dup;
}
void USBH_IRQHandler(void)
void USBH_IRQHandler(uint8_t busid)
{
uint32_t gint_status, chan_int;
gint_status = dwc2_get_glb_intstatus();
struct usbh_bus *bus;
bus = &g_usbhost_bus[busid];
gint_status = dwc2_get_glb_intstatus(bus);
if ((USB_OTG_GLB->GINTSTS & 0x1U) == USB_OTG_MODE_HOST) {
/* Avoid spurious interrupt */
if (gint_status == 0) {
@@ -1142,11 +1129,12 @@ void USBH_IRQHandler(void)
}
if (gint_status & USB_OTG_GINTSTS_HPRTINT) {
dwc2_port_irq_handler();
dwc2_port_irq_handler(bus);
}
if (gint_status & USB_OTG_GINTSTS_DISCINT) {
g_dwc2_hcd.port_csc = 1;
usbh_roothub_thread_wakeup(1);
g_dwc2_hcd[bus->hcd.hcd_id].port_csc = 1;
bus->hcd.roothub.int_buffer[0] = (1 << 1);
usbh_hub_thread_wakeup(&bus->hcd.roothub);
USB_OTG_GLB->GINTSTS = USB_OTG_GINTSTS_DISCINT;
}
@@ -1155,9 +1143,9 @@ void USBH_IRQHandler(void)
for (uint8_t i = 0U; i < CONFIG_USBHOST_PIPE_NUM; i++) {
if ((chan_int & (1UL << (i & 0xFU))) != 0U) {
if ((USB_OTG_HC(i)->HCCHAR & USB_OTG_HCCHAR_EPDIR) == USB_OTG_HCCHAR_EPDIR) {
dwc2_inchan_irq_handler(i);
dwc2_inchan_irq_handler(bus, i);
} else {
dwc2_outchan_irq_handler(i);
dwc2_outchan_irq_handler(bus, i);
}
}
}

Some files were not shown because too many files have changed in this diff Show More