Compare commits
56 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
850e96577c | ||
|
|
384b11eb88 | ||
|
|
cfbe5615c4 | ||
|
|
cbefa69715 | ||
|
|
9e0cc8347c | ||
|
|
8c72947794 | ||
|
|
d5b4cdd4bd | ||
|
|
3508879e1d | ||
|
|
5c36affc3c | ||
|
|
762c3cbb2f | ||
|
|
b4e952b371 | ||
|
|
756987050f | ||
|
|
64773ab5e8 | ||
|
|
743669861e | ||
|
|
0e3e9477cc | ||
|
|
56c90ab6f9 | ||
|
|
9c247f6e6b | ||
|
|
556fd6af63 | ||
|
|
4803a6826b | ||
|
|
e0551b3e7b | ||
|
|
31fa2b99c5 | ||
|
|
4313a2666e | ||
|
|
466d241c31 | ||
|
|
49116c6fbc | ||
|
|
e7a57289ce | ||
|
|
e34ecc6cbb | ||
|
|
d1c7fa8c19 | ||
|
|
920b02cb7c | ||
|
|
3f89d1b003 | ||
|
|
5897edffed | ||
|
|
a01c08ddaa | ||
|
|
dcad369d06 | ||
|
|
8232f64775 | ||
|
|
6fb3f31cbe | ||
|
|
eeb304ae08 | ||
|
|
fc80972284 | ||
|
|
feb69dcd95 | ||
|
|
cdfb7c3fb2 | ||
|
|
24511c4d4b | ||
|
|
c7cf09f6c3 | ||
|
|
6b0a0135ac | ||
|
|
04a300d803 | ||
|
|
0f5e05052f | ||
|
|
b773cecd2e | ||
|
|
c4a65146e8 | ||
|
|
6bc6b06076 | ||
|
|
125aad65d6 | ||
|
|
07ced6d023 | ||
|
|
45cca3930b | ||
|
|
eff338f8a7 | ||
|
|
1158fc3d8c | ||
|
|
d517f2594e | ||
|
|
b37f494304 | ||
|
|
5fe66b4f0d | ||
|
|
249e650c37 | ||
|
|
cbfac7ec0c |
6
.gitmodules
vendored
Normal 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
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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)` 受以下宏影响:
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
2
VERSION
@@ -1,5 +1,5 @@
|
||||
VERSION_MAJOR = 1
|
||||
VERSION_MINOR = 0
|
||||
VERSION_MINOR = 1
|
||||
PATCHLEVEL = 99
|
||||
VERSION_TWEAK = 0
|
||||
EXTRAVERSION = 0
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 */
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
399
class/wireless/usbh_bluetooth.c
Normal 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
|
||||
54
class/wireless/usbh_bluetooth.h
Normal 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 */
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 */
|
||||
|
||||
511
core/usbd_core.c
@@ -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
|
||||
}
|
||||
|
||||
242
core/usbh_core.c
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
130
demo/usb_host.c
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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卡 512,flash 4K),更改时需要是内存介质扇区的倍数。
|
||||
|
||||
虽然名字叫 block size,但是跟内存介质的 block size不是一个意思。
|
||||
msc 缓存的最大长度,缓存越大,USB 的速度越高,因为介质一般多个 block 读写速度比单个 block 高很多,比如 sd 卡。
|
||||
默认 512 ,如果是 flash 需要改成 4K, 缓存的大小需要是 介质的一个 block size 的整数倍。
|
||||
|
||||
CONFIG_USBDEV_MSC_MANUFACTURER_STRING
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
CORE
|
||||
-----------------
|
||||
|
||||
.. note:: 请注意,v1.1 版本开始增加 busid 形参,其余保持不变,所以 API 说明不做更新
|
||||
|
||||
端点结构体
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
|
||||
@@ -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
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
Porting
|
||||
=========================
|
||||
|
||||
.. note:: 请注意,v1.1 版本开始增加 busid 形参,其余保持不变,所以 API 说明不做更新
|
||||
|
||||
device controller(dcd)
|
||||
-------------------------
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 管理
|
||||
|
||||
@@ -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` 函数。
|
||||
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 24 KiB |
@@ -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 引脚一般使用 50000000UL,STM32F7/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** 文件。
|
||||
|
||||
|
||||
@@ -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 功能的芯片使用注意
|
||||
-------------------------------
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||