Initial commit: TXW82x FPV v2.7.0.7-42229 SDK + project sources
This commit is contained in:
368
sdk/lib/bus/rttusb/bsp/drv_usb11d.c
Normal file
368
sdk/lib/bus/rttusb/bsp/drv_usb11d.c
Normal file
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2017-10-30 ZYH the first version
|
||||
*/
|
||||
|
||||
/*
|
||||
针对 USB DMA RX , 需做的内存预留大小为 4 字节, 防止 DMA 内存越界引起的内存错误问题
|
||||
|
||||
USB1.1 SIE:
|
||||
(1) rx len % 4 == 1 实际 dma sram 会少 1 byte , 即 rx len - 1 (USB1.1驱动已修复)
|
||||
(2) rx len % 4 == 2 实际 dma sram 会多 1 byte , 即 rx len + 1
|
||||
(3) rx len % 4 == 0 || rx len % 4 == 3 实际 dma sram 长度与 rx len相同 , 即 rx len
|
||||
|
||||
USB2.0 SIE:
|
||||
(1) rx len % 4 == 1 实际 dma sram 会多 2 byte , 即 rx len + 2
|
||||
(2) rx len % 4 == 2 实际 dma sram 会多 1 byte , 即 rx len + 1
|
||||
(3) rx len % 4 == 0 || rx len % 4 == 3 实际 dma sram 长度与 rx len相同 , 即 rx len
|
||||
|
||||
*/
|
||||
|
||||
#include "drv_usb11d.h"
|
||||
#include <rtthread.h>
|
||||
#include "include/rttusb_device.h"
|
||||
#include "dev/usb/usb11_v0/hgusb11_v0_dev_api.h"
|
||||
|
||||
static struct ep_id _ep_pool[] =
|
||||
{
|
||||
{0x0, USB_EP_ATTR_TYPE_MASK, USB_DIR_INOUT, 64, ID_ASSIGNED },
|
||||
{0x1, USB_EP_ATTR_TYPE_MASK+1, USB_DIR_IN, 1024, ID_UNASSIGNED},
|
||||
{0x1, USB_EP_ATTR_TYPE_MASK+1, USB_DIR_OUT, 1024, ID_UNASSIGNED},
|
||||
{0x2, USB_EP_ATTR_TYPE_MASK+1, USB_DIR_IN, 1024, ID_UNASSIGNED},
|
||||
{0x2, USB_EP_ATTR_TYPE_MASK+1, USB_DIR_OUT, 1024, ID_UNASSIGNED},
|
||||
{0x3, USB_EP_ATTR_TYPE_MASK+1, USB_DIR_IN, 1024, ID_UNASSIGNED},
|
||||
{0x3, USB_EP_ATTR_TYPE_MASK+1, USB_DIR_OUT, 1024, ID_UNASSIGNED},
|
||||
{0xFF, USB_EP_ATTR_TYPE_MASK, USB_DIR_MASK, 0, ID_ASSIGNED },
|
||||
};
|
||||
|
||||
struct usb_device * _hg_pdc11;
|
||||
static struct udcd _hg_udc;
|
||||
|
||||
static rt_err_t _suspend(void);
|
||||
static rt_err_t _wakeup(void);
|
||||
|
||||
static uint32 hal_pcd11_bus_irq(uint32 irq, uint32 param1, uint32 param2, uint32 param3)
|
||||
{
|
||||
struct usb_device *p_usb_d = (struct usb_device *)param1;
|
||||
struct hgusb11_dev *p_dev = (struct hgusb11_dev *)p_usb_d;
|
||||
uint32 ep_num = param2 & 0xF;
|
||||
uint32 len = param3;
|
||||
|
||||
LOG_D("irq:%d %x %d %x\r\n", irq, param1, param2, param3);
|
||||
int32 ret_val = 1;
|
||||
switch (irq) {
|
||||
case USB_CONNECT: //7
|
||||
rt_usbd_connect_handler(&_hg_udc);
|
||||
break;
|
||||
case USB_DISCONNECT://8
|
||||
rt_usbd_disconnect_handler(&_hg_udc);
|
||||
break;
|
||||
case USB_DEV_RESET_IRQ://0
|
||||
rt_usbd_reset_handler(&_hg_udc);
|
||||
break;
|
||||
case USB_DEV_SUSPEND_IRQ://1
|
||||
_suspend();
|
||||
break;
|
||||
case USB_DEV_RESUME_IRQ://2
|
||||
_wakeup();
|
||||
break;
|
||||
case USB_DEV_SOF_IRQ://3
|
||||
rt_usbd_sof_handler(&_hg_udc);
|
||||
break;
|
||||
case USB_DEV_CTL_IRQ://4
|
||||
ret_val = 0;
|
||||
rt_usbd_ep0_setup_handler(&_hg_udc, (struct urequest *)p_dev->ep0_ctrl.ep0_buf);
|
||||
break;
|
||||
case USB_EP_RX_IRQ://5
|
||||
if (ep_num == 0) {
|
||||
rt_usbd_ep0_out_handler(&_hg_udc, len);
|
||||
} else {
|
||||
rt_usbd_ep_out_handler(&_hg_udc, ep_num, len);
|
||||
}
|
||||
break;
|
||||
case USB_EP_TX_IRQ://6
|
||||
if (ep_num == 0) {
|
||||
rt_usbd_ep0_in_handler(&_hg_udc);
|
||||
} else {
|
||||
rt_usbd_ep_in_handler(&_hg_udc, 0x80 | ep_num, len);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
static rt_err_t _ep_set_stall(rt_uint8_t address)
|
||||
{
|
||||
LOG_D("rtt stall\r\n");
|
||||
hgusb11_v0_dev_ep_set_stall((struct usb_device *)_hg_pdc11, address);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t _ep_clear_stall(rt_uint8_t address)
|
||||
{
|
||||
hgusb11_v0_dev_ep_clear_stall((struct usb_device *)_hg_pdc11, address);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t _set_address(rt_uint8_t address)
|
||||
{
|
||||
LOG_D("%s %d %d\r\n", __FUNCTION__, address);
|
||||
|
||||
hgusb11_v0_dev_set_address((struct usb_device *)_hg_pdc11, address);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t _set_config(rt_uint8_t address)
|
||||
{
|
||||
LOG_D("%s %d %d\r\n", __FUNCTION__, address);
|
||||
|
||||
hgusb11_v0_dev_set_config((struct usb_device *)_hg_pdc11, address);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t _ep_enable(uep_t ep)
|
||||
{
|
||||
LOG_D("%s %d %d\r\n", __FUNCTION__, ep->ep_desc->bEndpointAddress, ep->ep_desc->wMaxPacketSize);
|
||||
|
||||
RT_ASSERT(ep != RT_NULL);
|
||||
RT_ASSERT(ep->ep_desc != RT_NULL);
|
||||
|
||||
hgusb11_v0_dev_ep_enable((struct usb_device *)_hg_pdc11,
|
||||
ep->ep_desc->bEndpointAddress,
|
||||
ep->ep_desc->wMaxPacketSize,
|
||||
ep->ep_desc->bmAttributes);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t _ep_disable(uep_t ep)
|
||||
{
|
||||
LOG_D("%s %d %d\r\n", __FUNCTION__, ep->ep_desc->bEndpointAddress, ep->ep_desc->wMaxPacketSize);
|
||||
|
||||
RT_ASSERT(ep != RT_NULL);
|
||||
RT_ASSERT(ep->ep_desc != RT_NULL);
|
||||
|
||||
hgusb11_v0_dev_ep_disable((struct usb_device *)_hg_pdc11, ep->ep_desc->bEndpointAddress);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_size_t _ep_read(rt_uint8_t address, void *buffer)
|
||||
{
|
||||
RT_ASSERT(buffer != RT_NULL);
|
||||
|
||||
uint32 size = 0;
|
||||
|
||||
LOG_D("%s %d %d\r\n", __FUNCTION__, address, size);
|
||||
|
||||
size = hgusb11_v0_dev_ep_read((struct usb_device *)_hg_pdc11, address, buffer);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static rt_size_t _ep_read_prepare(rt_uint8_t address, void *buffer, rt_size_t size)
|
||||
{
|
||||
LOG_D("%s %d %d\r\n", __FUNCTION__, address, size);
|
||||
|
||||
hgusb11_v0_dev_ep_read_prepare((struct usb_device *)_hg_pdc11, address, buffer, size);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static rt_size_t _ep_write(rt_uint8_t address, void *buffer, rt_size_t size)
|
||||
{
|
||||
LOG_D("%s %d %d\r\n", __FUNCTION__, address, size);
|
||||
|
||||
hgusb11_v0_dev_ep_write((struct usb_device *)_hg_pdc11, address, buffer, size);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static rt_err_t _ep0_send_status(void)
|
||||
{
|
||||
LOG_D("%s\r\n", __FUNCTION__);
|
||||
|
||||
hgusb11_v0_dev_ep0_send_status((struct usb_device *)_hg_pdc11);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t _suspend(void)
|
||||
{
|
||||
LOG_D("%s\r\n", __FUNCTION__);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t _wakeup(void)
|
||||
{
|
||||
LOG_D("%s\r\n", __FUNCTION__);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t _deinit(struct usb_device *usb)
|
||||
{
|
||||
hgusb11_v0_dev_close((struct usb_device *)usb);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t _init(struct usb_device *usb)
|
||||
{
|
||||
//struct hgusb20_dev *dev = (struct hgusb20_dev *)usb;
|
||||
//int32 ret = RET_OK;
|
||||
|
||||
// if (usb == NULL) {
|
||||
// return NULL;
|
||||
// }
|
||||
//
|
||||
// ret = pin_func(dev->dev.dev.dev_id, 1);
|
||||
// if (ret) {
|
||||
//// USB_DEV_ERR_PRINTF("hgsdio20 dev request io failed!\r\n");
|
||||
// ASSERT(ret == RET_OK);
|
||||
// return ret;
|
||||
// }
|
||||
//
|
||||
// //SYSCTRL_REG_OPT(sysctrl_usb20_reset(););
|
||||
// sysctrl_usb20_clk_open();
|
||||
// hgusb20_dev_hw_init(dev);
|
||||
|
||||
usb_device_open(usb, (struct usb_device_cfg *)NULL);
|
||||
|
||||
//usb_device_ioctl(usb, USB_DEV_IO_CMD_AUTO_TX_NULL_PKT_ENABLE, USB_WIFI_TX_EP, 0);
|
||||
|
||||
usb_device_request_irq(usb, hal_pcd11_bus_irq, (uint32)usb);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
|
||||
const static struct udcd_ops _udc_ops =
|
||||
{
|
||||
_set_address,
|
||||
_set_config,
|
||||
_ep_set_stall,
|
||||
_ep_clear_stall,
|
||||
_ep_enable,
|
||||
_ep_disable,
|
||||
_ep_read_prepare,
|
||||
_ep_read,
|
||||
_ep_write,
|
||||
_ep0_send_status,
|
||||
_suspend,
|
||||
_wakeup,
|
||||
};
|
||||
|
||||
/**
|
||||
* usage :
|
||||
* 1、reg usb device in device.c: hgusb20_dev_attach(HG_USBDEV_DEVID, &usb20_dev);
|
||||
* 2、main init in main.c
|
||||
* rt_usbd_class_list_init
|
||||
* rt_usbd_winusb_class_register
|
||||
*
|
||||
*
|
||||
* hg_usbd_register(HG_USB_DEV_CONTROLLER_DEVID);
|
||||
*/
|
||||
|
||||
|
||||
void hg_usb11d_class_driver_register()
|
||||
{
|
||||
/* 若需同时注册多个device设备,需定义宏RT_USB_DEVICE_COMPOSITE成复合设备 */
|
||||
|
||||
rt_uint32_t devid = HG_USB11_DEV_CONTROLLER_DEVID;
|
||||
|
||||
rt_usbd_class_list_init(devid);
|
||||
|
||||
#ifdef RT_USB_DEVICE_VIDEO
|
||||
rt_usbd_uvc_device_class_register(devid);
|
||||
#endif
|
||||
#ifdef RT_USB_DEVICE_AUDIO_MIC
|
||||
rt_usbd_uac_mic_class_register(devid);
|
||||
#endif
|
||||
#ifdef RT_USB_DEVICE_AUDIO_SPEAKER
|
||||
audio_speaker_init();
|
||||
rt_usbd_uac_speaker_class_register(devid);
|
||||
#endif
|
||||
#ifdef RT_USB_DEVICE_MSTORAGE
|
||||
rt_usbd_msc_class_register(devid);
|
||||
#endif
|
||||
#ifdef RT_USB_DEVICE_RNDIS
|
||||
rt_usbd_rndis_class_register(devid);
|
||||
#endif
|
||||
#ifdef RT_USB_DEVICE_HID
|
||||
rt_usbd_hid_class_register(devid);
|
||||
#endif
|
||||
#ifdef RT_USB_DEVICE_WINUSB
|
||||
rt_usbd_winusb_class_register(devid);
|
||||
#endif
|
||||
#ifdef RT_USB_DEVICE_CDC
|
||||
rt_usbd_vcom_class_register(devid);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int hg_usb11d_register(rt_uint32_t devid)
|
||||
{
|
||||
struct usb_device *usb = (struct usb_device *)dev_get(HG_USB11DEV_DEVID);
|
||||
|
||||
_hg_pdc11 = usb;
|
||||
rt_memset((void *)&_hg_udc, 0, sizeof(struct udcd));
|
||||
_hg_udc.ops = &_udc_ops;
|
||||
|
||||
/* Register endpoint infomation */
|
||||
_hg_udc.ep_pool = _ep_pool;
|
||||
_hg_udc.ep0.id = &_ep_pool[0];
|
||||
|
||||
_hg_udc.device_is_hs = 0;
|
||||
|
||||
dev_register(devid, (struct dev_obj *)&_hg_udc);
|
||||
|
||||
rt_usb_device_init(devid, "usb11_device");
|
||||
|
||||
_init(usb);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
int hg_usb11d_unregister(rt_uint32_t devid)
|
||||
{
|
||||
struct usb_device *usb = (struct usb_device *)dev_get(HG_USB11DEV_DEVID);
|
||||
struct dev_obj *udc = (struct dev_obj *)dev_get(devid);
|
||||
|
||||
if(udc && _hg_pdc11 != RT_NULL){
|
||||
printf("%s %d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
// rt_usb_device_deinit(devid);
|
||||
|
||||
_deinit(usb);
|
||||
|
||||
//dev_unregister((struct dev_obj *)&_hg_udc);
|
||||
|
||||
_hg_pdc11 = RT_NULL;
|
||||
}
|
||||
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
int hg_usb11d_recover(rt_uint32_t devid)
|
||||
{
|
||||
struct usb_device *usb = (struct usb_device *)dev_get(HG_USB11DEV_DEVID);
|
||||
struct dev_obj *udc = (struct dev_obj *)dev_get(devid);
|
||||
if(udc){
|
||||
_hg_pdc11 = usb;
|
||||
// rt_usbd_core_init();
|
||||
_init(usb);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
17
sdk/lib/bus/rttusb/bsp/drv_usb11d.h
Normal file
17
sdk/lib/bus/rttusb/bsp/drv_usb11d.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2017-10-30 ZYH the first version
|
||||
*/
|
||||
#ifndef __HG_USB11D_H__
|
||||
#define __HG_USB11D_H__
|
||||
#include <rtthread.h>
|
||||
void hg_usb11d_class_driver_register();
|
||||
int hg_usb11d_register(rt_uint32_t devid);
|
||||
int hg_usb11d_unregister(rt_uint32_t devid);
|
||||
int hg_usb11d_recover(rt_uint32_t devid);
|
||||
#endif
|
||||
427
sdk/lib/bus/rttusb/bsp/drv_usb11h.c
Normal file
427
sdk/lib/bus/rttusb/bsp/drv_usb11h.c
Normal file
@@ -0,0 +1,427 @@
|
||||
/*
|
||||
针对 USB DMA RX , 需做的内存预留大小为 4 字节, 防止 DMA 内存越界引起的内存错误问题
|
||||
|
||||
USB1.1 SIE:
|
||||
(1) rx len % 4 == 1 实际 dma sram 会少 1 byte , 即 rx len - 1 (USB1.1驱动已修复)
|
||||
(2) rx len % 4 == 2 实际 dma sram 会多 1 byte , 即 rx len + 1
|
||||
(3) rx len % 4 == 0 || rx len % 4 == 3 实际 dma sram 长度与 rx len相同 , 即 rx len
|
||||
|
||||
USB2.0 SIE:
|
||||
(1) rx len % 4 == 1 实际 dma sram 会多 2 byte , 即 rx len + 2
|
||||
(2) rx len % 4 == 2 实际 dma sram 会多 1 byte , 即 rx len + 1
|
||||
(3) rx len % 4 == 0 || rx len % 4 == 3 实际 dma sram 长度与 rx len相同 , 即 rx len
|
||||
|
||||
*/
|
||||
#include <rtthread.h>
|
||||
#include <include/rttusb_host.h>
|
||||
#include "hal/usb_device.h"
|
||||
#include "dev/usb/usb11_v0/hgusb11_v0_host_api.h"
|
||||
#ifdef RT_USBH_UVC
|
||||
#include "usbh_video.h"
|
||||
#endif
|
||||
#ifdef RT_USBH_UAC
|
||||
#include "usbh_audio.h"
|
||||
#endif
|
||||
|
||||
#define USB11_HOST_MAX_PIPE 3
|
||||
|
||||
typedef struct {
|
||||
struct usb_device *usb;
|
||||
uhcd_t hcd;
|
||||
rt_uint32_t pipe_in_index; // 按bit记录主控可用端点
|
||||
rt_uint32_t pipe_out_index;
|
||||
struct os_event trx_lock;
|
||||
struct os_event trx_done;
|
||||
} usb_core_instance;
|
||||
|
||||
static usb_core_instance _hg_usbh;
|
||||
static volatile rt_bool_t connect_status = RT_FALSE;
|
||||
|
||||
#define USBH_REGISTER_FLAG BIT(1)
|
||||
static volatile rt_uint32_t usbh_flag = 0;
|
||||
|
||||
static rt_uint32_t hg_usbh_irq_hdl(rt_uint32_t irq, rt_uint32_t param1, rt_uint32_t param2, rt_uint32_t param3)
|
||||
{
|
||||
#if defined(RT_USBH_UVC) || defined(RT_USBH_UAC)
|
||||
struct hgusb11_host *p_dev = (struct hgusb11_host *)dev_get(HG_USB11HOST_DEVID);
|
||||
#endif
|
||||
usb_core_instance *core = (usb_core_instance *)param1;
|
||||
rt_uint32_t usb_ep = param2 & 0xF;
|
||||
|
||||
switch (irq) {
|
||||
case USB_DEV_RESET_IRQ:
|
||||
break;
|
||||
case USB_DEV_SUSPEND_IRQ:
|
||||
break;
|
||||
case USB_DEV_RESUME_IRQ:
|
||||
break;
|
||||
case USB_DEV_SOF_IRQ:
|
||||
break;
|
||||
case USB_DEV_CTL_IRQ:
|
||||
break;
|
||||
case USB_EP_RX_IRQ:
|
||||
os_event_set(&core->trx_done, BIT(usb_ep+16), NULL);
|
||||
if (connect_status) {
|
||||
#ifdef RT_USBH_UVC
|
||||
rtt_usbh_video_irq(p_dev, usb_ep, _hg_usbh.hcd);
|
||||
#endif
|
||||
#ifdef RT_USBH_UAC
|
||||
//rtt_usbh_audio_irq(p_dev, irq, usb_ep);
|
||||
#endif
|
||||
} else {
|
||||
hgusb11_v0_host_ep_abort(_hg_usbh.usb, USB_CORE_HOST_EP_RX, usb_ep);
|
||||
hgusb11_v0_host_reset_ep_rxcsr(usb_ep);
|
||||
rt_kprintf("usb11 connect status is NULL , stop in rx irq\n");
|
||||
}
|
||||
break;
|
||||
case USB_EP_TX_IRQ:
|
||||
os_event_set(&core->trx_done, BIT(usb_ep), NULL);
|
||||
if (connect_status) {
|
||||
#ifdef RT_USBH_UAC
|
||||
//rtt_usbh_audio_irq(p_dev, irq, usb_ep);
|
||||
#endif
|
||||
} else {
|
||||
hgusb11_v0_host_ep_abort(_hg_usbh.usb, USB_CORE_HOST_EP_TX, usb_ep);
|
||||
hgusb11_v0_host_reset_ep_txcsr(usb_ep);
|
||||
rt_kprintf("usb11 connect status is NULL , stop in tx irq\n");
|
||||
}
|
||||
break;
|
||||
case USB_CONNECT:
|
||||
if (hgusb11_v0_host_dev_speed_detect() && (usbh_flag & USBH_REGISTER_FLAG)) {
|
||||
if (!connect_status) {
|
||||
connect_status = RT_TRUE;
|
||||
rt_kprintf("usb11 connected\r\n");
|
||||
rt_usbh_root_hub_connect_handler(core->hcd, 1, RT_TRUE);
|
||||
// hg_usb_connect_detect_using();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case USB_DISCONNECT:
|
||||
if (!hgusb11_v0_host_dev_speed_detect() && (usbh_flag & USBH_REGISTER_FLAG)) {
|
||||
if (connect_status) {
|
||||
connect_status = RT_FALSE;
|
||||
rt_kprintf("usb11 disconnect\r\n");
|
||||
rt_usbh_root_hub_disconnect_handler(core->hcd, 1);
|
||||
// hg_usb_connect_detect_recfg();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case USB_BABBLE:
|
||||
break;
|
||||
case USB_XACT_ERR:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static rt_err_t drv_reset_port(rt_uint8_t port)
|
||||
{
|
||||
rt_kprintf("usb11 reset port\r\n");
|
||||
hgusb11_v0_host_reset();
|
||||
hgusb11_v0_host_set_address( 0);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_uint8_t drv_get_free_pipe_index(rt_uint32_t *pipe_index)
|
||||
{
|
||||
rt_uint8_t idx;
|
||||
for (idx = 1; idx <= USB11_HOST_MAX_PIPE; ++idx) {
|
||||
if (!(*pipe_index & BIT(idx))) {
|
||||
*pipe_index |= BIT(idx);
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
static inline void drv_free_pipe_index(rt_uint32_t *pipe_index, rt_uint8_t index)
|
||||
{
|
||||
*pipe_index &= ~BIT(index);
|
||||
}
|
||||
|
||||
static inline rt_bool_t drv_pipe_index_check(rt_uint32_t *pipe_index, rt_uint8_t index)
|
||||
{
|
||||
return (*pipe_index & BIT(index)) ? RT_TRUE : RT_FALSE;
|
||||
}
|
||||
|
||||
static int drv_pipe_xfer(upipe_t pipe, rt_uint8_t token, void *buffer, int nbytes, int timeouts)
|
||||
{
|
||||
struct usb_device *hgusb = (struct usb_device *)_hg_usbh.usb;
|
||||
rt_int32_t ret = RET_OK;
|
||||
int total_len = 0;
|
||||
rt_size_t remain_size;
|
||||
remain_size = nbytes;
|
||||
rt_uint8_t * pbuffer = (rt_uint8_t *)buffer;
|
||||
|
||||
if (!connect_status) {
|
||||
os_printf("connect_status is null\n");
|
||||
return -RT_EIO;
|
||||
}
|
||||
if (pipe->pipe_index > USB11_HOST_MAX_PIPE) {
|
||||
return -RT_EIO;
|
||||
}
|
||||
if ((pipe->ep.bEndpointAddress & USB_DIR_MASK) == USB_DIR_IN) {
|
||||
if (!drv_pipe_index_check(&_hg_usbh.pipe_in_index, pipe->pipe_index)) {
|
||||
return -RT_EIO;
|
||||
}
|
||||
} else {
|
||||
if (!drv_pipe_index_check(&_hg_usbh.pipe_out_index, pipe->pipe_index)) {
|
||||
return -RT_EIO;
|
||||
}
|
||||
}
|
||||
|
||||
hgusb11_v0_host_set_address(pipe->inst->address);
|
||||
|
||||
if ((pipe->ep.bEndpointAddress & USB_DIR_MASK) == USB_DIR_IN) {
|
||||
// RX需要互斥
|
||||
ret = os_event_wait(&_hg_usbh.trx_lock, BIT(16)/*BIT(pipe->pipe_index+16)*/, NULL,
|
||||
OS_EVENT_WMODE_AND|OS_EVENT_WMODE_CLEAR, osWaitForever);
|
||||
if (ret) {
|
||||
LOG_D("drv_pipe_xfer rx req timeout!\r\n");
|
||||
pipe->status = UPIPE_STATUS_ERROR;
|
||||
return RET_ERR;
|
||||
}
|
||||
// 端点0软件分包
|
||||
if (pipe->pipe_index == 0) {
|
||||
ret = hgusb11_v0_host_ep0_rx_kick(hgusb, pbuffer, remain_size);
|
||||
if(ret == RET_OK) {
|
||||
total_len = remain_size;
|
||||
} else {
|
||||
pipe->status = UPIPE_STATUS_ERROR;
|
||||
total_len = ret;
|
||||
}
|
||||
} else {
|
||||
os_event_clear(&_hg_usbh.trx_done, BIT(pipe->pipe_index+16), NULL);
|
||||
hgusb11_v0_host_ep_rx_kick(hgusb, pipe->pipe_index, (rt_uint8_t*)buffer, remain_size);
|
||||
ret = os_event_wait(&_hg_usbh.trx_done, BIT(pipe->pipe_index+16), NULL,
|
||||
OS_EVENT_WMODE_AND|OS_EVENT_WMODE_CLEAR, (timeouts ? timeouts : osWaitForever));
|
||||
if (ret) {
|
||||
LOG_D("drv_pipe_xfer rx timeout!\r\n");
|
||||
pipe->status = UPIPE_STATUS_ERROR;
|
||||
hgusb11_v0_host_ep_abort(_hg_usbh.usb, USB_CORE_HOST_EP_RX, pipe->pipe_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
usb_device_ioctl((struct usb_device *)hgusb, USB_HOST_GET_RX_DMA_LEN, pipe->pipe_index, (rt_uint32_t)&total_len);
|
||||
if (hgusb11_v0_host_is_xact_err(pipe->pipe_index, USB_DIR_IN)
|
||||
|| hgusb11_v0_host_is_rx_stall(pipe->pipe_index, USB_DIR_IN))
|
||||
{
|
||||
os_printf("%s usb1.1 rx dma err or stall, ep num is %d!!!!!\n",__FUNCTION__,pipe->pipe_index);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
os_event_set(&_hg_usbh.trx_lock, BIT(16)/*BIT(pipe->pipe_index+16)*/, NULL);
|
||||
} else {
|
||||
ret = os_event_wait(&_hg_usbh.trx_lock, BIT(pipe->pipe_index), NULL,
|
||||
OS_EVENT_WMODE_AND|OS_EVENT_WMODE_CLEAR, osWaitForever);
|
||||
if (ret) {
|
||||
LOG_D("drv_pipe_xfer tx req timeout!\r\n");
|
||||
pipe->status = UPIPE_STATUS_ERROR;
|
||||
return RET_ERR;
|
||||
}
|
||||
if (token == USBH_PID_SETUP) {
|
||||
// setup包只会是ep0
|
||||
ret = hgusb11_v0_host_ep0_tx_kick(hgusb, 1, buffer, remain_size);
|
||||
if (ret != RET_OK) {
|
||||
//TX ERROR
|
||||
total_len = 0;
|
||||
pipe->status = UPIPE_STATUS_ERROR;
|
||||
} else {
|
||||
total_len = 8;
|
||||
}
|
||||
} else {
|
||||
// 端点0软件分包
|
||||
if (pipe->pipe_index == 0) {
|
||||
ret = hgusb11_v0_host_ep0_tx_kick(hgusb, 0, buffer, remain_size);
|
||||
if(ret == RET_OK) {
|
||||
total_len = remain_size;
|
||||
} else {
|
||||
total_len = ret;
|
||||
pipe->status = UPIPE_STATUS_ERROR;
|
||||
}
|
||||
} else {
|
||||
os_event_clear(&_hg_usbh.trx_done, BIT(pipe->pipe_index), NULL);
|
||||
hgusb11_v0_host_ep_tx_kick(hgusb, pipe->pipe_index, (rt_uint8_t*)buffer, remain_size, 0);
|
||||
ret = os_event_wait(&_hg_usbh.trx_done, BIT(pipe->pipe_index), NULL,
|
||||
OS_EVENT_WMODE_AND|OS_EVENT_WMODE_CLEAR, (timeouts ? timeouts : osWaitForever));
|
||||
if (ret) {
|
||||
LOG_D("drv_pipe_xfer tx timeout!\r\n");
|
||||
pipe->status = UPIPE_STATUS_ERROR;
|
||||
hgusb11_v0_host_ep_abort(_hg_usbh.usb, USB_CORE_HOST_EP_TX, pipe->pipe_index);
|
||||
total_len = RET_ERR;
|
||||
} else {
|
||||
total_len = remain_size;
|
||||
if (hgusb11_v0_host_is_xact_err(pipe->pipe_index, USB_DIR_OUT)
|
||||
|| hgusb11_v0_host_is_rx_stall(pipe->pipe_index, USB_DIR_OUT))
|
||||
{
|
||||
os_printf("%s usb1.1 tx dma err or stall, ep num is %d!!!!!\n",__FUNCTION__,pipe->pipe_index);
|
||||
total_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
os_event_set(&_hg_usbh.trx_lock, BIT(pipe->pipe_index) | BIT(0), NULL);
|
||||
}
|
||||
|
||||
if (pipe->callback != RT_NULL) pipe->callback(pipe);
|
||||
// 其余情况都是和请求长度一致
|
||||
return total_len;
|
||||
}
|
||||
|
||||
static rt_err_t drv_open_pipe(upipe_t pipe)
|
||||
{
|
||||
|
||||
if ((pipe->ep.bEndpointAddress & USB_DIR_MASK) == USB_DIR_IN) {
|
||||
if ((pipe->ep.bEndpointAddress & USB_EPNO_MASK) != 0) {
|
||||
os_printf("drv open rx pipe\n");
|
||||
pipe->pipe_index = drv_get_free_pipe_index(&_hg_usbh.pipe_in_index);
|
||||
|
||||
hgusb11_v0_host_ep_init(_hg_usbh.usb,
|
||||
USB_CORE_HOST_EP_RX,
|
||||
pipe->pipe_index,
|
||||
(pipe->ep.bEndpointAddress & USB_EPNO_MASK),
|
||||
(pipe->ep.bmAttributes & USB_EP_ATTR_TYPE_MASK),
|
||||
pipe->ep.wMaxPacketSize);
|
||||
|
||||
if((pipe->ep.bmAttributes & USB_EP_ATTR_TYPE_MASK) != USB_EP_ATTR_BULK)
|
||||
{
|
||||
hgusb11_v0_host_set_ep_interval(USB_CORE_HOST_EP_RX, pipe->pipe_index, pipe->ep.bInterval);
|
||||
}
|
||||
else
|
||||
{
|
||||
//NAK TIMEOUT
|
||||
hgusb11_v0_host_set_ep_interval(USB_CORE_HOST_EP_RX, pipe->pipe_index, 0);
|
||||
}
|
||||
|
||||
} else {
|
||||
_hg_usbh.pipe_in_index |= BIT(0);
|
||||
}
|
||||
} else {
|
||||
if ((pipe->ep.bEndpointAddress & USB_EPNO_MASK) != 0) {
|
||||
os_printf("drv open tx pipe\n");
|
||||
pipe->pipe_index = drv_get_free_pipe_index(&_hg_usbh.pipe_out_index);
|
||||
hgusb11_v0_host_ep_init(_hg_usbh.usb,
|
||||
USB_CORE_HOST_EP_TX,
|
||||
pipe->pipe_index,
|
||||
(pipe->ep.bEndpointAddress & USB_EPNO_MASK),
|
||||
(pipe->ep.bmAttributes & USB_EP_ATTR_TYPE_MASK),
|
||||
pipe->ep.wMaxPacketSize);
|
||||
if((pipe->ep.bmAttributes & USB_EP_ATTR_TYPE_MASK) != USB_EP_ATTR_BULK)
|
||||
{
|
||||
hgusb11_v0_host_set_ep_interval(USB_CORE_HOST_EP_TX, pipe->pipe_index, pipe->ep.bInterval);
|
||||
}
|
||||
else
|
||||
{
|
||||
//NAK TIMEOUT
|
||||
hgusb11_v0_host_set_ep_interval(USB_CORE_HOST_EP_TX, pipe->pipe_index, 0);
|
||||
}
|
||||
|
||||
} else {
|
||||
_hg_usbh.pipe_out_index |= BIT(0);
|
||||
}
|
||||
}
|
||||
rt_kprintf("open pipe idx:%d ep%d dir:%x\r\n",
|
||||
pipe->pipe_index, (pipe->ep.bEndpointAddress & USB_EPNO_MASK), (pipe->ep.bEndpointAddress & USB_DIR_MASK));
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t drv_close_pipe(upipe_t pipe)
|
||||
{
|
||||
rt_kprintf("close pipe idx:%d\r\n", pipe->pipe_index);
|
||||
if ((pipe->ep.bEndpointAddress & USB_DIR_MASK) == USB_DIR_IN) {
|
||||
drv_free_pipe_index(&_hg_usbh.pipe_in_index, pipe->pipe_index);
|
||||
if (pipe->pipe_index != 0) {
|
||||
hgusb11_v0_host_ep_abort(_hg_usbh.usb, USB_CORE_HOST_EP_RX, pipe->pipe_index);
|
||||
os_event_set(&_hg_usbh.trx_lock, BIT(pipe->pipe_index+16), NULL);
|
||||
}
|
||||
} else {
|
||||
drv_free_pipe_index(&_hg_usbh.pipe_out_index, pipe->pipe_index);
|
||||
if (pipe->pipe_index != 0) {
|
||||
hgusb11_v0_host_ep_abort(_hg_usbh.usb, USB_CORE_HOST_EP_TX, pipe->pipe_index);
|
||||
os_event_set(&_hg_usbh.trx_lock, BIT(pipe->pipe_index), NULL);
|
||||
}
|
||||
}
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static const struct uhcd_ops _uhcd_ops = {
|
||||
drv_reset_port,
|
||||
drv_pipe_xfer,
|
||||
drv_open_pipe,
|
||||
drv_close_pipe,
|
||||
};
|
||||
|
||||
rt_err_t hg_usb11h_register(rt_uint32_t devid)
|
||||
{
|
||||
uhcd_t uhcd = RT_NULL;
|
||||
|
||||
uhcd = (uhcd_t)dev_get(devid);
|
||||
if (uhcd == RT_NULL) {
|
||||
uhcd = (uhcd_t)os_zalloc(sizeof(struct uhcd));
|
||||
if (uhcd == RT_NULL) {
|
||||
rt_kprintf("uhcd malloc failed\r\n");
|
||||
return -RT_ENOMEM;
|
||||
}
|
||||
|
||||
os_printf("%s %d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
uhcd->ops = (uhcd_ops_t)&_uhcd_ops;
|
||||
uhcd->num_ports = 1;
|
||||
dev_register(devid, (struct dev_obj *)uhcd);
|
||||
|
||||
os_memset(&_hg_usbh, 0, sizeof(usb_core_instance));
|
||||
_hg_usbh.hcd = uhcd;
|
||||
os_event_init(&_hg_usbh.trx_done);
|
||||
os_event_init(&_hg_usbh.trx_lock);
|
||||
os_event_set(&_hg_usbh.trx_lock, 0xffffffff, NULL);
|
||||
_hg_usbh.usb = (struct usb_device *)dev_get(HG_USB11HOST_DEVID);
|
||||
RT_ASSERT(_hg_usbh.usb);
|
||||
usbh_flag |= USBH_REGISTER_FLAG;
|
||||
usb_device_open(_hg_usbh.usb, NULL);
|
||||
usb_device_request_irq(_hg_usbh.usb, hg_usbh_irq_hdl, (rt_uint32_t)&_hg_usbh);
|
||||
|
||||
rt_usb_host_init(devid, "usb11_host");
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
rt_err_t hg_usb11h_unregister(rt_uint32_t devid)
|
||||
{
|
||||
uhcd_t uhc;
|
||||
uhc = (uhcd_t)dev_get(devid);
|
||||
if (uhc) {
|
||||
printf("%s %d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
usbh_flag &= ~USBH_REGISTER_FLAG;
|
||||
|
||||
if(connect_status) {
|
||||
connect_status = RT_FALSE;
|
||||
rt_usbh_root_hub_disconnect_handler(_hg_usbh.hcd, 1);
|
||||
}
|
||||
|
||||
rt_usb_host_deinit(devid);
|
||||
|
||||
if(_hg_usbh.usb)
|
||||
{
|
||||
usb_device_close(_hg_usbh.usb);
|
||||
os_event_del(&_hg_usbh.trx_done);
|
||||
os_event_del(&_hg_usbh.trx_lock);
|
||||
_hg_usbh.usb = RT_NULL;
|
||||
}
|
||||
|
||||
if(_hg_usbh.hcd)
|
||||
{
|
||||
dev_unregister((struct dev_obj *)_hg_usbh.hcd);
|
||||
os_free(_hg_usbh.hcd);
|
||||
_hg_usbh.hcd = RT_NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
408
sdk/lib/bus/rttusb/bsp/drv_usbd.c
Normal file
408
sdk/lib/bus/rttusb/bsp/drv_usbd.c
Normal file
@@ -0,0 +1,408 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2017-10-30 ZYH the first version
|
||||
*/
|
||||
|
||||
/*
|
||||
针对 USB DMA RX , 需做的内存预留大小为 4 字节, 防止 DMA 内存越界引起的内存错误问题
|
||||
|
||||
USB1.1 SIE:
|
||||
(1) rx len % 4 == 1 实际 dma sram 会少 1 byte , 即 rx len - 1 (USB1.1驱动已修复)
|
||||
(2) rx len % 4 == 2 实际 dma sram 会多 1 byte , 即 rx len + 1
|
||||
(3) rx len % 4 == 0 || rx len % 4 == 3 实际 dma sram 长度与 rx len相同 , 即 rx len
|
||||
|
||||
USB2.0 SIE:
|
||||
(1) rx len % 4 == 1 实际 dma sram 会多 2 byte , 即 rx len + 2
|
||||
(2) rx len % 4 == 2 实际 dma sram 会多 1 byte , 即 rx len + 1
|
||||
(3) rx len % 4 == 0 || rx len % 4 == 3 实际 dma sram 长度与 rx len相同 , 即 rx len
|
||||
|
||||
*/
|
||||
|
||||
#include "drv_usbd.h"
|
||||
#include <rtthread.h>
|
||||
#include "include/rttusb_device.h"
|
||||
#include "dev/usb/hgusb20_v1_dev_api.h"
|
||||
|
||||
static struct ep_id _ep_pool[] =
|
||||
{
|
||||
{0x0, USB_EP_ATTR_TYPE_MASK, USB_DIR_INOUT, 64, ID_ASSIGNED },
|
||||
{0x1, USB_EP_ATTR_TYPE_MASK+1, USB_DIR_IN, 1024, ID_UNASSIGNED},
|
||||
{0x1, USB_EP_ATTR_TYPE_MASK+1, USB_DIR_OUT, 1024, ID_UNASSIGNED},
|
||||
{0x2, USB_EP_ATTR_TYPE_MASK+1, USB_DIR_IN, 1024, ID_UNASSIGNED},
|
||||
{0x2, USB_EP_ATTR_TYPE_MASK+1, USB_DIR_OUT, 1024, ID_UNASSIGNED},
|
||||
{0x3, USB_EP_ATTR_TYPE_MASK+1, USB_DIR_IN, 1024, ID_UNASSIGNED},
|
||||
{0x3, USB_EP_ATTR_TYPE_MASK+1, USB_DIR_OUT, 1024, ID_UNASSIGNED},
|
||||
{0x4, USB_EP_ATTR_TYPE_MASK+1, USB_DIR_IN, 1024, ID_UNASSIGNED},
|
||||
{0x4, USB_EP_ATTR_TYPE_MASK+1, USB_DIR_OUT, 1024, ID_UNASSIGNED},
|
||||
{0x5, USB_EP_ATTR_TYPE_MASK+1, USB_DIR_IN, 1024, ID_UNASSIGNED},
|
||||
{0x5, USB_EP_ATTR_TYPE_MASK+1, USB_DIR_OUT, 1024, ID_UNASSIGNED},
|
||||
{0x6, USB_EP_ATTR_TYPE_MASK+1, USB_DIR_IN, 1024, ID_UNASSIGNED},
|
||||
{0x6, USB_EP_ATTR_TYPE_MASK+1, USB_DIR_OUT, 1024, ID_UNASSIGNED},
|
||||
{0xFF, USB_EP_ATTR_TYPE_MASK, USB_DIR_MASK, 0, ID_ASSIGNED },
|
||||
};
|
||||
|
||||
struct usb_device * _hg_pdc;
|
||||
static struct udcd _hg_udc;
|
||||
|
||||
static rt_err_t _suspend(void);
|
||||
static rt_err_t _wakeup(void);
|
||||
|
||||
static uint32 hal_pcd_bus_irq(uint32 irq, uint32 param1, uint32 param2, uint32 param3)
|
||||
{
|
||||
struct usb_device *p_usb_d = (struct usb_device *)param1;
|
||||
struct hgusb20_dev *p_dev = (struct hgusb20_dev *)p_usb_d;
|
||||
uint32 ep_num = param2 & 0xF;
|
||||
uint32 len = param3;
|
||||
|
||||
LOG_D("irq:%d %x %d %x\r\n", irq, param1, param2, param3);
|
||||
int32 ret_val = 1;
|
||||
switch (irq) {
|
||||
case USB_CONNECT: //7
|
||||
rt_usbd_connect_handler(&_hg_udc);
|
||||
break;
|
||||
case USB_DISCONNECT://8
|
||||
rt_usbd_disconnect_handler(&_hg_udc);
|
||||
break;
|
||||
case USB_DEV_RESET_IRQ://0
|
||||
rt_usbd_reset_handler(&_hg_udc);
|
||||
break;
|
||||
case USB_DEV_SUSPEND_IRQ://1
|
||||
_suspend();
|
||||
break;
|
||||
case USB_DEV_RESUME_IRQ://2
|
||||
_wakeup();
|
||||
break;
|
||||
case USB_DEV_SOF_IRQ://3
|
||||
rt_usbd_sof_handler(&_hg_udc);
|
||||
break;
|
||||
case USB_DEV_CTL_IRQ://4
|
||||
ret_val = 0;
|
||||
rt_usbd_ep0_setup_handler(&_hg_udc, (struct urequest *)p_dev->usb_ep0_rxbuf);
|
||||
break;
|
||||
case USB_EP_RX_IRQ://5
|
||||
if (ep_num == 0) {
|
||||
rt_usbd_ep0_out_handler(&_hg_udc, len);
|
||||
} else {
|
||||
rt_usbd_ep_out_handler(&_hg_udc, ep_num, len);
|
||||
}
|
||||
break;
|
||||
case USB_EP_TX_IRQ://6
|
||||
if (ep_num == 0) {
|
||||
rt_usbd_ep0_in_handler(&_hg_udc);
|
||||
} else {
|
||||
rt_usbd_ep_in_handler(&_hg_udc, 0x80 | ep_num, len);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
static rt_err_t _ep_set_stall(rt_uint8_t address)
|
||||
{
|
||||
LOG_D("rtt stall\r\n");
|
||||
hgusb20_dev_stall_ep((struct hgusb20_dev *)_hg_pdc, address);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t _ep_clear_stall(rt_uint8_t address)
|
||||
{
|
||||
hgusb20_dev_clear_ep((struct hgusb20_dev *)_hg_pdc, address);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t _set_address(rt_uint8_t address)
|
||||
{
|
||||
LOG_D("%s %d %d\r\n", __FUNCTION__, address);
|
||||
|
||||
hgusb20_dev_ep0_set_address((struct hgusb20_dev *)_hg_pdc, address);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t _set_config(rt_uint8_t address)
|
||||
{
|
||||
LOG_D("%s %d %d\r\n", __FUNCTION__, address);
|
||||
|
||||
hgusb20_dev_state_config((struct hgusb20_dev *)_hg_pdc);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t _ep_enable(uep_t ep)
|
||||
{
|
||||
LOG_D("%s %d %d\r\n", __FUNCTION__, ep->ep_desc->bEndpointAddress, ep->ep_desc->wMaxPacketSize);
|
||||
|
||||
RT_ASSERT(ep != RT_NULL);
|
||||
RT_ASSERT(ep->ep_desc != RT_NULL);
|
||||
|
||||
hgusb20_dev_ep_init((struct hgusb20_dev *)_hg_pdc, ep->ep_desc->bEndpointAddress,
|
||||
ep->ep_desc->wMaxPacketSize, ep->ep_desc->bmAttributes);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t _ep_disable(uep_t ep)
|
||||
{
|
||||
LOG_D("%s %d %d\r\n", __FUNCTION__, ep->ep_desc->bEndpointAddress, ep->ep_desc->wMaxPacketSize);
|
||||
|
||||
RT_ASSERT(ep != RT_NULL);
|
||||
RT_ASSERT(ep->ep_desc != RT_NULL);
|
||||
uint8_t ep_num = ep->ep_desc->bEndpointAddress & 0x7F;
|
||||
if (0 == ep) {
|
||||
hgusb20_dev_ep0_rx_abort((struct hgusb20_dev *)_hg_pdc);
|
||||
hgusb20_dev_ep0_tx_abort((struct hgusb20_dev *)_hg_pdc);
|
||||
} else {
|
||||
if (ep->ep_desc->bEndpointAddress & USB_DIR_IN) {
|
||||
hgusb20_ep_tx_abort((struct hgusb20_dev *)_hg_pdc, ep_num);
|
||||
} else {
|
||||
hgusb20_ep_rx_abort((struct hgusb20_dev *)_hg_pdc, ep_num);
|
||||
}
|
||||
}
|
||||
|
||||
//hgusb20_dev_ep_deinit(_hg_pdc, ep->ep_desc->bEndpointAddress);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_size_t _ep_read(rt_uint8_t address, void *buffer)
|
||||
{
|
||||
rt_size_t size = hgusb20_ep_get_sie_rx_len((struct hgusb20_dev *)_hg_pdc, (address & 0x7F));
|
||||
RT_ASSERT(buffer != RT_NULL);
|
||||
|
||||
LOG_D("%s %d %d\r\n", __FUNCTION__, address, size);
|
||||
address &= 0x7F;
|
||||
if (address) {
|
||||
/* EP1.. data buffer handle */
|
||||
} else {
|
||||
/* EP0.. data buffer handle */
|
||||
os_memcpy(buffer, ((struct hgusb20_dev *)_hg_pdc)->usb_ep0_rxbuf, size);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static rt_size_t _ep_read_prepare(rt_uint8_t address, void *buffer, rt_size_t size)
|
||||
{
|
||||
LOG_D("%s %d %d\r\n", __FUNCTION__, address, size);
|
||||
|
||||
address &= 0x7F;
|
||||
if (address) {
|
||||
hgusb20_dev_read(_hg_pdc, address, (uint8 *)buffer, size, 0);
|
||||
} else {
|
||||
#if 0
|
||||
if (NULL == buffer) {
|
||||
buffer = (void *)(((struct hgusb20_dev *)_hg_pdc)->usb_ep0_rxbuf);
|
||||
}
|
||||
if (0 == size) {
|
||||
size = 64-1;
|
||||
}
|
||||
hgusb20_dev_ep0_rx((struct hgusb20_dev *)_hg_pdc, buffer, size);
|
||||
#else
|
||||
if (buffer && size) {
|
||||
hgusb20_dev_ep0_rx_rtt((struct hgusb20_dev *)_hg_pdc, buffer, size);
|
||||
} else {
|
||||
/* status not kick rx, the hardware auto control */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
static rt_size_t _ep_write(rt_uint8_t address, void *buffer, rt_size_t size)
|
||||
{
|
||||
LOG_D("%s %d %d\r\n", __FUNCTION__, address, size);
|
||||
|
||||
address &= 0x7F;
|
||||
//printf("address:%x buffer:%x size:%d\n",address,buffer,size);
|
||||
if (address && buffer) {
|
||||
hgusb20_dev_write(_hg_pdc, address, (uint8 *)buffer, size, 0);
|
||||
} else {
|
||||
hgusb20_dev_ep0_tx_rtt((struct hgusb20_dev *)_hg_pdc, buffer, size);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static rt_err_t _ep0_send_status(void)
|
||||
{
|
||||
LOG_D("%s\r\n", __FUNCTION__);
|
||||
|
||||
hgusb20_dev_ep0_clrrx_pkt0((struct hgusb20_dev *)_hg_pdc);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t _suspend(void)
|
||||
{
|
||||
LOG_D("%s\r\n", __FUNCTION__);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t _wakeup(void)
|
||||
{
|
||||
LOG_D("%s\r\n", __FUNCTION__);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t _deinit(struct usb_device *usb)
|
||||
{
|
||||
hgusb20_dev_close(usb);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t _init(struct usb_device *usb)
|
||||
{
|
||||
//struct hgusb20_dev *dev = (struct hgusb20_dev *)usb;
|
||||
//int32 ret = RET_OK;
|
||||
|
||||
// if (usb == NULL) {
|
||||
// return NULL;
|
||||
// }
|
||||
//
|
||||
// ret = pin_func(dev->dev.dev.dev_id, 1);
|
||||
// if (ret) {
|
||||
//// USB_DEV_ERR_PRINTF("hgsdio20 dev request io failed!\r\n");
|
||||
// ASSERT(ret == RET_OK);
|
||||
// return ret;
|
||||
// }
|
||||
//
|
||||
// //SYSCTRL_REG_OPT(sysctrl_usb20_reset(););
|
||||
// sysctrl_usb20_clk_open();
|
||||
// hgusb20_dev_hw_init(dev);
|
||||
|
||||
usb_device_open(usb, (struct usb_device_cfg *)NULL);
|
||||
|
||||
//usb_device_ioctl(usb, USB_DEV_IO_CMD_AUTO_TX_NULL_PKT_ENABLE, USB_WIFI_TX_EP, 0);
|
||||
|
||||
usb_device_request_irq(usb, hal_pcd_bus_irq, (uint32)usb);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
|
||||
const static struct udcd_ops _udc_ops =
|
||||
{
|
||||
_set_address,
|
||||
_set_config,
|
||||
_ep_set_stall,
|
||||
_ep_clear_stall,
|
||||
_ep_enable,
|
||||
_ep_disable,
|
||||
_ep_read_prepare,
|
||||
_ep_read,
|
||||
_ep_write,
|
||||
_ep0_send_status,
|
||||
_suspend,
|
||||
_wakeup,
|
||||
};
|
||||
|
||||
/**
|
||||
* usage :
|
||||
* 1、reg usb device in device.c: hgusb20_dev_attach(HG_USBDEV_DEVID, &usb20_dev);
|
||||
* 2、main init in main.c
|
||||
* rt_usbd_class_list_init
|
||||
* rt_usbd_winusb_class_register
|
||||
*
|
||||
*
|
||||
* hg_usbd_register(HG_USB_DEV_CONTROLLER_DEVID);
|
||||
*/
|
||||
|
||||
|
||||
void hg_usbd_class_driver_register()
|
||||
{
|
||||
/* 若需同时注册多个device设备,需定义宏RT_USB_DEVICE_COMPOSITE成复合设备 */
|
||||
|
||||
rt_uint32_t devid = HG_USB_DEV_CONTROLLER_DEVID;
|
||||
|
||||
rt_usbd_class_list_init(devid);
|
||||
|
||||
#ifdef RT_USB_DEVICE_VIDEO
|
||||
rt_usbd_uvc_device_class_register(devid);
|
||||
#endif
|
||||
#ifdef RT_USB_DEVICE_AUDIO_MIC
|
||||
rt_usbd_uac_mic_class_register(devid);
|
||||
#endif
|
||||
#ifdef RT_USB_DEVICE_AUDIO_SPEAKER
|
||||
audio_speaker_init();
|
||||
rt_usbd_uac_speaker_class_register(devid);
|
||||
#endif
|
||||
#ifdef RT_USB_DEVICE_MSTORAGE
|
||||
rt_usbd_msc_class_register(devid);
|
||||
#endif
|
||||
#ifdef RT_USB_DEVICE_RNDIS
|
||||
rt_usbd_rndis_class_register(devid);
|
||||
#endif
|
||||
#ifdef RT_USB_DEVICE_HID
|
||||
rt_usbd_hid_class_register(devid);
|
||||
#endif
|
||||
#ifdef RT_USB_DEVICE_WINUSB
|
||||
rt_usbd_winusb_class_register(devid);
|
||||
#endif
|
||||
#ifdef RT_USB_DEVICE_CDC
|
||||
rt_usbd_vcom_class_register(devid);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
int hg_usbd_register(rt_uint32_t devid)
|
||||
{
|
||||
struct usb_device *usb = (struct usb_device *)dev_get(HG_USBDEV_DEVID);
|
||||
|
||||
_hg_pdc = usb;
|
||||
rt_memset((void *)&_hg_udc, 0, sizeof(struct udcd));
|
||||
_hg_udc.ops = &_udc_ops;
|
||||
|
||||
/* Register endpoint infomation */
|
||||
_hg_udc.ep_pool = _ep_pool;
|
||||
_hg_udc.ep0.id = &_ep_pool[0];
|
||||
|
||||
_hg_udc.device_is_hs = 1;
|
||||
|
||||
dev_register(devid, (struct dev_obj *)&_hg_udc);
|
||||
|
||||
rt_usb_device_init(devid, "usb20_device");
|
||||
|
||||
_init(usb);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
int hg_usbd_unregister(rt_uint32_t devid)
|
||||
{
|
||||
struct usb_device *usb = (struct usb_device *)dev_get(HG_USBDEV_DEVID);
|
||||
struct dev_obj *udc = (struct dev_obj *)dev_get(devid);
|
||||
|
||||
if(udc && _hg_pdc != RT_NULL){
|
||||
printf("%s %d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
// rt_usb_device_deinit(devid);
|
||||
|
||||
_deinit(usb);
|
||||
|
||||
//dev_unregister((struct dev_obj *)&_hg_udc);
|
||||
|
||||
_hg_pdc = RT_NULL;
|
||||
}
|
||||
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
int hg_usbd_recover(rt_uint32_t devid)
|
||||
{
|
||||
struct usb_device *usb = (struct usb_device *)dev_get(HG_USBDEV_DEVID);
|
||||
struct dev_obj *udc = (struct dev_obj *)dev_get(devid);
|
||||
if(udc){
|
||||
_hg_pdc = usb;
|
||||
// rt_usbd_core_init();
|
||||
_init(usb);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
17
sdk/lib/bus/rttusb/bsp/drv_usbd.h
Normal file
17
sdk/lib/bus/rttusb/bsp/drv_usbd.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2017-10-30 ZYH the first version
|
||||
*/
|
||||
#ifndef __HG_USBD_H__
|
||||
#define __HG_USBD_H__
|
||||
#include <rtthread.h>
|
||||
void hg_usbd_class_driver_register();
|
||||
int hg_usbd_register(rt_uint32_t devid);
|
||||
int hg_usbd_unregister(rt_uint32_t devid);
|
||||
int hg_usbd_recover(rt_uint32_t devid);
|
||||
#endif
|
||||
45
sdk/lib/bus/rttusb/bsp/drv_usbd_cdc.c
Normal file
45
sdk/lib/bus/rttusb/bsp/drv_usbd_cdc.c
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "rtthread.h"
|
||||
#include "include/rttusb_device.h"
|
||||
#include "cdc_vcom.h"
|
||||
|
||||
int usbd_cdc_putc(struct rt_serial_device *serial, char c)
|
||||
{
|
||||
if (serial) {
|
||||
return ((const struct rt_uart_ops *)serial->ops)->putc(serial, c);
|
||||
}
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
int usbd_cdc_getc(struct rt_serial_device *serial)
|
||||
{
|
||||
if (serial) {
|
||||
return ((const struct rt_uart_ops *)serial->ops)->getc(serial);
|
||||
}
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
rt_err_t usbd_cdc_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
|
||||
{
|
||||
if (serial) {
|
||||
return ((const struct rt_uart_ops *)serial->ops)->configure(serial, cfg);
|
||||
}
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
rt_err_t usbd_cdc_control(struct rt_serial_device *serial, int cmd, void *arg)
|
||||
{
|
||||
if (serial) {
|
||||
return ((const struct rt_uart_ops *)serial->ops)->control(serial, cmd, arg);
|
||||
}
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
rt_ssize_t usbd_cdc_transmit(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, rt_uint32_t tx_flag)
|
||||
{
|
||||
|
||||
if (serial) {
|
||||
os_printf("%s %d\n",__FUNCTION__,__LINE__);
|
||||
return ((const struct rt_uart_ops *)serial->ops)->transmit(serial, buf, size, tx_flag);
|
||||
}
|
||||
return -RT_ERROR;
|
||||
}
|
||||
11
sdk/lib/bus/rttusb/bsp/drv_usbd_cdc.h
Normal file
11
sdk/lib/bus/rttusb/bsp/drv_usbd_cdc.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef __DRV_USBD_CDC_H__
|
||||
#define __DRV_USBD_CDC_H__
|
||||
#include "rtthread.h"
|
||||
|
||||
int usbd_cdc_putc(struct rt_serial_device *serial, char c);
|
||||
int usbd_cdc_getc(struct rt_serial_device *serial);
|
||||
rt_err_t usbd_cdc_configure(struct rt_serial_device *serial, struct serial_configure *cfg);
|
||||
rt_err_t usbd_cdc_control(struct rt_serial_device *serial, int cmd, void *arg);
|
||||
rt_ssize_t usbd_cdc_transmit(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, rt_uint32_t tx_flag);
|
||||
|
||||
#endif
|
||||
496
sdk/lib/bus/rttusb/bsp/drv_usbh.c
Normal file
496
sdk/lib/bus/rttusb/bsp/drv_usbh.c
Normal file
@@ -0,0 +1,496 @@
|
||||
/*
|
||||
针对 USB DMA RX , 需做的内存预留大小为 4 字节, 防止 DMA 内存越界引起的内存错误问题
|
||||
|
||||
USB1.1 SIE:
|
||||
(1) rx len % 4 == 1 实际 dma sram 会少 1 byte , 即 rx len - 1 (USB1.1驱动已修复)
|
||||
(2) rx len % 4 == 2 实际 dma sram 会多 1 byte , 即 rx len + 1
|
||||
(3) rx len % 4 == 0 || rx len % 4 == 3 实际 dma sram 长度与 rx len相同 , 即 rx len
|
||||
|
||||
USB2.0 SIE:
|
||||
(1) rx len % 4 == 1 实际 dma sram 会多 2 byte , 即 rx len + 2
|
||||
(2) rx len % 4 == 2 实际 dma sram 会多 1 byte , 即 rx len + 1
|
||||
(3) rx len % 4 == 0 || rx len % 4 == 3 实际 dma sram 长度与 rx len相同 , 即 rx len
|
||||
|
||||
*/
|
||||
#include <rtthread.h>
|
||||
#include <include/rttusb_host.h>
|
||||
#include "hal/usb_device.h"
|
||||
#include "dev/usb/hgusb20_v1_dev_api.h"
|
||||
#include "math.h"
|
||||
|
||||
#define USB_HOST_MAX_PIPE 6
|
||||
|
||||
typedef struct {
|
||||
struct usb_device *usb;
|
||||
uhcd_t hcd;
|
||||
rt_uint32_t pipe_in_index; // 按bit记录主控可用端点
|
||||
rt_uint32_t pipe_out_index;
|
||||
struct os_event trx_lock;
|
||||
struct os_event trx_done;
|
||||
} usb_core_instance;
|
||||
|
||||
static usb_core_instance _hg_usbh;
|
||||
static volatile rt_bool_t connect_status = RT_FALSE;
|
||||
|
||||
#define USBH_REGISTER_FLAG BIT(1)
|
||||
static volatile rt_uint32_t usbh_flag = 0;
|
||||
|
||||
static rt_uint32_t hg_usbh_irq_hdl(rt_uint32_t irq, rt_uint32_t param1, rt_uint32_t param2, rt_uint32_t param3)
|
||||
{
|
||||
struct hgusb20_dev *p_dev = (struct hgusb20_dev *)dev_get(HG_USBDEV_DEVID);
|
||||
usb_core_instance *core = (usb_core_instance *)param1;
|
||||
rt_uint32_t usb_ep = param2 & 0xF;
|
||||
|
||||
//_os_printf("irq:%d\r\n", irq);
|
||||
switch (irq) {
|
||||
case USB_DEV_RESET_IRQ:
|
||||
break;
|
||||
case USB_DEV_SUSPEND_IRQ:
|
||||
break;
|
||||
case USB_DEV_RESUME_IRQ:
|
||||
break;
|
||||
case USB_DEV_SOF_IRQ:
|
||||
break;
|
||||
case USB_DEV_CTL_IRQ:
|
||||
break;
|
||||
case USB_EP_RX_IRQ:
|
||||
os_event_set(&core->trx_done, BIT(usb_ep+16), NULL);
|
||||
break;
|
||||
case USB_EP_TX_IRQ:
|
||||
os_event_set(&core->trx_done, BIT(usb_ep), NULL);
|
||||
break;
|
||||
case USB_CONNECT:
|
||||
if (hgusb20_is_device_online(p_dev) && (usbh_flag & USBH_REGISTER_FLAG)) {
|
||||
if (!connect_status) {
|
||||
connect_status = RT_TRUE;
|
||||
rt_kprintf("usb connected\r\n");
|
||||
rt_usbh_root_hub_connect_handler(core->hcd, 1, RT_TRUE);
|
||||
hg_usb_connect_detect_using();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case USB_DISCONNECT:
|
||||
if (!hgusb20_is_device_online(p_dev) && (usbh_flag & USBH_REGISTER_FLAG)) {
|
||||
if (connect_status) {
|
||||
connect_status = RT_FALSE;
|
||||
rt_kprintf("usb disconnect\r\n");
|
||||
rt_usbh_root_hub_disconnect_handler(core->hcd, 1);
|
||||
hg_usb_connect_detect_recfg();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case USB_BABBLE:
|
||||
break;
|
||||
case USB_XACT_ERR:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static rt_err_t drv_reset_port(rt_uint8_t port)
|
||||
{
|
||||
rt_kprintf("reset port\r\n");
|
||||
hgusb20_host_reset((struct hgusb20_dev *)_hg_usbh.usb);
|
||||
hgusb20_set_address((struct hgusb20_dev *)_hg_usbh.usb, 0);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_uint8_t drv_get_free_pipe_index(rt_uint32_t *pipe_index)
|
||||
{
|
||||
rt_uint8_t idx;
|
||||
for (idx = 1; idx <= USB_HOST_MAX_PIPE; ++idx) {
|
||||
if (!(*pipe_index & BIT(idx))) {
|
||||
*pipe_index |= BIT(idx);
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
static inline void drv_free_pipe_index(rt_uint32_t *pipe_index, rt_uint8_t index)
|
||||
{
|
||||
*pipe_index &= ~BIT(index);
|
||||
}
|
||||
|
||||
static inline rt_bool_t drv_pipe_index_check(rt_uint32_t *pipe_index, rt_uint8_t index)
|
||||
{
|
||||
if (index == 0) {
|
||||
return RT_TRUE;
|
||||
}
|
||||
|
||||
return (*pipe_index & BIT(index)) ? RT_TRUE : RT_FALSE;
|
||||
}
|
||||
|
||||
static int drv_pipe_xfer(upipe_t pipe, rt_uint8_t token, void *buffer, int nbytes, int timeouts)
|
||||
{
|
||||
struct hgusb20_dev *hgusb = (struct hgusb20_dev *)_hg_usbh.usb;
|
||||
rt_int32_t ret = RET_OK;
|
||||
rt_bool_t first_pkg = RT_TRUE;
|
||||
int total_len = 0;
|
||||
rt_size_t remain_size;
|
||||
rt_size_t send_size;
|
||||
rt_size_t ret_size;
|
||||
remain_size = nbytes;
|
||||
rt_uint8_t * pbuffer = (rt_uint8_t *)buffer;
|
||||
|
||||
if (!connect_status) {
|
||||
os_printf("connect_status is null\n");
|
||||
return -RT_EIO;
|
||||
}
|
||||
if (pipe->pipe_index > USB_HOST_MAX_PIPE) {
|
||||
return -RT_EIO;
|
||||
}
|
||||
if ((pipe->ep.bEndpointAddress & USB_DIR_MASK) == USB_DIR_IN) {
|
||||
if (!drv_pipe_index_check(&_hg_usbh.pipe_in_index, pipe->pipe_index)) {
|
||||
return -RT_EIO;
|
||||
}
|
||||
} else {
|
||||
if (!drv_pipe_index_check(&_hg_usbh.pipe_out_index, pipe->pipe_index)) {
|
||||
return -RT_EIO;
|
||||
}
|
||||
}
|
||||
|
||||
pipe->status = UPIPE_STATUS_OK;
|
||||
|
||||
hgusb20_set_address(hgusb, pipe->inst->address);
|
||||
|
||||
if ((pipe->ep.bEndpointAddress & USB_DIR_MASK) == USB_DIR_IN) {
|
||||
// RX不用互斥
|
||||
ret = os_event_wait(&_hg_usbh.trx_lock, BIT(pipe->pipe_index+16), NULL,
|
||||
OS_EVENT_WMODE_AND|OS_EVENT_WMODE_CLEAR, osWaitForever);
|
||||
if (ret) {
|
||||
LOG_D("drv_pipe_xfer rx req timeout!\r\n");
|
||||
pipe->status = UPIPE_STATUS_ERROR;
|
||||
return RET_ERR;
|
||||
}
|
||||
// 端点0软件分包
|
||||
if (pipe->pipe_index == 0) {
|
||||
do {
|
||||
send_size = (remain_size > pipe->ep.wMaxPacketSize) ? pipe->ep.wMaxPacketSize : remain_size;
|
||||
ret = hgusb20_host_ep0_rx(hgusb, pbuffer, first_pkg);
|
||||
if (ret) {
|
||||
pipe->status = UPIPE_STATUS_ERROR;
|
||||
break;
|
||||
}
|
||||
first_pkg = RT_FALSE;
|
||||
ret_size = hgusb->ep0_ptr.rx_len;
|
||||
total_len += hgusb->ep0_ptr.rx_len;
|
||||
if (ret_size == send_size) {
|
||||
remain_size -= send_size;
|
||||
pbuffer += send_size;
|
||||
} else {
|
||||
// 收到包小于packet size即短包(应该不会大于吧)提前结束
|
||||
break;
|
||||
}
|
||||
} while (remain_size > 0);
|
||||
} else {
|
||||
os_event_clear(&_hg_usbh.trx_done, BIT(pipe->pipe_index+16), NULL);
|
||||
hgusb20_ep_rx_kick(hgusb, pipe->pipe_index, (rt_uint32_t)buffer, nbytes);
|
||||
ret = os_event_wait(&_hg_usbh.trx_done, BIT(pipe->pipe_index+16), NULL,
|
||||
OS_EVENT_WMODE_AND|OS_EVENT_WMODE_CLEAR, (timeouts ? timeouts : osWaitForever));
|
||||
if (ret) {
|
||||
LOG_D("drv_pipe_xfer rx timeout!\r\n");
|
||||
pipe->status = UPIPE_STATUS_ERROR;
|
||||
hgusb20_ep_rx_abort(hgusb, pipe->pipe_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
usb_device_ioctl((struct usb_device *)hgusb, USB_HOST_GET_RX_DMA_LEN, pipe->pipe_index, (rt_uint32_t)&total_len);
|
||||
if (hgusb20_host_is_xact_err(hgusb, pipe->pipe_index, USB_DIR_IN)
|
||||
|| hgusb20_host_is_rx_stall(hgusb, pipe->pipe_index, USB_DIR_IN))
|
||||
{
|
||||
os_printf("%s usb2.0 rx dma err or stall, ep num is %d!!!!!\n",__FUNCTION__,pipe->pipe_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
os_event_set(&_hg_usbh.trx_lock, BIT(pipe->pipe_index+16), NULL);
|
||||
} else {
|
||||
// TX需要互斥
|
||||
ret = os_event_wait(&_hg_usbh.trx_lock, BIT(pipe->pipe_index), NULL,
|
||||
OS_EVENT_WMODE_AND|OS_EVENT_WMODE_CLEAR, osWaitForever);
|
||||
if (ret) {
|
||||
LOG_D("drv_pipe_xfer tx req timeout!\r\n");
|
||||
pipe->status = UPIPE_STATUS_ERROR;
|
||||
return RET_ERR;
|
||||
}
|
||||
if (token == USBH_PID_SETUP) {
|
||||
// setup包只会是ep0
|
||||
os_memcpy(&hgusb->usb_ctrl.cmd, buffer, nbytes);
|
||||
ret = hgusb20_host_ep0_setup(hgusb);
|
||||
if (ret) {
|
||||
//TX ERROR
|
||||
total_len = 0;
|
||||
pipe->status = UPIPE_STATUS_ERROR;
|
||||
} else {
|
||||
total_len = 8;
|
||||
}
|
||||
} else {
|
||||
// 端点0软件分包
|
||||
if (pipe->pipe_index == 0) {
|
||||
do {
|
||||
send_size = (remain_size > pipe->ep.wMaxPacketSize) ? pipe->ep.wMaxPacketSize : remain_size;
|
||||
ret = hgusb20_host_ep0_tx(hgusb, buffer, send_size);
|
||||
if (ret) {
|
||||
pipe->status = UPIPE_STATUS_ERROR;
|
||||
break;
|
||||
}
|
||||
total_len += send_size;
|
||||
remain_size -= send_size;
|
||||
pbuffer += send_size;
|
||||
} while (remain_size > 0);
|
||||
} else {
|
||||
os_event_clear(&_hg_usbh.trx_done, BIT(pipe->pipe_index), NULL);
|
||||
hgusb20_ep_tx_kick(hgusb, pipe->pipe_index, (rt_uint32_t)buffer, nbytes);
|
||||
ret = os_event_wait(&_hg_usbh.trx_done, BIT(pipe->pipe_index), NULL,
|
||||
OS_EVENT_WMODE_AND|OS_EVENT_WMODE_CLEAR, (timeouts ? timeouts : osWaitForever));
|
||||
if (ret) {
|
||||
LOG_D("drv_pipe_xfer tx timeout!\r\n");
|
||||
total_len = 0;
|
||||
pipe->status = UPIPE_STATUS_ERROR;
|
||||
hgusb20_ep_tx_abort(hgusb, pipe->pipe_index);
|
||||
} else {
|
||||
total_len = nbytes;
|
||||
if (hgusb20_host_is_xact_err(hgusb, pipe->pipe_index, USB_DIR_OUT)
|
||||
|| hgusb20_host_is_rx_stall(hgusb, pipe->pipe_index, USB_DIR_OUT))
|
||||
{
|
||||
os_printf("%s usb2.0 tx dma err or stall, ep num is %d!!!!!\n",__FUNCTION__,pipe->pipe_index);
|
||||
total_len = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
os_event_set(&_hg_usbh.trx_lock, BIT(pipe->pipe_index), NULL);
|
||||
}
|
||||
|
||||
if (pipe->callback != RT_NULL) pipe->callback(pipe);
|
||||
// 其余情况都是和请求长度一致
|
||||
return total_len;
|
||||
}
|
||||
|
||||
static rt_err_t drv_open_pipe(upipe_t pipe)
|
||||
{
|
||||
rt_uint32_t m;
|
||||
if ((pipe->ep.bEndpointAddress & USB_DIR_MASK) == USB_DIR_IN) {
|
||||
if ((pipe->ep.bEndpointAddress & USB_EPNO_MASK) != 0) {
|
||||
os_printf("drv open rx pipe\n");
|
||||
pipe->pipe_index = drv_get_free_pipe_index(&_hg_usbh.pipe_in_index);
|
||||
|
||||
hgusb20_pipe_attr usb_pipe;
|
||||
usb_pipe.dev_addr = pipe->inst->address;
|
||||
usb_pipe.dev_hub_port = pipe->inst->port;
|
||||
usb_pipe.u_usb_hub_addr.dev_hub_addr = 0;//hub_set_addr;
|
||||
usb_pipe.u_usb_hub_addr.hub_mtt_en = 0;//usb_sw->hub_mtt_en;
|
||||
usb_pipe.ep_host = pipe->pipe_index;
|
||||
usb_pipe.ep_dev = (pipe->ep.bEndpointAddress & USB_EPNO_MASK);
|
||||
usb_pipe.ep_type = (pipe->ep.bmAttributes & USB_EP_ATTR_TYPE_MASK);
|
||||
usb_pipe.ep_speed = 0;//usb_sw->child[usb_sw->current_connect_port].speed;
|
||||
usb_pipe.max_pkt_size = pipe->ep.wMaxPacketSize;
|
||||
hgusb20_host_rx_pipe_combine((struct hgusb20_dev *)_hg_usbh.usb, &usb_pipe);
|
||||
|
||||
if((pipe->ep.bmAttributes & USB_EP_ATTR_TYPE_MASK) != USB_EP_ATTR_BULK)
|
||||
{
|
||||
if((pipe->ep.bmAttributes & USB_EP_ATTR_TYPE_MASK) == USB_EP_ATTR_INT)
|
||||
{
|
||||
if (((struct hgusb20_dev *)_hg_usbh.usb)->usb_ctrl.bus_high_speed) {
|
||||
m = log2(pipe->ep.bInterval) + 1;
|
||||
os_printf("m = %d\r\n",m);
|
||||
hgusb20_host_set_interval((struct hgusb20_dev *)_hg_usbh.usb, pipe->pipe_index, USB_CORE_HOST_EP_RX, m);
|
||||
} else {
|
||||
hgusb20_host_set_interval((struct hgusb20_dev *)_hg_usbh.usb, pipe->pipe_index, USB_CORE_HOST_EP_RX, pipe->ep.bInterval);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m = log2(pipe->ep.bInterval) + 1;
|
||||
os_printf("m = %d\r\n",m);
|
||||
hgusb20_host_set_interval((struct hgusb20_dev *)_hg_usbh.usb, pipe->pipe_index, USB_CORE_HOST_EP_RX, m);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//NAK TIMEOUT
|
||||
hgusb20_host_set_interval((struct hgusb20_dev *)_hg_usbh.usb, pipe->pipe_index, USB_CORE_HOST_EP_RX, 0);
|
||||
}
|
||||
|
||||
} else {
|
||||
_hg_usbh.pipe_in_index |= BIT(0);
|
||||
}
|
||||
} else {
|
||||
if ((pipe->ep.bEndpointAddress & USB_EPNO_MASK) != 0) {
|
||||
os_printf("drv open tx pipe\n");
|
||||
pipe->pipe_index = drv_get_free_pipe_index(&_hg_usbh.pipe_out_index);
|
||||
|
||||
hgusb20_pipe_attr usb_pipe;
|
||||
usb_pipe.dev_addr = pipe->inst->address;
|
||||
usb_pipe.dev_hub_port = pipe->inst->port;
|
||||
usb_pipe.u_usb_hub_addr.dev_hub_addr = 0;//hub_set_addr;
|
||||
usb_pipe.u_usb_hub_addr.hub_mtt_en = 0;//usb_sw->hub_mtt_en;
|
||||
usb_pipe.ep_host = pipe->pipe_index;
|
||||
usb_pipe.ep_dev = (pipe->ep.bEndpointAddress & USB_EPNO_MASK);
|
||||
usb_pipe.ep_type = (pipe->ep.bmAttributes & USB_EP_ATTR_TYPE_MASK);
|
||||
usb_pipe.ep_speed = 0;//usb_sw->child[usb_sw->current_connect_port].speed;
|
||||
usb_pipe.max_pkt_size = pipe->ep.wMaxPacketSize;
|
||||
hgusb20_host_tx_pipe_combine((struct hgusb20_dev *)_hg_usbh.usb, &usb_pipe);
|
||||
|
||||
if((pipe->ep.bmAttributes & USB_EP_ATTR_TYPE_MASK) != USB_EP_ATTR_BULK)
|
||||
{
|
||||
if((pipe->ep.bmAttributes & USB_EP_ATTR_TYPE_MASK) == USB_EP_ATTR_INT)
|
||||
{
|
||||
if (((struct hgusb20_dev *)_hg_usbh.usb)->usb_ctrl.bus_high_speed) {
|
||||
m = log2(pipe->ep.bInterval) + 1;
|
||||
os_printf("m = %d\r\n",m);
|
||||
hgusb20_host_set_interval((struct hgusb20_dev *)_hg_usbh.usb, pipe->pipe_index, USB_CORE_HOST_EP_TX, m);
|
||||
} else {
|
||||
hgusb20_host_set_interval((struct hgusb20_dev *)_hg_usbh.usb, pipe->pipe_index, USB_CORE_HOST_EP_TX, pipe->ep.bInterval);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m = log2(pipe->ep.bInterval) + 1;
|
||||
os_printf("m = %d\r\n",m);
|
||||
hgusb20_host_set_interval((struct hgusb20_dev *)_hg_usbh.usb, pipe->pipe_index, USB_CORE_HOST_EP_TX, m);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//NAK TIMEOUT
|
||||
hgusb20_host_set_interval((struct hgusb20_dev *)_hg_usbh.usb, pipe->pipe_index, USB_CORE_HOST_EP_TX, 0);
|
||||
}
|
||||
|
||||
} else {
|
||||
_hg_usbh.pipe_out_index |= BIT(0);
|
||||
}
|
||||
}
|
||||
rt_kprintf("open pipe idx:%d ep%d dir:%x\r\n",
|
||||
pipe->pipe_index, (pipe->ep.bEndpointAddress & USB_EPNO_MASK), (pipe->ep.bEndpointAddress & USB_DIR_MASK));
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t drv_close_pipe(upipe_t pipe)
|
||||
{
|
||||
rt_kprintf("close pipe idx:%d\r\n", pipe->pipe_index);
|
||||
if ((pipe->ep.bEndpointAddress & USB_DIR_MASK) == USB_DIR_IN) {
|
||||
drv_free_pipe_index(&_hg_usbh.pipe_in_index, pipe->pipe_index);
|
||||
if (pipe->pipe_index != 0) {
|
||||
hgusb20_ep_rx_abort((struct hgusb20_dev *)_hg_usbh.usb, pipe->pipe_index);
|
||||
os_event_set(&_hg_usbh.trx_lock, BIT(pipe->pipe_index+16), NULL);
|
||||
}
|
||||
} else {
|
||||
drv_free_pipe_index(&_hg_usbh.pipe_out_index, pipe->pipe_index);
|
||||
if (pipe->pipe_index != 0) {
|
||||
hgusb20_ep_tx_abort((struct hgusb20_dev *)_hg_usbh.usb, pipe->pipe_index);
|
||||
os_event_set(&_hg_usbh.trx_lock, BIT(pipe->pipe_index), NULL);
|
||||
}
|
||||
}
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t drv_hub_port_set(uhub_param_t param)
|
||||
{
|
||||
hgusb20_pipe_attr usb_ep0_pipe;
|
||||
usb_ep0_pipe.u_usb_hub_addr.dev_hub_addr = param->hub_addr;
|
||||
usb_ep0_pipe.u_usb_hub_addr.hub_mtt_en = param->hub_mtt_en;
|
||||
usb_ep0_pipe.dev_addr = param->dev_addr;
|
||||
usb_ep0_pipe.dev_hub_port = param->dev_port;
|
||||
|
||||
switch (param->dev_speed)
|
||||
{
|
||||
case RTTUSB_DEV_LowSpeed:
|
||||
usb_ep0_pipe.ep_speed = 0xC0;
|
||||
break;
|
||||
|
||||
case RTTUSB_DEV_FullSpeed:
|
||||
usb_ep0_pipe.ep_speed = 0x80;
|
||||
break;
|
||||
|
||||
case RTTUSB_DEV_HighSpeed:
|
||||
usb_ep0_pipe.ep_speed = 0x40;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
hgusb20_host_hub_ep0_mange((struct hgusb20_dev *)_hg_usbh.usb, &usb_ep0_pipe);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static const struct uhcd_ops _uhcd_ops = {
|
||||
drv_reset_port,
|
||||
drv_pipe_xfer,
|
||||
drv_open_pipe,
|
||||
drv_close_pipe,
|
||||
drv_hub_port_set,
|
||||
};
|
||||
|
||||
rt_err_t hg_usbh_register(rt_uint32_t devid)
|
||||
{
|
||||
uhcd_t uhcd = RT_NULL;
|
||||
|
||||
uhcd = (uhcd_t)dev_get(devid);
|
||||
if (uhcd == RT_NULL) {
|
||||
uhcd = (uhcd_t)os_zalloc(sizeof(struct uhcd));
|
||||
if (uhcd == RT_NULL) {
|
||||
rt_kprintf("uhcd malloc failed\r\n");
|
||||
return -RT_ENOMEM;
|
||||
}
|
||||
|
||||
os_printf("%s %d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
uhcd->ops = &_uhcd_ops;
|
||||
uhcd->num_ports = 1;
|
||||
dev_register(devid, (struct dev_obj *)uhcd);
|
||||
|
||||
os_memset(&_hg_usbh, 0, sizeof(usb_core_instance));
|
||||
_hg_usbh.hcd = uhcd;
|
||||
os_event_init(&_hg_usbh.trx_done);
|
||||
os_event_init(&_hg_usbh.trx_lock);
|
||||
os_event_set(&_hg_usbh.trx_lock, 0xffffffff, NULL);
|
||||
_hg_usbh.usb = (struct usb_device *)dev_get(HG_USBDEV_DEVID);
|
||||
RT_ASSERT(_hg_usbh.usb);
|
||||
usbh_flag |= USBH_REGISTER_FLAG;
|
||||
usb_device_open(_hg_usbh.usb, NULL);
|
||||
usb_device_request_irq(_hg_usbh.usb, hg_usbh_irq_hdl, (rt_uint32_t)&_hg_usbh);
|
||||
|
||||
rt_usb_host_init(devid, "usb20_host");
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
rt_err_t hg_usbh_unregister(rt_uint32_t devid)
|
||||
{
|
||||
uhcd_t uhc;
|
||||
uhc = (uhcd_t)dev_get(devid);
|
||||
if (uhc) {
|
||||
printf("%s %d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
usbh_flag &= ~USBH_REGISTER_FLAG;
|
||||
|
||||
if(connect_status) {
|
||||
connect_status = RT_FALSE;
|
||||
rt_usbh_root_hub_disconnect_handler(_hg_usbh.hcd, 1);
|
||||
}
|
||||
|
||||
rt_usb_host_deinit(devid);
|
||||
|
||||
if(_hg_usbh.usb)
|
||||
{
|
||||
usb_device_close(_hg_usbh.usb);
|
||||
os_event_del(&_hg_usbh.trx_done);
|
||||
os_event_del(&_hg_usbh.trx_lock);
|
||||
_hg_usbh.usb = RT_NULL;
|
||||
}
|
||||
|
||||
if(_hg_usbh.hcd)
|
||||
{
|
||||
dev_unregister((struct dev_obj *)_hg_usbh.hcd);
|
||||
os_free(_hg_usbh.hcd);
|
||||
_hg_usbh.hcd = RT_NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
550
sdk/lib/bus/rttusb/bsp/drv_usbh_fpv.c
Normal file
550
sdk/lib/bus/rttusb/bsp/drv_usbh_fpv.c
Normal file
@@ -0,0 +1,550 @@
|
||||
/*
|
||||
针对 USB DMA RX , 需做的内存预留大小为 4 字节, 防止 DMA 内存越界引起的内存错误问题
|
||||
|
||||
USB1.1 SIE:
|
||||
(1) rx len % 4 == 1 实际 dma sram 会少 1 byte , 即 rx len - 1 (USB1.1驱动已修复)
|
||||
(2) rx len % 4 == 2 实际 dma sram 会多 1 byte , 即 rx len + 1
|
||||
(3) rx len % 4 == 0 || rx len % 4 == 3 实际 dma sram 长度与 rx len相同 , 即 rx len
|
||||
|
||||
USB2.0 SIE:
|
||||
(1) rx len % 4 == 1 实际 dma sram 会多 2 byte , 即 rx len + 2
|
||||
(2) rx len % 4 == 2 实际 dma sram 会多 1 byte , 即 rx len + 1
|
||||
(3) rx len % 4 == 0 || rx len % 4 == 3 实际 dma sram 长度与 rx len相同 , 即 rx len
|
||||
|
||||
*/
|
||||
#include <rtthread.h>
|
||||
#include <include/rttusb_host.h>
|
||||
#include "hal/usb_device.h"
|
||||
#include "dev/usb/hgusb20_v1_dev_api.h"
|
||||
#include "math.h"
|
||||
#ifdef RT_USBH_UVC
|
||||
#include "usbh_video.h"
|
||||
#endif
|
||||
#ifdef RT_USBH_UAC
|
||||
#include "usbh_audio.h"
|
||||
#endif
|
||||
|
||||
#define USB_HOST_MAX_PIPE 6
|
||||
|
||||
typedef struct {
|
||||
struct usb_device *usb;
|
||||
uhcd_t hcd;
|
||||
rt_uint32_t pipe_in_index; // 按bit记录主控可用端点
|
||||
rt_uint32_t pipe_out_index;
|
||||
struct os_event trx_lock;
|
||||
struct os_event trx_done;
|
||||
} usb_core_instance;
|
||||
|
||||
static usb_core_instance _hg_usbh;
|
||||
static volatile rt_bool_t connect_status = RT_FALSE;
|
||||
|
||||
#define USBH_REGISTER_FLAG BIT(1)
|
||||
static volatile rt_uint32_t usbh_flag = 0;
|
||||
|
||||
static rt_uint32_t hg_usbh_irq_hdl(rt_uint32_t irq, rt_uint32_t param1, rt_uint32_t param2, rt_uint32_t param3)
|
||||
{
|
||||
struct hgusb20_dev *p_dev = (struct hgusb20_dev *)dev_get(HG_USBDEV_DEVID);
|
||||
usb_core_instance *core = (usb_core_instance *)param1;
|
||||
rt_uint32_t usb_ep = param2 & 0xF;
|
||||
|
||||
switch (irq) {
|
||||
case USB_DEV_RESET_IRQ:
|
||||
break;
|
||||
case USB_DEV_SUSPEND_IRQ:
|
||||
break;
|
||||
case USB_DEV_RESUME_IRQ:
|
||||
break;
|
||||
case USB_DEV_SOF_IRQ:
|
||||
break;
|
||||
case USB_DEV_CTL_IRQ:
|
||||
break;
|
||||
case USB_EP_RX_IRQ:
|
||||
os_event_set(&core->trx_done, BIT(usb_ep+16), NULL);
|
||||
if (connect_status) {
|
||||
#ifdef RT_USBH_UVC
|
||||
rtt_usbh_video_irq(p_dev, usb_ep, _hg_usbh.hcd);
|
||||
#endif
|
||||
#ifdef RT_USBH_UAC
|
||||
rtt_usbh_audio_irq(p_dev, irq, usb_ep);
|
||||
#endif
|
||||
} else {
|
||||
hgusb20_ep_rx_abort(p_dev, usb_ep);
|
||||
hgusb20_host_reset_ep_rxcsr(p_dev, usb_ep);
|
||||
rt_kprintf("connect status is NULL , stop in rx irq\n");
|
||||
}
|
||||
break;
|
||||
case USB_EP_TX_IRQ:
|
||||
os_event_set(&core->trx_done, BIT(usb_ep), NULL);
|
||||
if (connect_status) {
|
||||
#ifdef RT_USBH_UAC
|
||||
rtt_usbh_audio_irq(p_dev, irq, usb_ep);
|
||||
#endif
|
||||
} else {
|
||||
hgusb20_ep_tx_abort(p_dev, usb_ep);
|
||||
hgusb20_host_reset_ep_txcsr(p_dev, usb_ep);
|
||||
rt_kprintf("connect status is NULL , stop in tx irq\n");
|
||||
}
|
||||
break;
|
||||
case USB_CONNECT:
|
||||
if (hgusb20_is_device_online(p_dev) && (usbh_flag & USBH_REGISTER_FLAG)) {
|
||||
if (!connect_status) {
|
||||
connect_status = RT_TRUE;
|
||||
rt_kprintf("usb connected\r\n");
|
||||
rt_usbh_root_hub_connect_handler(core->hcd, 1, RT_TRUE);
|
||||
hg_usb_connect_detect_using();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case USB_DISCONNECT:
|
||||
if (!hgusb20_is_device_online(p_dev) && (usbh_flag & USBH_REGISTER_FLAG)) {
|
||||
if (connect_status) {
|
||||
connect_status = RT_FALSE;
|
||||
rt_kprintf("usb disconnect\r\n");
|
||||
rt_usbh_root_hub_disconnect_handler(core->hcd, 1);
|
||||
hg_usb_connect_detect_recfg();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case USB_BABBLE:
|
||||
break;
|
||||
case USB_XACT_ERR:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static rt_err_t drv_reset_port(rt_uint8_t port)
|
||||
{
|
||||
rt_kprintf("reset port\r\n");
|
||||
hgusb20_host_reset((struct hgusb20_dev *)_hg_usbh.usb);
|
||||
hgusb20_set_address((struct hgusb20_dev *)_hg_usbh.usb, 0);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_uint8_t drv_get_free_pipe_index(rt_uint32_t *pipe_index)
|
||||
{
|
||||
rt_uint8_t idx;
|
||||
for (idx = 1; idx <= USB_HOST_MAX_PIPE; ++idx) {
|
||||
if (!(*pipe_index & BIT(idx))) {
|
||||
*pipe_index |= BIT(idx);
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
static inline void drv_free_pipe_index(rt_uint32_t *pipe_index, rt_uint8_t index)
|
||||
{
|
||||
*pipe_index &= ~BIT(index);
|
||||
}
|
||||
|
||||
static inline rt_bool_t drv_pipe_index_check(rt_uint32_t *pipe_index, rt_uint8_t index)
|
||||
{
|
||||
if (index == 0) {
|
||||
return RT_TRUE;
|
||||
}
|
||||
|
||||
return (*pipe_index & BIT(index)) ? RT_TRUE : RT_FALSE;
|
||||
}
|
||||
|
||||
rt_uint8_t drv_get_specific_pipe(rt_uint8_t index, rt_uint8_t in_or_out)
|
||||
{
|
||||
if(index <= USB_HOST_MAX_PIPE && index >= 0){
|
||||
if(in_or_out == USB_DIR_IN){
|
||||
os_printf("drv_get_specific_pipe in:%d\r\n",index);
|
||||
_hg_usbh.pipe_in_index |= BIT(index);
|
||||
return index;
|
||||
} else {
|
||||
os_printf("drv_get_specific_pipe out:%d\r\n",index);
|
||||
_hg_usbh.pipe_out_index |= BIT(index);
|
||||
return index;
|
||||
}
|
||||
} else
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
void drv_free_specific_pipe(rt_uint8_t index, rt_uint8_t in_or_out)
|
||||
{
|
||||
os_printf("drv_free_specific_pipe:%d\r\n",index);
|
||||
if(index <= USB_HOST_MAX_PIPE && index >= 0){
|
||||
if(in_or_out == USB_DIR_IN)
|
||||
_hg_usbh.pipe_in_index &= ~BIT(index);
|
||||
else
|
||||
_hg_usbh.pipe_out_index &= ~BIT(index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int drv_pipe_xfer(upipe_t pipe, rt_uint8_t token, void *buffer, int nbytes, int timeouts)
|
||||
{
|
||||
struct hgusb20_dev *hgusb = (struct hgusb20_dev *)_hg_usbh.usb;
|
||||
rt_int32_t ret = RET_OK;
|
||||
rt_bool_t first_pkg = RT_TRUE;
|
||||
int total_len = 0;
|
||||
rt_size_t remain_size;
|
||||
rt_size_t send_size;
|
||||
rt_size_t ret_size;
|
||||
remain_size = nbytes;
|
||||
rt_uint8_t * pbuffer = (rt_uint8_t *)buffer;
|
||||
|
||||
if (!connect_status) {
|
||||
os_printf("connect_status is null\n");
|
||||
return -RT_EIO;
|
||||
}
|
||||
if (pipe->pipe_index > USB_HOST_MAX_PIPE) {
|
||||
return -RT_EIO;
|
||||
}
|
||||
if ((pipe->ep.bEndpointAddress & USB_DIR_MASK) == USB_DIR_IN) {
|
||||
if (!drv_pipe_index_check(&_hg_usbh.pipe_in_index, pipe->pipe_index)) {
|
||||
return -RT_EIO;
|
||||
}
|
||||
} else {
|
||||
if (!drv_pipe_index_check(&_hg_usbh.pipe_out_index, pipe->pipe_index)) {
|
||||
return -RT_EIO;
|
||||
}
|
||||
}
|
||||
|
||||
pipe->status = UPIPE_STATUS_OK;
|
||||
|
||||
hgusb20_set_address(hgusb, pipe->inst->address);
|
||||
|
||||
if ((pipe->ep.bEndpointAddress & USB_DIR_MASK) == USB_DIR_IN) {
|
||||
// RX不用互斥
|
||||
ret = os_event_wait(&_hg_usbh.trx_lock, BIT(pipe->pipe_index+16), NULL,
|
||||
OS_EVENT_WMODE_AND|OS_EVENT_WMODE_CLEAR, osWaitForever);
|
||||
if (ret) {
|
||||
LOG_D("drv_pipe_xfer rx req timeout!\r\n");
|
||||
pipe->status = UPIPE_STATUS_ERROR;
|
||||
return RET_ERR;
|
||||
}
|
||||
// 端点0软件分包
|
||||
if (pipe->pipe_index == 0) {
|
||||
do {
|
||||
send_size = (remain_size > pipe->ep.wMaxPacketSize) ? pipe->ep.wMaxPacketSize : remain_size;
|
||||
ret = hgusb20_host_ep0_rx(hgusb, pbuffer, first_pkg);
|
||||
if (ret) {
|
||||
pipe->status = UPIPE_STATUS_ERROR;
|
||||
break;
|
||||
}
|
||||
first_pkg = RT_FALSE;
|
||||
ret_size = hgusb->ep0_ptr.rx_len;
|
||||
total_len += hgusb->ep0_ptr.rx_len;
|
||||
if (ret_size == send_size) {
|
||||
remain_size -= send_size;
|
||||
pbuffer += send_size;
|
||||
} else {
|
||||
// 收到包小于packet size即短包(应该不会大于吧)提前结束
|
||||
break;
|
||||
}
|
||||
} while (remain_size > 0);
|
||||
} else {
|
||||
os_event_clear(&_hg_usbh.trx_done, BIT(pipe->pipe_index+16), NULL);
|
||||
hgusb20_ep_rx_kick(hgusb, pipe->pipe_index, (rt_uint32_t)buffer, nbytes);
|
||||
ret = os_event_wait(&_hg_usbh.trx_done, BIT(pipe->pipe_index+16), NULL,
|
||||
OS_EVENT_WMODE_AND|OS_EVENT_WMODE_CLEAR, (timeouts ? timeouts : osWaitForever));
|
||||
if (ret) {
|
||||
LOG_D("drv_pipe_xfer rx timeout!\r\n");
|
||||
pipe->status = UPIPE_STATUS_ERROR;
|
||||
hgusb20_ep_rx_abort(hgusb, pipe->pipe_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
usb_device_ioctl((struct usb_device *)hgusb, USB_HOST_GET_RX_DMA_LEN, pipe->pipe_index, (rt_uint32_t)&total_len);
|
||||
if (hgusb20_host_is_xact_err(hgusb, pipe->pipe_index, USB_DIR_IN)
|
||||
|| hgusb20_host_is_rx_stall(hgusb, pipe->pipe_index, USB_DIR_IN))
|
||||
{
|
||||
os_printf("%s usb2.0 rx dma err or stall, ep num is %d!!!!!\n",__FUNCTION__,pipe->pipe_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
os_event_set(&_hg_usbh.trx_lock, BIT(pipe->pipe_index+16), NULL);
|
||||
} else {
|
||||
// TX需要互斥
|
||||
ret = os_event_wait(&_hg_usbh.trx_lock, BIT(pipe->pipe_index), NULL,
|
||||
OS_EVENT_WMODE_AND|OS_EVENT_WMODE_CLEAR, osWaitForever);
|
||||
if (ret) {
|
||||
LOG_D("drv_pipe_xfer tx req timeout!\r\n");
|
||||
pipe->status = UPIPE_STATUS_ERROR;
|
||||
return RET_ERR;
|
||||
}
|
||||
if (token == USBH_PID_SETUP) {
|
||||
// setup包只会是ep0
|
||||
os_memcpy(&hgusb->usb_ctrl.cmd, buffer, nbytes);
|
||||
ret = hgusb20_host_ep0_setup(hgusb);
|
||||
if (ret) {
|
||||
//TX ERROR
|
||||
total_len = 0;
|
||||
pipe->status = UPIPE_STATUS_ERROR;
|
||||
} else {
|
||||
total_len = 8;
|
||||
}
|
||||
} else {
|
||||
// 端点0软件分包
|
||||
if (pipe->pipe_index == 0) {
|
||||
do {
|
||||
send_size = (remain_size > pipe->ep.wMaxPacketSize) ? pipe->ep.wMaxPacketSize : remain_size;
|
||||
ret = hgusb20_host_ep0_tx(hgusb, buffer, send_size);
|
||||
if (ret) {
|
||||
pipe->status = UPIPE_STATUS_ERROR;
|
||||
break;
|
||||
}
|
||||
total_len += send_size;
|
||||
remain_size -= send_size;
|
||||
pbuffer += send_size;
|
||||
} while (remain_size > 0);
|
||||
} else {
|
||||
os_event_clear(&_hg_usbh.trx_done, BIT(pipe->pipe_index), NULL);
|
||||
hgusb20_ep_tx_kick(hgusb, pipe->pipe_index, (rt_uint32_t)buffer, nbytes);
|
||||
ret = os_event_wait(&_hg_usbh.trx_done, BIT(pipe->pipe_index), NULL,
|
||||
OS_EVENT_WMODE_AND|OS_EVENT_WMODE_CLEAR, (timeouts ? timeouts : osWaitForever));
|
||||
if (ret) {
|
||||
os_printf("drv_pipe_xfer tx timeout!\r\n");
|
||||
total_len = 0;
|
||||
pipe->status = UPIPE_STATUS_ERROR;
|
||||
hgusb20_ep_tx_abort(hgusb, pipe->pipe_index);
|
||||
} else {
|
||||
total_len = nbytes;
|
||||
if (hgusb20_host_is_xact_err(hgusb, pipe->pipe_index, USB_DIR_OUT)
|
||||
|| hgusb20_host_is_rx_stall(hgusb, pipe->pipe_index, USB_DIR_OUT))
|
||||
{
|
||||
os_printf("%s usb2.0 tx dma err or stall, ep num is %d!!!!!\n",__FUNCTION__,pipe->pipe_index);
|
||||
total_len = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
os_event_set(&_hg_usbh.trx_lock, BIT(pipe->pipe_index), NULL);
|
||||
}
|
||||
|
||||
if (pipe->callback != RT_NULL) pipe->callback(pipe);
|
||||
// 其余情况都是和请求长度一致
|
||||
return total_len;
|
||||
}
|
||||
|
||||
static rt_err_t drv_open_pipe(upipe_t pipe)
|
||||
{
|
||||
rt_uint32_t m;
|
||||
if ((pipe->ep.bEndpointAddress & USB_DIR_MASK) == USB_DIR_IN) {
|
||||
if ((pipe->ep.bEndpointAddress & USB_EPNO_MASK) != 0) {
|
||||
os_printf("drv open rx pipe\n");
|
||||
pipe->pipe_index = drv_get_free_pipe_index(&_hg_usbh.pipe_in_index);
|
||||
|
||||
hgusb20_pipe_attr usb_pipe;
|
||||
usb_pipe.dev_addr = pipe->inst->address;
|
||||
usb_pipe.dev_hub_port = pipe->inst->port;
|
||||
usb_pipe.u_usb_hub_addr.dev_hub_addr = 0;//hub_set_addr;
|
||||
usb_pipe.u_usb_hub_addr.hub_mtt_en = 0;//usb_sw->hub_mtt_en;
|
||||
usb_pipe.ep_host = pipe->pipe_index;
|
||||
usb_pipe.ep_dev = (pipe->ep.bEndpointAddress & USB_EPNO_MASK);
|
||||
usb_pipe.ep_type = (pipe->ep.bmAttributes & USB_EP_ATTR_TYPE_MASK);
|
||||
usb_pipe.ep_speed = 0;//usb_sw->child[usb_sw->current_connect_port].speed;
|
||||
usb_pipe.max_pkt_size = pipe->ep.wMaxPacketSize;
|
||||
hgusb20_host_rx_pipe_combine((struct hgusb20_dev *)_hg_usbh.usb, &usb_pipe);
|
||||
|
||||
if((pipe->ep.bmAttributes & USB_EP_ATTR_TYPE_MASK) != USB_EP_ATTR_BULK)
|
||||
{
|
||||
if((pipe->ep.bmAttributes & USB_EP_ATTR_TYPE_MASK) == USB_EP_ATTR_INT)
|
||||
{
|
||||
if (((struct hgusb20_dev *)_hg_usbh.usb)->usb_ctrl.bus_high_speed) {
|
||||
m = log2(pipe->ep.bInterval) + 1;
|
||||
os_printf("m = %d\r\n",m);
|
||||
hgusb20_host_set_interval((struct hgusb20_dev *)_hg_usbh.usb, pipe->pipe_index, USB_CORE_HOST_EP_RX, m);
|
||||
} else {
|
||||
hgusb20_host_set_interval((struct hgusb20_dev *)_hg_usbh.usb, pipe->pipe_index, USB_CORE_HOST_EP_RX, pipe->ep.bInterval);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m = log2(pipe->ep.bInterval) + 1;
|
||||
os_printf("m = %d\r\n",m);
|
||||
hgusb20_host_set_interval((struct hgusb20_dev *)_hg_usbh.usb, pipe->pipe_index, USB_CORE_HOST_EP_RX, m);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//NAK TIMEOUT
|
||||
hgusb20_host_set_interval((struct hgusb20_dev *)_hg_usbh.usb, pipe->pipe_index, USB_CORE_HOST_EP_RX, 0);
|
||||
}
|
||||
|
||||
} else {
|
||||
_hg_usbh.pipe_in_index |= BIT(0);
|
||||
}
|
||||
} else {
|
||||
if ((pipe->ep.bEndpointAddress & USB_EPNO_MASK) != 0) {
|
||||
os_printf("drv open tx pipe\n");
|
||||
pipe->pipe_index = drv_get_free_pipe_index(&_hg_usbh.pipe_out_index);
|
||||
|
||||
hgusb20_pipe_attr usb_pipe;
|
||||
usb_pipe.dev_addr = pipe->inst->address;
|
||||
usb_pipe.dev_hub_port = pipe->inst->port;
|
||||
usb_pipe.u_usb_hub_addr.dev_hub_addr = 0;//hub_set_addr;
|
||||
usb_pipe.u_usb_hub_addr.hub_mtt_en = 0;//usb_sw->hub_mtt_en;
|
||||
usb_pipe.ep_host = pipe->pipe_index;
|
||||
usb_pipe.ep_dev = (pipe->ep.bEndpointAddress & USB_EPNO_MASK);
|
||||
usb_pipe.ep_type = (pipe->ep.bmAttributes & USB_EP_ATTR_TYPE_MASK);
|
||||
usb_pipe.ep_speed = 0;//usb_sw->child[usb_sw->current_connect_port].speed;
|
||||
usb_pipe.max_pkt_size = pipe->ep.wMaxPacketSize;
|
||||
hgusb20_host_tx_pipe_combine((struct hgusb20_dev *)_hg_usbh.usb, &usb_pipe);
|
||||
|
||||
if((pipe->ep.bmAttributes & USB_EP_ATTR_TYPE_MASK) != USB_EP_ATTR_BULK)
|
||||
{
|
||||
if((pipe->ep.bmAttributes & USB_EP_ATTR_TYPE_MASK) == USB_EP_ATTR_INT)
|
||||
{
|
||||
if (((struct hgusb20_dev *)_hg_usbh.usb)->usb_ctrl.bus_high_speed) {
|
||||
m = log2(pipe->ep.bInterval) + 1;
|
||||
os_printf("m = %d\r\n",m);
|
||||
hgusb20_host_set_interval((struct hgusb20_dev *)_hg_usbh.usb, pipe->pipe_index, USB_CORE_HOST_EP_TX, m);
|
||||
} else {
|
||||
hgusb20_host_set_interval((struct hgusb20_dev *)_hg_usbh.usb, pipe->pipe_index, USB_CORE_HOST_EP_TX, pipe->ep.bInterval);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m = log2(pipe->ep.bInterval) + 1;
|
||||
os_printf("m = %d\r\n",m);
|
||||
hgusb20_host_set_interval((struct hgusb20_dev *)_hg_usbh.usb, pipe->pipe_index, USB_CORE_HOST_EP_TX, m);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//NAK TIMEOUT
|
||||
hgusb20_host_set_interval((struct hgusb20_dev *)_hg_usbh.usb, pipe->pipe_index, USB_CORE_HOST_EP_TX, 0);
|
||||
}
|
||||
|
||||
} else {
|
||||
_hg_usbh.pipe_out_index |= BIT(0);
|
||||
}
|
||||
}
|
||||
rt_kprintf("open pipe idx:%d ep%d dir:%x\r\n",
|
||||
pipe->pipe_index, (pipe->ep.bEndpointAddress & USB_EPNO_MASK), (pipe->ep.bEndpointAddress & USB_DIR_MASK));
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t drv_close_pipe(upipe_t pipe)
|
||||
{
|
||||
rt_kprintf("close pipe idx:%d\r\n", pipe->pipe_index);
|
||||
if ((pipe->ep.bEndpointAddress & USB_DIR_MASK) == USB_DIR_IN) {
|
||||
drv_free_pipe_index(&_hg_usbh.pipe_in_index, pipe->pipe_index);
|
||||
if (pipe->pipe_index != 0) {
|
||||
hgusb20_ep_rx_abort((struct hgusb20_dev *)_hg_usbh.usb, pipe->pipe_index);
|
||||
os_event_set(&_hg_usbh.trx_lock, BIT(pipe->pipe_index+16), NULL);
|
||||
}
|
||||
} else {
|
||||
drv_free_pipe_index(&_hg_usbh.pipe_out_index, pipe->pipe_index);
|
||||
if (pipe->pipe_index != 0) {
|
||||
hgusb20_ep_tx_abort((struct hgusb20_dev *)_hg_usbh.usb, pipe->pipe_index);
|
||||
os_event_set(&_hg_usbh.trx_lock, BIT(pipe->pipe_index), NULL);
|
||||
}
|
||||
}
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t drv_hub_port_set(uhub_param_t param)
|
||||
{
|
||||
hgusb20_pipe_attr usb_ep0_pipe;
|
||||
usb_ep0_pipe.u_usb_hub_addr.dev_hub_addr = param->hub_addr;
|
||||
usb_ep0_pipe.u_usb_hub_addr.hub_mtt_en = param->hub_mtt_en;
|
||||
usb_ep0_pipe.dev_addr = param->dev_addr;
|
||||
usb_ep0_pipe.dev_hub_port = param->dev_port;
|
||||
|
||||
switch (param->dev_speed)
|
||||
{
|
||||
case RTTUSB_DEV_LowSpeed:
|
||||
usb_ep0_pipe.ep_speed = 0x3;
|
||||
break;
|
||||
|
||||
case RTTUSB_DEV_FullSpeed:
|
||||
usb_ep0_pipe.ep_speed = 0x2;
|
||||
break;
|
||||
|
||||
case RTTUSB_DEV_HighSpeed:
|
||||
usb_ep0_pipe.ep_speed = 0x1;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
hgusb20_host_hub_ep0_mange((struct hgusb20_dev *)_hg_usbh.usb, &usb_ep0_pipe);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static const struct uhcd_ops _uhcd_ops = {
|
||||
drv_reset_port,
|
||||
drv_pipe_xfer,
|
||||
drv_open_pipe,
|
||||
drv_close_pipe,
|
||||
drv_hub_port_set,
|
||||
};
|
||||
|
||||
rt_err_t hg_usbh_register(rt_uint32_t devid)
|
||||
{
|
||||
uhcd_t uhcd = RT_NULL;
|
||||
|
||||
uhcd = (uhcd_t)dev_get(devid);
|
||||
if (uhcd == RT_NULL) {
|
||||
uhcd = (uhcd_t)os_zalloc(sizeof(struct uhcd));
|
||||
if (uhcd == RT_NULL) {
|
||||
rt_kprintf("uhcd malloc failed\r\n");
|
||||
return -RT_ENOMEM;
|
||||
}
|
||||
|
||||
os_printf("%s %d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
uhcd->ops = (uhcd_ops_t)&_uhcd_ops;
|
||||
uhcd->num_ports = 1;
|
||||
dev_register(devid, (struct dev_obj *)uhcd);
|
||||
|
||||
os_memset(&_hg_usbh, 0, sizeof(usb_core_instance));
|
||||
_hg_usbh.hcd = uhcd;
|
||||
os_event_init(&_hg_usbh.trx_done);
|
||||
os_event_init(&_hg_usbh.trx_lock);
|
||||
os_event_set(&_hg_usbh.trx_lock, 0xffffffff, NULL);
|
||||
_hg_usbh.usb = (struct usb_device *)dev_get(HG_USBDEV_DEVID);
|
||||
RT_ASSERT(_hg_usbh.usb);
|
||||
usbh_flag |= USBH_REGISTER_FLAG;
|
||||
usb_device_open(_hg_usbh.usb, NULL);
|
||||
usb_device_request_irq(_hg_usbh.usb, hg_usbh_irq_hdl, (rt_uint32_t)&_hg_usbh);
|
||||
|
||||
rt_usb_host_init(devid, "usb20_host");
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
rt_err_t hg_usbh_unregister(rt_uint32_t devid)
|
||||
{
|
||||
uhcd_t uhc;
|
||||
uhc = (uhcd_t)dev_get(devid);
|
||||
if (uhc) {
|
||||
printf("%s %d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
usbh_flag &= ~USBH_REGISTER_FLAG;
|
||||
|
||||
if(connect_status) {
|
||||
connect_status = RT_FALSE;
|
||||
rt_usbh_root_hub_disconnect_handler(_hg_usbh.hcd, 1);
|
||||
}
|
||||
|
||||
rt_usb_host_deinit(devid);
|
||||
|
||||
if(_hg_usbh.usb)
|
||||
{
|
||||
usb_device_close(_hg_usbh.usb);
|
||||
os_event_del(&_hg_usbh.trx_done);
|
||||
os_event_del(&_hg_usbh.trx_lock);
|
||||
_hg_usbh.usb = RT_NULL;
|
||||
}
|
||||
|
||||
if(_hg_usbh.hcd)
|
||||
{
|
||||
dev_unregister((struct dev_obj *)_hg_usbh.hcd);
|
||||
os_free(_hg_usbh.hcd);
|
||||
_hg_usbh.hcd = RT_NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
214
sdk/lib/bus/rttusb/bsp/usb_detect.c
Normal file
214
sdk/lib/bus/rttusb/bsp/usb_detect.c
Normal file
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
USB 主从切换检测
|
||||
*/
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
#include "dev/usb/hgusb20_v1_dev_api.h"
|
||||
#include "osal/work.h"
|
||||
#include "include/rttusb_host.h"
|
||||
#include "include/rttusb_device.h"
|
||||
#include "drv_usbd.h"
|
||||
#include "lib/heap/sysheap.h"
|
||||
|
||||
|
||||
enum {
|
||||
USB_STATUS_NONE, //未连接
|
||||
USB_STATUS_DEVICE, //当Device
|
||||
USB_STATUS_HOST, //当Host
|
||||
USB_STATUS_USING, //使用中
|
||||
};
|
||||
|
||||
struct usb_connect_structure
|
||||
{
|
||||
struct os_work usb_detect_wk;
|
||||
uint32_t usb_connect_status; //0:无状态 1:USB_STATUS_DEVICE 2:USB_STATUS_HOST 3:USB使用中
|
||||
uint32_t usb_connect_last_status;
|
||||
}hg_usb_detect;
|
||||
|
||||
rt_err_t hg_usbh_register(rt_uint32_t devid);
|
||||
rt_err_t hg_usbh_unregister(rt_uint32_t devid);
|
||||
|
||||
extern struct hgusb20_dev usb20_dev;
|
||||
static void hg_usb_detect_device_open()
|
||||
{
|
||||
uint32 mask = 0;
|
||||
struct usb_device *p_dev = (struct usb_device *)dev_get(HG_USBDEV_DEVID);
|
||||
|
||||
if(p_dev == NULL)
|
||||
{
|
||||
os_printf("%s %d\n",__FUNCTION__,__LINE__);
|
||||
mask = disable_irq();
|
||||
hgusb20_dev_attach(HG_USBDEV_DEVID, &usb20_dev);
|
||||
enable_irq(mask);
|
||||
|
||||
hg_usbd_recover(HG_USB_DEV_CONTROLLER_DEVID);
|
||||
}else{
|
||||
os_printf("%s p_dev is exist\n",__FUNCTION__);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void hg_usb_detect_device_close()
|
||||
{
|
||||
struct usb_device *p_dev = (struct usb_device *)dev_get(HG_USBDEV_DEVID);
|
||||
|
||||
if(p_dev)
|
||||
{
|
||||
os_printf("%s %d p_dev:%x\n",__FUNCTION__,__LINE__,p_dev);
|
||||
dev_unregister((struct dev_obj *)p_dev);
|
||||
}else{
|
||||
os_printf("%s p_dev is NULL\n",__FUNCTION__);
|
||||
}
|
||||
}
|
||||
|
||||
static void hg_usb_detect_host_open()
|
||||
{
|
||||
uint32 mask = 0;
|
||||
uint32_t ret;
|
||||
struct usb_device *p_dev = (struct usb_device *)dev_get(HG_USBDEV_DEVID);
|
||||
|
||||
if(p_dev == NULL)
|
||||
{
|
||||
mask = disable_irq();
|
||||
ret = hgusb20_host_attach(HG_USBDEV_DEVID, &usb20_dev);
|
||||
enable_irq(mask);
|
||||
p_dev = (struct usb_device *)dev_get(HG_USBDEV_DEVID);
|
||||
|
||||
hg_usbh_register(HG_USB_HOST_CONTROLLER_DEVID);
|
||||
}else{
|
||||
os_printf("%s p_dev is exist\n",__FUNCTION__);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void hg_usb_detect_host_close()
|
||||
{
|
||||
struct usb_device *p_dev = (struct usb_device *)dev_get(HG_USBDEV_DEVID);
|
||||
|
||||
if(p_dev)
|
||||
{
|
||||
os_printf("%s %d\n",__FUNCTION__,__LINE__);
|
||||
dev_unregister((struct dev_obj *)p_dev);
|
||||
}else{
|
||||
os_printf("%s p_dev is NULL\n",__FUNCTION__);
|
||||
}
|
||||
}
|
||||
|
||||
static void hg_usb_detect_init()
|
||||
{
|
||||
hg_usbh_unregister(HG_USB_HOST_CONTROLLER_DEVID);
|
||||
hg_usbd_unregister(HG_USB_DEV_CONTROLLER_DEVID);
|
||||
}
|
||||
|
||||
|
||||
static int32 hg_usb_connect_detect_work(struct os_work *work)
|
||||
{
|
||||
uint8_t ret;
|
||||
uint8_t detect_tem = USB_CONNECTED_NONE;
|
||||
static uint32_t timeout = 0;
|
||||
struct hgusb20_dev *p_dev = (struct hgusb20_dev *)dev_get(HG_USBDEV_DEVID);
|
||||
if(p_dev == NULL)
|
||||
{
|
||||
os_printf("hg_usb_connect_detect_work: dev_get fail\n");
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
if(hg_usb_detect.usb_connect_status == USB_STATUS_NONE)
|
||||
{
|
||||
timeout++;
|
||||
}
|
||||
else
|
||||
{
|
||||
timeout = 0;
|
||||
}
|
||||
|
||||
switch(hg_usb_detect.usb_connect_status) {
|
||||
case USB_STATUS_NONE:
|
||||
if(timeout > 2)
|
||||
{
|
||||
hg_usb_detect_init(); //检测前关闭应用线程
|
||||
while(1) //误检测判断
|
||||
{
|
||||
ret = hgusb20_connected(p_dev);
|
||||
if(detect_tem != ret) {
|
||||
detect_tem = ret;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
os_printf("USB_STATUS_NONE freemem:%d \r\n", sysheap_freesize(&sram_heap));
|
||||
hg_usb_detect.usb_connect_status = detect_tem;
|
||||
os_printf("===hgusb20_connected ret:%d===\n",detect_tem);
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_STATUS_DEVICE: //检测到插入电脑,关闭主机模式,开启从机模式
|
||||
hg_usb_detect_host_close();
|
||||
hg_usb_detect_device_open();
|
||||
os_printf("USB_STATUS_DEVICE freemem:%d \r\n", sysheap_freesize(&sram_heap));
|
||||
hg_usb_detect.usb_connect_last_status = USB_STATUS_DEVICE;
|
||||
hg_usb_detect.usb_connect_status = USB_STATUS_USING;
|
||||
break;
|
||||
|
||||
case USB_STATUS_HOST: //检测到插入设备,关闭从机模式,开启主机模式
|
||||
hg_usb_detect_device_close();
|
||||
hg_usb_detect_host_open();
|
||||
os_printf("USB_STATUS_HOST freemem:%d \r\n", sysheap_freesize(&sram_heap));
|
||||
hg_usb_detect.usb_connect_last_status = USB_STATUS_HOST;
|
||||
hg_usb_detect.usb_connect_status = USB_STATUS_USING;
|
||||
break;
|
||||
|
||||
case USB_STATUS_USING:
|
||||
if(hg_usb_detect.usb_connect_last_status == USB_STATUS_DEVICE) { //如果是从机模式,在这里检测是否脱离主机
|
||||
ret = hgusb20_is_host_online(p_dev);
|
||||
os_printf("hgusb20_is_host_online:%d\n",ret);
|
||||
if(!ret) {
|
||||
hg_usb_detect.usb_connect_status = USB_STATUS_NONE;
|
||||
} else {
|
||||
hg_usb_detect.usb_connect_status = USB_STATUS_USING;
|
||||
}
|
||||
}
|
||||
os_sleep_ms(10);
|
||||
break;
|
||||
}
|
||||
|
||||
__exit:
|
||||
os_run_work_delay(&hg_usb_detect.usb_detect_wk, 500); //重新检测的时间配置
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hg_usb_connect_detect_using(void)
|
||||
{
|
||||
os_printf("%s %d\n",__FUNCTION__,__LINE__);
|
||||
hg_usb_detect.usb_connect_status = USB_STATUS_USING;
|
||||
}
|
||||
|
||||
void hg_usb_connect_detect_recfg(void)
|
||||
{
|
||||
os_printf("%s %d\n",__FUNCTION__,__LINE__);
|
||||
hg_usb_detect.usb_connect_status = USB_STATUS_NONE;
|
||||
}
|
||||
|
||||
void hg_usb_connect_detect_init(void)
|
||||
{
|
||||
/* RTT USB Device 未留有释放内存接口,避免重复申请空间,因而先初始化 USB Device */
|
||||
/* 前面一定要在 devic.c 先调用 hgusb20_dev_attach */
|
||||
/* 若需同时注册多个device设备,需定义宏RT_USB_DEVICE_COMPOSITE成复合设备 */
|
||||
/* 若要注册host设备请参考 usbhost.c 文件 */
|
||||
|
||||
hg_usbd_class_driver_register();
|
||||
|
||||
hg_usbd_register(HG_USB_DEV_CONTROLLER_DEVID);
|
||||
|
||||
OS_WORK_INIT(&hg_usb_detect.usb_detect_wk, hg_usb_connect_detect_work, 0);
|
||||
os_run_work_delay(&hg_usb_detect.usb_detect_wk, 500);
|
||||
}
|
||||
|
||||
void hg_usb_connect_detect_deinit(void)
|
||||
{
|
||||
os_work_cancle(&hg_usb_detect.usb_detect_wk, 1);
|
||||
}
|
||||
Reference in New Issue
Block a user