#include "include/rttusb_host.h" #include "cdc.h" #ifdef RT_USBH_VENDOR_YUGE #include "yuge.h" #endif #ifdef RT_USBH_VENDOR_ZXINFO #include "zxinfo.h" #endif #ifdef RT_USBH_CDC #ifdef RT_USBH_CDC_THREAD #define EVENT_CDC_DATA_START (1 << 0) #define EVENT_CDC_DATA_END (1 << 1) static ucdc_data_t cdc_d; static rt_event_t cdc_data_event; uint8_t buff_out[64] __attribute__((aligned(4))); uint8_t buff_in[64 + USB_RX_BUFF_RESERVE_SIZE] __attribute__((aligned(4))); #endif static struct uclass_driver cdc_driver; 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; } #ifdef RT_USBH_CDC_THREAD int32 demo_atcmd_cdc_trans_ctrl(const char *cmd, char *argv[], uint32 argc) { if(*argv[0] == '1') { rt_usbh_cdc_trans_init(); } else if(*argv[0] == '2') { rt_usbh_cdc_trans_deinit(); } printf("OK/n"); return 0; } void rt_usbh_cdc_trans_init() { if (cdc_data_event != RT_NULL) { rt_event_send(cdc_data_event, EVENT_CDC_DATA_START); } } void rt_usbh_cdc_trans_deinit() { if (cdc_data_event != RT_NULL) { rt_event_send(cdc_data_event, EVENT_CDC_DATA_END); } } static void rt_usbh_cdc_communication_thread(void* arg) { int i; struct uhintf **intf = arg; // uhcd_t hcd = NULL; // uintf_desc_t intf_desc; int timeout = USB_TIMEOUT_BASIC; rt_uint32_t e; struct usb_cdc_line_coding *line_coding = (struct usb_cdc_line_coding *)rt_malloc(sizeof(struct usb_cdc_line_coding) + USB_RX_BUFF_RESERVE_SIZE); if(line_coding == RT_NULL) { rt_kprintf("rt_usbh_cdc_communication_thread malloc line_coding failed\n"); goto __exit; } os_printf("rt_usbh_cdc_communication_thread arg:%x\n",arg); cdc_d->thread_state = 1; cdc_d->line_coding = line_coding; while(1) { if (rt_event_recv(cdc_data_event, EVENT_CDC_DATA_START | EVENT_CDC_DATA_END, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 1000, &e) != RT_EOK) { continue; } if (e & EVENT_CDC_DATA_START) { }else if(e & EVENT_CDC_DATA_END) { goto __exit; }else { continue; } os_printf("cdc translate strat\n"); memset(line_coding, 0, sizeof(struct usb_cdc_line_coding)); 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); memset(line_coding, 0, sizeof(struct usb_cdc_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); if(cdc_d->pipe_in == RT_NULL && cdc_d->pipe_out == RT_NULL) { for(i = 0; i < intf[1]->intf_desc->bNumEndpoints; i++) { uep_desc_t ep_desc; upipe_t pipe; rt_usbh_get_endpoint_descriptor(intf[1]->intf_desc, i, &ep_desc); if(ep_desc == RT_NULL) { rt_kprintf("rt_usb_get_endpoint_descriptor error\n"); return ; } 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_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); } } } if(cdc_d->pipe_in != RT_NULL && cdc_d->pipe_out != RT_NULL) { buff_out[0] = 0xAA; buff_out[1] = 0x55; buff_out[2] = 0xD1; buff_out[3] = 0x00; buff_out[4] = 0x00; buff_out[5] = 0x00; buff_out[6] = 0x00; buff_out[7] = 0x00; buff_out[8] = 0x00; buff_out[9] = 0xD0; memset(buff_in,0,10); rt_usb_hcd_pipe_xfer(intf[0]->device->hcd, cdc_d->pipe_out, buff_out, 64, timeout); rt_usb_hcd_pipe_xfer(intf[0]->device->hcd, cdc_d->pipe_in, buff_in, 64, timeout); for(int i = 0; i < 10; i++) { printf("buff_in[%d]:%x\n",i,buff_in[i]); } } } __exit: if (cdc_d->line_coding != RT_NULL) { rt_free(cdc_d->line_coding); cdc_d->line_coding = RT_NULL; } rt_thread_suspend(cdc_d->thread); cdc_d->thread_state = 0; return ; } #endif static rt_err_t rt_usbh_cdc_enable(void *arg) { struct uhintf **intf = arg; uhcd_t hcd = NULL; if (intf[0] == 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_CDC_THREAD cdc_d = rt_malloc(sizeof(struct ucdc_data)); if(cdc_d == RT_NULL) { rt_kprintf("allocate cdc_d memory failed\n"); return -RT_ENOMEM; } rt_memset(cdc_d, 0, sizeof(struct ucdc_data)); cdc_d->device = intf[0]->device; os_printf("cdc_d:%x cdc_d->device:%x hcd:%x\n",cdc_d,cdc_d->device,cdc_d->device->hcd); intf[0]->user_data = (void *)cdc_d; os_printf("rt_usbh_cdc_enable arg:%x\n",arg); cdc_data_event = rt_event_create("cdc_data_event", RT_IPC_FLAG_FIFO); cdc_d->thread = rt_thread_create("cdc_comm_thread",rt_usbh_cdc_communication_thread,arg,1024,OS_TASK_PRIORITY_NORMAL,0); if(cdc_d->thread != RT_NULL) { rt_thread_startup(cdc_d->thread); } #endif #ifdef RT_USBH_VENDOR_YUGE if (intf[0]->device->dev_desc.idVendor == USB_VENDOR_ID_YUGE) { rt_usbh_yuge_at_run(intf); } #endif #ifdef RT_USBH_VENDOR_ZXINFO if (intf[0]->device->dev_desc.idVendor == USB_VENDOR_ID_ZXINFO) { rt_usbh_zxinfo_at_run(intf); } #endif return RET_OK; } static rt_err_t rt_usbh_cdc_disable(void *arg) { struct uhintf *intf = arg; #ifdef RT_USBH_CDC_THREAD rt_usbh_cdc_trans_deinit(); while(!cdc_d->thread_state) { rt_thread_delay(1); } if(cdc_d->thread != RT_NULL) { rt_thread_delete(cdc_d->thread); cdc_d->thread = RT_NULL; } if(cdc_data_event != RT_NULL) { rt_event_delete(cdc_data_event); cdc_data_event = RT_NULL; } if(cdc_d != RT_NULL) { rt_free(cdc_d); cdc_d = RT_NULL; } #endif #ifdef RT_USBH_VENDOR_YUGE if (intf->device->dev_desc.idVendor == USB_VENDOR_ID_YUGE) { rt_usbh_yuge_at_stop(intf); } #endif #ifdef RT_USBH_VENDOR_ZXINFO if (intf->device->dev_desc.idVendor == USB_VENDOR_ID_ZXINFO) { rt_usbh_zxinfo_at_stop(intf); } #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