Files
OpenTXW81X/sdk/lib/bus/rttusb/usbhost/class/cdc.c
T
2025-08-27 09:51:58 +01:00

325 lines
9.1 KiB
C

#include "include/usb_host.h"
#include "cdc.h"
#ifdef RT_USBH_CDC
static struct uclass_driver cdc_driver;
volatile ucdc_data_t cdc_d;
uint8_t buff_out[64] __attribute__((aligned(4)));
uint8_t buff_in[64] __attribute__((aligned(4)));
rt_err_t rt_usbh_cdc_send_command(uinst_t device, void* buffer, int nbytes)
{
struct urequest setup;
int timeout = USB_TIMEOUT_BASIC;
RT_ASSERT(device != RT_NULL);
setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_CLASS |
USB_REQ_TYPE_INTERFACE;
setup.bRequest = SEND_ENCAPSULATED_COMMAND;
setup.wIndex = 0;
setup.wLength = nbytes;
setup.wValue = 0;
if(rt_usb_hcd_setup_xfer(device->hcd, device->pipe_ep0_out, &setup, timeout) == 8)
{
if(rt_usb_hcd_pipe_xfer(device->hcd, device->pipe_ep0_out, buffer, nbytes, timeout) == nbytes)
{
if(rt_usb_hcd_pipe_xfer(device->hcd, device->pipe_ep0_in, RT_NULL, 0, timeout) == 0)
{
return nbytes;
}
}
}
return RT_ERROR;
}
rt_err_t rt_usbh_cdc_get_response(uinst_t device, void* buffer, int nbytes)
{
struct urequest setup;
int timeout = USB_TIMEOUT_BASIC;
int ret_size;
RT_ASSERT(device != RT_NULL);
setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_CLASS |
USB_REQ_TYPE_INTERFACE;
setup.bRequest = GET_ENCAPSULATED_RESPONSE;
setup.wIndex = 0;
setup.wLength = nbytes;
setup.wValue = 0;
if(rt_usb_hcd_setup_xfer(device->hcd, device->pipe_ep0_out, &setup, timeout) == 8)
{
ret_size = rt_usb_hcd_pipe_xfer(device->hcd, device->pipe_ep0_in, buffer, nbytes, timeout);
if(ret_size > 0)
{
if(rt_usb_hcd_pipe_xfer(device->hcd, device->pipe_ep0_out, RT_NULL, 0, timeout) == 0)
{
return ret_size;
}
}
}
return RT_ERROR;
}
rt_err_t rt_usbh_cdc_get_line_coding(uinst_t device, int intf, void* buffer)
{
struct urequest setup;
int timeout = USB_TIMEOUT_BASIC;
int ret_size;
RT_ASSERT(device != RT_NULL);
setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_CLASS |
USB_REQ_TYPE_INTERFACE;
setup.bRequest = GET_LINE_CODING;
setup.wIndex = intf;
setup.wLength = 7;
setup.wValue = 0;
if(rt_usb_hcd_setup_xfer(device->hcd, device->pipe_ep0_out, &setup, timeout) == 8)
{
ret_size = rt_usb_hcd_pipe_xfer(device->hcd, device->pipe_ep0_in, buffer, 7, timeout);
if(ret_size == 7)
{
if(rt_usb_hcd_pipe_xfer(device->hcd, device->pipe_ep0_out, RT_NULL, 0, timeout) == 0)
{
return ret_size;
}
}
}
return RT_ERROR;
}
rt_err_t rt_usbh_cdc_set_line_coding(uinst_t device, int intf, void* buffer)
{
struct urequest setup;
int timeout = USB_TIMEOUT_BASIC;
RT_ASSERT(device != RT_NULL);
setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE;
setup.bRequest = SET_LINE_CODING;
setup.wIndex = intf; // interface
setup.wLength = 7;
setup.wValue = 0;
if(rt_usb_hcd_setup_xfer(device->hcd, device->pipe_ep0_out, &setup, timeout) == 8)
{
if(rt_usb_hcd_pipe_xfer(device->hcd, device->pipe_ep0_out, buffer, 7, timeout) == 7)
{
if(rt_usb_hcd_pipe_xfer(device->hcd, device->pipe_ep0_in, RT_NULL, 0, timeout) == 0)
{
return RT_EOK;
}
}
}
return -RT_ERROR;
}
rt_err_t rt_usbh_cdc_set_control_line_state(uinst_t device, int intf, void * buffer, int len)
{
struct urequest setup;
int timeout = USB_TIMEOUT_BASIC;
RT_ASSERT(device != RT_NULL);
setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE;
setup.bRequest = SET_CONTROL_LINE_STATE;
setup.wIndex = intf; // interface
setup.wLength = len;
setup.wValue = 0;
if(rt_usb_hcd_setup_xfer(device->hcd, device->pipe_ep0_out, &setup, timeout) == 8)
{
if(rt_usb_hcd_pipe_xfer(device->hcd, device->pipe_ep0_in, RT_NULL, 0, timeout) == 0)
{
return RT_EOK;
}
}
return -RT_ERROR;
}
void analysis_cdc_line_coding(struct usb_cdc_line_coding * line_coding)
{
os_printf("=========line coding=========\n");
os_printf("dwDTERate:%d\n", line_coding->dwDTERate);
os_printf("bCharFormat:%d\n", line_coding->bCharFormat);
os_printf("bParityType:%d\n", line_coding->bParityType);
os_printf("bDataBits:%d\n", line_coding->bDataBits);
os_printf("=============================\n");
}
static rt_err_t rt_usbh_get_CDC_interface_descriptor(ucfg_desc_t cfg_desc, int num,
uintf_desc_t* intf_desc)
{
rt_uint32_t ptr, depth = 0;
udesc_t desc;
/* check parameter */
RT_ASSERT(cfg_desc != RT_NULL);
ptr = (rt_uint32_t)cfg_desc + cfg_desc->bLength;
while(ptr < (rt_uint32_t)cfg_desc + cfg_desc->wTotalLength)
{
if(depth++ > 0x40)
{
*intf_desc = RT_NULL;
return -RT_EIO;
}
desc = (udesc_t)ptr;
if(desc->type == USB_DESC_TYPE_INTERFACE)
{
if(((uintf_desc_t)desc)->bNumEndpoints == 0)
{
ptr = (rt_uint32_t)desc + desc->bLength;
continue;
}
if(((uintf_desc_t)desc)->bInterfaceNumber == num)
{
*intf_desc = (uintf_desc_t)desc;
LOG_D("rt_usb_get_interface_descriptor: %d", num);
return RT_EOK;
}
}
ptr = (rt_uint32_t)desc + desc->bLength;
}
rt_kprintf("rt_usb_get_interface_descriptor %d failed\n", num);
return -RT_EIO;
}
static rt_err_t rt_usbh_cdc_enable(void *arg)
{
struct uhintf **intf = arg;
uhcd_t hcd = NULL;
if (intf == NULL) {
return -EIO;
}
hcd = intf[0]->device->hcd;
os_printf("subclass %d, protocal %d\r\n",
intf[0]->intf_desc->bInterfaceSubClass,
intf[0]->intf_desc->bInterfaceProtocol);
#ifdef RT_USBH_UVC
int i;
struct usb_cdc_line_coding line_coding;
upipe_t pipe;
uintf_desc_t intf_desc = RT_NULL;
cdc_d = rt_malloc(sizeof(struct ucdc_data));
if(cdc_d == RT_NULL)
{
rt_kprintf("allocate cdc_d memory failed\n");
return -RT_ENOMEM;
}
os_printf("cdc_d:%x\n",cdc_d);
cdc_d->line_coding = &line_coding;
cdc_d->device = intf[0]->device;
rt_memset(cdc_d, 0, sizeof(struct ucdc_data));
intf[0]->user_data = (void *)cdc_d;
rt_usbh_cdc_get_line_coding(intf[0]->device, intf[0]->intf_desc->bInterfaceNumber, &line_coding);
analysis_cdc_line_coding(&line_coding);
line_coding.dwDTERate = BAUD_RATE_2000000;
line_coding.bCharFormat = STOP_BITS_1;
line_coding.bParityType = PARITY_NONE;
line_coding.bDataBits = DATA_BITS_8;
rt_usbh_cdc_set_line_coding(intf[0]->device, intf[0]->intf_desc->bInterfaceNumber, &line_coding);
analysis_cdc_line_coding(&line_coding);
rt_usbh_cdc_get_line_coding(intf[0]->device, intf[0]->intf_desc->bInterfaceNumber, &line_coding);
rt_usbh_cdc_set_control_line_state(intf[0]->device, intf[0]->intf_desc->bInterfaceNumber, RT_NULL, 0);
analysis_cdc_line_coding(&line_coding);
rt_usbh_get_CDC_interface_descriptor(intf[0]->device->cfg_desc, 1, &intf_desc);
for(i = 0; i < intf_desc->bNumEndpoints; i++)
{
uep_desc_t ep_desc;
rt_usbh_get_endpoint_descriptor(intf_desc, i, &ep_desc);
if(ep_desc == RT_NULL)
{
rt_kprintf("rt_usb_get_endpoint_descriptor error\n");
return -RT_ERROR;
}
analysis_usb_ep_desc(ep_desc); //获取端点描述符 打印端点描述符信息
/* the endpoint type of mass storage class should be BULK */
if((ep_desc->bmAttributes & USB_EP_ATTR_TYPE_MASK) != USB_EP_ATTR_BULK)
continue;
if (rt_usb_hcd_alloc_pipe(intf[0]->device->hcd, &pipe, intf[0]->device, ep_desc) != RT_EOK) {
rt_kprintf("alloc pipe failed\n");
return -RT_ERROR;
}
rt_usb_instance_add_pipe(intf[0]->device, pipe);
if ((ep_desc->bEndpointAddress & USB_DIR_MASK) == USB_DIR_IN) {
cdc_d->pipe_in = pipe;
os_printf("cdc_d->pipe_in:%x pipe:%x\n",cdc_d->pipe_in,pipe);
} else {
cdc_d->pipe_out = pipe;
os_printf("cdc_d->pipe_out:%x pipe:%x\n",cdc_d->pipe_out,pipe);
}
}
buff_out[0] = 0xAA;
buff_out[1] = 0x55;
buff_out[2] = 0xF1;
rt_usb_hcd_pipe_xfer(intf[0]->device->hcd, cdc_d->pipe_out, buff_out, 8, 0);
memset(buff_in,0,8);
rt_usb_hcd_pipe_xfer(intf[0]->device->hcd, cdc_d->pipe_in, buff_in, 8, 0);
for(int i = 0; i < 8; i++)
{
printf("buff_in[%d]:%x\n",i,buff_in[i]);
}
#endif
return RET_OK;
}
static rt_err_t rt_usbh_cdc_disable(void *arg)
{
#ifdef RT_USBH_UVC
struct uhintf *intf = arg;
if (intf == NULL) {
return -EIO;
}
if(cdc_d != RT_NULL)
rt_free(cdc_d);
#endif
return RET_OK;
}
ucd_t rt_usbh_class_driver_cdc(void)
{
cdc_driver.class_code = USB_CLASS_COMM;
cdc_driver.enable = rt_usbh_cdc_enable;
cdc_driver.disable = rt_usbh_cdc_disable;
return &cdc_driver;
}
#endif