support multi USB IP for host
This commit is contained in:
@@ -111,6 +111,7 @@ CherryUSB Host Stack has the following functions:
|
||||
- Support Remote NDIS (RNDIS)
|
||||
- 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.
|
||||
|
||||
|
||||
@@ -109,6 +109,7 @@ CherryUSB Host 协议栈当前实现以下功能:
|
||||
- 支持 Remote NDIS (RNDIS)
|
||||
- 支持 Vendor 类 class
|
||||
- 支持 USB modeswitch
|
||||
- 支持相同 USB IP 的多主机
|
||||
|
||||
同时,CherryUSB Host 协议栈还提供了 lsusb 的功能,借助 shell 插件可以查看所有挂载设备的信息,包括外部 hub 上的设备的信息。
|
||||
|
||||
|
||||
@@ -91,6 +91,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
|
||||
@@ -137,18 +138,16 @@
|
||||
|
||||
/* ================ 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_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
|
||||
|
||||
@@ -15,15 +15,8 @@
|
||||
|
||||
#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][32];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_intbuf[CONFIG_USBHOST_MAX_BUS][CONFIG_USBHOST_MAX_EXTHUBS + 1][CONFIG_USB_ALIGN_SIZE];
|
||||
|
||||
extern int usbh_free_devaddr(struct usbh_hubport *hport);
|
||||
extern int usbh_enumerate(struct usbh_hubport *hport);
|
||||
@@ -67,17 +60,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 +83,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 +127,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 +216,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 +234,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 +252,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 +270,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) {
|
||||
@@ -341,6 +319,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;
|
||||
|
||||
@@ -354,6 +333,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;
|
||||
@@ -394,10 +374,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;
|
||||
@@ -423,7 +405,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);
|
||||
@@ -461,7 +443,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);
|
||||
@@ -602,9 +584,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);
|
||||
@@ -622,7 +605,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -638,9 +621,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;
|
||||
}
|
||||
@@ -648,55 +633,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];
|
||||
@@ -705,12 +676,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
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
235
core/usbh_core.c
235
core/usbh_core.c
@@ -8,33 +8,19 @@
|
||||
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][CONFIG_USBHOST_REQUEST_BUFFER_LEN];
|
||||
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];
|
||||
|
||||
/* 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 +213,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 +332,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 +357,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 +398,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 +420,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 +454,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 +487,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 +506,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 +523,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,10 +629,53 @@ errout:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_initialize(void)
|
||||
struct usbh_bus *usbh_alloc_bus(uint8_t busid, uint32_t reg_base)
|
||||
{
|
||||
memset(&g_usbh_bus, 0, sizeof(struct usbh_bus));
|
||||
struct usbh_bus *bus;
|
||||
struct usbh_hub *hub;
|
||||
|
||||
if (busid > CONFIG_USBHOST_MAX_BUS) {
|
||||
USB_LOG_ERR("bus overflow\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
bus = usb_malloc(sizeof(struct usbh_bus));
|
||||
if (bus == NULL) {
|
||||
USB_LOG_ERR("No memory to alloc bus\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return bus;
|
||||
}
|
||||
|
||||
int usbh_initialize(struct usbh_bus *bus)
|
||||
{
|
||||
#ifdef __ARMCC_VERSION /* ARM C Compiler */
|
||||
extern const int usbh_class_info$$Base;
|
||||
extern const int usbh_class_info$$Limit;
|
||||
@@ -658,17 +690,19 @@ int usbh_initialize(void)
|
||||
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(struct usbh_bus *bus)
|
||||
{
|
||||
return usbh_hub_deinitialize();
|
||||
usbh_hub_deinitialize(bus);
|
||||
|
||||
usb_slist_init(&bus->hub_list);
|
||||
usb_slist_remove(&g_bus_head, &bus->list);
|
||||
|
||||
usb_free(bus);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_control_transfer(struct usbh_hubport *hport, struct usb_setup_packet *setup, uint8_t *buffer)
|
||||
@@ -695,16 +729,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 +753,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 +779,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 +819,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,8 +31,8 @@ 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)
|
||||
@@ -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,
|
||||
@@ -225,8 +256,9 @@ 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);
|
||||
struct usbh_bus *usbh_alloc_bus(uint8_t busid, uint32_t reg_base);
|
||||
int usbh_initialize(struct usbh_bus *bus);
|
||||
int usbh_deinitialize(struct usbh_bus *bus);
|
||||
void *usbh_find_class_instance(const char *devname);
|
||||
|
||||
int lsusb(int argc, char **argv);
|
||||
|
||||
@@ -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
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
@@ -216,17 +216,17 @@ EHCI 是 intel 制定的标准主机控制器接口,任何厂家都必须实
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
//Host Controller Capability Register BASE
|
||||
#define CONFIG_USB_EHCI_HCCR_BASE (0xxx)
|
||||
//Host Controller Operational Register BASE
|
||||
#define CONFIG_USB_EHCI_HCOR_BASE (0xxx)
|
||||
//Host Controller Operational Register BASE 距离基地址的偏移
|
||||
#define CONFIG_USB_EHCI_HCOR_OFFSET (0x14)
|
||||
//是否打印 ehci 配置信息
|
||||
#define CONFIG_USB_EHCI_INFO_ENABLE
|
||||
//是否关闭保留寄存器的占位,默认保留 9 个双字的占位
|
||||
#define CONFIG_USB_ECHI_HCOR_RESERVED_DISABLE
|
||||
#define CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE
|
||||
//是否使能 configflag 寄存器中的 bit0
|
||||
#define CONFIG_USB_EHCI_CONFIGFLAG
|
||||
//是否使能 port power bit
|
||||
#define CONFIG_USB_EHCI_PORT_POWER
|
||||
//是否查看 ehci 配置信息
|
||||
#define CONFIG_USB_EHCI_PRINT_HW_PARAM
|
||||
|
||||
同时由于 EHCI 只是主机控制器并且只支持高速,一般配合一个 otg 控制器和一个低速全速兼容控制单元,而速度的获取一般是在 otg 寄存器中,所以需要用户实现 `usbh_get_port_speed` 函数。
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 53 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 51 KiB |
@@ -4,7 +4,6 @@
|
||||
在学习 USB 或者是学习 CherryUSB 代码之前,我们需要先基于现有的 demo 进行快速验证,为什么?是为了提升对 USB 的兴趣,能有信心进行下一步的动作,如果 demo 都跑不起来,或者自己摸索写代码,或者先看 USB 基本概念,结果看到最后,
|
||||
发现一点都看不懂,概念好多,根本记不住,从而丧失对 USB 的兴趣。因此,先跑 demo 非常重要。下面我将给大家罗列目前支持的 demo 仓库。
|
||||
|
||||
|
||||
基于 bouffalolab 系列芯片
|
||||
---------------------------
|
||||
|
||||
@@ -105,6 +104,15 @@ USB Device 移植要点
|
||||
#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 USBD_IRQHandler USB_LP_CAN1_RX0_IRQHandler
|
||||
#define USBD_BASE (0x40005C00UL)
|
||||
#define CONFIG_USBDEV_EP_NUM 8
|
||||
#define CONFIG_USBDEV_FSDEV_PMA_ACCESS 2
|
||||
|
||||
- 编译器推荐使用 **AC6**。勾选 **Microlib**,并实现 **printf** ,方便后续查看 log。
|
||||
|
||||
.. figure:: img/stm32_10.png
|
||||
@@ -134,12 +142,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,12 +149,16 @@ 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`,并传入 bus 句柄
|
||||
- 调用 `usbh_alloc_bus` 创建 bus, `busid` 从 0 开始,不能超过 `CONFIG_USBHOST_MAX_BUS`
|
||||
- 调用 `usbh_initialize` 即可
|
||||
- 启动线程
|
||||
|
||||
.. figure:: img/stm32_18.png
|
||||
.. figure:: img/stm32_19.png
|
||||
.. figure:: img/stm32_20.png
|
||||
|
||||
- 如果使用 **msc**,并且带文件系统,需要自行添加文件系统文件了,对应的 porting 编写参考 **fatfs_usbh.c** 文件。
|
||||
|
||||
@@ -20,14 +20,14 @@ USB Device 移植要点
|
||||
USB Host 移植要点
|
||||
-----------------------
|
||||
|
||||
.. note:: 请注意,当前是最新版本,支持多 port 功能,`USBH_BASE` 和 `USBH_IRQHandler` 的宏不能再使用,并且必须调用 `usbh_alloc_bus`,具体按照以下步骤执行。
|
||||
|
||||
- 拷贝 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_alloc_bus` 创建 bus,填入 USB IP 的基地址, `busid` 从 0 开始,不能超过 `CONFIG_USBHOST_MAX_BUS`
|
||||
- 在中断函数中调用 `USBH_IRQHandler`,并传入 bus 句柄, 如果你的 SDK 中中断入口已经存在 `USBH_IRQHandler` ,请更改 USB 协议栈中的名称
|
||||
- 调用 `usbh_initialize`
|
||||
- 如果使用的是 GCC ,需要在链接脚本(ld)中添加如下代码:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
.. figure:: img/config_file.png
|
||||
|
||||
* 使用 `scons --target=mdk` 或者 `scons` 进行编译
|
||||
* 使用 `scons --target=mdk5` 或者 `scons` 进行编译
|
||||
|
||||
主机配置
|
||||
--------------------------
|
||||
@@ -48,15 +48,36 @@
|
||||
|
||||
.. 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_alloc_bus` 和 `usbh_initialize`,
|
||||
* 以上内容我们推荐放在 **board.c** 中,如下代码:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
struct usbh_bus *usb_otg_hs_bus;
|
||||
|
||||
void OTG_HS_IRQHandler(void)
|
||||
{
|
||||
extern void USBH_IRQHandler(struct usbh_bus *bus);
|
||||
USBH_IRQHandler(usb_otg_hs_bus);
|
||||
}
|
||||
|
||||
int usbh_init(void)
|
||||
{
|
||||
usb_otg_hs_bus = usbh_alloc_bus(0, USB_OTG_HS_PERIPH_BASE);
|
||||
usbh_initialize(usb_otg_hs_bus);
|
||||
return 0;
|
||||
}
|
||||
|
||||
INIT_APP_EXPORT(usbh_init);
|
||||
|
||||
* 使用 `scons --target=mdk5` 或者 `scons` 进行编译,需要使用 AC6 编译器
|
||||
* 如果使用的是 GCC ,需要在链接脚本(ld)中添加如下代码:
|
||||
|
||||
.. code-block:: C
|
||||
@@ -71,17 +92,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
|
||||
@@ -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,7 @@ 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 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;
|
||||
|
||||
@@ -217,7 +209,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,7 +233,7 @@ 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;
|
||||
@@ -288,7 +280,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,7 +300,7 @@ static int usbh_reset_port(const uint8_t port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t usbh_get_port_speed(const uint8_t port)
|
||||
static uint8_t usbh_get_port_speed(struct usbh_bus *bus, const uint8_t port)
|
||||
{
|
||||
__IO uint32_t hprt0 = 0U;
|
||||
uint8_t speed;
|
||||
@@ -332,7 +324,7 @@ static uint8_t usbh_get_port_speed(const uint8_t port)
|
||||
* @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);
|
||||
@@ -478,10 +474,10 @@ int usb_hc_init(void)
|
||||
/* This is vendor register */
|
||||
USB_OTG_GLB->GCCFG = usbh_get_dwc2_gccfg_conf();
|
||||
|
||||
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,7 +858,7 @@ 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);
|
||||
|
||||
@@ -864,51 +866,51 @@ static void dwc2_inchan_irq_handler(uint8_t ch_num)
|
||||
urb->errorcode = 0;
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC);
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(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;
|
||||
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(ch_num);
|
||||
dwc2_halt(bus, ch_num);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK) {
|
||||
urb->errorcode = -USB_ERR_NAK;
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(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;
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET);
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
dwc2_halt(bus, ch_num);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR) {
|
||||
urb->errorcode = -USB_ERR_IO;
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR);
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
dwc2_halt(bus, ch_num);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_BBERR) == USB_OTG_HCINT_BBERR) {
|
||||
urb->errorcode = -USB_ERR_BABBLE;
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_BBERR);
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
dwc2_halt(bus, ch_num);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR) {
|
||||
urb->errorcode = -USB_ERR_IO;
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR);
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
dwc2_halt(bus, ch_num);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR) {
|
||||
urb->errorcode = -USB_ERR_DT;
|
||||
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(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);
|
||||
@@ -931,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);
|
||||
@@ -946,7 +948,7 @@ static void dwc2_inchan_irq_handler(uint8_t ch_num)
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -955,7 +957,7 @@ 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);
|
||||
|
||||
@@ -963,48 +965,48 @@ static void dwc2_outchan_irq_handler(uint8_t ch_num)
|
||||
urb->errorcode = 0;
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC);
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
dwc2_halt(bus, ch_num);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR) {
|
||||
urb->errorcode = -USB_ERR_IO;
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR);
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
dwc2_halt(bus, ch_num);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL) {
|
||||
urb->errorcode = -USB_ERR_STALL;
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL);
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
dwc2_halt(bus, ch_num);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK) {
|
||||
urb->errorcode = -USB_ERR_NAK;
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
dwc2_halt(bus, ch_num);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_NYET) == USB_OTG_HCINT_NYET) {
|
||||
urb->errorcode = -USB_ERR_NAK;
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET);
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
dwc2_halt(bus, ch_num);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR) {
|
||||
urb->errorcode = -USB_ERR_IO;
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR);
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(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;
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR);
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
dwc2_halt(bus, ch_num);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR) {
|
||||
urb->errorcode = -USB_ERR_DT;
|
||||
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(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);
|
||||
@@ -1035,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);
|
||||
@@ -1053,7 +1055,7 @@ static void dwc2_outchan_irq_handler(uint8_t ch_num)
|
||||
}
|
||||
}
|
||||
|
||||
static void dwc2_port_irq_handler(void)
|
||||
static void dwc2_port_irq_handler(struct usbh_bus *bus)
|
||||
{
|
||||
__IO uint32_t hprt0, hprt0_dup, regval;
|
||||
|
||||
@@ -1067,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)
|
||||
@@ -1106,16 +1109,16 @@ 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(struct usbh_bus *bus)
|
||||
{
|
||||
uint32_t gint_status, chan_int;
|
||||
gint_status = dwc2_get_glb_intstatus();
|
||||
gint_status = dwc2_get_glb_intstatus(bus);
|
||||
if ((USB_OTG_GLB->GINTSTS & 0x1U) == USB_OTG_MODE_HOST) {
|
||||
/* Avoid spurious interrupt */
|
||||
if (gint_status == 0) {
|
||||
@@ -1123,11 +1126,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;
|
||||
}
|
||||
@@ -1136,9 +1140,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,8 @@
|
||||
#include "usbh_hub.h"
|
||||
#include "usb_hc_ehci.h"
|
||||
|
||||
#ifndef USBH_IRQHandler
|
||||
#define USBH_IRQHandler USBH_IRQHandler
|
||||
#endif
|
||||
|
||||
#define EHCI_HCCR ((struct ehci_hccr *)CONFIG_USB_EHCI_HCCR_BASE)
|
||||
#define EHCI_HCOR ((struct ehci_hcor *)CONFIG_USB_EHCI_HCOR_BASE)
|
||||
#define EHCI_HCCR ((struct ehci_hccr *)(bus->hcd.reg_base))
|
||||
#define EHCI_HCOR ((struct ehci_hcor *)(bus->hcd.reg_base + CONFIG_USB_EHCI_HCOR_OFFSET))
|
||||
|
||||
#define EHCI_PTR2ADDR(x) ((uint32_t)(x) & ~0x1F)
|
||||
#define EHCI_ADDR2QH(x) ((struct ehci_qh_hw *)((uint32_t)(x) & ~0x1F))
|
||||
@@ -31,7 +27,7 @@
|
||||
#define CONFIG_USB_EHCI_QTD_NUM (CONFIG_USBHOST_PIPE_NUM + 3)
|
||||
#define CONFIG_USB_EHCI_ITD_NUM 20
|
||||
|
||||
extern uint8_t usbh_get_port_speed(const uint8_t port);
|
||||
extern uint8_t usbh_get_port_speed(struct usbh_bus *bus, const uint8_t port);
|
||||
|
||||
struct ehci_qh_hw {
|
||||
struct ehci_qh hw;
|
||||
@@ -63,11 +59,11 @@ struct ehci_hcd {
|
||||
bool ehci_itd_used[CONFIG_USB_EHCI_ITD_NUM];
|
||||
};
|
||||
|
||||
extern struct ehci_hcd g_ehci_hcd;
|
||||
extern uint32_t g_framelist[];
|
||||
extern struct ehci_hcd g_ehci_hcd[CONFIG_USBHOST_MAX_BUS];
|
||||
extern uint32_t g_framelist[CONFIG_USBHOST_MAX_BUS][CONFIG_USB_EHCI_FRAME_LIST_SIZE];
|
||||
|
||||
int ehci_iso_urb_init(struct usbh_urb *urb);
|
||||
void ehci_remove_itd_urb(struct usbh_urb *urb);
|
||||
void ehci_scan_isochronous_list(void);
|
||||
int ehci_iso_urb_init(struct usbh_bus *bus, struct usbh_urb *urb);
|
||||
void ehci_remove_itd_urb(struct usbh_bus *bus, struct usbh_urb *urb);
|
||||
void ehci_scan_isochronous_list(struct usbh_bus *bus);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,9 +10,16 @@
|
||||
#include "usbh_core.h"
|
||||
#include "usb_ehci_priv.h"
|
||||
|
||||
extern void USBH_IRQHandler(void);
|
||||
extern void USBH_IRQHandler(struct usbh_bus *bus);
|
||||
|
||||
void usb_hc_low_level_init(void)
|
||||
const uint8_t aic_irq_table[] = {
|
||||
USB_HOST0_EHCI_IRQn,
|
||||
#ifdef HPM_USB1_BASE
|
||||
USB_HOST1_EHCI_IRQn
|
||||
#endif
|
||||
};
|
||||
|
||||
void usb_hc_low_level_init(struct usbh_bus *bus)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
@@ -22,13 +29,13 @@ void usb_hc_low_level_init(void)
|
||||
#endif
|
||||
|
||||
/* set phy type: UTMI/ULPI */
|
||||
val = readl((volatile void *)(unsigned long)(CONFIG_USB_EHCI_HCCR_BASE+0x800));
|
||||
val = readl((volatile void *)(unsigned long)(bus->hcd.reg_base+0x800));
|
||||
#ifdef FPGA_BOARD_ARTINCHIP
|
||||
/* fpga phy type = ULPI */
|
||||
writel((val & ~0x1U), (volatile void *)(unsigned long)(CONFIG_USB_EHCI_HCCR_BASE+0x800));
|
||||
writel((val & ~0x1U), (volatile void *)(unsigned long)(bus->hcd.reg_base+0x800));
|
||||
#else
|
||||
/* board phy type = UTMI */
|
||||
writel((val | 0x1), (volatile void *)(unsigned long)(CONFIG_USB_EHCI_HCCR_BASE+0x800));
|
||||
writel((val | 0x1), (volatile void *)(unsigned long)(bus->hcd.reg_base+0x800));
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
@@ -37,9 +44,9 @@ void usb_hc_low_level_init(void)
|
||||
Must increase the OUT threshold to avoid underrun. (FIFO size - 4)
|
||||
*/
|
||||
#ifdef FPGA_BOARD_ARTINCHIP
|
||||
writel((32 | (127 << 16)), (volatile void *)(unsigned long)(CONFIG_USB_EHCI_HCCR_BASE+0x94));
|
||||
writel((32 | (127 << 16)), (volatile void *)(unsigned long)(bus->hcd.reg_base+0x94));
|
||||
#else
|
||||
writel((32 | (32 << 16)), (volatile void *)(unsigned long)(CONFIG_USB_EHCI_HCCR_BASE+0x94));
|
||||
writel((32 | (32 << 16)), (volatile void *)(unsigned long)(bus->hcd.reg_base+0x94));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -55,12 +62,12 @@ void usb_hc_low_level_init(void)
|
||||
aicos_udelay(300);
|
||||
|
||||
/* register interrupt callback */
|
||||
aicos_request_irq(CONFIG_USB_EHCI_IRQ_NUM, (irq_handler_t)USBH_IRQHandler,
|
||||
0, "usb_host_ehci", NULL);
|
||||
aicos_irq_enable(CONFIG_USB_EHCI_IRQ_NUM);
|
||||
aicos_request_irq(aic_irq_table[bus->hcd.hcd_id], (irq_handler_t)USBH_IRQHandler,
|
||||
0, "usb_host_ehci", bus);
|
||||
aicos_irq_enable(aic_irq_table[bus->hcd.hcd_id]);
|
||||
}
|
||||
|
||||
uint8_t usbh_get_port_speed(const uint8_t port)
|
||||
uint8_t usbh_get_port_speed(struct usbh_bus *bus, const uint8_t port)
|
||||
{
|
||||
/* Defined by individual manufacturers */
|
||||
uint32_t regval;
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#define USB_SOF_TIMER_MASK_AFTER_RESET_HS (0x44C)
|
||||
#define USB_SOF_TIMER_MASK_AFTER_RESET_FS (0x2710)
|
||||
|
||||
extern void USBH_IRQHandler();
|
||||
extern void USBH_IRQHandler(struct usbh_bus *bus);
|
||||
|
||||
static void bflb_usb_phy_init(void)
|
||||
{
|
||||
@@ -83,7 +83,7 @@ static void bflb_usb_phy_init(void)
|
||||
bflb_mtimer_delay_ms(2);
|
||||
}
|
||||
|
||||
void usb_hc_low_level_init(void)
|
||||
void usb_hc_low_level_init(struct usbh_bus *bus)
|
||||
{
|
||||
uint32_t regval;
|
||||
|
||||
@@ -117,7 +117,7 @@ void usb_hc_low_level_init(void)
|
||||
putreg32(regval, BLFB_USB_BASE + USB_GLB_INT_OFFSET);
|
||||
}
|
||||
|
||||
uint8_t usbh_get_port_speed(const uint8_t port)
|
||||
uint8_t usbh_get_port_speed(struct usbh_bus *bus, const uint8_t port)
|
||||
{
|
||||
uint8_t speed = 3;
|
||||
|
||||
|
||||
@@ -7,10 +7,27 @@
|
||||
#error "hpm ehci must set CONFIG_USB_EHCI_HPMICRO=1"
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_HPM_USBH_BASE) || !defined(CONFIG_HPM_USBH_IRQn)
|
||||
#error "hpm ehci must config CONFIG_HPM_USBH_BASE and CONFIG_HPM_USBH_IRQn"
|
||||
#if !defined(CONFIG_USB_EHCI_HCOR_OFFSET) || CONFIG_USB_EHCI_HCOR_OFFSET != 0x140
|
||||
#error "hpm ehci must config CONFIG_USB_EHCI_HCOR_OFFSET to 0x140"
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_USB_EHCI_PRINT_HW_PARAM) || !defined(CONFIG_USB_EHCI_PORT_POWER)
|
||||
#error "hpm ehci must enable CONFIG_USB_EHCI_PORT_POWER and disable CONFIG_USB_EHCI_PRINT_HW_PARAM"
|
||||
#endif
|
||||
|
||||
struct usbh_bus *hpm_usb_bus0;
|
||||
|
||||
#ifdef HPM_USB1_BASE
|
||||
struct usbh_bus *hpm_usb_bus1;
|
||||
#endif
|
||||
|
||||
const uint8_t hpm_irq_table[] = {
|
||||
IRQn_USB0,
|
||||
#ifdef HPM_USB1_BASE
|
||||
IRQn_USB1
|
||||
#endif
|
||||
};
|
||||
|
||||
static void usb_host_mode_init(USB_Type *ptr)
|
||||
{
|
||||
/* Set mode to host, must be set immediately after reset */
|
||||
@@ -30,23 +47,23 @@ static void usb_host_mode_init(USB_Type *ptr)
|
||||
ptr->USBCMD &= ~USB_USBCMD_ITC_MASK;
|
||||
}
|
||||
|
||||
void usb_hc_low_level_init(void)
|
||||
void usb_hc_low_level_init(struct usbh_bus *bus)
|
||||
{
|
||||
usb_phy_init((USB_Type *)CONFIG_HPM_USBH_BASE);
|
||||
intc_m_enable_irq(CONFIG_HPM_USBH_IRQn);
|
||||
usb_phy_init((USB_Type *)(bus->hcd.reg_base));
|
||||
intc_m_enable_irq(hpm_irq_table[bus->hcd.hcd_id]);
|
||||
}
|
||||
|
||||
void usb_hc_low_level2_init(void)
|
||||
void usb_hc_low_level2_init(struct usbh_bus *bus)
|
||||
{
|
||||
usb_host_mode_init((USB_Type *)CONFIG_HPM_USBH_BASE);
|
||||
usb_host_mode_init((USB_Type *)(bus->hcd.reg_base));
|
||||
}
|
||||
|
||||
uint8_t usbh_get_port_speed(const uint8_t port)
|
||||
uint8_t usbh_get_port_speed(struct usbh_bus *bus, const uint8_t port)
|
||||
{
|
||||
(void)port;
|
||||
uint8_t speed;
|
||||
|
||||
speed = usb_get_port_speed((USB_Type *)CONFIG_HPM_USBH_BASE);
|
||||
speed = usb_get_port_speed((USB_Type *)(bus->hcd.reg_base));
|
||||
|
||||
if (speed == 0x00) {
|
||||
return USB_SPEED_FULL;
|
||||
@@ -61,10 +78,18 @@ uint8_t usbh_get_port_speed(const uint8_t port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern void USBH_IRQHandler(void);
|
||||
extern void USBH_IRQHandler(struct usbh_bus *bus);
|
||||
|
||||
void isr_usbh(void)
|
||||
void isr_usbh0(void)
|
||||
{
|
||||
USBH_IRQHandler();
|
||||
USBH_IRQHandler(hpm_usb_bus0);
|
||||
}
|
||||
SDK_DECLARE_EXT_ISR_M(CONFIG_HPM_USBH_IRQn, isr_usbh)
|
||||
SDK_DECLARE_EXT_ISR_M(IRQn_USB0, isr_usbh0)
|
||||
|
||||
#ifdef HPM_USB1_BASE
|
||||
void isr_usbh1(void)
|
||||
{
|
||||
USBH_IRQHandler(hpm_usb_bus1);
|
||||
}
|
||||
SDK_DECLARE_EXT_ISR_M(IRQn_USB1, isr_usbh1)
|
||||
#endif
|
||||
|
||||
@@ -11,7 +11,7 @@ static int ehci_slot;
|
||||
static int ehci_function;
|
||||
static int ehci_vector;
|
||||
|
||||
extern void USBH_IRQHandler(void *para);
|
||||
extern void USBH_IRQHandler(struct usbh_bus *bus);
|
||||
|
||||
void ehci_pci_scan(int bus, int slot, int fun, int vector)
|
||||
{
|
||||
@@ -21,7 +21,7 @@ void ehci_pci_scan(int bus, int slot, int fun, int vector)
|
||||
ehci_vector = vector;
|
||||
pci_read_config_dword(bus, slot, fun, PCI_BASE_ADDRESS_0, &echi_base);
|
||||
}
|
||||
void usb_hc_low_level_init(void)
|
||||
void usb_hc_low_level_init(struct usbh_bus *bus)
|
||||
{
|
||||
//set software own ehci
|
||||
uint32_t legacy_val;
|
||||
@@ -38,7 +38,7 @@ void usb_hc_low_level_init(void)
|
||||
"USBirq",
|
||||
RTEMS_INTERRUPT_SHARED,
|
||||
USBH_IRQHandler,
|
||||
(void *)0);
|
||||
(void *)bus);
|
||||
|
||||
if (sc != RTEMS_SUCCESSFUL) {
|
||||
printf("USB install isr falied,%s\n", rtems_status_text(sc));
|
||||
@@ -46,7 +46,7 @@ void usb_hc_low_level_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t usbh_get_port_speed(const uint8_t port)
|
||||
uint8_t usbh_get_port_speed(struct usbh_bus *bus, const uint8_t port)
|
||||
{
|
||||
printf("USB_SPEED_HIGH present\n");
|
||||
return USB_SPEED_HIGH;
|
||||
|
||||
@@ -11,32 +11,32 @@
|
||||
#define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */
|
||||
#define EHCI_TUNE_MULT_TT 1
|
||||
|
||||
struct ehci_hcd g_ehci_hcd;
|
||||
struct ehci_hcd g_ehci_hcd[CONFIG_USBHOST_MAX_BUS];
|
||||
|
||||
USB_NOCACHE_RAM_SECTION struct ehci_qh_hw ehci_qh_pool[CONFIG_USB_EHCI_QH_NUM];
|
||||
USB_NOCACHE_RAM_SECTION struct ehci_qtd_hw ehci_qtd_pool[CONFIG_USB_EHCI_QTD_NUM];
|
||||
USB_NOCACHE_RAM_SECTION struct ehci_qh_hw ehci_qh_pool[CONFIG_USBHOST_MAX_BUS][CONFIG_USB_EHCI_QH_NUM];
|
||||
USB_NOCACHE_RAM_SECTION struct ehci_qtd_hw ehci_qtd_pool[CONFIG_USBHOST_MAX_BUS][CONFIG_USB_EHCI_QTD_NUM];
|
||||
|
||||
/* The head of the asynchronous queue */
|
||||
USB_NOCACHE_RAM_SECTION struct ehci_qh_hw g_async_qh_head;
|
||||
USB_NOCACHE_RAM_SECTION struct ehci_qh_hw g_async_qh_head[CONFIG_USBHOST_MAX_BUS];
|
||||
/* The head of the periodic queue */
|
||||
USB_NOCACHE_RAM_SECTION struct ehci_qh_hw g_periodic_qh_head[EHCI_PERIOIDIC_QH_NUM];
|
||||
USB_NOCACHE_RAM_SECTION struct ehci_qh_hw g_periodic_qh_head[CONFIG_USBHOST_MAX_BUS][EHCI_PERIOIDIC_QH_NUM];
|
||||
|
||||
/* The frame list */
|
||||
USB_NOCACHE_RAM_SECTION uint32_t g_framelist[CONFIG_USB_EHCI_FRAME_LIST_SIZE] __attribute__((aligned(4096)));
|
||||
USB_NOCACHE_RAM_SECTION uint32_t g_framelist[CONFIG_USBHOST_MAX_BUS][CONFIG_USB_EHCI_FRAME_LIST_SIZE] __attribute__((aligned(4096)));
|
||||
|
||||
static struct ehci_qh_hw *ehci_qh_alloc(void)
|
||||
static struct ehci_qh_hw *ehci_qh_alloc(struct usbh_bus *bus)
|
||||
{
|
||||
struct ehci_qh_hw *qh;
|
||||
usb_osal_sem_t waitsem;
|
||||
size_t flags;
|
||||
|
||||
for (uint32_t i = 0; i < CONFIG_USB_EHCI_QH_NUM; i++) {
|
||||
if (!g_ehci_hcd.ehci_qh_used[i]) {
|
||||
if (!g_ehci_hcd[bus->hcd.hcd_id].ehci_qh_used[i]) {
|
||||
flags = usb_osal_enter_critical_section();
|
||||
g_ehci_hcd.ehci_qh_used[i] = true;
|
||||
g_ehci_hcd[bus->hcd.hcd_id].ehci_qh_used[i] = true;
|
||||
usb_osal_leave_critical_section(flags);
|
||||
|
||||
qh = &ehci_qh_pool[i];
|
||||
qh = &ehci_qh_pool[bus->hcd.hcd_id][i];
|
||||
waitsem = qh->waitsem;
|
||||
memset(qh, 0, sizeof(struct ehci_qh_hw));
|
||||
qh->hw.hlp = QTD_LIST_END;
|
||||
@@ -49,14 +49,14 @@ static struct ehci_qh_hw *ehci_qh_alloc(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void ehci_qh_free(struct ehci_qh_hw *qh)
|
||||
static void ehci_qh_free(struct usbh_bus *bus, struct ehci_qh_hw *qh)
|
||||
{
|
||||
size_t flags;
|
||||
|
||||
for (uint32_t i = 0; i < CONFIG_USB_EHCI_QH_NUM; i++) {
|
||||
if (&ehci_qh_pool[i] == qh) {
|
||||
if (&ehci_qh_pool[bus->hcd.hcd_id][i] == qh) {
|
||||
flags = usb_osal_enter_critical_section();
|
||||
g_ehci_hcd.ehci_qh_used[i] = false;
|
||||
g_ehci_hcd[bus->hcd.hcd_id].ehci_qh_used[i] = false;
|
||||
usb_osal_leave_critical_section(flags);
|
||||
|
||||
qh->urb = NULL;
|
||||
@@ -65,18 +65,18 @@ static void ehci_qh_free(struct ehci_qh_hw *qh)
|
||||
}
|
||||
}
|
||||
|
||||
static struct ehci_qtd_hw *ehci_qtd_alloc(void)
|
||||
static struct ehci_qtd_hw *ehci_qtd_alloc(struct usbh_bus *bus)
|
||||
{
|
||||
struct ehci_qtd_hw *qtd;
|
||||
size_t flags;
|
||||
|
||||
for (uint32_t i = 0; i < CONFIG_USB_EHCI_QTD_NUM; i++) {
|
||||
if (!g_ehci_hcd.ehci_qtd_used[i]) {
|
||||
if (!g_ehci_hcd[bus->hcd.hcd_id].ehci_qtd_used[i]) {
|
||||
flags = usb_osal_enter_critical_section();
|
||||
g_ehci_hcd.ehci_qtd_used[i] = true;
|
||||
g_ehci_hcd[bus->hcd.hcd_id].ehci_qtd_used[i] = true;
|
||||
usb_osal_leave_critical_section(flags);
|
||||
|
||||
qtd = &ehci_qtd_pool[i];
|
||||
qtd = &ehci_qtd_pool[bus->hcd.hcd_id][i];
|
||||
memset(qtd, 0, sizeof(struct ehci_qtd_hw));
|
||||
qtd->hw.next_qtd = QTD_LIST_END;
|
||||
qtd->hw.alt_next_qtd = QTD_LIST_END;
|
||||
@@ -87,14 +87,14 @@ static struct ehci_qtd_hw *ehci_qtd_alloc(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void ehci_qtd_free(struct ehci_qtd_hw *qtd)
|
||||
static void ehci_qtd_free(struct usbh_bus *bus, struct ehci_qtd_hw *qtd)
|
||||
{
|
||||
size_t flags;
|
||||
|
||||
for (uint32_t i = 0; i < CONFIG_USB_EHCI_QTD_NUM; i++) {
|
||||
if (&ehci_qtd_pool[i] == qtd) {
|
||||
if (&ehci_qtd_pool[bus->hcd.hcd_id][i] == qtd) {
|
||||
flags = usb_osal_enter_critical_section();
|
||||
g_ehci_hcd.ehci_qtd_used[i] = false;
|
||||
g_ehci_hcd[bus->hcd.hcd_id].ehci_qtd_used[i] = false;
|
||||
usb_osal_leave_critical_section(flags);
|
||||
|
||||
qtd->urb = NULL;
|
||||
@@ -144,17 +144,17 @@ static int ehci_caculate_smask(int binterval)
|
||||
return (0x1 << (order % 8));
|
||||
}
|
||||
|
||||
static struct ehci_qh_hw *ehci_get_periodic_qhead(uint8_t interval)
|
||||
static struct ehci_qh_hw *ehci_get_periodic_qhead(struct usbh_bus *bus, uint8_t interval)
|
||||
{
|
||||
interval /= 8;
|
||||
|
||||
for (uint8_t i = 0; i < EHCI_PERIOIDIC_QH_NUM - 1; i++) {
|
||||
interval >>= 1;
|
||||
if (interval == 0) {
|
||||
return &g_periodic_qh_head[i];
|
||||
return &g_periodic_qh_head[bus->hcd.hcd_id][i];
|
||||
}
|
||||
}
|
||||
return &g_periodic_qh_head[EHCI_PERIOIDIC_QH_NUM - 1];
|
||||
return &g_periodic_qh_head[bus->hcd.hcd_id][EHCI_PERIOIDIC_QH_NUM - 1];
|
||||
}
|
||||
|
||||
static void ehci_qh_fill(struct ehci_qh_hw *qh,
|
||||
@@ -297,7 +297,7 @@ static void ehci_qtd_fill(struct ehci_qtd_hw *qtd, uint32_t bufaddr, size_t bufl
|
||||
qtd->total_len = buflen;
|
||||
}
|
||||
|
||||
static struct ehci_qh_hw *ehci_control_urb_init(struct usbh_urb *urb, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen)
|
||||
static struct ehci_qh_hw *ehci_control_urb_init(struct usbh_bus *bus, struct usbh_urb *urb, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen)
|
||||
{
|
||||
struct ehci_qh_hw *qh = NULL;
|
||||
struct ehci_qtd_hw *qtd_setup = NULL;
|
||||
@@ -306,24 +306,24 @@ static struct ehci_qh_hw *ehci_control_urb_init(struct usbh_urb *urb, struct usb
|
||||
uint32_t token;
|
||||
size_t flags;
|
||||
|
||||
qh = ehci_qh_alloc();
|
||||
qh = ehci_qh_alloc(bus);
|
||||
if (qh == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qtd_setup = ehci_qtd_alloc();
|
||||
qtd_setup = ehci_qtd_alloc(bus);
|
||||
if (buflen > 0) {
|
||||
qtd_data = ehci_qtd_alloc();
|
||||
qtd_data = ehci_qtd_alloc(bus);
|
||||
}
|
||||
|
||||
qtd_status = ehci_qtd_alloc();
|
||||
qtd_status = ehci_qtd_alloc(bus);
|
||||
if (qtd_status == NULL) {
|
||||
ehci_qh_free(qh);
|
||||
ehci_qh_free(bus, qh);
|
||||
if (qtd_setup) {
|
||||
ehci_qtd_free(qtd_setup);
|
||||
ehci_qtd_free(bus, qtd_setup);
|
||||
}
|
||||
if (qtd_data) {
|
||||
ehci_qtd_free(qtd_data);
|
||||
ehci_qtd_free(bus, qtd_data);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -397,7 +397,7 @@ static struct ehci_qh_hw *ehci_control_urb_init(struct usbh_urb *urb, struct usb
|
||||
qh->urb = urb;
|
||||
urb->hcpriv = qh;
|
||||
/* add qh into async list */
|
||||
ehci_qh_add_head(&g_async_qh_head, qh);
|
||||
ehci_qh_add_head(&g_async_qh_head[bus->hcd.hcd_id], qh);
|
||||
|
||||
EHCI_HCOR->usbcmd |= EHCI_USBCMD_ASEN;
|
||||
|
||||
@@ -405,7 +405,7 @@ static struct ehci_qh_hw *ehci_control_urb_init(struct usbh_urb *urb, struct usb
|
||||
return qh;
|
||||
}
|
||||
|
||||
static struct ehci_qh_hw *ehci_bulk_urb_init(struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen)
|
||||
static struct ehci_qh_hw *ehci_bulk_urb_init(struct usbh_bus *bus, struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen)
|
||||
{
|
||||
struct ehci_qh_hw *qh = NULL;
|
||||
struct ehci_qtd_hw *qtd = NULL;
|
||||
@@ -416,19 +416,19 @@ static struct ehci_qh_hw *ehci_bulk_urb_init(struct usbh_urb *urb, uint8_t *buff
|
||||
uint32_t token;
|
||||
size_t flags;
|
||||
|
||||
qh = ehci_qh_alloc();
|
||||
qh = ehci_qh_alloc(bus);
|
||||
if (qh == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < CONFIG_USB_EHCI_QTD_NUM; i++) {
|
||||
if (!g_ehci_hcd.ehci_qtd_used[i]) {
|
||||
if (!g_ehci_hcd[bus->hcd.hcd_id].ehci_qtd_used[i]) {
|
||||
qtd_num++;
|
||||
}
|
||||
}
|
||||
|
||||
if (qtd_num < ((buflen + 0x3fff) / 0x4000)) {
|
||||
ehci_qh_free(qh);
|
||||
ehci_qh_free(bus, qh);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -444,7 +444,7 @@ static struct ehci_qh_hw *ehci_bulk_urb_init(struct usbh_urb *urb, uint8_t *buff
|
||||
urb->hport->port);
|
||||
|
||||
while (buflen >= 0) {
|
||||
qtd = ehci_qtd_alloc();
|
||||
qtd = ehci_qtd_alloc(bus);
|
||||
|
||||
if (buflen > 0x4000) {
|
||||
xfer_len = 0x4000;
|
||||
@@ -504,7 +504,7 @@ static struct ehci_qh_hw *ehci_bulk_urb_init(struct usbh_urb *urb, uint8_t *buff
|
||||
qh->urb = urb;
|
||||
urb->hcpriv = qh;
|
||||
/* add qh into async list */
|
||||
ehci_qh_add_head(&g_async_qh_head, qh);
|
||||
ehci_qh_add_head(&g_async_qh_head[bus->hcd.hcd_id], qh);
|
||||
|
||||
EHCI_HCOR->usbcmd |= EHCI_USBCMD_ASEN;
|
||||
|
||||
@@ -512,7 +512,7 @@ static struct ehci_qh_hw *ehci_bulk_urb_init(struct usbh_urb *urb, uint8_t *buff
|
||||
return qh;
|
||||
}
|
||||
|
||||
static struct ehci_qh_hw *ehci_intr_urb_init(struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen)
|
||||
static struct ehci_qh_hw *ehci_intr_urb_init(struct usbh_bus *bus, struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen)
|
||||
{
|
||||
struct ehci_qh_hw *qh = NULL;
|
||||
struct ehci_qtd_hw *qtd = NULL;
|
||||
@@ -523,19 +523,19 @@ static struct ehci_qh_hw *ehci_intr_urb_init(struct usbh_urb *urb, uint8_t *buff
|
||||
uint32_t token;
|
||||
size_t flags;
|
||||
|
||||
qh = ehci_qh_alloc();
|
||||
qh = ehci_qh_alloc(bus);
|
||||
if (qh == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < CONFIG_USB_EHCI_QTD_NUM; i++) {
|
||||
if (!g_ehci_hcd.ehci_qtd_used[i]) {
|
||||
if (!g_ehci_hcd[bus->hcd.hcd_id].ehci_qtd_used[i]) {
|
||||
qtd_num++;
|
||||
}
|
||||
}
|
||||
|
||||
if (qtd_num < ((buflen + 0x3fff) / 0x4000)) {
|
||||
ehci_qh_free(qh);
|
||||
ehci_qh_free(bus, qh);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -551,7 +551,7 @@ static struct ehci_qh_hw *ehci_intr_urb_init(struct usbh_urb *urb, uint8_t *buff
|
||||
urb->hport->port);
|
||||
|
||||
while (buflen >= 0) {
|
||||
qtd = ehci_qtd_alloc();
|
||||
qtd = ehci_qtd_alloc(bus);
|
||||
|
||||
if (buflen > 0x4000) {
|
||||
xfer_len = 0x4000;
|
||||
@@ -612,9 +612,9 @@ static struct ehci_qh_hw *ehci_intr_urb_init(struct usbh_urb *urb, uint8_t *buff
|
||||
urb->hcpriv = qh;
|
||||
/* add qh into periodic list */
|
||||
if (urb->hport->speed == USB_SPEED_HIGH) {
|
||||
ehci_qh_add_head(ehci_get_periodic_qhead(urb->ep->bInterval), qh);
|
||||
ehci_qh_add_head(ehci_get_periodic_qhead(bus, urb->ep->bInterval), qh);
|
||||
} else {
|
||||
ehci_qh_add_head(ehci_get_periodic_qhead(urb->ep->bInterval * 8), qh);
|
||||
ehci_qh_add_head(ehci_get_periodic_qhead(bus, urb->ep->bInterval * 8), qh);
|
||||
}
|
||||
|
||||
EHCI_HCOR->usbcmd |= EHCI_USBCMD_PSEN;
|
||||
@@ -623,7 +623,7 @@ static struct ehci_qh_hw *ehci_intr_urb_init(struct usbh_urb *urb, uint8_t *buff
|
||||
return qh;
|
||||
}
|
||||
|
||||
static void ehci_urb_waitup(struct usbh_urb *urb)
|
||||
static void ehci_urb_waitup(struct usbh_bus *bus, struct usbh_urb *urb)
|
||||
{
|
||||
struct ehci_qh_hw *qh;
|
||||
|
||||
@@ -637,7 +637,7 @@ static void ehci_urb_waitup(struct usbh_urb *urb)
|
||||
urb->timeout = 0;
|
||||
usb_osal_sem_give(qh->waitsem);
|
||||
} else {
|
||||
ehci_qh_free(qh);
|
||||
ehci_qh_free(bus, qh);
|
||||
}
|
||||
|
||||
if (urb->complete) {
|
||||
@@ -649,7 +649,7 @@ static void ehci_urb_waitup(struct usbh_urb *urb)
|
||||
}
|
||||
}
|
||||
|
||||
static void ehci_qh_scan_qtds(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh)
|
||||
static void ehci_qh_scan_qtds(struct usbh_bus *bus, struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh)
|
||||
{
|
||||
struct ehci_qtd_hw *qtd;
|
||||
|
||||
@@ -660,13 +660,13 @@ static void ehci_qh_scan_qtds(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh)
|
||||
while (qtd) {
|
||||
qtd->urb->actual_length += (qtd->total_len - ((qtd->hw.token & QTD_TOKEN_NBYTES_MASK) >> QTD_TOKEN_NBYTES_SHIFT));
|
||||
|
||||
ehci_qtd_free(qtd);
|
||||
ehci_qtd_free(bus, qtd);
|
||||
qh->first_qtd = qtd->hw.next_qtd;
|
||||
qtd = EHCI_ADDR2QTD(qh->first_qtd);
|
||||
}
|
||||
}
|
||||
|
||||
static void ehci_check_qh(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh)
|
||||
static void ehci_check_qh(struct usbh_bus *bus, struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh)
|
||||
{
|
||||
struct usbh_urb *urb;
|
||||
struct ehci_qtd_hw *qtd;
|
||||
@@ -711,10 +711,10 @@ static void ehci_check_qh(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh)
|
||||
}
|
||||
}
|
||||
|
||||
ehci_qh_scan_qtds(qhead, qh);
|
||||
ehci_qh_scan_qtds(bus, qhead, qh);
|
||||
|
||||
if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) {
|
||||
ehci_urb_waitup(urb);
|
||||
ehci_urb_waitup(bus, urb);
|
||||
} else {
|
||||
qh->remove_in_iaad = 1;
|
||||
|
||||
@@ -722,7 +722,7 @@ static void ehci_check_qh(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh)
|
||||
}
|
||||
}
|
||||
|
||||
static void ehci_kill_qh(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh)
|
||||
static void ehci_kill_qh(struct usbh_bus *bus, struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh)
|
||||
{
|
||||
struct ehci_qtd_hw *qtd;
|
||||
|
||||
@@ -731,19 +731,19 @@ static void ehci_kill_qh(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh)
|
||||
qtd = EHCI_ADDR2QTD(qh->first_qtd);
|
||||
|
||||
while (qtd) {
|
||||
ehci_qtd_free(qtd);
|
||||
ehci_qtd_free(bus, qtd);
|
||||
qh->first_qtd = qtd->hw.next_qtd;
|
||||
qtd = EHCI_ADDR2QTD(qh->first_qtd);
|
||||
}
|
||||
}
|
||||
|
||||
static int usbh_reset_port(const uint8_t port)
|
||||
static int usbh_reset_port(struct usbh_bus *bus, const uint8_t port)
|
||||
{
|
||||
volatile uint32_t timeout = 0;
|
||||
uint32_t regval;
|
||||
|
||||
#if defined(CONFIG_USB_EHCI_HPMICRO) && CONFIG_USB_EHCI_HPMICRO
|
||||
if ((*(volatile uint32_t *)(CONFIG_HPM_USBH_BASE + 0x224) & 0xc0) == (2 << 6)) { /* Hardcode for hpm */
|
||||
if ((*(volatile uint32_t *)(bus->hcd.reg_base + 0x224) & 0xc0) == (2 << 6)) { /* Hardcode for hpm */
|
||||
EHCI_HCOR->portsc[port - 1] |= (1 << 29);
|
||||
} else {
|
||||
EHCI_HCOR->portsc[port - 1] &= ~(1 << 29);
|
||||
@@ -767,15 +767,15 @@ static int usbh_reset_port(const uint8_t port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usb_hc_low_level_init(void)
|
||||
__WEAK void usb_hc_low_level_init(struct usbh_bus *bus)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usb_hc_low_level2_init(void)
|
||||
__WEAK void usb_hc_low_level2_init(struct usbh_bus *bus)
|
||||
{
|
||||
}
|
||||
|
||||
int usb_hc_init(void)
|
||||
int usb_hc_init(struct usbh_bus *bus)
|
||||
{
|
||||
uint32_t interval;
|
||||
struct ehci_qh_hw *qh;
|
||||
@@ -783,7 +783,7 @@ int usb_hc_init(void)
|
||||
volatile uint32_t timeout = 0;
|
||||
uint32_t regval;
|
||||
|
||||
memset(&g_ehci_hcd, 0, sizeof(struct ehci_hcd));
|
||||
memset(&g_ehci_hcd[bus->hcd.hcd_id], 0, sizeof(struct ehci_hcd));
|
||||
|
||||
if (sizeof(struct ehci_qh_hw) % 32) {
|
||||
USB_LOG_ERR("struct ehci_qh_hw is not align 32\r\n");
|
||||
@@ -795,41 +795,41 @@ int usb_hc_init(void)
|
||||
}
|
||||
|
||||
for (uint8_t index = 0; index < CONFIG_USB_EHCI_QH_NUM; index++) {
|
||||
qh = &ehci_qh_pool[index];
|
||||
qh = &ehci_qh_pool[bus->hcd.hcd_id][index];
|
||||
qh->waitsem = usb_osal_sem_create(0);
|
||||
}
|
||||
|
||||
memset(&g_async_qh_head, 0, sizeof(struct ehci_qh_hw));
|
||||
g_async_qh_head.hw.hlp = QH_HLP_QH(&g_async_qh_head);
|
||||
g_async_qh_head.hw.epchar = QH_EPCHAR_H;
|
||||
g_async_qh_head.hw.overlay.next_qtd = QTD_LIST_END;
|
||||
g_async_qh_head.hw.overlay.alt_next_qtd = QTD_LIST_END;
|
||||
g_async_qh_head.hw.overlay.token = QTD_TOKEN_STATUS_HALTED;
|
||||
g_async_qh_head.first_qtd = QTD_LIST_END;
|
||||
memset(&g_async_qh_head[bus->hcd.hcd_id], 0, sizeof(struct ehci_qh_hw));
|
||||
g_async_qh_head[bus->hcd.hcd_id].hw.hlp = QH_HLP_QH(&g_async_qh_head[bus->hcd.hcd_id]);
|
||||
g_async_qh_head[bus->hcd.hcd_id].hw.epchar = QH_EPCHAR_H;
|
||||
g_async_qh_head[bus->hcd.hcd_id].hw.overlay.next_qtd = QTD_LIST_END;
|
||||
g_async_qh_head[bus->hcd.hcd_id].hw.overlay.alt_next_qtd = QTD_LIST_END;
|
||||
g_async_qh_head[bus->hcd.hcd_id].hw.overlay.token = QTD_TOKEN_STATUS_HALTED;
|
||||
g_async_qh_head[bus->hcd.hcd_id].first_qtd = QTD_LIST_END;
|
||||
|
||||
memset(g_framelist, 0, sizeof(uint32_t) * CONFIG_USB_EHCI_FRAME_LIST_SIZE);
|
||||
memset(g_framelist[bus->hcd.hcd_id], 0, sizeof(uint32_t) * CONFIG_USB_EHCI_FRAME_LIST_SIZE);
|
||||
|
||||
for (int i = EHCI_PERIOIDIC_QH_NUM - 1; i >= 0; i--) {
|
||||
memset(&g_periodic_qh_head[i], 0, sizeof(struct ehci_qh_hw));
|
||||
g_periodic_qh_head[i].hw.hlp = QH_HLP_END;
|
||||
g_periodic_qh_head[i].hw.epchar = QH_EPCAPS_SSMASK(1);
|
||||
g_periodic_qh_head[i].hw.overlay.next_qtd = QTD_LIST_END;
|
||||
g_periodic_qh_head[i].hw.overlay.alt_next_qtd = QTD_LIST_END;
|
||||
g_periodic_qh_head[i].hw.overlay.token = QTD_TOKEN_STATUS_HALTED;
|
||||
g_periodic_qh_head[i].first_qtd = QTD_LIST_END;
|
||||
memset(&g_periodic_qh_head[bus->hcd.hcd_id][i], 0, sizeof(struct ehci_qh_hw));
|
||||
g_periodic_qh_head[bus->hcd.hcd_id][i].hw.hlp = QH_HLP_END;
|
||||
g_periodic_qh_head[bus->hcd.hcd_id][i].hw.epchar = QH_EPCAPS_SSMASK(1);
|
||||
g_periodic_qh_head[bus->hcd.hcd_id][i].hw.overlay.next_qtd = QTD_LIST_END;
|
||||
g_periodic_qh_head[bus->hcd.hcd_id][i].hw.overlay.alt_next_qtd = QTD_LIST_END;
|
||||
g_periodic_qh_head[bus->hcd.hcd_id][i].hw.overlay.token = QTD_TOKEN_STATUS_HALTED;
|
||||
g_periodic_qh_head[bus->hcd.hcd_id][i].first_qtd = QTD_LIST_END;
|
||||
|
||||
interval = 1 << i;
|
||||
for (uint32_t j = interval - 1; j < CONFIG_USB_EHCI_FRAME_LIST_SIZE; j += interval) {
|
||||
if (g_framelist[j] == 0) {
|
||||
g_framelist[j] = QH_HLP_QH(&g_periodic_qh_head[i]);
|
||||
if (g_framelist[bus->hcd.hcd_id][j] == 0) {
|
||||
g_framelist[bus->hcd.hcd_id][j] = QH_HLP_QH(&g_periodic_qh_head[bus->hcd.hcd_id][i]);
|
||||
} else {
|
||||
qh = EHCI_ADDR2QH(g_framelist[j]);
|
||||
qh = EHCI_ADDR2QH(g_framelist[bus->hcd.hcd_id][j]);
|
||||
while (1) {
|
||||
if (qh == &g_periodic_qh_head[i]) {
|
||||
if (qh == &g_periodic_qh_head[bus->hcd.hcd_id][i]) {
|
||||
break;
|
||||
}
|
||||
if (qh->hw.hlp == QH_HLP_END) {
|
||||
qh->hw.hlp = QH_HLP_QH(&g_periodic_qh_head[i]);
|
||||
qh->hw.hlp = QH_HLP_QH(&g_periodic_qh_head[bus->hcd.hcd_id][i]);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -839,7 +839,7 @@ int usb_hc_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
usb_hc_low_level_init();
|
||||
usb_hc_low_level_init(bus);
|
||||
|
||||
EHCI_HCOR->usbcmd |= EHCI_USBCMD_HCRESET;
|
||||
while (EHCI_HCOR->usbcmd & EHCI_USBCMD_HCRESET) {
|
||||
@@ -850,19 +850,19 @@ int usb_hc_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
usb_hc_low_level2_init();
|
||||
usb_hc_low_level2_init(bus);
|
||||
|
||||
EHCI_HCOR->usbintr = 0;
|
||||
EHCI_HCOR->usbsts = EHCI_HCOR->usbsts;
|
||||
#if CONFIG_USB_EHCI_HCCR_BASE != 0
|
||||
#ifdef CONFIG_USB_EHCI_PRINT_HW_PARAM
|
||||
USB_LOG_INFO("EHCI HCIVERSION:%04x\r\n", (int)EHCI_HCCR->hciversion);
|
||||
USB_LOG_INFO("EHCI HCSPARAMS:%06x\r\n", (int)EHCI_HCCR->hcsparams);
|
||||
USB_LOG_INFO("EHCI HCCPARAMS:%04x\r\n", (int)EHCI_HCCR->hccparams);
|
||||
#endif
|
||||
/* Set the Current Asynchronous List Address. */
|
||||
EHCI_HCOR->asynclistaddr = EHCI_PTR2ADDR(&g_async_qh_head);
|
||||
EHCI_HCOR->asynclistaddr = EHCI_PTR2ADDR(&g_async_qh_head[bus->hcd.hcd_id]);
|
||||
/* Set the Periodic Frame List Base Address. */
|
||||
EHCI_HCOR->periodiclistbase = EHCI_PTR2ADDR(g_framelist);
|
||||
EHCI_HCOR->periodiclistbase = EHCI_PTR2ADDR(g_framelist[bus->hcd.hcd_id]);
|
||||
|
||||
regval = 0;
|
||||
#if CONFIG_USB_EHCI_FRAME_LIST_SIZE == 1024
|
||||
@@ -906,7 +906,7 @@ int usb_hc_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_hc_deinit(void)
|
||||
int usb_hc_deinit(struct usbh_bus *bus)
|
||||
{
|
||||
struct ehci_qh_hw *qh;
|
||||
|
||||
@@ -944,19 +944,19 @@ int usb_hc_deinit(void)
|
||||
EHCI_HCOR->usbsts = EHCI_HCOR->usbsts;
|
||||
|
||||
for (uint8_t index = 0; index < CONFIG_USB_EHCI_QH_NUM; index++) {
|
||||
qh = &ehci_qh_pool[index];
|
||||
qh = &ehci_qh_pool[bus->hcd.hcd_id][index];
|
||||
usb_osal_sem_delete(qh->waitsem);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t usbh_get_frame_number(void)
|
||||
uint16_t usbh_get_frame_number(struct usbh_bus *bus)
|
||||
{
|
||||
return (((EHCI_HCOR->frindex & EHCI_FRINDEX_MASK) >> 3) & 0x3ff);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
uint8_t nports;
|
||||
uint8_t port;
|
||||
@@ -1010,7 +1010,8 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
EHCI_HCOR->portsc[port - 1] |= EHCI_PORTSC_RESUME;
|
||||
usb_osal_msleep(20);
|
||||
EHCI_HCOR->portsc[port - 1] &= ~EHCI_PORTSC_RESUME;
|
||||
while (EHCI_HCOR->portsc[port - 1] & EHCI_PORTSC_RESUME) {}
|
||||
while (EHCI_HCOR->portsc[port - 1] & EHCI_PORTSC_RESUME) {
|
||||
}
|
||||
|
||||
temp = EHCI_HCOR->usbcmd;
|
||||
temp |= EHCI_USBCMD_ASEN;
|
||||
@@ -1018,7 +1019,8 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
temp |= EHCI_USBCMD_RUN;
|
||||
EHCI_HCOR->usbcmd = temp;
|
||||
|
||||
while ((EHCI_HCOR->usbcmd & EHCI_USBCMD_RUN) == 0) {}
|
||||
while ((EHCI_HCOR->usbcmd & EHCI_USBCMD_RUN) == 0) {
|
||||
}
|
||||
|
||||
case HUB_PORT_FEATURE_C_SUSPEND:
|
||||
break;
|
||||
@@ -1055,10 +1057,12 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
temp &= ~EHCI_USBCMD_RUN;
|
||||
EHCI_HCOR->usbcmd = temp;
|
||||
|
||||
while (EHCI_HCOR->usbcmd & EHCI_USBCMD_RUN) {}
|
||||
while (EHCI_HCOR->usbcmd & EHCI_USBCMD_RUN) {
|
||||
}
|
||||
|
||||
EHCI_HCOR->portsc[port - 1] |= EHCI_PORTSC_SUSPEND;
|
||||
while ((EHCI_HCOR->portsc[port - 1] & EHCI_PORTSC_SUSPEND) == 0) {}
|
||||
while ((EHCI_HCOR->portsc[port - 1] & EHCI_PORTSC_SUSPEND) == 0) {
|
||||
}
|
||||
break;
|
||||
case HUB_PORT_FEATURE_POWER:
|
||||
#ifdef CONFIG_USB_EHCI_PORT_POWER
|
||||
@@ -1066,7 +1070,7 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
#endif
|
||||
break;
|
||||
case HUB_PORT_FEATURE_RESET:
|
||||
usbh_reset_port(port);
|
||||
usbh_reset_port(bus, port);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1096,9 +1100,9 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
if (temp & EHCI_PORTSC_PE) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1130,11 +1134,14 @@ int usbh_submit_urb(struct usbh_urb *urb)
|
||||
int ret = 0;
|
||||
struct usbh_hub *hub;
|
||||
struct usbh_hubport *hport;
|
||||
struct usbh_bus *bus;
|
||||
|
||||
if (!urb || !urb->hport || !urb->ep) {
|
||||
if (!urb || !urb->hport || !urb->ep || !urb->hport->bus) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
bus = urb->hport->bus;
|
||||
|
||||
/* find active hubport in roothub */
|
||||
hport = urb->hport;
|
||||
hub = urb->hport->parent;
|
||||
@@ -1147,7 +1154,7 @@ int usbh_submit_urb(struct usbh_urb *urb)
|
||||
return -USB_ERR_NOTCONN;
|
||||
}
|
||||
|
||||
if ((urb->errorcode == -USB_ERR_BUSY) && (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) != USB_ENDPOINT_TYPE_ISOCHRONOUS)) {
|
||||
if (urb->errorcode == -USB_ERR_BUSY) {
|
||||
return -USB_ERR_BUSY;
|
||||
}
|
||||
|
||||
@@ -1161,21 +1168,21 @@ int usbh_submit_urb(struct usbh_urb *urb)
|
||||
|
||||
switch (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes)) {
|
||||
case USB_ENDPOINT_TYPE_CONTROL:
|
||||
qh = ehci_control_urb_init(urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
qh = ehci_control_urb_init(bus, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
if (qh == NULL) {
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
urb->hcpriv = qh;
|
||||
break;
|
||||
case USB_ENDPOINT_TYPE_BULK:
|
||||
qh = ehci_bulk_urb_init(urb, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
qh = ehci_bulk_urb_init(bus, urb, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
if (qh == NULL) {
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
urb->hcpriv = qh;
|
||||
break;
|
||||
case USB_ENDPOINT_TYPE_INTERRUPT:
|
||||
qh = ehci_intr_urb_init(urb, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
qh = ehci_intr_urb_init(bus, urb, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
if (qh == NULL) {
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
@@ -1183,7 +1190,7 @@ int usbh_submit_urb(struct usbh_urb *urb)
|
||||
break;
|
||||
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
|
||||
#ifdef CONFIG_USB_EHCI_ISO
|
||||
ret = ehci_iso_urb_init(urb);
|
||||
ret = ehci_iso_urb_init(bus, urb);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
@@ -1199,7 +1206,7 @@ int usbh_submit_urb(struct usbh_urb *urb)
|
||||
urb->timeout = 0;
|
||||
ret = urb->errorcode;
|
||||
/* we can free qh when waitsem is done */
|
||||
ehci_qh_free(qh);
|
||||
ehci_qh_free(bus, qh);
|
||||
}
|
||||
return ret;
|
||||
errout_timeout:
|
||||
@@ -1211,32 +1218,35 @@ errout_timeout:
|
||||
int usbh_kill_urb(struct usbh_urb *urb)
|
||||
{
|
||||
struct ehci_qh_hw *qh;
|
||||
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();
|
||||
|
||||
EHCI_HCOR->usbcmd &= ~(EHCI_USBCMD_PSEN | EHCI_USBCMD_ASEN);
|
||||
|
||||
if ((USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_CONTROL) || (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_BULK)) {
|
||||
qh = EHCI_ADDR2QH(g_async_qh_head.hw.hlp);
|
||||
while ((qh != &g_async_qh_head) && qh) {
|
||||
qh = EHCI_ADDR2QH(g_async_qh_head[bus->hcd.hcd_id].hw.hlp);
|
||||
while ((qh != &g_async_qh_head[bus->hcd.hcd_id]) && qh) {
|
||||
if (qh->urb == urb) {
|
||||
ehci_kill_qh(&g_async_qh_head, qh);
|
||||
ehci_kill_qh(bus, &g_async_qh_head[bus->hcd.hcd_id], qh);
|
||||
}
|
||||
qh = EHCI_ADDR2QH(qh->hw.hlp);
|
||||
}
|
||||
} else if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) {
|
||||
qh = EHCI_ADDR2QH(g_periodic_qh_head[EHCI_PERIOIDIC_QH_NUM - 1].hw.hlp);
|
||||
qh = EHCI_ADDR2QH(g_periodic_qh_head[bus->hcd.hcd_id][EHCI_PERIOIDIC_QH_NUM - 1].hw.hlp);
|
||||
while (qh) {
|
||||
if (qh->urb == urb) {
|
||||
if (urb->hport->speed == USB_SPEED_HIGH) {
|
||||
ehci_kill_qh(ehci_get_periodic_qhead(urb->ep->bInterval), qh);
|
||||
ehci_kill_qh(bus, ehci_get_periodic_qhead(bus, urb->ep->bInterval), qh);
|
||||
} else {
|
||||
ehci_kill_qh(ehci_get_periodic_qhead(urb->ep->bInterval * 8), qh);
|
||||
ehci_kill_qh(bus, ehci_get_periodic_qhead(bus, urb->ep->bInterval * 8), qh);
|
||||
}
|
||||
}
|
||||
qh = EHCI_ADDR2QH(qh->hw.hlp);
|
||||
@@ -1261,7 +1271,7 @@ int usbh_kill_urb(struct usbh_urb *urb)
|
||||
urb->errorcode = -USB_ERR_SHUTDOWN;
|
||||
usb_osal_sem_give(qh->waitsem);
|
||||
} else {
|
||||
ehci_qh_free(qh);
|
||||
ehci_qh_free(bus, qh);
|
||||
}
|
||||
|
||||
usb_osal_leave_critical_section(flags);
|
||||
@@ -1269,37 +1279,37 @@ int usbh_kill_urb(struct usbh_urb *urb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ehci_scan_async_list(void)
|
||||
static void ehci_scan_async_list(struct usbh_bus *bus)
|
||||
{
|
||||
struct ehci_qh_hw *qh;
|
||||
|
||||
qh = EHCI_ADDR2QH(g_async_qh_head.hw.hlp);
|
||||
while ((qh != &g_async_qh_head) && qh) {
|
||||
qh = EHCI_ADDR2QH(g_async_qh_head[bus->hcd.hcd_id].hw.hlp);
|
||||
while ((qh != &g_async_qh_head[bus->hcd.hcd_id]) && qh) {
|
||||
if (qh->urb) {
|
||||
ehci_check_qh(&g_async_qh_head, qh);
|
||||
ehci_check_qh(bus, &g_async_qh_head[bus->hcd.hcd_id], qh);
|
||||
}
|
||||
qh = EHCI_ADDR2QH(qh->hw.hlp);
|
||||
}
|
||||
}
|
||||
|
||||
static void ehci_scan_periodic_list(void)
|
||||
static void ehci_scan_periodic_list(struct usbh_bus *bus)
|
||||
{
|
||||
struct ehci_qh_hw *qh;
|
||||
|
||||
qh = EHCI_ADDR2QH(g_periodic_qh_head[EHCI_PERIOIDIC_QH_NUM - 1].hw.hlp);
|
||||
qh = EHCI_ADDR2QH(g_periodic_qh_head[bus->hcd.hcd_id][EHCI_PERIOIDIC_QH_NUM - 1].hw.hlp);
|
||||
while (qh) {
|
||||
if (qh->urb) {
|
||||
if (qh->urb->hport->speed == USB_SPEED_HIGH) {
|
||||
ehci_check_qh(ehci_get_periodic_qhead(qh->urb->ep->bInterval), qh);
|
||||
ehci_check_qh(bus, ehci_get_periodic_qhead(bus, qh->urb->ep->bInterval), qh);
|
||||
} else {
|
||||
ehci_check_qh(ehci_get_periodic_qhead(qh->urb->ep->bInterval * 8), qh);
|
||||
ehci_check_qh(bus, ehci_get_periodic_qhead(bus, qh->urb->ep->bInterval * 8), qh);
|
||||
}
|
||||
}
|
||||
qh = EHCI_ADDR2QH(qh->hw.hlp);
|
||||
}
|
||||
}
|
||||
|
||||
void USBH_IRQHandler(void)
|
||||
void USBH_IRQHandler(struct usbh_bus *bus)
|
||||
{
|
||||
uint32_t usbsts;
|
||||
|
||||
@@ -1307,18 +1317,18 @@ void USBH_IRQHandler(void)
|
||||
EHCI_HCOR->usbsts = usbsts;
|
||||
|
||||
if (usbsts & EHCI_USBSTS_INT) {
|
||||
ehci_scan_async_list();
|
||||
ehci_scan_periodic_list();
|
||||
ehci_scan_async_list(bus);
|
||||
ehci_scan_periodic_list(bus);
|
||||
#ifdef CONFIG_USB_EHCI_ISO
|
||||
ehci_scan_isochronous_list();
|
||||
ehci_scan_isochronous_list(bus);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (usbsts & EHCI_USBSTS_ERR) {
|
||||
ehci_scan_async_list();
|
||||
ehci_scan_periodic_list();
|
||||
ehci_scan_async_list(bus);
|
||||
ehci_scan_periodic_list(bus);
|
||||
#ifdef CONFIG_USB_EHCI_ISO
|
||||
ehci_scan_isochronous_list();
|
||||
ehci_scan_isochronous_list(bus);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1330,30 +1340,31 @@ void USBH_IRQHandler(void)
|
||||
if ((portsc & EHCI_PORTSC_CCS) == EHCI_PORTSC_CCS) {
|
||||
} else {
|
||||
for (uint8_t index = 0; index < CONFIG_USB_EHCI_QH_NUM; index++) {
|
||||
g_ehci_hcd.ehci_qh_used[index] = false;
|
||||
g_ehci_hcd[bus->hcd.hcd_id].ehci_qh_used[index] = false;
|
||||
}
|
||||
for (uint8_t index = 0; index < CONFIG_USB_EHCI_QTD_NUM; index++) {
|
||||
g_ehci_hcd.ehci_qtd_used[index] = false;
|
||||
g_ehci_hcd[bus->hcd.hcd_id].ehci_qtd_used[index] = false;
|
||||
}
|
||||
for (uint8_t index = 0; index < CONFIG_USB_EHCI_ITD_NUM; index++) {
|
||||
g_ehci_hcd.ehci_itd_used[index] = false;
|
||||
g_ehci_hcd[bus->hcd.hcd_id].ehci_itd_used[index] = false;
|
||||
}
|
||||
}
|
||||
|
||||
usbh_roothub_thread_wakeup(port + 1);
|
||||
bus->hcd.roothub.int_buffer[0] |= (1 << (port + 1));
|
||||
usbh_hub_thread_wakeup(&bus->hcd.roothub);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (usbsts & EHCI_USBSTS_IAA) {
|
||||
for (uint8_t index = 0; index < CONFIG_USB_EHCI_QH_NUM; index++) {
|
||||
struct ehci_qh_hw *qh = &ehci_qh_pool[index];
|
||||
if (g_ehci_hcd.ehci_qh_used[index] && qh->remove_in_iaad) {
|
||||
ehci_urb_waitup(qh->urb);
|
||||
struct ehci_qh_hw *qh = &ehci_qh_pool[bus->hcd.hcd_id][index];
|
||||
if (g_ehci_hcd[bus->hcd.hcd_id].ehci_qh_used[index] && qh->remove_in_iaad) {
|
||||
ehci_urb_waitup(bus, qh->urb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (usbsts & EHCI_USBSTS_FATAL) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,15 +14,7 @@
|
||||
#define HWREGB(x) \
|
||||
(*((volatile uint8_t *)(x)))
|
||||
|
||||
#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
|
||||
|
||||
#define USB_BASE USBH_BASE
|
||||
#define USB_BASE (bus->hcd.reg_base)
|
||||
|
||||
#if CONFIG_USBHOST_PIPE_NUM != 4
|
||||
#error musb host ip only supports 4 pipe num
|
||||
@@ -148,6 +140,7 @@ struct musb_pipe {
|
||||
uint8_t chidx;
|
||||
bool inuse;
|
||||
uint32_t xfrd;
|
||||
volatile uint8_t ep0_state;
|
||||
usb_osal_sem_t waitsem;
|
||||
struct usbh_urb *urb;
|
||||
};
|
||||
@@ -157,23 +150,21 @@ struct musb_hcd {
|
||||
volatile bool port_pec;
|
||||
volatile bool port_pe;
|
||||
struct musb_pipe pipe_pool[CONFIG_USBHOST_PIPE_NUM];
|
||||
} g_musb_hcd;
|
||||
|
||||
static volatile uint8_t usb_ep0_state = USB_EP0_STATE_SETUP;
|
||||
} g_musb_hcd[CONFIG_USBHOST_MAX_BUS];
|
||||
|
||||
/* get current active ep */
|
||||
static uint8_t musb_get_active_ep(void)
|
||||
static uint8_t musb_get_active_ep(struct usbh_bus *bus)
|
||||
{
|
||||
return HWREGB(USB_BASE + MUSB_EPIDX_OFFSET);
|
||||
}
|
||||
|
||||
/* set the active ep */
|
||||
static void musb_set_active_ep(uint8_t ep_index)
|
||||
static void musb_set_active_ep(struct usbh_bus *bus, uint8_t ep_index)
|
||||
{
|
||||
HWREGB(USB_BASE + MUSB_EPIDX_OFFSET) = ep_index;
|
||||
}
|
||||
|
||||
static void musb_fifo_flush(uint8_t ep)
|
||||
static void musb_fifo_flush(struct usbh_bus *bus, uint8_t ep)
|
||||
{
|
||||
uint8_t ep_idx = ep & 0x7f;
|
||||
if (ep_idx == 0) {
|
||||
@@ -190,7 +181,7 @@ static void musb_fifo_flush(uint8_t ep)
|
||||
}
|
||||
}
|
||||
|
||||
static void musb_write_packet(uint8_t ep_idx, uint8_t *buffer, uint16_t len)
|
||||
static void musb_write_packet(struct usbh_bus *bus, uint8_t ep_idx, uint8_t *buffer, uint16_t len)
|
||||
{
|
||||
uint32_t *buf32;
|
||||
uint8_t *buf8;
|
||||
@@ -221,7 +212,7 @@ static void musb_write_packet(uint8_t ep_idx, uint8_t *buffer, uint16_t len)
|
||||
}
|
||||
}
|
||||
|
||||
static void musb_read_packet(uint8_t ep_idx, uint8_t *buffer, uint16_t len)
|
||||
static void musb_read_packet(struct usbh_bus *bus, uint8_t ep_idx, uint8_t *buffer, uint16_t len)
|
||||
{
|
||||
uint32_t *buf32;
|
||||
uint8_t *buf8;
|
||||
@@ -252,13 +243,13 @@ static void musb_read_packet(uint8_t ep_idx, uint8_t *buffer, uint16_t len)
|
||||
}
|
||||
}
|
||||
|
||||
void musb_control_urb_init(uint8_t chidx, struct usbh_urb *urb, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen)
|
||||
void musb_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)
|
||||
{
|
||||
uint8_t old_ep_index;
|
||||
uint8_t speed = USB_TXTYPE1_SPEED_FULL;
|
||||
|
||||
old_ep_index = musb_get_active_ep();
|
||||
musb_set_active_ep(chidx);
|
||||
old_ep_index = musb_get_active_ep(bus);
|
||||
musb_set_active_ep(bus, chidx);
|
||||
|
||||
if (urb->hport->speed == USB_SPEED_HIGH) {
|
||||
speed = USB_TYPE0_SPEED_HIGH;
|
||||
@@ -273,18 +264,18 @@ void musb_control_urb_init(uint8_t chidx, struct usbh_urb *urb, struct usb_setup
|
||||
HWREGB(USB_TXHUBADDR_BASE(chidx)) = 0;
|
||||
HWREGB(USB_TXHUBPORT_BASE(chidx)) = 0;
|
||||
|
||||
musb_write_packet(chidx, (uint8_t *)setup, 8);
|
||||
musb_write_packet(bus, chidx, (uint8_t *)setup, 8);
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_CSRL0_TXRDY | USB_CSRL0_SETUP;
|
||||
musb_set_active_ep(old_ep_index);
|
||||
musb_set_active_ep(bus, old_ep_index);
|
||||
}
|
||||
|
||||
void musb_bulk_urb_init(uint8_t chidx, struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen)
|
||||
void musb_bulk_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen)
|
||||
{
|
||||
uint8_t old_ep_index;
|
||||
uint8_t speed = USB_TXTYPE1_SPEED_FULL;
|
||||
|
||||
old_ep_index = musb_get_active_ep();
|
||||
musb_set_active_ep(chidx);
|
||||
old_ep_index = musb_get_active_ep(bus);
|
||||
musb_set_active_ep(bus, chidx);
|
||||
|
||||
if (urb->hport->speed == USB_SPEED_HIGH) {
|
||||
speed = USB_TXTYPE1_SPEED_HIGH;
|
||||
@@ -315,23 +306,23 @@ void musb_bulk_urb_init(uint8_t chidx, struct usbh_urb *urb, uint8_t *buffer, ui
|
||||
buflen = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
|
||||
}
|
||||
|
||||
musb_write_packet(chidx, buffer, buflen);
|
||||
musb_write_packet(bus, chidx, buffer, buflen);
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) &= ~USB_TXCSRH1_MODE;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) |= USB_TXCSRH1_MODE;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_TXCSRL1_TXRDY;
|
||||
|
||||
HWREGH(USB_BASE + MUSB_TXIE_OFFSET) |= (1 << chidx);
|
||||
}
|
||||
musb_set_active_ep(old_ep_index);
|
||||
musb_set_active_ep(bus, old_ep_index);
|
||||
}
|
||||
|
||||
void musb_intr_urb_init(uint8_t chidx, struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen)
|
||||
void musb_intr_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen)
|
||||
{
|
||||
uint8_t old_ep_index;
|
||||
uint8_t speed = USB_TXTYPE1_SPEED_FULL;
|
||||
|
||||
old_ep_index = musb_get_active_ep();
|
||||
musb_set_active_ep(chidx);
|
||||
old_ep_index = musb_get_active_ep(bus);
|
||||
musb_set_active_ep(bus, chidx);
|
||||
|
||||
if (urb->hport->speed == USB_SPEED_HIGH) {
|
||||
speed = USB_TXTYPE1_SPEED_HIGH;
|
||||
@@ -362,28 +353,28 @@ void musb_intr_urb_init(uint8_t chidx, struct usbh_urb *urb, uint8_t *buffer, ui
|
||||
buflen = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
|
||||
}
|
||||
|
||||
musb_write_packet(chidx, buffer, buflen);
|
||||
musb_write_packet(bus, chidx, buffer, buflen);
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) &= ~USB_TXCSRH1_MODE;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) |= USB_TXCSRH1_MODE;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_TXCSRL1_TXRDY;
|
||||
|
||||
HWREGH(USB_BASE + MUSB_TXIE_OFFSET) |= (1 << chidx);
|
||||
}
|
||||
musb_set_active_ep(old_ep_index);
|
||||
musb_set_active_ep(bus, old_ep_index);
|
||||
}
|
||||
|
||||
static int usbh_reset_port(const uint8_t port)
|
||||
static int usbh_reset_port(struct usbh_bus *bus, const uint8_t port)
|
||||
{
|
||||
g_musb_hcd.port_pe = 0;
|
||||
g_musb_hcd[bus->hcd.hcd_id].port_pe = 0;
|
||||
HWREGB(USB_BASE + MUSB_POWER_OFFSET) |= USB_POWER_RESET;
|
||||
usb_osal_msleep(20);
|
||||
HWREGB(USB_BASE + MUSB_POWER_OFFSET) &= ~(USB_POWER_RESET);
|
||||
usb_osal_msleep(20);
|
||||
g_musb_hcd.port_pe = 1;
|
||||
g_musb_hcd[bus->hcd.hcd_id].port_pe = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t usbh_get_port_speed(const uint8_t port)
|
||||
static uint8_t usbh_get_port_speed(struct usbh_bus *bus, const uint8_t port)
|
||||
{
|
||||
uint8_t speed = USB_SPEED_UNKNOWN;
|
||||
|
||||
@@ -403,8 +394,8 @@ static int musb_pipe_alloc(void)
|
||||
int chidx;
|
||||
|
||||
for (chidx = 1; chidx < CONFIG_USBHOST_PIPE_NUM; chidx++) {
|
||||
if (!g_musb_hcd.pipe_pool[chidx].inuse) {
|
||||
g_musb_hcd.pipe_pool[chidx].inuse = true;
|
||||
if (!g_musb_hcd[bus->hcd.hcd_id].pipe_pool[chidx].inuse) {
|
||||
g_musb_hcd[bus->hcd.hcd_id].pipe_pool[chidx].inuse = true;
|
||||
return chidx;
|
||||
}
|
||||
}
|
||||
@@ -420,24 +411,24 @@ static void musb_pipe_free(struct musb_pipe *pipe)
|
||||
#endif
|
||||
}
|
||||
|
||||
__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)
|
||||
{
|
||||
uint8_t regval;
|
||||
uint32_t fifo_offset = 0;
|
||||
|
||||
memset(&g_musb_hcd, 0, sizeof(struct musb_hcd));
|
||||
memset(&g_musb_hcd[bus->hcd.hcd_id], 0, sizeof(struct musb_hcd));
|
||||
|
||||
for (uint8_t i = 0; i < CONFIG_USBHOST_PIPE_NUM; i++) {
|
||||
g_musb_hcd.pipe_pool[i].waitsem = usb_osal_sem_create(0);
|
||||
g_musb_hcd[bus->hcd.hcd_id].pipe_pool[i].waitsem = usb_osal_sem_create(0);
|
||||
}
|
||||
|
||||
usb_hc_low_level_init();
|
||||
usb_hc_low_level_init(bus);
|
||||
|
||||
musb_set_active_ep(0);
|
||||
musb_set_active_ep(bus, 0);
|
||||
HWREGB(USB_BASE + MUSB_IND_TXINTERVAL_OFFSET) = 0;
|
||||
HWREGB(USB_BASE + MUSB_TXFIFOSZ_OFFSET) = USB_TXFIFOSZ_SIZE_64;
|
||||
HWREGH(USB_BASE + MUSB_TXFIFOADD_OFFSET) = 0;
|
||||
@@ -446,7 +437,7 @@ int usb_hc_init(void)
|
||||
fifo_offset += 64;
|
||||
|
||||
for (uint8_t i = 1; i < CONIFG_USB_MUSB_PIPE_NUM; i++) {
|
||||
musb_set_active_ep(i);
|
||||
musb_set_active_ep(bus, i);
|
||||
HWREGB(USB_BASE + MUSB_TXFIFOSZ_OFFSET) = USB_TXFIFOSZ_SIZE_512;
|
||||
HWREGH(USB_BASE + MUSB_TXFIFOADD_OFFSET) = fifo_offset;
|
||||
HWREGB(USB_BASE + MUSB_RXFIFOSZ_OFFSET) = USB_TXFIFOSZ_SIZE_512;
|
||||
@@ -474,7 +465,7 @@ int usb_hc_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_hc_deinit(void)
|
||||
int usb_hc_deinit(struct usbh_bus *bus)
|
||||
{
|
||||
HWREGB(USB_BASE + MUSB_IE_OFFSET) = 0;
|
||||
HWREGH(USB_BASE + MUSB_TXIE_OFFSET) = 0;
|
||||
@@ -484,13 +475,13 @@ int usb_hc_deinit(void)
|
||||
HWREGB(USB_BASE + MUSB_DEVCTL_OFFSET) &= ~USB_DEVCTL_SESSION;
|
||||
|
||||
for (uint8_t i = 0; i < CONFIG_USBHOST_PIPE_NUM; i++) {
|
||||
usb_osal_sem_delete(g_musb_hcd.pipe_pool[i].waitsem);
|
||||
usb_osal_sem_delete(g_musb_hcd[bus->hcd.hcd_id].pipe_pool[i].waitsem);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
uint8_t nports;
|
||||
uint8_t port;
|
||||
@@ -544,10 +535,10 @@ 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_musb_hcd.port_csc = 0;
|
||||
g_musb_hcd[bus->hcd.hcd_id].port_csc = 0;
|
||||
break;
|
||||
case HUB_PORT_FEATURE_C_ENABLE:
|
||||
g_musb_hcd.port_pec = 0;
|
||||
g_musb_hcd[bus->hcd.hcd_id].port_pec = 0;
|
||||
break;
|
||||
case HUB_PORT_FEATURE_C_OVER_CURREN:
|
||||
break;
|
||||
@@ -568,7 +559,7 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
case HUB_PORT_FEATURE_POWER:
|
||||
break;
|
||||
case HUB_PORT_FEATURE_RESET:
|
||||
usbh_reset_port(port);
|
||||
usbh_reset_port(bus, port);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -581,19 +572,19 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
}
|
||||
|
||||
status = 0;
|
||||
if (g_musb_hcd.port_csc) {
|
||||
if (g_musb_hcd[bus->hcd.hcd_id].port_csc) {
|
||||
status |= (1 << HUB_PORT_FEATURE_C_CONNECTION);
|
||||
}
|
||||
if (g_musb_hcd.port_pec) {
|
||||
if (g_musb_hcd[bus->hcd.hcd_id].port_pec) {
|
||||
status |= (1 << HUB_PORT_FEATURE_C_ENABLE);
|
||||
}
|
||||
|
||||
if (g_musb_hcd.port_pe) {
|
||||
if (g_musb_hcd[bus->hcd.hcd_id].port_pe) {
|
||||
status |= (1 << HUB_PORT_FEATURE_CONNECTION);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -610,11 +601,12 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
int usbh_submit_urb(struct usbh_urb *urb)
|
||||
{
|
||||
struct musb_pipe *pipe;
|
||||
struct usbh_bus *bus;
|
||||
int chidx;
|
||||
size_t flags;
|
||||
int ret = 0;
|
||||
|
||||
if (!urb || !urb->hport || !urb->ep) {
|
||||
if (!urb || !urb->hport || !urb->ep || !urb->hport->bus) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
@@ -626,6 +618,8 @@ int usbh_submit_urb(struct usbh_urb *urb)
|
||||
return -USB_ERR_BUSY;
|
||||
}
|
||||
|
||||
bus = urb->hport->bus;
|
||||
|
||||
flags = usb_osal_enter_critical_section();
|
||||
|
||||
if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_CONTROL) {
|
||||
@@ -638,7 +632,7 @@ int usbh_submit_urb(struct usbh_urb *urb)
|
||||
}
|
||||
}
|
||||
|
||||
pipe = &g_musb_hcd.pipe_pool[chidx];
|
||||
pipe = &g_musb_hcd[bus->hcd.hcd_id].pipe_pool[chidx];
|
||||
pipe->chidx = chidx;
|
||||
pipe->urb = urb;
|
||||
|
||||
@@ -650,17 +644,17 @@ int usbh_submit_urb(struct usbh_urb *urb)
|
||||
|
||||
switch (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes)) {
|
||||
case USB_ENDPOINT_TYPE_CONTROL:
|
||||
usb_ep0_state = USB_EP0_STATE_SETUP;
|
||||
musb_control_urb_init(0, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
pipe->ep0_state = USB_EP0_STATE_SETUP;
|
||||
musb_control_urb_init(bus, 0, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
break;
|
||||
case USB_ENDPOINT_TYPE_BULK:
|
||||
musb_bulk_urb_init(chidx, urb, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
musb_bulk_urb_init(bus, chidx, urb, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
break;
|
||||
case USB_ENDPOINT_TYPE_INTERRUPT:
|
||||
musb_intr_urb_init(chidx, urb, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
musb_intr_urb_init(bus, chidx, urb, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
break;
|
||||
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
|
||||
break;
|
||||
return -USB_ERR_NOTSUPP;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -687,12 +681,15 @@ errout_timeout:
|
||||
int usbh_kill_urb(struct usbh_urb *urb)
|
||||
{
|
||||
struct musb_pipe *pipe;
|
||||
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();
|
||||
|
||||
pipe = (struct musb_pipe *)urb->hcpriv;
|
||||
@@ -735,59 +732,59 @@ static void musb_urb_waitup(struct usbh_urb *urb)
|
||||
}
|
||||
}
|
||||
|
||||
void handle_ep0(void)
|
||||
void handle_ep0(struct usbh_bus *bus)
|
||||
{
|
||||
uint8_t ep0_status;
|
||||
struct musb_pipe *pipe;
|
||||
struct usbh_urb *urb;
|
||||
uint32_t size;
|
||||
|
||||
pipe = (struct musb_pipe *)&g_musb_hcd.pipe_pool[0];
|
||||
pipe = (struct musb_pipe *)&g_musb_hcd[bus->hcd.hcd_id].pipe_pool[0];
|
||||
urb = pipe->urb;
|
||||
if (urb == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
musb_set_active_ep(0);
|
||||
musb_set_active_ep(bus, 0);
|
||||
ep0_status = HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET);
|
||||
if (ep0_status & USB_CSRL0_STALLED) {
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_CSRL0_STALLED;
|
||||
usb_ep0_state = USB_EP0_STATE_SETUP;
|
||||
pipe->ep0_state = USB_EP0_STATE_SETUP;
|
||||
urb->errorcode = -USB_ERR_STALL;
|
||||
musb_urb_waitup(urb);
|
||||
return;
|
||||
}
|
||||
if (ep0_status & USB_CSRL0_ERROR) {
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_CSRL0_ERROR;
|
||||
musb_fifo_flush(0);
|
||||
usb_ep0_state = USB_EP0_STATE_SETUP;
|
||||
musb_fifo_flush(bus, 0);
|
||||
pipe->ep0_state = USB_EP0_STATE_SETUP;
|
||||
urb->errorcode = -USB_ERR_IO;
|
||||
musb_urb_waitup(urb);
|
||||
return;
|
||||
}
|
||||
if (ep0_status & USB_CSRL0_STALL) {
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_CSRL0_STALL;
|
||||
usb_ep0_state = USB_EP0_STATE_SETUP;
|
||||
pipe->ep0_state = USB_EP0_STATE_SETUP;
|
||||
urb->errorcode = -USB_ERR_STALL;
|
||||
musb_urb_waitup(urb);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (usb_ep0_state) {
|
||||
switch (pipe->ep0_state) {
|
||||
case USB_EP0_STATE_SETUP:
|
||||
urb->actual_length += 8;
|
||||
if (urb->transfer_buffer_length) {
|
||||
if (urb->setup->bmRequestType & 0x80) {
|
||||
usb_ep0_state = USB_EP0_STATE_IN_DATA;
|
||||
pipe->ep0_state = USB_EP0_STATE_IN_DATA;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_CSRL0_REQPKT;
|
||||
} else {
|
||||
usb_ep0_state = USB_EP0_STATE_OUT_DATA;
|
||||
pipe->ep0_state = USB_EP0_STATE_OUT_DATA;
|
||||
size = urb->transfer_buffer_length;
|
||||
if (size > USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) {
|
||||
size = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
|
||||
}
|
||||
|
||||
musb_write_packet(0, urb->transfer_buffer, size);
|
||||
musb_write_packet(bus, 0, urb->transfer_buffer, size);
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_CSRL0_TXRDY;
|
||||
|
||||
urb->transfer_buffer += size;
|
||||
@@ -795,7 +792,7 @@ void handle_ep0(void)
|
||||
urb->actual_length += size;
|
||||
}
|
||||
} else {
|
||||
usb_ep0_state = USB_EP0_STATE_IN_STATUS;
|
||||
pipe->ep0_state = USB_EP0_STATE_IN_STATUS;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = (USB_CSRL0_REQPKT | USB_CSRL0_STATUS);
|
||||
}
|
||||
break;
|
||||
@@ -807,14 +804,14 @@ void handle_ep0(void)
|
||||
}
|
||||
|
||||
size = MIN(size, HWREGH(USB_BASE + MUSB_IND_RXCOUNT_OFFSET));
|
||||
musb_read_packet(0, urb->transfer_buffer, size);
|
||||
musb_read_packet(bus, 0, urb->transfer_buffer, size);
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_CSRL0_RXRDY;
|
||||
urb->transfer_buffer += size;
|
||||
urb->transfer_buffer_length -= size;
|
||||
urb->actual_length += size;
|
||||
|
||||
if ((size < USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) || (urb->transfer_buffer_length == 0)) {
|
||||
usb_ep0_state = USB_EP0_STATE_OUT_STATUS;
|
||||
pipe->ep0_state = USB_EP0_STATE_OUT_STATUS;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = (USB_CSRL0_TXRDY | USB_CSRL0_STATUS);
|
||||
} else {
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_CSRL0_REQPKT;
|
||||
@@ -828,14 +825,14 @@ void handle_ep0(void)
|
||||
size = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
|
||||
}
|
||||
|
||||
musb_write_packet(0, urb->transfer_buffer, size);
|
||||
musb_write_packet(bus, 0, urb->transfer_buffer, size);
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_CSRL0_TXRDY;
|
||||
|
||||
urb->transfer_buffer += size;
|
||||
urb->transfer_buffer_length -= size;
|
||||
urb->actual_length += size;
|
||||
} else {
|
||||
usb_ep0_state = USB_EP0_STATE_IN_STATUS;
|
||||
pipe->ep0_state = USB_EP0_STATE_IN_STATUS;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = (USB_CSRL0_REQPKT | USB_CSRL0_STATUS);
|
||||
}
|
||||
break;
|
||||
@@ -853,7 +850,7 @@ void handle_ep0(void)
|
||||
}
|
||||
}
|
||||
|
||||
void USBH_IRQHandler(void)
|
||||
void USBH_IRQHandler(struct usbh_bus *bus)
|
||||
{
|
||||
uint32_t is;
|
||||
uint32_t txis;
|
||||
@@ -871,20 +868,22 @@ void USBH_IRQHandler(void)
|
||||
|
||||
HWREGB(USB_BASE + MUSB_IS_OFFSET) = is;
|
||||
|
||||
old_ep_idx = musb_get_active_ep();
|
||||
old_ep_idx = musb_get_active_ep(bus);
|
||||
|
||||
if (is & USB_IS_CONN) {
|
||||
g_musb_hcd.port_csc = 1;
|
||||
g_musb_hcd.port_pec = 1;
|
||||
g_musb_hcd.port_pe = 1;
|
||||
usbh_roothub_thread_wakeup(1);
|
||||
g_musb_hcd[bus->hcd.hcd_id].port_csc = 1;
|
||||
g_musb_hcd[bus->hcd.hcd_id].port_pec = 1;
|
||||
g_musb_hcd[bus->hcd.hcd_id].port_pe = 1;
|
||||
bus->hcd.roothub.int_buffer[0] = (1 << 1);
|
||||
usbh_hub_thread_wakeup(&bus->hcd.roothub);
|
||||
}
|
||||
|
||||
if (is & USB_IS_DISCON) {
|
||||
g_musb_hcd.port_csc = 1;
|
||||
g_musb_hcd.port_pec = 1;
|
||||
g_musb_hcd.port_pe = 0;
|
||||
usbh_roothub_thread_wakeup(1);
|
||||
g_musb_hcd[bus->hcd.hcd_id].port_csc = 1;
|
||||
g_musb_hcd[bus->hcd.hcd_id].port_pec = 1;
|
||||
g_musb_hcd[bus->hcd.hcd_id].port_pe = 0;
|
||||
bus->hcd.roothub.int_buffer[0] = (1 << 1);
|
||||
usbh_hub_thread_wakeup(&bus->hcd.roothub);
|
||||
}
|
||||
|
||||
if (is & USB_IS_SOF) {
|
||||
@@ -910,16 +909,16 @@ void USBH_IRQHandler(void)
|
||||
if (txis & USB_TXIE_EP0) {
|
||||
txis &= ~USB_TXIE_EP0;
|
||||
HWREGH(USB_BASE + MUSB_TXIS_OFFSET) = USB_TXIE_EP0;
|
||||
handle_ep0();
|
||||
handle_ep0(bus);
|
||||
}
|
||||
|
||||
for (ep_idx = 1; ep_idx < CONIFG_USB_MUSB_PIPE_NUM; ep_idx++) {
|
||||
if (txis & (1 << ep_idx)) {
|
||||
HWREGH(USB_BASE + MUSB_TXIS_OFFSET) = (1 << ep_idx);
|
||||
|
||||
pipe = &g_musb_hcd.pipe_pool[ep_idx];
|
||||
pipe = &g_musb_hcd[bus->hcd.hcd_id].pipe_pool[ep_idx];
|
||||
urb = pipe->urb;
|
||||
musb_set_active_ep(ep_idx);
|
||||
musb_set_active_ep(bus, ep_idx);
|
||||
|
||||
ep_csrl_status = HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET);
|
||||
|
||||
@@ -951,7 +950,7 @@ void USBH_IRQHandler(void)
|
||||
urb->errorcode = 0;
|
||||
musb_urb_waitup(urb);
|
||||
} else {
|
||||
musb_write_packet(ep_idx, urb->transfer_buffer, size);
|
||||
musb_write_packet(bus, ep_idx, urb->transfer_buffer, size);
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_TXCSRL1_TXRDY;
|
||||
}
|
||||
}
|
||||
@@ -963,9 +962,9 @@ void USBH_IRQHandler(void)
|
||||
if (rxis & (1 << ep_idx)) {
|
||||
HWREGH(USB_BASE + MUSB_RXIS_OFFSET) = (1 << ep_idx); // clear isr flag
|
||||
|
||||
pipe = &g_musb_hcd.pipe_pool[ep_idx];
|
||||
pipe = &g_musb_hcd[bus->hcd.hcd_id].pipe_pool[ep_idx];
|
||||
urb = pipe->urb;
|
||||
musb_set_active_ep(ep_idx);
|
||||
musb_set_active_ep(bus, ep_idx);
|
||||
|
||||
ep_csrl_status = HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET);
|
||||
//ep_csrh_status = HWREGB(USB_BASE + MUSB_IND_RXCSRH_OFFSET); // todo:for iso transfer
|
||||
@@ -989,7 +988,7 @@ void USBH_IRQHandler(void)
|
||||
}
|
||||
size = MIN(size, HWREGH(USB_BASE + MUSB_IND_RXCOUNT_OFFSET));
|
||||
|
||||
musb_read_packet(ep_idx, urb->transfer_buffer, size);
|
||||
musb_read_packet(bus, ep_idx, urb->transfer_buffer, size);
|
||||
|
||||
HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) &= ~USB_RXCSRL1_RXRDY;
|
||||
|
||||
@@ -1007,5 +1006,5 @@ void USBH_IRQHandler(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
musb_set_active_ep(old_ep_idx);
|
||||
musb_set_active_ep(bus, old_ep_idx);
|
||||
}
|
||||
|
||||
7
third_party/rt-thread-5.0/msh_cmd.c
vendored
7
third_party/rt-thread-5.0/msh_cmd.c
vendored
@@ -70,15 +70,8 @@ MSH_CMD_EXPORT(audio_v2_test, start audio_v2_test);
|
||||
#endif
|
||||
|
||||
#if defined(PKG_CHERRYUSB_HOST)
|
||||
void usbh_class_test(void);
|
||||
MSH_CMD_EXPORT(usbh_class_test, start usbh_class_test);
|
||||
|
||||
int lsusb(int argc, char **argv);
|
||||
MSH_CMD_EXPORT(lsusb, start lsusb);
|
||||
|
||||
int usbh_initialize(void);
|
||||
//INIT_APP_EXPORT(usbh_initialize);
|
||||
MSH_CMD_EXPORT(usbh_initialize, start usbh_initialize);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user