[update][cherryusb] sync from cherryusb master
This commit is contained in:
parent
daef36c40e
commit
240594aa20
@ -1,4 +1,4 @@
|
||||
sdk_generate_library()
|
||||
sdk_generate_library()
|
||||
sdk_add_include_directories(common)
|
||||
sdk_add_include_directories(osal)
|
||||
sdk_add_include_directories(core)
|
||||
|
@ -6,6 +6,8 @@
|
||||
#ifndef CHERRYUSB_CONFIG_H
|
||||
#define CHERRYUSB_CONFIG_H
|
||||
|
||||
#define CHERRYUSB_VERSION 0x000700
|
||||
|
||||
/* ================ USB common Configuration ================ */
|
||||
|
||||
#define CONFIG_USB_PRINTF(...) printf(__VA_ARGS__)
|
||||
@ -42,6 +44,17 @@
|
||||
/* Enable test mode */
|
||||
// #define CONFIG_USBDEV_TEST_MODE
|
||||
|
||||
//#define CONFIG_USBDEV_TX_RX_THREAD
|
||||
|
||||
#ifdef CONFIG_USBDEV_TX_RX_THREAD
|
||||
#ifndef CONFIG_USBDEV_TX_RX_PRIO
|
||||
#define CONFIG_USBDEV_TX_RX_PRIO 4
|
||||
#endif
|
||||
#ifndef CONFIG_USBDEV_TX_RX_STACKSIZE
|
||||
#define CONFIG_USBDEV_TX_RX_STACKSIZE 2048
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_MSC_BLOCK_SIZE
|
||||
#define CONFIG_USBDEV_MSC_BLOCK_SIZE 512
|
||||
#endif
|
||||
@ -58,18 +71,6 @@
|
||||
#define CONFIG_USBDEV_MSC_VERSION_STRING "0.01"
|
||||
#endif
|
||||
|
||||
// #define CONFIG_USBDEV_MSC_THREAD
|
||||
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
#ifndef CONFIG_USBDEV_MSC_STACKSIZE
|
||||
#define CONFIG_USBDEV_MSC_STACKSIZE 2048
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_MSC_PRIO
|
||||
#define CONFIG_USBDEV_MSC_PRIO 4
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_AUDIO_VERSION
|
||||
#define CONFIG_USBDEV_AUDIO_VERSION 0x0100
|
||||
#endif
|
||||
@ -78,13 +79,31 @@
|
||||
#define CONFIG_USBDEV_AUDIO_MAX_CHANNEL 8
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE
|
||||
#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 128
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE
|
||||
#define CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE 1536
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_RNDIS_VENDOR_ID
|
||||
#define CONFIG_USBDEV_RNDIS_VENDOR_ID 0x0000ffff
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_RNDIS_VENDOR_DESC
|
||||
#define CONFIG_USBDEV_RNDIS_VENDOR_DESC "CherryUSB"
|
||||
#endif
|
||||
|
||||
#define CONFIG_USBDEV_RNDIS_USING_LWIP
|
||||
|
||||
/* ================ USB HOST Stack Configuration ================== */
|
||||
|
||||
#define CONFIG_USBHOST_MAX_RHPORTS 1
|
||||
#define CONFIG_USBHOST_MAX_EXTHUBS 1
|
||||
#define CONFIG_USBHOST_MAX_EHPORTS 4
|
||||
#define CONFIG_USBHOST_MAX_INTERFACES 6
|
||||
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 8
|
||||
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 1
|
||||
#define CONFIG_USBHOST_MAX_ENDPOINTS 4
|
||||
|
||||
#define CONFIG_USBHOST_DEV_NAMELEN 16
|
||||
|
@ -146,6 +146,7 @@ static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
USB_LOG_INFO("Register CDC ACM Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
usbh_cdc_acm_run(cdc_acm_class);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -166,6 +167,7 @@ static int usbh_cdc_acm_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
usbh_pipe_free(cdc_acm_class->bulkout);
|
||||
}
|
||||
|
||||
usbh_cdc_acm_stop(cdc_acm_class);
|
||||
memset(cdc_acm_class, 0, sizeof(struct usbh_cdc_acm));
|
||||
usb_free(cdc_acm_class);
|
||||
|
||||
@ -176,12 +178,38 @@ static int usbh_cdc_acm_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_cdc_data_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbh_cdc_data_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
__WEAK void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const struct usbh_class_driver cdc_acm_class_driver = {
|
||||
.driver_name = "cdc_acm",
|
||||
.connect = usbh_cdc_acm_connect,
|
||||
.disconnect = usbh_cdc_acm_disconnect
|
||||
};
|
||||
|
||||
const struct usbh_class_driver cdc_data_class_driver = {
|
||||
.driver_name = "cdc_data",
|
||||
.connect = usbh_cdc_data_connect,
|
||||
.disconnect = usbh_cdc_data_disconnect
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info cdc_acm_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = USB_DEVICE_CLASS_CDC,
|
||||
@ -191,3 +219,13 @@ CLASS_INFO_DEFINE const struct usbh_class_info cdc_acm_class_info = {
|
||||
.pid = 0x00,
|
||||
.class_driver = &cdc_acm_class_driver
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info cdc_data_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS,
|
||||
.class = USB_DEVICE_CLASS_CDC_DATA,
|
||||
.subclass = 0x00,
|
||||
.protocol = 0x00,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.class_driver = &cdc_data_class_driver
|
||||
};
|
||||
|
@ -32,6 +32,8 @@ int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_
|
||||
int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding);
|
||||
int usbh_cdc_acm_set_line_state(struct usbh_cdc_acm *cdc_acm_class, bool dtr, bool rts);
|
||||
|
||||
void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class);
|
||||
void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -148,7 +148,8 @@ int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
USB_LOG_INFO("Register HID Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
return 0;
|
||||
usbh_hid_run(hid_class);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
@ -168,6 +169,7 @@ int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
usbh_pipe_free(hid_class->intout);
|
||||
}
|
||||
|
||||
usbh_hid_stop(hid_class);
|
||||
memset(hid_class, 0, sizeof(struct usbh_hid));
|
||||
usb_free(hid_class);
|
||||
|
||||
@ -178,27 +180,27 @@ int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
return ret;
|
||||
}
|
||||
|
||||
__WEAK void usbh_hid_run(struct usbh_hid *hid_class)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
__WEAK void usbh_hid_stop(struct usbh_hid *hid_class)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const struct usbh_class_driver hid_class_driver = {
|
||||
.driver_name = "hid",
|
||||
.connect = usbh_hid_connect,
|
||||
.disconnect = usbh_hid_disconnect
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info hid_keyboard_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info hid_custom_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS,
|
||||
.class = USB_DEVICE_CLASS_HID,
|
||||
.subclass = HID_SUBCLASS_BOOTIF,
|
||||
.protocol = HID_PROTOCOL_KEYBOARD,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.class_driver = &hid_class_driver
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info hid_mouse_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = USB_DEVICE_CLASS_HID,
|
||||
.subclass = HID_SUBCLASS_BOOTIF,
|
||||
.protocol = HID_PROTOCOL_MOUSE,
|
||||
.subclass = 0x00,
|
||||
.protocol = 0x00,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.class_driver = &hid_class_driver
|
||||
|
@ -25,6 +25,8 @@ extern "C" {
|
||||
int usbh_hid_set_idle(struct usbh_hid *hid_class, uint8_t report_id, uint8_t duration);
|
||||
int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer);
|
||||
|
||||
void usbh_hid_run(struct usbh_hid *hid_class);
|
||||
void usbh_hid_stop(struct usbh_hid *hid_class);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -7,8 +7,9 @@
|
||||
|
||||
#define DEV_FORMAT "/dev/hub%d"
|
||||
|
||||
#define DEBOUNCE_TIMEOUT 400
|
||||
#define DEBOUNCE_TIME_STEP 25
|
||||
#define HUB_DEBOUNCE_TIMEOUT 1500
|
||||
#define HUB_DEBOUNCE_STEP 25
|
||||
#define HUB_DEBOUNCE_STABLE 100
|
||||
#define DELAY_TIME_AFTER_RESET 200
|
||||
|
||||
#define EXTHUB_FIRST_INDEX 2
|
||||
@ -17,23 +18,24 @@ static uint32_t g_devinuse = 0;
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_buf[32];
|
||||
|
||||
usb_slist_t hub_event_head = USB_SLIST_OBJECT_INIT(hub_event_head);
|
||||
usb_slist_t hub_class_head = USB_SLIST_OBJECT_INIT(hub_class_head);
|
||||
|
||||
usb_osal_sem_t hub_event_wait;
|
||||
usb_osal_thread_t hub_thread;
|
||||
usb_osal_mq_t hub_mq;
|
||||
|
||||
USB_NOCACHE_RAM_SECTION struct usbh_hub roothub;
|
||||
struct usbh_hubport roothub_parent_port;
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
USB_NOCACHE_RAM_SECTION struct usbh_hub exthub[CONFIG_USBHOST_MAX_EXTHUBS];
|
||||
|
||||
#endif
|
||||
extern int usbh_hport_activate_ep0(struct usbh_hubport *hport);
|
||||
extern int usbh_hport_deactivate_ep0(struct usbh_hubport *hport);
|
||||
extern int usbh_enumerate(struct usbh_hubport *hport);
|
||||
static void usbh_hub_thread_wakeup(struct usbh_hub *hub);
|
||||
|
||||
static const char *speed_table[] = { "error-speed", "low-speed", "full-speed", "high-speed", "wireless-speed", "super-speed", "superplus-speed" };
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
static int usbh_hub_devno_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
@ -55,6 +57,17 @@ static void usbh_hub_devno_free(uint8_t devno)
|
||||
g_devinuse &= ~(1 << devno);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void usbh_hub_register(struct usbh_hub *hub)
|
||||
{
|
||||
usb_slist_add_tail(&hub_class_head, &hub->list);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -225,12 +238,7 @@ static int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t fe
|
||||
}
|
||||
}
|
||||
|
||||
static void usbh_hub_thread_wakeup(struct usbh_hub *hub)
|
||||
{
|
||||
usb_slist_add_tail(&hub_event_head, &hub->hub_event_list);
|
||||
usb_osal_sem_give(hub_event_wait);
|
||||
}
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
static void hub_int_complete_callback(void *arg, int nbytes)
|
||||
{
|
||||
struct usbh_hub *hub = (struct usbh_hub *)arg;
|
||||
@ -326,7 +334,7 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
usbh_hport_deactivate_ep0(child);
|
||||
for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) {
|
||||
if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) {
|
||||
ret = CLASS_DISCONNECT(child, i);
|
||||
CLASS_DISCONNECT(child, i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -342,20 +350,20 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void usbh_roothub_register(void)
|
||||
static void usbh_hubport_release(struct usbh_hubport *child)
|
||||
{
|
||||
memset(&roothub, 0, sizeof(struct usbh_hub));
|
||||
memset(&roothub_parent_port, 0, sizeof(struct usbh_hubport));
|
||||
roothub_parent_port.port = 1;
|
||||
roothub_parent_port.dev_addr = 1;
|
||||
roothub.connected = true;
|
||||
roothub.index = 1;
|
||||
roothub.is_roothub = true;
|
||||
roothub.parent = &roothub_parent_port;
|
||||
roothub.hub_addr = roothub_parent_port.dev_addr;
|
||||
roothub.hub_desc.bNbrPorts = CONFIG_USBHOST_MAX_RHPORTS;
|
||||
usbh_hub_register(&roothub);
|
||||
if (child->connected) {
|
||||
child->connected = false;
|
||||
usbh_hport_deactivate_ep0(child);
|
||||
for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) {
|
||||
if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) {
|
||||
CLASS_DISCONNECT(child, i);
|
||||
}
|
||||
}
|
||||
child->config.config_desc.bNumInterfaces = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void usbh_hub_events(struct usbh_hub *hub)
|
||||
@ -419,8 +427,7 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
||||
if (portchange & HUB_PORT_STATUS_C_CONNECTION) {
|
||||
uint16_t connection = 0;
|
||||
uint16_t debouncestable = 0;
|
||||
for (uint32_t debouncetime = 0; debouncetime < DEBOUNCE_TIMEOUT; debouncetime += DEBOUNCE_TIME_STEP) {
|
||||
usb_osal_msleep(DEBOUNCE_TIME_STEP);
|
||||
for (uint32_t debouncetime = 0; debouncetime < HUB_DEBOUNCE_TIMEOUT; debouncetime += HUB_DEBOUNCE_STEP) {
|
||||
/* Read hub port status */
|
||||
ret = usbh_hub_get_portstatus(hub, port + 1, &port_status);
|
||||
if (ret < 0) {
|
||||
@ -432,21 +439,29 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
||||
portchange = port_status.wPortChange;
|
||||
|
||||
USB_LOG_DBG("Port %u, status:0x%02x, change:0x%02x\r\n", port + 1, portstatus, portchange);
|
||||
if ((portstatus & HUB_PORT_STATUS_CONNECTION) == connection) {
|
||||
if (connection) {
|
||||
if (++debouncestable == 4) {
|
||||
|
||||
if (!(portchange & HUB_PORT_STATUS_C_CONNECTION) &&
|
||||
((portstatus & HUB_PORT_STATUS_CONNECTION) == connection)) {
|
||||
debouncestable += HUB_DEBOUNCE_STEP;
|
||||
if (debouncestable >= HUB_DEBOUNCE_STABLE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
debouncestable = 0;
|
||||
}
|
||||
|
||||
connection = portstatus & HUB_PORT_STATUS_CONNECTION;
|
||||
}
|
||||
|
||||
if (portchange & HUB_PORT_STATUS_C_CONNECTION) {
|
||||
usbh_hub_clear_feature(hub, port + 1, HUB_PORT_FEATURE_C_CONNECTION);
|
||||
}
|
||||
|
||||
usb_osal_msleep(HUB_DEBOUNCE_STEP);
|
||||
}
|
||||
|
||||
/** check if debounce ok */
|
||||
if (debouncestable < HUB_DEBOUNCE_STABLE) {
|
||||
USB_LOG_ERR("Failed to debounce port %u\r\n", port + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Last, check connect status */
|
||||
@ -484,6 +499,8 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
||||
}
|
||||
|
||||
child = &hub->child[port];
|
||||
/** release child sources first */
|
||||
usbh_hubport_release(child);
|
||||
|
||||
memset(child, 0, sizeof(struct usbh_hubport));
|
||||
child->parent = hub;
|
||||
@ -498,25 +515,22 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
||||
}
|
||||
} else {
|
||||
USB_LOG_ERR("Failed to enable port %u\r\n", port + 1);
|
||||
|
||||
child = &hub->child[port];
|
||||
/** release child sources */
|
||||
usbh_hubport_release(child);
|
||||
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
child = &hub->child[port];
|
||||
child->connected = false;
|
||||
usbh_hport_deactivate_ep0(child);
|
||||
for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) {
|
||||
if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) {
|
||||
CLASS_DISCONNECT(child, i);
|
||||
}
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Device on Hub %u, Port %u disconnected\r\n", hub->index, port + 1);
|
||||
usbh_device_unmount_done_callback(child);
|
||||
child->config.config_desc.bNumInterfaces = 0;
|
||||
/** release child sources */
|
||||
usbh_hubport_release(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hub->int_buffer[0] = 0;
|
||||
/* Start next hub int transfer */
|
||||
if (!hub->is_roothub && hub->connected) {
|
||||
usbh_submit_urb(&hub->intin_urb);
|
||||
@ -525,24 +539,35 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
||||
|
||||
static void usbh_hub_thread(void *argument)
|
||||
{
|
||||
size_t flags;
|
||||
struct usbh_hub *hub;
|
||||
int ret = 0;
|
||||
|
||||
usb_hc_init();
|
||||
while (1) {
|
||||
ret = usb_osal_sem_take(hub_event_wait, 0xffffffff);
|
||||
ret = usb_osal_mq_recv(hub_mq, (uint32_t *)&hub, 0xffffffff);
|
||||
if (ret < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
while (!usb_slist_isempty(&hub_event_head)) {
|
||||
struct usbh_hub *hub = usb_slist_first_entry(&hub_event_head, struct usbh_hub, hub_event_list);
|
||||
flags = usb_osal_enter_critical_section();
|
||||
usb_slist_remove(&hub_event_head, &hub->hub_event_list);
|
||||
usb_osal_leave_critical_section(flags);
|
||||
usbh_hub_events(hub);
|
||||
}
|
||||
}
|
||||
|
||||
static void usbh_roothub_register(void)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static void usbh_hub_thread_wakeup(struct usbh_hub *hub)
|
||||
{
|
||||
usb_osal_mq_send(hub_mq, (uint32_t)hub);
|
||||
}
|
||||
|
||||
void usbh_roothub_thread_wakeup(uint8_t port)
|
||||
@ -551,22 +576,12 @@ void usbh_roothub_thread_wakeup(uint8_t port)
|
||||
usbh_hub_thread_wakeup(&roothub);
|
||||
}
|
||||
|
||||
void usbh_hub_register(struct usbh_hub *hub)
|
||||
{
|
||||
usb_slist_add_tail(&hub_class_head, &hub->list);
|
||||
}
|
||||
|
||||
void usbh_hub_unregister(struct usbh_hub *hub)
|
||||
{
|
||||
usb_slist_remove(&hub_class_head, &hub->list);
|
||||
}
|
||||
|
||||
int usbh_hub_initialize(void)
|
||||
{
|
||||
usbh_roothub_register();
|
||||
|
||||
hub_event_wait = usb_osal_sem_create(0);
|
||||
if (hub_event_wait == NULL) {
|
||||
hub_mq = usb_osal_mq_create(7);
|
||||
if (hub_mq == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -576,19 +591,20 @@ int usbh_hub_initialize(void)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct usbh_class_driver hub_driver = {
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
const struct usbh_class_driver hub_class_driver = {
|
||||
.driver_name = "hub",
|
||||
.connect = usbh_hub_connect,
|
||||
.disconnect = usbh_hub_disconnect
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info hub_info = {
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info hub_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS,
|
||||
.class = USB_DEVICE_CLASS_HUB,
|
||||
.subclass = 0,
|
||||
.protocol = 0,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.class_driver = &hub_driver
|
||||
.class_driver = &hub_class_driver
|
||||
};
|
||||
#endif
|
||||
|
@ -19,8 +19,6 @@ extern usb_slist_t hub_class_head;
|
||||
extern "C" {
|
||||
#endif
|
||||
void usbh_roothub_thread_wakeup(uint8_t port);
|
||||
void usbh_hub_register(struct usbh_hub *hub);
|
||||
void usbh_hub_unregister(struct usbh_hub *hub);
|
||||
int usbh_hub_initialize(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -6,13 +6,6 @@
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_msc.h"
|
||||
#include "usb_scsi.h"
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
#include "usb_osal.h"
|
||||
#endif
|
||||
|
||||
#define MSC_THREAD_OP_READ_MEM 1
|
||||
#define MSC_THREAD_OP_WRITE_MEM 2
|
||||
#define MSC_THREAD_OP_WRITE_DONE 3
|
||||
|
||||
#define MSD_OUT_EP_IDX 0
|
||||
#define MSD_IN_EP_IDX 1
|
||||
@ -49,13 +42,6 @@ USB_NOCACHE_RAM_SECTION struct usbd_msc_cfg_priv {
|
||||
uint8_t block_buffer[CONFIG_USBDEV_MSC_BLOCK_SIZE];
|
||||
} usbd_msc_cfg;
|
||||
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
static volatile uint8_t thread_op;
|
||||
static usb_osal_sem_t msc_sem;
|
||||
static usb_osal_thread_t msc_thread;
|
||||
static volatile uint32_t current_byte_read;
|
||||
#endif
|
||||
|
||||
static void usbd_msc_reset(void)
|
||||
{
|
||||
usbd_msc_cfg.stage = MSC_READ_CBW;
|
||||
@ -635,17 +621,11 @@ static bool SCSI_processRead(void)
|
||||
|
||||
transfer_len = MIN(usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE);
|
||||
|
||||
/* Start reading one sector */
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
thread_op = MSC_THREAD_OP_READ_MEM;
|
||||
usb_osal_sem_give(msc_sem);
|
||||
return true;
|
||||
#else
|
||||
if (usbd_msc_sector_read(usbd_msc_cfg.start_sector, usbd_msc_cfg.block_buffer, transfer_len) != 0) {
|
||||
SCSI_SetSenseData(SCSI_KCQHE_UREINRESERVEDAREA);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, usbd_msc_cfg.block_buffer, transfer_len);
|
||||
|
||||
usbd_msc_cfg.start_sector += (transfer_len / usbd_msc_cfg.scsi_blk_size);
|
||||
@ -659,47 +639,15 @@ static bool SCSI_processRead(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
static void usbd_msc_thread_memory_read_done(void)
|
||||
{
|
||||
size_t flags;
|
||||
uint32_t transfer_len;
|
||||
|
||||
flags = usb_osal_enter_critical_section();
|
||||
|
||||
transfer_len = MIN(usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE);
|
||||
|
||||
usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr,
|
||||
usbd_msc_cfg.block_buffer, transfer_len);
|
||||
|
||||
usbd_msc_cfg.start_sector += (transfer_len / usbd_msc_cfg.scsi_blk_size);
|
||||
usbd_msc_cfg.nsectors -= (transfer_len / usbd_msc_cfg.scsi_blk_size);
|
||||
usbd_msc_cfg.csw.dDataResidue -= transfer_len;
|
||||
|
||||
if (usbd_msc_cfg.nsectors == 0) {
|
||||
usbd_msc_cfg.stage = MSC_SEND_CSW;
|
||||
}
|
||||
usb_osal_leave_critical_section(flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool SCSI_processWrite(uint32_t nbytes)
|
||||
{
|
||||
uint32_t data_len = 0;
|
||||
USB_LOG_DBG("write lba:%d\r\n", usbd_msc_cfg.start_sector);
|
||||
|
||||
/* Start writing one sector */
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
thread_op = MSC_THREAD_OP_WRITE_MEM;
|
||||
current_byte_read = nbytes;
|
||||
usb_osal_sem_give(msc_sem);
|
||||
return true;
|
||||
#else
|
||||
if (usbd_msc_sector_write(usbd_msc_cfg.start_sector, usbd_msc_cfg.block_buffer, nbytes) != 0) {
|
||||
SCSI_SetSenseData(SCSI_KCQHE_WRITEFAULT);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
usbd_msc_cfg.start_sector += (nbytes / usbd_msc_cfg.scsi_blk_size);
|
||||
usbd_msc_cfg.nsectors -= (nbytes / usbd_msc_cfg.scsi_blk_size);
|
||||
@ -715,29 +663,6 @@ static bool SCSI_processWrite(uint32_t nbytes)
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
static void usbd_msc_thread_memory_write_done()
|
||||
{
|
||||
size_t flags;
|
||||
uint32_t data_len = 0;
|
||||
|
||||
flags = usb_osal_enter_critical_section();
|
||||
|
||||
usbd_msc_cfg.start_sector += (current_byte_read / usbd_msc_cfg.scsi_blk_size);
|
||||
usbd_msc_cfg.nsectors -= (current_byte_read / usbd_msc_cfg.scsi_blk_size);
|
||||
usbd_msc_cfg.csw.dDataResidue -= current_byte_read;
|
||||
|
||||
if (usbd_msc_cfg.nsectors == 0) {
|
||||
usbd_msc_send_csw(CSW_STATUS_CMD_PASSED);
|
||||
} else {
|
||||
data_len = MIN(usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE);
|
||||
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, usbd_msc_cfg.block_buffer, data_len);
|
||||
}
|
||||
|
||||
usb_osal_leave_critical_section(flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool SCSI_CBWDecode(uint32_t nbytes)
|
||||
{
|
||||
uint8_t *buf2send = usbd_msc_cfg.block_buffer;
|
||||
@ -883,35 +808,6 @@ void mass_storage_bulk_in(uint8_t ep, uint32_t nbytes)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
static void usbd_msc_thread(void *argument)
|
||||
{
|
||||
uint32_t data_len = 0;
|
||||
while (1) {
|
||||
usb_osal_sem_take(msc_sem, 0xffffffff);
|
||||
|
||||
switch (thread_op) {
|
||||
case MSC_THREAD_OP_READ_MEM:
|
||||
data_len = MIN(usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE);
|
||||
if (usbd_msc_sector_read(usbd_msc_cfg.start_sector, usbd_msc_cfg.block_buffer, data_len) != 0) {
|
||||
SCSI_SetSenseData(SCSI_KCQHE_UREINRESERVEDAREA);
|
||||
}
|
||||
usbd_msc_thread_memory_read_done();
|
||||
break;
|
||||
case MSC_THREAD_OP_WRITE_MEM:
|
||||
data_len = MIN(usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE);
|
||||
if (usbd_msc_sector_write(usbd_msc_cfg.start_sector, usbd_msc_cfg.block_buffer, data_len) != 0) {
|
||||
SCSI_SetSenseData(SCSI_KCQHE_WRITEFAULT);
|
||||
}
|
||||
usbd_msc_thread_memory_write_done();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
struct usbd_interface *usbd_msc_init_intf(struct usbd_interface *intf, const uint8_t out_ep, const uint8_t in_ep)
|
||||
{
|
||||
intf->class_interface_handler = msc_storage_class_interface_request_handler;
|
||||
@ -935,14 +831,6 @@ struct usbd_interface *usbd_msc_init_intf(struct usbd_interface *intf, const uin
|
||||
USB_LOG_ERR("msc block buffer overflow\r\n");
|
||||
return NULL;
|
||||
}
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
msc_sem = usb_osal_sem_create(1);
|
||||
msc_thread = usb_osal_thread_create("usbd_msc", CONFIG_USBDEV_MSC_STACKSIZE, CONFIG_USBDEV_MSC_PRIO, usbd_msc_thread, NULL);
|
||||
if (msc_thread == NULL) {
|
||||
USB_LOG_ERR("no enough memory to alloc msc thread\r\n");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return intf;
|
||||
}
|
||||
|
@ -13,7 +13,9 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* Init msc interface driver */
|
||||
struct usbd_interface *usbd_msc_init_intf(struct usbd_interface *intf, const uint8_t out_ep, const uint8_t in_ep);
|
||||
struct usbd_interface *usbd_msc_init_intf(struct usbd_interface *intf,
|
||||
const uint8_t out_ep,
|
||||
const uint8_t in_ep);
|
||||
|
||||
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size);
|
||||
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length);
|
||||
|
@ -371,6 +371,7 @@ static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
USB_LOG_INFO("Register MSC Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
usbh_msc_run(msc_class);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -391,6 +392,7 @@ static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
usbh_pipe_free(msc_class->bulkout);
|
||||
}
|
||||
|
||||
usbh_msc_stop(msc_class);
|
||||
memset(msc_class, 0, sizeof(struct usbh_msc));
|
||||
usb_free(msc_class);
|
||||
|
||||
@ -401,6 +403,16 @@ static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
return ret;
|
||||
}
|
||||
|
||||
__WEAK void usbh_msc_run(struct usbh_msc *msc_class)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
__WEAK void usbh_msc_stop(struct usbh_msc *msc_class)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const struct usbh_class_driver msc_class_driver = {
|
||||
.driver_name = "msc",
|
||||
.connect = usbh_msc_connect,
|
||||
|
@ -25,6 +25,8 @@ struct usbh_msc {
|
||||
int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors);
|
||||
int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors);
|
||||
|
||||
void usbh_msc_run(struct usbh_msc *msc_class);
|
||||
void usbh_msc_stop(struct usbh_msc *msc_class);
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -742,7 +742,10 @@ void usbd_video_probe_and_commit_controls_init(uint32_t dwFrameInterval, uint32_
|
||||
usbd_video_cfg.commit.bMaxVersion = 0;
|
||||
}
|
||||
|
||||
struct usbd_interface *usbd_video_init_intf(struct usbd_interface *intf, uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
|
||||
struct usbd_interface *usbd_video_init_intf(struct usbd_interface *intf,
|
||||
uint32_t dwFrameInterval,
|
||||
uint32_t dwMaxVideoFrameSize,
|
||||
uint32_t dwMaxPayloadTransferSize)
|
||||
{
|
||||
intf->class_interface_handler = video_class_interface_request_handler;
|
||||
intf->class_endpoint_handler = NULL;
|
||||
|
@ -32,7 +32,7 @@ static int __s_b_1732446u[256] = { 0 };
|
||||
static int __s_g_337633u[256] = { 0 };
|
||||
static int __s_g_698001v[256] = { 0 };
|
||||
|
||||
static void inityuyv2rgb_table(void)
|
||||
void usbh_video_inityuyv2rgb_table(void)
|
||||
{
|
||||
for (int i = 0; i < 256; i++) {
|
||||
__s_r_1370705v[i] = (1.370705 * (i - 128));
|
||||
@ -42,7 +42,7 @@ static void inityuyv2rgb_table(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void yuyv2rgb565(void *input, void *output, uint32_t len)
|
||||
void usbh_video_yuyv2rgb565(void *input, void *output, uint32_t len)
|
||||
{
|
||||
int y0, u, y1, v;
|
||||
uint8_t r, g, b;
|
||||
@ -134,47 +134,84 @@ int usbh_videostreaming_get_cur_probe(struct usbh_video *video_class)
|
||||
return usbh_video_get_cur(video_class, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26);
|
||||
}
|
||||
|
||||
int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
|
||||
int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex)
|
||||
{
|
||||
video_class->probe.bFormatIndex = formatindex;
|
||||
video_class->probe.bFrameIndex = frameindex;
|
||||
video_class->probe.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
|
||||
video_class->probe.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
|
||||
video_class->probe.dwMaxPayloadTransferSize = 0;
|
||||
return usbh_video_set_cur(video_class, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26);
|
||||
}
|
||||
|
||||
int usbh_videostreaming_set_cur_commit(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
|
||||
int usbh_videostreaming_set_cur_commit(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex)
|
||||
{
|
||||
memcpy(&video_class->commit, &video_class->probe, sizeof(struct video_probe_and_commit_controls));
|
||||
video_class->commit.bFormatIndex = formatindex;
|
||||
video_class->commit.bFrameIndex = frameindex;
|
||||
video_class->commit.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
|
||||
video_class->commit.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
|
||||
return usbh_video_set_cur(video_class, video_class->data_intf, 0x00, VIDEO_VS_COMMIT_CONTROL, (uint8_t *)&video_class->commit, 26);
|
||||
}
|
||||
|
||||
int usbh_video_open(struct usbh_video *video_class, uint8_t altsetting)
|
||||
int usbh_video_open(struct usbh_video *video_class,
|
||||
uint8_t format_type,
|
||||
uint16_t wWidth,
|
||||
uint16_t wHeight,
|
||||
uint8_t altsetting)
|
||||
{
|
||||
struct usb_setup_packet *setup = &video_class->hport->setup;
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
uint8_t mult;
|
||||
uint16_t mps;
|
||||
int ret;
|
||||
bool found = false;
|
||||
uint8_t formatidx = 0;
|
||||
uint8_t frameidx = 0;
|
||||
|
||||
if (video_class->is_opened) {
|
||||
return -EMFILE;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < video_class->num_of_formats; i++) {
|
||||
if (format_type == video_class->format[i].format_type) {
|
||||
formatidx = i + 1;
|
||||
for (uint8_t j = 0; j < video_class->format[i].num_of_frames; j++) {
|
||||
if ((wWidth == video_class->format[i].frame[j].wWidth) &&
|
||||
(wHeight == video_class->format[i].frame[j].wHeight)) {
|
||||
frameidx = j + 1;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found == false) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (altsetting > (video_class->num_of_intf_altsettings - 1)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = USB_REQUEST_SET_INTERFACE;
|
||||
setup->wValue = altsetting;
|
||||
setup->wIndex = video_class->data_intf;
|
||||
setup->wLength = 0;
|
||||
|
||||
ret = usbh_control_transfer(video_class->hport->ep0, setup, NULL);
|
||||
ret = usbh_videostreaming_get_cur_probe(video_class);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = usbh_videostreaming_get_cur_probe(video_class);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = usbh_videostreaming_get_cur_probe(video_class);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = usbh_videostreaming_set_cur_commit(video_class, formatidx, frameidx);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@ -189,15 +226,46 @@ int usbh_video_open(struct usbh_video *video_class, uint8_t altsetting)
|
||||
video_class->isoout_mps = mps * (mult + 1);
|
||||
usbh_hport_activate_epx(&video_class->isoout, video_class->hport, ep_desc);
|
||||
}
|
||||
USB_LOG_INFO("Open video and select altsetting:%u\r\n", altsetting);
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = USB_REQUEST_SET_INTERFACE;
|
||||
setup->wValue = altsetting;
|
||||
setup->wIndex = video_class->data_intf;
|
||||
setup->wLength = 0;
|
||||
|
||||
ret = usbh_control_transfer(video_class->hport->ep0, setup, NULL);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Open video and select formatidx:%u, frameidx:%u, altsetting:%u\r\n", formatidx, frameidx, altsetting);
|
||||
video_class->is_opened = true;
|
||||
video_class->current_format = format_type;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_video_close(struct usbh_video *video_class)
|
||||
{
|
||||
struct usb_setup_packet *setup = &video_class->hport->setup;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
USB_LOG_INFO("Close video device\r\n");
|
||||
|
||||
if (video_class->is_opened == false) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
video_class->is_opened = false;
|
||||
|
||||
if (video_class->isoin) {
|
||||
usbh_pipe_free(video_class->isoin);
|
||||
video_class->isoin = NULL;
|
||||
}
|
||||
|
||||
if (video_class->isoout) {
|
||||
usbh_pipe_free(video_class->isoout);
|
||||
video_class->isoout = NULL;
|
||||
}
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = USB_REQUEST_SET_INTERFACE;
|
||||
@ -209,24 +277,11 @@ int usbh_video_close(struct usbh_video *video_class)
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
if (video_class->isoin) {
|
||||
usbh_pipe_free(video_class->isoin);
|
||||
video_class->isoin = NULL;
|
||||
}
|
||||
|
||||
if (video_class->isoout) {
|
||||
usbh_pipe_free(video_class->isoout);
|
||||
video_class->isoout = NULL;
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Close video device\r\n");
|
||||
video_class->is_opened = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void usbh_video_list_info(struct usbh_video *video_class)
|
||||
{
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
uint8_t mult;
|
||||
uint16_t mps;
|
||||
@ -235,8 +290,6 @@ void usbh_video_list_info(struct usbh_video *video_class)
|
||||
USB_LOG_INFO("bcdVDC:%04x\r\n", video_class->bcdVDC);
|
||||
USB_LOG_INFO("Num of altsettings:%02x\r\n", video_class->num_of_intf_altsettings);
|
||||
|
||||
hport = video_class->hport;
|
||||
|
||||
for (uint8_t i = 1; i < video_class->num_of_intf_altsettings; i++) {
|
||||
ep_desc = &video_class->hport->config.intf[video_class->data_intf].altsetting[i].ep[0].ep_desc;
|
||||
|
||||
@ -266,18 +319,14 @@ void usbh_video_list_info(struct usbh_video *video_class)
|
||||
}
|
||||
}
|
||||
|
||||
usbh_videostreaming_get_cur_probe(video_class);
|
||||
|
||||
USB_LOG_INFO("dwMaxVideoFrameSize:%u,dwMaxPayloadTransferSize:%u\r\n", (int)video_class->probe.dwMaxVideoFrameSize, (int)video_class->probe.dwMaxPayloadTransferSize);
|
||||
|
||||
USB_LOG_INFO("============= Video device information ===================\r\n");
|
||||
}
|
||||
|
||||
static int usbh_video_ctrl_intf_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
int ret;
|
||||
uint8_t cur_iface = 0xff;
|
||||
uint8_t cur_alt_setting = 0xff;
|
||||
// uint8_t cur_alt_setting = 0xff;
|
||||
uint8_t frame_index = 0xff;
|
||||
uint8_t format_index = 0xff;
|
||||
uint8_t num_of_frames = 0xff;
|
||||
@ -378,14 +427,16 @@ static int usbh_video_ctrl_intf_connect(struct usbh_hubport *hport, uint8_t intf
|
||||
usbh_video_list_info(video_class);
|
||||
|
||||
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, video_class->minor);
|
||||
|
||||
#ifdef CONFIG_USBHOST_UVC_YUV2RGB
|
||||
inityuyv2rgb_table();
|
||||
#endif
|
||||
USB_LOG_INFO("Register Video Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
return 0;
|
||||
usbh_video_run(video_class);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_video_ctrl_intf_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
static int usbh_video_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
@ -402,6 +453,7 @@ static int usbh_video_ctrl_intf_disconnect(struct usbh_hubport *hport, uint8_t i
|
||||
usbh_pipe_free(video_class->isoout);
|
||||
}
|
||||
|
||||
usbh_video_stop(video_class);
|
||||
memset(video_class, 0, sizeof(struct usbh_video));
|
||||
usb_free(video_class);
|
||||
|
||||
@ -412,13 +464,12 @@ static int usbh_video_ctrl_intf_disconnect(struct usbh_hubport *hport, uint8_t i
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_video_data_intf_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
static int usbh_video_streaming_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
USB_LOG_WRN("Ignore video data intf\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbh_video_data_intf_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
static int usbh_video_streaming_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -427,9 +478,9 @@ void usbh_videostreaming_parse_mjpeg(struct usbh_urb *urb, struct usbh_videostre
|
||||
{
|
||||
struct usbh_iso_frame_packet *iso_packet;
|
||||
uint32_t num_of_iso_packets;
|
||||
uint8_t *tmp_buf;
|
||||
uint8_t data_offset;
|
||||
uint32_t data_len;
|
||||
uint8_t header_len = 0;
|
||||
|
||||
num_of_iso_packets = urb->num_of_iso_packets;
|
||||
iso_packet = urb->iso_packet;
|
||||
@ -448,11 +499,10 @@ void usbh_videostreaming_parse_mjpeg(struct usbh_urb *urb, struct usbh_videostre
|
||||
if (iso_packet[i].actual_length == 0) { /* skip no data */
|
||||
continue;
|
||||
}
|
||||
if (iso_packet[i].actual_length < iso_packet[i].transfer_buffer[0]) { /* do not be illegal */
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
if ((iso_packet[i].transfer_buffer[0] > 12) || (iso_packet[i].transfer_buffer[0] == 0)) { /* do not be illegal */
|
||||
|
||||
header_len = iso_packet[i].transfer_buffer[0];
|
||||
|
||||
if ((header_len > 12) || (header_len == 0)) { /* do not be illegal */
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
@ -461,20 +511,20 @@ void usbh_videostreaming_parse_mjpeg(struct usbh_urb *urb, struct usbh_videostre
|
||||
continue;
|
||||
}
|
||||
|
||||
data_offset = iso_packet[i].transfer_buffer[0];
|
||||
data_len = iso_packet[i].actual_length - iso_packet[i].transfer_buffer[0];
|
||||
|
||||
tmp_buf = stream->bufbase + stream->bufoffset;
|
||||
stream->bufoffset += data_len;
|
||||
|
||||
memcpy(tmp_buf, &iso_packet[i].transfer_buffer[data_offset], data_len);
|
||||
if ((stream->bufbase[0] != 0xff) && (stream->bufbase[1] != 0xd8)) {
|
||||
if ((stream->bufoffset == 0) && (iso_packet[i].transfer_buffer[header_len] != 0xff) && (iso_packet[i].transfer_buffer[header_len + 1] != 0xd8)) {
|
||||
stream->bufoffset = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
data_offset = iso_packet[i].transfer_buffer[0];
|
||||
data_len = iso_packet[i].actual_length - iso_packet[i].transfer_buffer[0];
|
||||
|
||||
usbh_videostreaming_output(&iso_packet[i].transfer_buffer[data_offset], data_len);
|
||||
|
||||
stream->bufoffset += data_len;
|
||||
|
||||
if (iso_packet[i].transfer_buffer[1] & (1 << 1)) {
|
||||
if ((stream->bufbase[stream->bufoffset - 2] != 0xff) && (stream->bufbase[stream->bufoffset - 1] != 0xd9)) {
|
||||
if ((iso_packet[i].transfer_buffer[iso_packet[i].actual_length - 2] != 0xff) && (iso_packet[i].transfer_buffer[iso_packet[i].actual_length - 1] != 0xd9)) {
|
||||
stream->bufoffset = 0;
|
||||
continue;
|
||||
}
|
||||
@ -486,13 +536,13 @@ void usbh_videostreaming_parse_mjpeg(struct usbh_urb *urb, struct usbh_videostre
|
||||
}
|
||||
}
|
||||
|
||||
void usbh_videostreaming_parse_yuyv2rgb565(struct usbh_urb *urb, struct usbh_videostreaming *stream)
|
||||
void usbh_videostreaming_parse_yuyv2(struct usbh_urb *urb, struct usbh_videostreaming *stream)
|
||||
{
|
||||
struct usbh_iso_frame_packet *iso_packet;
|
||||
uint32_t num_of_iso_packets;
|
||||
uint8_t *tmp_buf;
|
||||
uint8_t data_offset;
|
||||
uint32_t data_len;
|
||||
uint8_t header_len = 0;
|
||||
|
||||
num_of_iso_packets = urb->num_of_iso_packets;
|
||||
iso_packet = urb->iso_packet;
|
||||
@ -512,11 +562,10 @@ void usbh_videostreaming_parse_yuyv2rgb565(struct usbh_urb *urb, struct usbh_vid
|
||||
if (iso_packet[i].actual_length == 0) { /* skip no data */
|
||||
continue;
|
||||
}
|
||||
if (iso_packet[i].actual_length < iso_packet[i].transfer_buffer[0]) { /* do not be illegal */
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
if ((iso_packet[i].transfer_buffer[0] > 12) || (iso_packet[i].transfer_buffer[0] == 0)) { /* do not be illegal */
|
||||
|
||||
header_len = iso_packet[i].transfer_buffer[0];
|
||||
|
||||
if ((header_len > 12) || (header_len == 0)) { /* do not be illegal */
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
@ -528,10 +577,9 @@ void usbh_videostreaming_parse_yuyv2rgb565(struct usbh_urb *urb, struct usbh_vid
|
||||
data_offset = iso_packet[i].transfer_buffer[0];
|
||||
data_len = iso_packet[i].actual_length - iso_packet[i].transfer_buffer[0];
|
||||
|
||||
tmp_buf = stream->bufbase + stream->bufoffset;
|
||||
usbh_videostreaming_output(&iso_packet[i].transfer_buffer[data_offset], data_len);
|
||||
stream->bufoffset += data_len;
|
||||
|
||||
yuyv2rgb565(&iso_packet[i].transfer_buffer[data_offset], tmp_buf, data_len);
|
||||
if (iso_packet[i].transfer_buffer[1] & (1 << 1)) {
|
||||
if (stream->video_one_frame_callback) {
|
||||
stream->video_one_frame_callback(stream);
|
||||
@ -541,34 +589,46 @@ void usbh_videostreaming_parse_yuyv2rgb565(struct usbh_urb *urb, struct usbh_vid
|
||||
}
|
||||
}
|
||||
|
||||
const struct usbh_class_driver video_class_ctrl_intf_driver = {
|
||||
.driver_name = "video",
|
||||
.connect = usbh_video_ctrl_intf_connect,
|
||||
.disconnect = usbh_video_ctrl_intf_disconnect
|
||||
__WEAK void usbh_video_run(struct usbh_video *video_class)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usbh_video_stop(struct usbh_video *video_class)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usbh_videostreaming_output(uint8_t *input, uint32_t input_len)
|
||||
{
|
||||
}
|
||||
|
||||
const struct usbh_class_driver video_ctrl_class_driver = {
|
||||
.driver_name = "video_ctrl",
|
||||
.connect = usbh_video_ctrl_connect,
|
||||
.disconnect = usbh_video_ctrl_disconnect
|
||||
};
|
||||
|
||||
const struct usbh_class_driver video_class_data_intf_driver = {
|
||||
.driver_name = "video",
|
||||
.connect = usbh_video_data_intf_connect,
|
||||
.disconnect = usbh_video_data_intf_disconnect
|
||||
const struct usbh_class_driver video_streaming_class_driver = {
|
||||
.driver_name = "video_streaming",
|
||||
.connect = usbh_video_streaming_connect,
|
||||
.disconnect = usbh_video_streaming_disconnect
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info video_ctrl_intf_class_info = {
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info video_ctrl_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = USB_DEVICE_CLASS_VIDEO,
|
||||
.subclass = VIDEO_SC_VIDEOCONTROL,
|
||||
.protocol = VIDEO_PC_PROTOCOL_UNDEFINED,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.class_driver = &video_class_ctrl_intf_driver
|
||||
.class_driver = &video_ctrl_class_driver
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info video_data_intf_class_info = {
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info video_streaming_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = USB_DEVICE_CLASS_VIDEO,
|
||||
.subclass = VIDEO_SC_VIDEOSTREAMING,
|
||||
.protocol = VIDEO_PC_PROTOCOL_UNDEFINED,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.class_driver = &video_class_data_intf_driver
|
||||
.class_driver = &video_streaming_class_driver
|
||||
};
|
@ -41,6 +41,7 @@ struct usbh_video {
|
||||
uint16_t isoin_mps;
|
||||
uint16_t isoout_mps;
|
||||
bool is_opened;
|
||||
uint8_t current_format;
|
||||
uint16_t bcdVDC;
|
||||
uint8_t num_of_intf_altsettings;
|
||||
uint8_t num_of_formats;
|
||||
@ -51,19 +52,30 @@ struct usbh_video {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void usbh_video_inityuyv2rgb_table(void);
|
||||
void usbh_video_yuyv2rgb565(void *input, void *output, uint32_t len);
|
||||
|
||||
int usbh_video_get_cur(struct usbh_video *video_class, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len);
|
||||
int usbh_video_set_cur(struct usbh_video *video_class, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len);
|
||||
int usbh_videostreaming_get_cur_probe(struct usbh_video *video_class);
|
||||
int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize);
|
||||
int usbh_videostreaming_set_cur_commit(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize);
|
||||
int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex);
|
||||
int usbh_videostreaming_set_cur_commit(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex);
|
||||
|
||||
int usbh_video_open(struct usbh_video *video_class, uint8_t altsetting);
|
||||
int usbh_video_open(struct usbh_video *video_class,
|
||||
uint8_t format_type,
|
||||
uint16_t wWidth,
|
||||
uint16_t wHeight,
|
||||
uint8_t altsetting);
|
||||
int usbh_video_close(struct usbh_video *video_class);
|
||||
|
||||
void usbh_video_list_info(struct usbh_video *video_class);
|
||||
|
||||
void usbh_videostreaming_parse_mjpeg(struct usbh_urb *urb, struct usbh_videostreaming *stream);
|
||||
void usbh_videostreaming_parse_yuyv2rgb565(struct usbh_urb *urb, struct usbh_videostreaming *stream);
|
||||
void usbh_videostreaming_parse_yuyv2(struct usbh_urb *urb, struct usbh_videostreaming *stream);
|
||||
void usbh_videostreaming_output(uint8_t *input, uint32_t input_len);
|
||||
|
||||
void usbh_video_run(struct usbh_video *video_class);
|
||||
void usbh_video_stop(struct usbh_video *video_class);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ struct usbd_endpoint_cfg {
|
||||
uint8_t ep_addr; /* Endpoint addr with direction */
|
||||
uint8_t ep_type; /* Endpoint type */
|
||||
uint16_t ep_mps; /* Endpoint max packet size */
|
||||
uint8_t ep_mult; /* Endpoint additional transcations in micro frame */
|
||||
};
|
||||
|
||||
/**
|
||||
@ -44,6 +45,15 @@ int usb_dc_deinit(void);
|
||||
*/
|
||||
int usbd_set_address(const uint8_t addr);
|
||||
|
||||
/**
|
||||
* @brief Get USB device speed
|
||||
*
|
||||
* @param[in] port port index
|
||||
*
|
||||
* @return port speed, USB_SPEED_LOW or USB_SPEED_FULL or USB_SPEED_HIGH
|
||||
*/
|
||||
uint8_t usbd_get_port_speed(const uint8_t port);
|
||||
|
||||
/**
|
||||
* @brief configure and enable endpoint.
|
||||
*
|
||||
|
@ -548,6 +548,14 @@ struct usb_bos_header_descriptor {
|
||||
uint8_t bNumDeviceCaps;
|
||||
} __PACKED;
|
||||
|
||||
/* BOS Capability extension Descriptor*/
|
||||
struct usb_bos_capability_extension_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDevCapabilityType;
|
||||
uint32_t bmAttributes;
|
||||
} __PACKED;
|
||||
|
||||
/* BOS Capability platform Descriptor */
|
||||
struct usb_bos_capability_platform_descriptor {
|
||||
uint8_t bLength;
|
||||
@ -557,6 +565,18 @@ struct usb_bos_capability_platform_descriptor {
|
||||
uint8_t PlatformCapabilityUUID[16];
|
||||
} __PACKED;
|
||||
|
||||
/* BOS Capability superspeed Descriptor */
|
||||
struct usb_bos_capability_superspeed_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDevCapabilityType;
|
||||
uint8_t bmAttributes;
|
||||
uint16_t wSpeedsSupported;
|
||||
uint8_t bFunctionalitySupport;
|
||||
uint8_t bU1DevExitLat;
|
||||
uint16_t wU2DevExitLat;
|
||||
} __PACKED;
|
||||
|
||||
/* BOS Capability MS OS Descriptors version 2 */
|
||||
struct usb_bos_capability_msosv2_descriptor {
|
||||
uint32_t dwWindowsVersion;
|
||||
@ -572,14 +592,6 @@ struct usb_bos_capability_webusb_descriptor {
|
||||
uint8_t iLandingPage;
|
||||
} __PACKED;
|
||||
|
||||
/* BOS Capability extension Descriptor*/
|
||||
struct usb_bos_capability_extension_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDevCapabilityType;
|
||||
uint32_t bmAttributes;
|
||||
} __PACKED;
|
||||
|
||||
/* Microsoft OS 2.0 Platform Capability Descriptor
|
||||
* See https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/
|
||||
* microsoft-defined-usb-descriptors
|
||||
|
@ -56,6 +56,7 @@ struct usbh_urb {
|
||||
uint32_t timeout;
|
||||
int errorcode;
|
||||
uint32_t num_of_iso_packets;
|
||||
uint32_t start_frame;
|
||||
usbh_complete_callback_t complete;
|
||||
void *arg;
|
||||
struct usbh_iso_frame_packet iso_packet[0];
|
||||
@ -68,6 +69,12 @@ struct usbh_urb {
|
||||
*/
|
||||
int usb_hc_init(void);
|
||||
|
||||
/**
|
||||
* @brief Get frame number.
|
||||
*
|
||||
* @return frame number.
|
||||
*/
|
||||
uint16_t usbh_get_frame_number(void);
|
||||
/**
|
||||
* @brief control roothub.
|
||||
*
|
||||
|
@ -44,12 +44,12 @@
|
||||
#ifndef __ALIGNED
|
||||
#define __ALIGNED(x) __attribute__((aligned(x)))
|
||||
#endif
|
||||
#elif defined(__ICCARM__)
|
||||
#elif defined(__ICCARM__) || defined(__ICCRX__)
|
||||
#ifndef __USED
|
||||
#if __ICCARM_V8
|
||||
#define __USED __attribute__((used))
|
||||
#else
|
||||
#define __USED _Pragma("__root")
|
||||
#define __USED __root
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -6,6 +6,9 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#ifdef CONFIG_USBDEV_TX_RX_THREAD
|
||||
#include "usb_osal.h"
|
||||
#endif
|
||||
|
||||
/* general descriptor field offsets */
|
||||
#define DESC_bLength 0 /** Length offset */
|
||||
@ -23,6 +26,12 @@
|
||||
#define USB_EP_OUT_NUM 8
|
||||
#define USB_EP_IN_NUM 8
|
||||
|
||||
struct usbd_tx_rx_msg {
|
||||
uint8_t ep;
|
||||
uint32_t nbytes;
|
||||
usbd_endpoint_callback cb;
|
||||
};
|
||||
|
||||
USB_NOCACHE_RAM_SECTION struct usbd_core_cfg_priv {
|
||||
/** Setup packet */
|
||||
USB_MEM_ALIGNX struct usb_setup_packet setup;
|
||||
@ -35,17 +44,19 @@ USB_NOCACHE_RAM_SECTION struct usbd_core_cfg_priv {
|
||||
/** Zero length packet flag of control transfer */
|
||||
bool zlp_flag;
|
||||
/** Pointer to registered descriptors */
|
||||
#if defined(CHERRYUSB_VERSION) && (CHERRYUSB_VERSION > 0x000700)
|
||||
struct usb_descriptor *descriptors;
|
||||
#else
|
||||
const uint8_t *descriptors;
|
||||
#endif
|
||||
/* Buffer used for storing standard, class and vendor request data */
|
||||
USB_MEM_ALIGNX uint8_t req_data[CONFIG_USBDEV_REQUEST_BUFFER_LEN];
|
||||
|
||||
usbd_endpoint_callback in_ep_cb[USB_EP_IN_NUM];
|
||||
usbd_endpoint_callback out_ep_cb[USB_EP_OUT_NUM];
|
||||
|
||||
/** Variable to check whether the usb has been configured */
|
||||
bool configured;
|
||||
/** Currently selected configuration */
|
||||
uint8_t configuration;
|
||||
uint8_t speed;
|
||||
#ifdef CONFIG_USBDEV_TEST_MODE
|
||||
bool test_mode;
|
||||
#endif
|
||||
@ -58,6 +69,14 @@ static struct usb_msosv1_descriptor *msosv1_desc;
|
||||
static struct usb_msosv2_descriptor *msosv2_desc;
|
||||
static struct usb_bos_descriptor *bos_desc;
|
||||
|
||||
struct usbd_tx_rx_msg tx_msg[USB_EP_IN_NUM];
|
||||
struct usbd_tx_rx_msg rx_msg[USB_EP_OUT_NUM];
|
||||
|
||||
#ifdef CONFIG_USBDEV_TX_RX_THREAD
|
||||
usb_osal_mq_t usbd_tx_rx_mq;
|
||||
usb_osal_thread_t usbd_tx_rx_thread;
|
||||
#endif
|
||||
|
||||
static void usbd_class_event_notify_handler(uint8_t event, void *arg);
|
||||
|
||||
static void usbd_print_setup(struct usb_setup_packet *setup)
|
||||
@ -135,6 +154,119 @@ static bool usbd_reset_endpoint(const struct usb_endpoint_descriptor *ep_desc)
|
||||
*
|
||||
* @return true if the descriptor was found, false otherwise
|
||||
*/
|
||||
#if defined(CHERRYUSB_VERSION) && (CHERRYUSB_VERSION > 0x000700)
|
||||
static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
uint8_t type = 0U;
|
||||
uint8_t index = 0U;
|
||||
bool found = true;
|
||||
uint8_t str_len = 0;
|
||||
|
||||
type = HI_BYTE(type_index);
|
||||
index = LO_BYTE(type_index);
|
||||
|
||||
switch (type) {
|
||||
case USB_DESCRIPTOR_TYPE_DEVICE:
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->device_descriptor;
|
||||
*len = usbd_core_cfg.descriptors->device_descriptor[0];
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_CONFIGURATION:
|
||||
usbd_core_cfg.speed = usbd_get_port_speed(0);
|
||||
if (usbd_core_cfg.speed == USB_SPEED_HIGH) {
|
||||
if (usbd_core_cfg.descriptors->hs_config_descriptor[index]) {
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->hs_config_descriptor[index];
|
||||
*len = (usbd_core_cfg.descriptors->hs_config_descriptor[index][CONF_DESC_wTotalLength] |
|
||||
(usbd_core_cfg.descriptors->hs_config_descriptor[index][CONF_DESC_wTotalLength + 1] << 8));
|
||||
} else {
|
||||
found = false;
|
||||
}
|
||||
} else {
|
||||
if (usbd_core_cfg.descriptors->fs_config_descriptor[index]) {
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->fs_config_descriptor[index];
|
||||
*len = (usbd_core_cfg.descriptors->fs_config_descriptor[index][CONF_DESC_wTotalLength] |
|
||||
(usbd_core_cfg.descriptors->fs_config_descriptor[index][CONF_DESC_wTotalLength + 1] << 8));
|
||||
} else {
|
||||
found = false;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_STRING:
|
||||
if (index == USB_STRING_LANGID_INDEX) {
|
||||
(*data)[0] = 0x04;
|
||||
(*data)[1] = 0x03;
|
||||
(*data)[2] = 0x09;
|
||||
(*data)[3] = 0x04;
|
||||
*len = 4;
|
||||
} else if (index == USB_OSDESC_STRING_DESC_INDEX) {
|
||||
if (usbd_core_cfg.descriptors->msosv1_descriptor) {
|
||||
USB_LOG_INFO("read MS OS 1.0 descriptor string\r\n");
|
||||
*data = usbd_core_cfg.descriptors->msosv1_descriptor->string;
|
||||
*len = usbd_core_cfg.descriptors->msosv1_descriptor->string_len;
|
||||
} else {
|
||||
}
|
||||
} else {
|
||||
if (usbd_core_cfg.descriptors->string_descriptor[index - 1]) {
|
||||
str_len = strlen((const char *)usbd_core_cfg.descriptors->string_descriptor[index - 1]);
|
||||
|
||||
(*data)[0] = str_len * 2 + 2;
|
||||
(*data)[1] = 0x03;
|
||||
for (uint16_t i = 0; i < str_len; i++) {
|
||||
(*data)[i * 2 + 2] = usbd_core_cfg.descriptors->string_descriptor[index - 1][i];
|
||||
(*data)[i * 2 + 3] = 0;
|
||||
}
|
||||
|
||||
*len = str_len * 2 + 2;
|
||||
} else {
|
||||
found = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER:
|
||||
if (usbd_core_cfg.descriptors->device_quality_descriptor) {
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->device_quality_descriptor;
|
||||
*len = usbd_core_cfg.descriptors->device_quality_descriptor[0];
|
||||
} else {
|
||||
found = false;
|
||||
}
|
||||
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_OTHER_SPEED:
|
||||
if (usbd_core_cfg.speed == USB_SPEED_HIGH) {
|
||||
if (usbd_core_cfg.descriptors->fs_other_speed_descriptor) {
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->fs_other_speed_descriptor;
|
||||
*len = (usbd_core_cfg.descriptors->fs_other_speed_descriptor[CONF_DESC_wTotalLength] |
|
||||
(usbd_core_cfg.descriptors->fs_other_speed_descriptor[CONF_DESC_wTotalLength] << 8));
|
||||
} else {
|
||||
found = false;
|
||||
}
|
||||
} else {
|
||||
if (usbd_core_cfg.descriptors->hs_other_speed_descriptor) {
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->hs_other_speed_descriptor;
|
||||
*len = (usbd_core_cfg.descriptors->hs_other_speed_descriptor[CONF_DESC_wTotalLength] |
|
||||
(usbd_core_cfg.descriptors->hs_other_speed_descriptor[CONF_DESC_wTotalLength] << 8));
|
||||
} else {
|
||||
found = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_DESCRIPTOR_TYPE_BINARY_OBJECT_STORE:
|
||||
USB_LOG_INFO("read BOS descriptor string\r\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (found == false) {
|
||||
/* nothing found */
|
||||
USB_LOG_ERR("descriptor <type:%x,index:%x> not found!\r\n", type, index);
|
||||
}
|
||||
return found;
|
||||
}
|
||||
#else
|
||||
static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
uint8_t type = 0U;
|
||||
@ -220,6 +352,7 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l
|
||||
|
||||
return found;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief set USB configuration
|
||||
@ -235,11 +368,19 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l
|
||||
*/
|
||||
static bool usbd_set_configuration(uint8_t config_index, uint8_t alt_setting)
|
||||
{
|
||||
uint8_t *p = (uint8_t *)usbd_core_cfg.descriptors;
|
||||
uint8_t cur_alt_setting = 0xFF;
|
||||
uint8_t cur_config = 0xFF;
|
||||
bool found = false;
|
||||
|
||||
uint8_t *p;
|
||||
#if defined(CHERRYUSB_VERSION) && (CHERRYUSB_VERSION > 0x000700)
|
||||
if (usbd_core_cfg.speed == USB_SPEED_HIGH) {
|
||||
p = (uint8_t *)usbd_core_cfg.descriptors->hs_config_descriptor[0];
|
||||
} else {
|
||||
p = (uint8_t *)usbd_core_cfg.descriptors->fs_config_descriptor[0];
|
||||
}
|
||||
#else
|
||||
p = (uint8_t *)usbd_core_cfg.descriptors;
|
||||
#endif
|
||||
/* configure endpoints for this configuration/altsetting */
|
||||
while (p[DESC_bLength] != 0U) {
|
||||
switch (p[DESC_bDescriptorType]) {
|
||||
@ -289,13 +430,21 @@ static bool usbd_set_configuration(uint8_t config_index, uint8_t alt_setting)
|
||||
*/
|
||||
static bool usbd_set_interface(uint8_t iface, uint8_t alt_setting)
|
||||
{
|
||||
const uint8_t *p = usbd_core_cfg.descriptors;
|
||||
const uint8_t *if_desc = NULL;
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
uint8_t cur_alt_setting = 0xFF;
|
||||
uint8_t cur_iface = 0xFF;
|
||||
bool ret = false;
|
||||
|
||||
uint8_t *p;
|
||||
#if defined(CHERRYUSB_VERSION) && (CHERRYUSB_VERSION > 0x000700)
|
||||
if (usbd_core_cfg.speed == USB_SPEED_HIGH) {
|
||||
p = (uint8_t *)usbd_core_cfg.descriptors->hs_config_descriptor[0];
|
||||
} else {
|
||||
p = (uint8_t *)usbd_core_cfg.descriptors->fs_config_descriptor[0];
|
||||
}
|
||||
#else
|
||||
p = (uint8_t *)usbd_core_cfg.descriptors;
|
||||
#endif
|
||||
USB_LOG_DBG("iface %u alt_setting %u\r\n", iface, alt_setting);
|
||||
|
||||
while (p[DESC_bLength] != 0U) {
|
||||
@ -638,6 +787,40 @@ static int usbd_class_request_handler(struct usb_setup_packet *setup, uint8_t **
|
||||
*/
|
||||
static int usbd_vendor_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
#if defined(CHERRYUSB_VERSION) && (CHERRYUSB_VERSION > 0x000700)
|
||||
if (usbd_core_cfg.descriptors->msosv1_descriptor) {
|
||||
if (setup->bRequest == usbd_core_cfg.descriptors->msosv1_descriptor->vendor_code) {
|
||||
switch (setup->wIndex) {
|
||||
case 0x04:
|
||||
USB_LOG_INFO("get Compat ID\r\n");
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->msosv1_descriptor->compat_id;
|
||||
*len = usbd_core_cfg.descriptors->msosv1_descriptor->compat_id_len;
|
||||
return 0;
|
||||
case 0x05:
|
||||
USB_LOG_INFO("get Compat id properties\r\n");
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->msosv1_descriptor->comp_id_property;
|
||||
*len = usbd_core_cfg.descriptors->msosv1_descriptor->comp_id_property_len;
|
||||
return 0;
|
||||
default:
|
||||
USB_LOG_ERR("unknown vendor code\r\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else if (usbd_core_cfg.descriptors->msosv2_descriptor) {
|
||||
if (setup->bRequest == usbd_core_cfg.descriptors->msosv2_descriptor->vendor_code) {
|
||||
switch (setup->wIndex) {
|
||||
case WINUSB_REQUEST_GET_DESCRIPTOR_SET:
|
||||
USB_LOG_INFO("GET MS OS 2.0 Descriptor\r\n");
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->msosv2_descriptor->compat_id;
|
||||
*len = usbd_core_cfg.descriptors->msosv2_descriptor->compat_id_len;
|
||||
return 0;
|
||||
default:
|
||||
USB_LOG_ERR("unknown vendor code\r\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (msosv1_desc) {
|
||||
if (setup->bRequest == msosv1_desc->vendor_code) {
|
||||
switch (setup->wIndex) {
|
||||
@ -672,7 +855,7 @@ static int usbd_vendor_request_handler(struct usb_setup_packet *setup, uint8_t *
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
usb_slist_t *i;
|
||||
|
||||
usb_slist_for_each(i, &usbd_intf_head)
|
||||
@ -766,6 +949,7 @@ void usbd_event_reset_handler(void)
|
||||
usbd_set_address(0);
|
||||
usbd_core_cfg.configured = 0;
|
||||
usbd_core_cfg.configuration = 0;
|
||||
|
||||
#ifdef CONFIG_USBDEV_TEST_MODE
|
||||
usbd_core_cfg.test_mode = false;
|
||||
#endif
|
||||
@ -823,9 +1007,10 @@ void usbd_event_ep0_setup_complete_handler(uint8_t *psetup)
|
||||
}
|
||||
#endif
|
||||
/* Send smallest of requested and offered length */
|
||||
usbd_core_cfg.ep0_data_buf_residue = MIN(usbd_core_cfg.ep0_data_buf_len,
|
||||
setup->wLength);
|
||||
usbd_core_cfg.ep0_data_buf_residue = MIN(usbd_core_cfg.ep0_data_buf_len, setup->wLength);
|
||||
|
||||
#if defined(CHERRYUSB_VERSION) && (CHERRYUSB_VERSION > 0x000700)
|
||||
#else
|
||||
/* check if the data buf addr matches align size,if not, copy into align buf */
|
||||
#ifndef CONFIG_USBDEV_ALIGN_CHECK_DISABLE
|
||||
if (((unsigned long)usbd_core_cfg.ep0_data_buf) & (CONFIG_USB_ALIGN_SIZE - 1)) {
|
||||
@ -837,12 +1022,14 @@ void usbd_event_ep0_setup_complete_handler(uint8_t *psetup)
|
||||
memcpy(usbd_core_cfg.req_data, usbd_core_cfg.ep0_data_buf, usbd_core_cfg.ep0_data_buf_residue);
|
||||
usbd_core_cfg.ep0_data_buf = usbd_core_cfg.req_data;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
/* Send data or status to host */
|
||||
usbd_ep_start_write(USB_CONTROL_IN_EP0, usbd_core_cfg.ep0_data_buf, usbd_core_cfg.ep0_data_buf_residue);
|
||||
/*
|
||||
* Set ZLP flag when host asks for a bigger length and the data size is multiplier of USB_CTRL_EP_MPS,
|
||||
* to indicate the transfer done after zlp sent.
|
||||
* Set ZLP flag when host asks for a bigger length and the data size is
|
||||
* multiplier of USB_CTRL_EP_MPS, to indicate the transfer done after zlp
|
||||
* sent.
|
||||
*/
|
||||
if ((setup->wLength > usbd_core_cfg.ep0_data_buf_len) && (!(usbd_core_cfg.ep0_data_buf_len % USB_CTRL_EP_MPS))) {
|
||||
usbd_core_cfg.zlp_flag = true;
|
||||
@ -850,9 +1037,8 @@ void usbd_event_ep0_setup_complete_handler(uint8_t *psetup)
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_event_ep_in_complete_handler(uint8_t ep, uint32_t nbytes)
|
||||
void usbd_event_ep0_in_complete_handler(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
if (ep == USB_CONTROL_IN_EP0) {
|
||||
struct usb_setup_packet *setup = &usbd_core_cfg.setup;
|
||||
|
||||
usbd_core_cfg.ep0_data_buf += nbytes;
|
||||
@ -881,16 +1067,10 @@ void usbd_event_ep_in_complete_handler(uint8_t ep, uint32_t nbytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (usbd_core_cfg.in_ep_cb[ep & 0x7f]) {
|
||||
usbd_core_cfg.in_ep_cb[ep & 0x7f](ep, nbytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_event_ep_out_complete_handler(uint8_t ep, uint32_t nbytes)
|
||||
void usbd_event_ep0_out_complete_handler(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
if (ep == USB_CONTROL_OUT_EP0) {
|
||||
struct usb_setup_packet *setup = &usbd_core_cfg.setup;
|
||||
|
||||
if (nbytes > 0) {
|
||||
@ -917,17 +1097,70 @@ void usbd_event_ep_out_complete_handler(uint8_t ep, uint32_t nbytes)
|
||||
/* Read out status completely, do nothing */
|
||||
USB_LOG_DBG("EP0 recv out status\r\n");
|
||||
}
|
||||
} else {
|
||||
if (usbd_core_cfg.out_ep_cb[ep & 0x7f]) {
|
||||
usbd_core_cfg.out_ep_cb[ep & 0x7f](ep, nbytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_event_ep_in_complete_handler(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
#ifndef CONFIG_USBDEV_TX_RX_THREAD
|
||||
if (tx_msg[ep & 0x7f].cb) {
|
||||
tx_msg[ep & 0x7f].cb(ep, nbytes);
|
||||
}
|
||||
#else
|
||||
tx_msg[ep & 0x7f].nbytes = nbytes;
|
||||
usb_osal_mq_send(usbd_tx_rx_mq, (uint32_t)&tx_msg[ep & 0x7f]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void usbd_event_ep_out_complete_handler(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
#ifndef CONFIG_USBDEV_TX_RX_THREAD
|
||||
if (rx_msg[ep & 0x7f].cb) {
|
||||
rx_msg[ep & 0x7f].cb(ep, nbytes);
|
||||
}
|
||||
#else
|
||||
rx_msg[ep & 0x7f].nbytes = nbytes;
|
||||
usb_osal_mq_send(usbd_tx_rx_mq, (uint32_t)&rx_msg[ep & 0x7f]);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBDEV_TX_RX_THREAD
|
||||
static void usbdev_tx_rx_thread(void *argument)
|
||||
{
|
||||
struct usbd_tx_rx_msg *msg;
|
||||
int ret;
|
||||
|
||||
while (1) {
|
||||
ret = usb_osal_mq_recv(usbd_tx_rx_mq, (uint32_t *)&msg, 0xffffffff);
|
||||
if (ret < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (msg->cb) {
|
||||
msg->cb(msg->ep, msg->nbytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CHERRYUSB_VERSION) && (CHERRYUSB_VERSION > 0x000700)
|
||||
void usbd_desc_register(struct usb_descriptor *desc)
|
||||
{
|
||||
usbd_core_cfg.descriptors = desc;
|
||||
usbd_core_cfg.intf_offset = 0;
|
||||
tx_msg[0].ep = 0x80;
|
||||
tx_msg[0].cb = usbd_event_ep0_in_complete_handler;
|
||||
rx_msg[0].ep = 0x00;
|
||||
rx_msg[0].cb = usbd_event_ep0_out_complete_handler;
|
||||
}
|
||||
#else
|
||||
void usbd_desc_register(const uint8_t *desc)
|
||||
{
|
||||
usbd_core_cfg.descriptors = desc;
|
||||
usbd_core_cfg.intf_offset = 0;
|
||||
tx_msg[0].ep = 0x80;
|
||||
tx_msg[0].cb = usbd_event_ep0_in_complete_handler;
|
||||
rx_msg[0].ep = 0x00;
|
||||
rx_msg[0].cb = usbd_event_ep0_out_complete_handler;
|
||||
}
|
||||
|
||||
/* Register MS OS Descriptors version 1 */
|
||||
@ -946,6 +1179,7 @@ void usbd_bos_desc_register(struct usb_bos_descriptor *desc)
|
||||
{
|
||||
bos_desc = desc;
|
||||
}
|
||||
#endif
|
||||
|
||||
void usbd_add_interface(struct usbd_interface *intf)
|
||||
{
|
||||
@ -957,9 +1191,11 @@ void usbd_add_interface(struct usbd_interface *intf)
|
||||
void usbd_add_endpoint(struct usbd_endpoint *ep)
|
||||
{
|
||||
if (ep->ep_addr & 0x80) {
|
||||
usbd_core_cfg.in_ep_cb[ep->ep_addr & 0x7f] = ep->ep_cb;
|
||||
tx_msg[ep->ep_addr & 0x7f].ep = ep->ep_addr;
|
||||
tx_msg[ep->ep_addr & 0x7f].cb = ep->ep_cb;
|
||||
} else {
|
||||
usbd_core_cfg.out_ep_cb[ep->ep_addr & 0x7f] = ep->ep_cb;
|
||||
rx_msg[ep->ep_addr & 0x7f].ep = ep->ep_addr;
|
||||
rx_msg[ep->ep_addr & 0x7f].cb = ep->ep_cb;
|
||||
}
|
||||
}
|
||||
|
||||
@ -970,6 +1206,16 @@ bool usb_device_is_configured(void)
|
||||
|
||||
int usbd_initialize(void)
|
||||
{
|
||||
#ifdef CONFIG_USBDEV_TX_RX_THREAD
|
||||
usbd_tx_rx_mq = usb_osal_mq_create(32);
|
||||
if (usbd_tx_rx_mq == NULL) {
|
||||
return -1;
|
||||
}
|
||||
usbd_tx_rx_thread = usb_osal_thread_create("usbd_tx_rx", CONFIG_USBDEV_TX_RX_STACKSIZE, CONFIG_USBDEV_TX_RX_PRIO, usbdev_tx_rx_thread, NULL);
|
||||
if (usbd_tx_rx_thread == NULL) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return usb_dc_init();
|
||||
}
|
||||
|
||||
@ -978,5 +1224,7 @@ int usbd_deinitialize(void)
|
||||
usbd_core_cfg.intf_offset = 0;
|
||||
usb_slist_init(&usbd_intf_head);
|
||||
usb_dc_deinit();
|
||||
#ifdef CONFIG_USBDEV_TX_RX_THREAD
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -62,10 +62,25 @@ struct usbd_interface {
|
||||
uint8_t intf_num;
|
||||
};
|
||||
|
||||
struct usb_descriptor {
|
||||
const uint8_t *device_descriptor;
|
||||
const uint8_t **fs_config_descriptor;
|
||||
const uint8_t **hs_config_descriptor;
|
||||
const uint8_t *device_quality_descriptor;
|
||||
const uint8_t *other_speed_descriptor;
|
||||
const char **string_descriptor;
|
||||
struct usb_msosv1_descriptor *msosv1_descriptor;
|
||||
struct usb_msosv2_descriptor *msosv2_descriptor;
|
||||
struct usb_bos_descriptor *bos_descriptor;
|
||||
};
|
||||
#if defined(CHERRYUSB_VERSION) && (CHERRYUSB_VERSION > 0x000700)
|
||||
void usbd_desc_register(struct usb_descriptor *desc);
|
||||
#else
|
||||
void usbd_desc_register(const uint8_t *desc);
|
||||
void usbd_msosv1_desc_register(struct usb_msosv1_descriptor *desc);
|
||||
void usbd_msosv2_desc_register(struct usb_msosv2_descriptor *desc);
|
||||
void usbd_bos_desc_register(struct usb_bos_descriptor *desc);
|
||||
#endif
|
||||
|
||||
void usbd_add_interface(struct usbd_interface *intf);
|
||||
void usbd_add_endpoint(struct usbd_endpoint *ep);
|
||||
|
@ -109,7 +109,11 @@ static const struct usbh_class_driver *usbh_find_class_driver(uint8_t class, uin
|
||||
if (index->vid == vid && index->pid == pid && index->class == class) {
|
||||
return index->class_driver;
|
||||
}
|
||||
} else if (index->match_flags & (USB_CLASS_MATCH_INTF_CLASS)) {
|
||||
} else if ((index->match_flags & (USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS)) == (USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS)) {
|
||||
if (index->class == class && index->subclass == subclass) {
|
||||
return index->class_driver;
|
||||
}
|
||||
} else if ((index->match_flags & (USB_CLASS_MATCH_INTF_CLASS)) == USB_CLASS_MATCH_INTF_CLASS) {
|
||||
if (index->class == class) {
|
||||
return index->class_driver;
|
||||
}
|
||||
@ -618,14 +622,14 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
||||
USB_LOG_INFO("Loading %s class driver\r\n", class_driver->driver_name);
|
||||
ret = CLASS_CONNECT(hport, i);
|
||||
if (ret < 0) {
|
||||
ret = CLASS_DISCONNECT(hport, i);
|
||||
CLASS_DISCONNECT(hport, i);
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
usbh_device_mount_done_callback(hport);
|
||||
errout:
|
||||
if (ret < 0) {
|
||||
hport->config.config_desc.bNumInterfaces = 0;
|
||||
usbh_hport_deactivate_ep0(hport);
|
||||
}
|
||||
if (hport->raw_config_desc) {
|
||||
@ -689,6 +693,9 @@ int usbh_initialize(void)
|
||||
extern uint32_t __usbh_class_info_end__;
|
||||
usbh_class_info_table_begin = (struct usbh_class_info *)&__usbh_class_info_start__;
|
||||
usbh_class_info_table_end = (struct usbh_class_info *)&__usbh_class_info_end__;
|
||||
#elif defined(__ICCARM__) || defined(__ICCRX__)
|
||||
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 */
|
||||
@ -795,11 +802,3 @@ int lsusb(int argc, char **argv)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbh_device_mount_done_callback(struct usbh_hubport *hport)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usbh_device_unmount_done_callback(struct usbh_hubport *hport)
|
||||
{
|
||||
}
|
||||
|
@ -39,6 +39,9 @@ extern "C" {
|
||||
#define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1)
|
||||
#elif defined(__GNUC__)
|
||||
#define CLASS_INFO_DEFINE __attribute__((section(".usbh_class_info"))) __USED __ALIGNED(1)
|
||||
#elif defined(__ICCARM__) || defined(__ICCRX__)
|
||||
#pragma section="usbh_class_info"
|
||||
#define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1)
|
||||
#endif
|
||||
|
||||
static inline void usbh_control_urb_fill(struct usbh_urb *urb,
|
||||
@ -160,7 +163,6 @@ struct usbh_hub {
|
||||
struct usb_hub_descriptor hub_desc;
|
||||
struct usbh_hubport child[CONFIG_USBHOST_MAX_EHPORTS];
|
||||
struct usbh_hubport *parent;
|
||||
usb_slist_t hub_event_list;
|
||||
};
|
||||
|
||||
int usbh_hport_activate_epx(usbh_pipe_t *pipe, struct usbh_hubport *hport, struct usb_endpoint_descriptor *ep_desc);
|
||||
@ -181,8 +183,6 @@ int usbh_initialize(void);
|
||||
struct usbh_hubport *usbh_find_hubport(uint8_t dev_addr);
|
||||
void *usbh_find_class_instance(const char *devname);
|
||||
|
||||
void usbh_device_mount_done_callback(struct usbh_hubport *hport);
|
||||
void usbh_device_unmount_done_callback(struct usbh_hubport *hport);
|
||||
|
||||
int lsusb(int argc, char **argv);
|
||||
#ifdef __cplusplus
|
||||
|
@ -12,12 +12,11 @@
|
||||
typedef void *usb_osal_thread_t;
|
||||
typedef void *usb_osal_sem_t;
|
||||
typedef void *usb_osal_mutex_t;
|
||||
typedef void *usb_osal_mq_t;
|
||||
typedef void (*usb_thread_entry_t)(void *argument);
|
||||
|
||||
usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args);
|
||||
|
||||
void usb_osal_timer_init(uint32_t poll_ms, void (*hub_poll_callback)(void));
|
||||
|
||||
usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count);
|
||||
void usb_osal_sem_delete(usb_osal_sem_t sem);
|
||||
int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout);
|
||||
@ -28,10 +27,13 @@ void usb_osal_mutex_delete(usb_osal_mutex_t mutex);
|
||||
int usb_osal_mutex_take(usb_osal_mutex_t mutex);
|
||||
int usb_osal_mutex_give(usb_osal_mutex_t mutex);
|
||||
|
||||
usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs);
|
||||
int usb_osal_mq_send(usb_osal_mq_t mq, uint32_t addr);
|
||||
int usb_osal_mq_recv(usb_osal_mq_t mq, uint32_t *addr, uint32_t timeout);
|
||||
|
||||
size_t usb_osal_enter_critical_section(void);
|
||||
void usb_osal_leave_critical_section(size_t flag);
|
||||
|
||||
void usb_osal_msleep(uint32_t delay);
|
||||
|
||||
#endif /* USB_OSAL_H */
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <FreeRTOS.h>
|
||||
#include "semphr.h"
|
||||
#include "timers.h"
|
||||
#include "event_groups.h"
|
||||
|
||||
usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args)
|
||||
{
|
||||
@ -17,13 +18,6 @@ usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size,
|
||||
return (usb_osal_thread_t)htask;
|
||||
}
|
||||
|
||||
void usb_osal_timer_init(uint32_t poll_ms, void (*hub_poll_callback)(void))
|
||||
{
|
||||
TimerHandle_t handle = xTimerCreate("usbh_hub_poll", poll_ms, pdTRUE, 0, (TimerCallbackFunction_t)hub_poll_callback);
|
||||
|
||||
xTimerStart(handle, 1000);
|
||||
}
|
||||
|
||||
usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count)
|
||||
{
|
||||
return (usb_osal_sem_t)xSemaphoreCreateCounting(1, initial_count);
|
||||
@ -49,7 +43,7 @@ int usb_osal_sem_give(usb_osal_sem_t sem)
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
return (ret == pdPASS) ? 0 : -EINVAL;
|
||||
return (ret == pdPASS) ? 0 : -ETIMEDOUT;
|
||||
}
|
||||
|
||||
usb_osal_mutex_t usb_osal_mutex_create(void)
|
||||
@ -69,7 +63,30 @@ int usb_osal_mutex_take(usb_osal_mutex_t mutex)
|
||||
|
||||
int usb_osal_mutex_give(usb_osal_mutex_t mutex)
|
||||
{
|
||||
return (xSemaphoreGive((SemaphoreHandle_t)mutex) == pdPASS) ? 0 : -EINVAL;
|
||||
return (xSemaphoreGive((SemaphoreHandle_t)mutex) == pdPASS) ? 0 : -ETIMEDOUT;
|
||||
}
|
||||
|
||||
usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs)
|
||||
{
|
||||
return (usb_osal_mq_t)xQueueCreate(max_msgs, 4);
|
||||
}
|
||||
|
||||
int usb_osal_mq_send(usb_osal_mq_t mq, uint32_t addr)
|
||||
{
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
int ret;
|
||||
|
||||
ret = xQueueSendFromISR((usb_osal_mq_t)mq, &addr, &xHigherPriorityTaskWoken);
|
||||
if (ret == pdPASS) {
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
return (ret == pdPASS) ? 0 : -ETIMEDOUT;
|
||||
}
|
||||
|
||||
int usb_osal_mq_recv(usb_osal_mq_t mq, uint32_t *addr, uint32_t timeout)
|
||||
{
|
||||
return (xQueueReceive((usb_osal_mq_t)mq, addr, timeout) == pdPASS) ? 0 : -ETIMEDOUT;
|
||||
}
|
||||
|
||||
size_t usb_osal_enter_critical_section(void)
|
||||
|
@ -32,9 +32,9 @@ int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout)
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
result = rt_sem_take((rt_sem_t)sem, rt_tick_from_millisecond(timeout));
|
||||
if (result == RT_ETIMEOUT) {
|
||||
if (result == -RT_ETIMEOUT) {
|
||||
ret = -ETIMEDOUT;
|
||||
} else if (result == RT_ERROR) {
|
||||
} else if (result == -RT_ERROR) {
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
ret = 0;
|
||||
@ -68,6 +68,33 @@ int usb_osal_mutex_give(usb_osal_mutex_t mutex)
|
||||
return (int)rt_mutex_release((rt_mutex_t)mutex);
|
||||
}
|
||||
|
||||
usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs)
|
||||
{
|
||||
return (usb_osal_mq_t)rt_mq_create("usbh_mq", 4, max_msgs, RT_IPC_FLAG_FIFO);
|
||||
}
|
||||
|
||||
int usb_osal_mq_send(usb_osal_mq_t mq, uint32_t addr)
|
||||
{
|
||||
return rt_mq_send((rt_mq_t)mq, &addr, 4);
|
||||
}
|
||||
|
||||
int usb_osal_mq_recv(usb_osal_mq_t mq, uint32_t *addr, uint32_t timeout)
|
||||
{
|
||||
int ret = 0;
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
result = rt_mq_recv((rt_mq_t)mq, addr, 4, rt_tick_from_millisecond(timeout));
|
||||
if (result == -RT_ETIMEOUT) {
|
||||
ret = -ETIMEDOUT;
|
||||
} else if (result == -RT_ERROR) {
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return (int)ret;
|
||||
}
|
||||
|
||||
size_t usb_osal_enter_critical_section(void)
|
||||
{
|
||||
return rt_hw_interrupt_disable();
|
||||
|
@ -31,7 +31,7 @@
|
||||
|
||||
#define CONFIG_USB_EHCI_QH_NUM CONFIG_USBHOST_PIPE_NUM
|
||||
#define CONFIG_USB_EHCI_QTD_NUM (CONFIG_USBHOST_PIPE_NUM * 3)
|
||||
#define CONFIG_USB_EHCI_ITD_NUM 256
|
||||
#define CONFIG_USB_EHCI_ITD_NUM 10
|
||||
|
||||
extern uint8_t usbh_get_port_speed(const uint8_t port);
|
||||
|
||||
@ -53,9 +53,9 @@ struct ehci_pipe {
|
||||
struct usbh_hubport *hport;
|
||||
struct ehci_qh_hw *qh;
|
||||
struct usbh_urb *urb;
|
||||
struct ehci_itd_hw *itdpool;
|
||||
uint32_t itd_num;
|
||||
uint32_t used_itd_num;
|
||||
uint16_t current_itd;
|
||||
uint16_t used_itd_num;
|
||||
uint16_t start_frame;
|
||||
usb_slist_t iso_list;
|
||||
};
|
||||
|
||||
@ -71,14 +71,12 @@ struct ehci_qtd_hw {
|
||||
|
||||
struct ehci_itd_hw {
|
||||
struct ehci_itd hw;
|
||||
struct usbh_iso_frame_packet *iso_packet;
|
||||
uint32_t start_frame;
|
||||
usb_slist_t list;
|
||||
} __attribute__((aligned(32)));
|
||||
|
||||
struct ehci_hcd {
|
||||
bool ehci_qh_used[CONFIG_USB_EHCI_QH_NUM];
|
||||
bool ehci_qtd_used[CONFIG_USB_EHCI_QTD_NUM];
|
||||
bool ehci_itd_used[CONFIG_USB_EHCI_ITD_NUM];
|
||||
struct ehci_pipe pipe_pool[CONFIG_USB_EHCI_QH_NUM];
|
||||
} g_ehci_hcd;
|
||||
|
||||
@ -155,7 +153,31 @@ static void ehci_qtd_free(struct ehci_qtd_hw *qtd)
|
||||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
static struct ehci_itd_hw *ehci_itd_alloc(void)
|
||||
{
|
||||
struct ehci_itd_hw *itd;
|
||||
for (uint32_t i = 0; i < CONFIG_USB_EHCI_ITD_NUM; i++) {
|
||||
if (!g_ehci_hcd.ehci_itd_used[i]) {
|
||||
g_ehci_hcd.ehci_itd_used[i] = true;
|
||||
itd = &ehci_itd_pool[i];
|
||||
memset(itd, 0, sizeof(struct ehci_itd_hw));
|
||||
return itd;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void ehci_itd_free(struct ehci_itd_hw *itd)
|
||||
{
|
||||
for (uint32_t i = 0; i < CONFIG_USB_EHCI_ITD_NUM; i++) {
|
||||
if (&ehci_itd_pool[i] == itd) {
|
||||
g_ehci_hcd.ehci_itd_used[i] = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
static struct ehci_pipe *ehci_pipe_alloc(void)
|
||||
{
|
||||
int pipe;
|
||||
@ -203,18 +225,18 @@ static inline void ehci_qh_remove(struct ehci_qh_hw *head, struct ehci_qh_hw *n)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void ehci_itd_add_head(struct ehci_itd_hw *itd)
|
||||
static inline void ehci_itd_add_head(struct ehci_itd_hw *itd, uint32_t sched_frame)
|
||||
{
|
||||
itd->hw.nlp = g_framelist[itd->start_frame];
|
||||
g_framelist[itd->start_frame] = ITD_NLP_ITD(itd);
|
||||
itd->hw.nlp = g_framelist[sched_frame];
|
||||
g_framelist[sched_frame] = ITD_NLP_ITD(itd);
|
||||
}
|
||||
|
||||
static inline void ehci_itd_remove(struct ehci_itd_hw *itd)
|
||||
static inline void ehci_itd_remove(struct ehci_itd_hw *itd, uint32_t sched_frame)
|
||||
{
|
||||
if (g_framelist[itd->start_frame] == ITD_NLP_ITD(itd)) {
|
||||
g_framelist[itd->start_frame] = itd->hw.nlp;
|
||||
if (g_framelist[sched_frame] == ITD_NLP_ITD(itd)) {
|
||||
g_framelist[sched_frame] = itd->hw.nlp;
|
||||
} else {
|
||||
struct ehci_itd_hw *tmp_itd = EHCI_ADDR2ITD(g_framelist[itd->start_frame]);
|
||||
struct ehci_itd_hw *tmp_itd = EHCI_ADDR2ITD(g_framelist[sched_frame]);
|
||||
while ((EHCI_ADDR2ITD(tmp_itd->hw.nlp) != itd) && tmp_itd) {
|
||||
tmp_itd = EHCI_ADDR2ITD(tmp_itd->hw.nlp);
|
||||
}
|
||||
@ -405,11 +427,6 @@ static void ehci_itd_tscl_fill(struct ehci_itd_hw *itd,
|
||||
ITD_TSCL_STATUS_ACTIVE; /* Status */
|
||||
}
|
||||
|
||||
static uint16_t ehci_get_frame_id(void)
|
||||
{
|
||||
return (EHCI_HCOR->frindex & EHCI_FRINDEX_MASK) >> 3;
|
||||
}
|
||||
|
||||
static struct ehci_qh_hw *ehci_control_pipe_init(struct ehci_pipe *pipe, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen)
|
||||
{
|
||||
struct ehci_qh_hw *qh = NULL;
|
||||
@ -678,59 +695,53 @@ static struct ehci_qh_hw *ehci_intr_pipe_init(struct ehci_pipe *pipe, uint8_t *b
|
||||
static int ehci_iso_pipe_init(struct ehci_pipe *pipe, struct usbh_iso_frame_packet *iso_packet, uint32_t num_of_iso_packets)
|
||||
{
|
||||
struct ehci_itd_hw *itd;
|
||||
struct usbh_urb *urb;
|
||||
uint32_t start_addr;
|
||||
uint16_t next_frame;
|
||||
uint16_t sched_frame;
|
||||
uint32_t bufaddr_in_uframe;
|
||||
uint32_t buflen_in_uframe;
|
||||
uint32_t itd_nums;
|
||||
uint32_t num_of_used_iso_packets = 0;
|
||||
size_t flags;
|
||||
uint32_t used_iso_packets;
|
||||
|
||||
//EHCI_HCOR->usbcmd &= ~EHCI_USBCMD_PSEN;
|
||||
|
||||
if (pipe->speed == USB_SPEED_HIGH) {
|
||||
itd_nums = (num_of_iso_packets + 7) / 8;
|
||||
next_frame = (ehci_get_frame_id() + 2) & 0x3ff;
|
||||
used_iso_packets = 0;
|
||||
|
||||
if (itd_nums > pipe->itd_num) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
urb = pipe->urb;
|
||||
sched_frame = urb->start_frame;
|
||||
|
||||
pipe->current_itd = 0;
|
||||
pipe->used_itd_num = itd_nums;
|
||||
ehci_iso_pipe_add_tail(pipe);
|
||||
|
||||
for (uint32_t i = 0; i < itd_nums; i++) {
|
||||
itd = &pipe->itdpool[i];
|
||||
|
||||
itd = &ehci_itd_pool[i];
|
||||
memset(itd, 0, sizeof(struct ehci_itd_hw));
|
||||
|
||||
start_addr = ((uint32_t)iso_packet[used_iso_packets].transfer_buffer);
|
||||
|
||||
/* fill itd bpl */
|
||||
start_addr = ((uint32_t)iso_packet[num_of_used_iso_packets].transfer_buffer);
|
||||
|
||||
itd->iso_packet = &iso_packet[num_of_used_iso_packets];
|
||||
|
||||
ehci_itd_bpl_fill(itd, pipe, start_addr);
|
||||
|
||||
/* fill itd tscl for micro-frame */
|
||||
for (uint8_t mf = 0; mf < 8; mf++) {
|
||||
bufaddr_in_uframe = ((uint32_t)iso_packet[num_of_used_iso_packets].transfer_buffer);
|
||||
buflen_in_uframe = iso_packet[num_of_used_iso_packets].transfer_buffer_length;
|
||||
bufaddr_in_uframe = ((uint32_t)iso_packet[used_iso_packets].transfer_buffer);
|
||||
buflen_in_uframe = iso_packet[used_iso_packets].transfer_buffer_length;
|
||||
ehci_itd_tscl_fill(itd, pipe, mf, start_addr, bufaddr_in_uframe, buflen_in_uframe);
|
||||
num_of_used_iso_packets++;
|
||||
if (num_of_used_iso_packets == num_of_iso_packets) {
|
||||
used_iso_packets++;
|
||||
if (used_iso_packets == num_of_iso_packets) {
|
||||
itd->hw.tscl[mf] |= ITD_TSCL_IOC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
flags = usb_osal_enter_critical_section();
|
||||
|
||||
itd->start_frame = next_frame;
|
||||
ehci_itd_add_head(itd);
|
||||
next_frame = (next_frame + 1) & 0x3ff;
|
||||
usb_osal_leave_critical_section(flags);
|
||||
ehci_itd_add_head(itd, sched_frame);
|
||||
sched_frame = (sched_frame + 1) & 0x3ff;
|
||||
}
|
||||
|
||||
ehci_iso_pipe_add_tail(pipe);
|
||||
} else {
|
||||
}
|
||||
//EHCI_HCOR->usbcmd |= EHCI_USBCMD_PSEN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -837,27 +848,18 @@ static void ehci_kill_qh(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh)
|
||||
ehci_qh_free(qh);
|
||||
}
|
||||
|
||||
static void ehci_check_itd(struct ehci_itd_hw *itd)
|
||||
static int ehci_check_itd(struct ehci_itd_hw *itd, struct usbh_iso_frame_packet *iso_packet)
|
||||
{
|
||||
struct usbh_iso_frame_packet *iso_packet;
|
||||
|
||||
iso_packet = itd->iso_packet;
|
||||
|
||||
for (uint8_t mf = 0; mf < 8; mf++) {
|
||||
if (itd->hw.tscl[mf] & ITD_TSCL_STATUS_MASK) {
|
||||
if (itd->hw.tscl[mf] & ITD_TSCL_STATUS_XACTERR) {
|
||||
iso_packet[mf].errorcode = -EIO;
|
||||
} else if (itd->hw.tscl[mf] & ITD_TSCL_STATUS_BABBLE) {
|
||||
iso_packet[mf].errorcode = -EPERM;
|
||||
} else if (itd->hw.tscl[mf] & ITD_TSCL_STATUS_DBERROR) {
|
||||
iso_packet[mf].errorcode = -EIO;
|
||||
} else if (itd->hw.tscl[mf] & ITD_TSCL_STATUS_ACTIVE) {
|
||||
}
|
||||
return -EIO;
|
||||
} else {
|
||||
iso_packet[mf].actual_length = ((itd->hw.tscl[mf] & ITD_TSCL_LENGTH_MASK) >> ITD_TSCL_LENGTH_SHIFT);
|
||||
iso_packet[mf].errorcode = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbh_reset_port(const uint8_t port)
|
||||
@ -992,7 +994,7 @@ int usb_hc_init(void)
|
||||
#error Unsupported frame size list size
|
||||
#endif
|
||||
|
||||
regval |= EHCI_USBCMD_ITHRE_1MF;
|
||||
regval |= EHCI_USBCMD_ITHRE_8MF;
|
||||
regval |= EHCI_USBCMD_ASEN;
|
||||
regval |= EHCI_USBCMD_PSEN;
|
||||
regval |= EHCI_USBCMD_RUN;
|
||||
@ -1023,6 +1025,11 @@ int usb_hc_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t usbh_get_frame_number(void)
|
||||
{
|
||||
return (((EHCI_HCOR->frindex & EHCI_FRINDEX_MASK) >> 3) & 0x3ff);
|
||||
}
|
||||
|
||||
int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
{
|
||||
uint8_t nports;
|
||||
@ -1202,11 +1209,6 @@ int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg)
|
||||
ppipe->dev_addr = ep_cfg->hport->dev_addr;
|
||||
ppipe->hport = ep_cfg->hport;
|
||||
|
||||
if (ppipe->ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
|
||||
ppipe->itdpool = ehci_itd_pool;
|
||||
ppipe->itd_num = CONFIG_USB_EHCI_ITD_NUM;
|
||||
}
|
||||
|
||||
/* restore variable */
|
||||
ppipe->inuse = true;
|
||||
ppipe->waitsem = waitsem;
|
||||
@ -1257,8 +1259,6 @@ int usbh_submit_urb(struct usbh_urb *urb)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
flags = usb_osal_enter_critical_section();
|
||||
|
||||
if (!pipe->hport->connected) {
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -1267,6 +1267,8 @@ int usbh_submit_urb(struct usbh_urb *urb)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
flags = usb_osal_enter_critical_section();
|
||||
|
||||
pipe->waiter = false;
|
||||
pipe->xfrd = 0;
|
||||
pipe->qh = NULL;
|
||||
@ -1298,12 +1300,7 @@ int usbh_submit_urb(struct usbh_urb *urb)
|
||||
}
|
||||
break;
|
||||
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
|
||||
ret = ehci_iso_pipe_init(pipe, urb->iso_packet, urb->num_of_iso_packets);
|
||||
if (ret < 0) {
|
||||
pipe->urb = NULL;
|
||||
pipe->waiter = false;
|
||||
return ret;
|
||||
}
|
||||
ehci_iso_pipe_init(pipe, urb->iso_packet, urb->num_of_iso_packets);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -1315,10 +1312,8 @@ int usbh_submit_urb(struct usbh_urb *urb)
|
||||
if (ret < 0) {
|
||||
goto errout_timeout;
|
||||
}
|
||||
if (pipe->ep_type != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
|
||||
ret = urb->errorcode;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
errout_timeout:
|
||||
/* Timeout will run here */
|
||||
@ -1333,6 +1328,7 @@ int usbh_kill_urb(struct usbh_urb *urb)
|
||||
struct ehci_pipe *iso_pipe;
|
||||
struct ehci_qh_hw *qh = NULL;
|
||||
struct ehci_itd_hw *itd;
|
||||
uint32_t sched_frame;
|
||||
usb_slist_t *i;
|
||||
|
||||
size_t flags;
|
||||
@ -1378,11 +1374,12 @@ int usbh_kill_urb(struct usbh_urb *urb)
|
||||
iso_pipe = usb_slist_entry(i, struct ehci_pipe, iso_list);
|
||||
|
||||
if (pipe == iso_pipe) {
|
||||
sched_frame = urb->start_frame;
|
||||
for (uint32_t j = 0; j < pipe->used_itd_num; j++) {
|
||||
itd = &pipe->itdpool[j];
|
||||
ehci_check_itd(itd);
|
||||
itd = &ehci_itd_pool[j];
|
||||
/* remove itd from list */
|
||||
ehci_itd_remove(itd);
|
||||
ehci_itd_remove(itd, sched_frame);
|
||||
urb->start_frame = (sched_frame + 1) & 0x3ff;
|
||||
}
|
||||
pipe->used_itd_num = 0;
|
||||
ehci_iso_pipe_remove(pipe);
|
||||
@ -1437,19 +1434,27 @@ static void ehci_scan_isochronous_list(void)
|
||||
{
|
||||
struct ehci_itd_hw *itd;
|
||||
struct ehci_pipe *pipe;
|
||||
struct usbh_urb *urb;
|
||||
uint32_t sched_frame;
|
||||
usb_slist_t *i;
|
||||
int errorcode = 0;
|
||||
|
||||
usb_slist_for_each(i, &iso_pipe_list_head)
|
||||
{
|
||||
pipe = usb_slist_entry(i, struct ehci_pipe, iso_list);
|
||||
urb = pipe->urb;
|
||||
|
||||
sched_frame = urb->start_frame;
|
||||
|
||||
for (uint32_t j = 0; j < pipe->used_itd_num; j++) {
|
||||
itd = &pipe->itdpool[j];
|
||||
ehci_check_itd(itd);
|
||||
itd = &ehci_itd_pool[j];
|
||||
errorcode = ehci_check_itd(itd, &urb->iso_packet[j * 8]);
|
||||
/* remove itd from list */
|
||||
ehci_itd_remove(itd);
|
||||
ehci_itd_remove(itd, sched_frame);
|
||||
urb->start_frame = (sched_frame + 1) & 0x3ff;
|
||||
urb->errorcode = errorcode;
|
||||
}
|
||||
pipe->used_itd_num = 0;
|
||||
|
||||
ehci_iso_pipe_remove(pipe);
|
||||
ehci_pipe_waitup(pipe);
|
||||
}
|
||||
@ -1490,6 +1495,16 @@ void USBH_IRQHandler(void)
|
||||
usb_osal_sem_give(pipe->waitsem);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t index = 0; index < CONFIG_USB_EHCI_QH_NUM; index++) {
|
||||
g_ehci_hcd.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;
|
||||
}
|
||||
for (uint8_t index = 0; index < CONFIG_USB_EHCI_ITD_NUM; index++) {
|
||||
g_ehci_hcd.ehci_itd_used[index] = false;
|
||||
}
|
||||
}
|
||||
usbh_roothub_thread_wakeup(port + 1);
|
||||
}
|
||||
|
@ -195,25 +195,42 @@ int hid_test(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void usbh_device_mount_done_callback(struct usbh_hubport *hport)
|
||||
{
|
||||
}
|
||||
|
||||
void usbh_device_unmount_done_callback(struct usbh_hubport *hport)
|
||||
{
|
||||
}
|
||||
|
||||
static void usbh_class_test_thread(void *argument)
|
||||
{
|
||||
while (1) {
|
||||
printf("helloworld\r\n");
|
||||
//printf("helloworld\r\n");
|
||||
usb_osal_msleep(1000);
|
||||
cdc_acm_test();
|
||||
msc_test();
|
||||
hid_test();
|
||||
//video_test();
|
||||
}
|
||||
}
|
||||
|
||||
void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class)
|
||||
{
|
||||
}
|
||||
|
||||
void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class)
|
||||
{
|
||||
}
|
||||
|
||||
void usbh_hid_run(struct usbh_hid *hid_class)
|
||||
{
|
||||
}
|
||||
|
||||
void usbh_hid_stop(struct usbh_hid *hid_class)
|
||||
{
|
||||
}
|
||||
|
||||
void usbh_msc_run(struct usbh_msc *msc_class)
|
||||
{
|
||||
}
|
||||
|
||||
void usbh_msc_stop(struct usbh_msc *msc_class)
|
||||
{
|
||||
}
|
||||
|
||||
void usbh_class_test(void)
|
||||
{
|
||||
usb_osal_thread_create("usbh_test", 4096, CONFIG_USBHOST_PSC_PRIO + 1, usbh_class_test_thread, NULL);
|
||||
|
Reference in New Issue
Block a user