/* * drv_usbd.c * * Created on: 2017Äê2ÔÂ1ÈÕ * Author: Urey */ #include #include #include "x1000.h" #include "x1000_dwc.h" static struct udcd __x1000_usbd; static dwc_handle __dwc_hdl; //#define USBD_DEBUG #ifdef USBD_DEBUG #define USBD_DBG(fmt, args...) rt_kprintf(fmt ,##args) #else #define USBD_DBG(fmt, args...) #endif static void __delay(void) { int i; for (i = 0; i < 1000; i++); } static struct ep_id __ep_pool[] = { {0x00, USB_EP_ATTR_CONTROL, USB_DIR_INOUT, 64, ID_ASSIGNED}, #if DWC_FORCE_SPEED_FULL {0x01, USB_EP_ATTR_INT, USB_DIR_IN, 64, ID_UNASSIGNED}, {0x02, USB_EP_ATTR_BULK, USB_DIR_OUT, 64, ID_UNASSIGNED}, {0x02, USB_EP_ATTR_BULK, USB_DIR_IN, 64, ID_UNASSIGNED}, {0x04, USB_EP_ATTR_BULK, USB_DIR_OUT, 64, ID_UNASSIGNED}, {0x04, USB_EP_ATTR_BULK, USB_DIR_IN, 64, ID_UNASSIGNED}, #else {0x01, USB_EP_ATTR_INT, USB_DIR_IN, 512, ID_UNASSIGNED}, {0x01, USB_EP_ATTR_INT, USB_DIR_OUT, 512, ID_UNASSIGNED}, {0x02, USB_EP_ATTR_BULK, USB_DIR_OUT, 512, ID_UNASSIGNED}, {0x02, USB_EP_ATTR_BULK, USB_DIR_IN, 512, ID_UNASSIGNED}, {0x04, USB_EP_ATTR_BULK, USB_DIR_OUT, 512, ID_UNASSIGNED}, {0x04, USB_EP_ATTR_BULK, USB_DIR_IN, 512, ID_UNASSIGNED}, {0x06, USB_EP_ATTR_BULK, USB_DIR_OUT, 512, ID_UNASSIGNED}, {0x06, USB_EP_ATTR_BULK, USB_DIR_IN, 512, ID_UNASSIGNED}, #endif {0xFF, USB_EP_ATTR_TYPE_MASK, USB_DIR_MASK, 0, ID_ASSIGNED} }; #define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ') static void dump_hex(const rt_uint8_t *ptr, rt_size_t buflen) { unsigned char *buf = (unsigned char*)ptr; int i, j; for (i=0; iep_desc != RT_NULL); RT_DEBUG_LOG(RT_DEBUG_USB,("%s ,address = %02x\n", __func__,EP_ADDRESS(ep))); if(ep->id->dir == USB_DIR_IN) dwc_enable_in_ep(&__dwc_hdl,ep->id->addr); else dwc_enable_out_ep(&__dwc_hdl,ep->id->addr); return RT_EOK; } static rt_err_t __ep_disable(uep_t ep) { RT_ASSERT(ep != RT_NULL); RT_ASSERT(ep->ep_desc != RT_NULL); RT_DEBUG_LOG(RT_DEBUG_USB,("%s\n", __func__)); // USB_DisableEP(EP_ADDRESS(ep)); return RT_EOK; } static rt_size_t __ep_read_prepare(rt_uint8_t address, void *buffer, rt_size_t size) { dwc_ep *pep ; RT_DEBUG_LOG(RT_DEBUG_USB,("%s address = %02x,size = %d\n", __func__,address,size)); pep = __dwc_hdl.dep[address & 0x0F + DWC_EP_OUT_OFS]; pep->ep_state = EP_DATA; pep->xfer_len = size; // pep->xfer_buff = buffer; pep->xfer_count = 0; dwc_handle_ep_data_out_phase(&__dwc_hdl, address); return size; } static rt_size_t __ep_read(rt_uint8_t address, void *buffer) { rt_size_t size = 0; RT_ASSERT(buffer != RT_NULL); RT_DEBUG_LOG(RT_DEBUG_USB,("%s\n", __func__)); size = HW_GetPKT(&__dwc_hdl,address,(uint8_t *)buffer,0); return size; } static rt_size_t __ep_write(rt_uint8_t address, void *buffer, rt_size_t size) { RT_DEBUG_LOG(RT_DEBUG_USB,("%s address = %02x,buffer = %08x ,size = %d\n", __func__,address,(uint32_t)buffer,size)); size = HW_SendPKT(&__dwc_hdl,address,(const uint8_t *)buffer,size); return size; } static rt_err_t __ep0_send_status(void) { RT_DEBUG_LOG(RT_DEBUG_USB,("%s\n", __func__)); HW_SendPKT(&__dwc_hdl,0,0,0); return RT_EOK; } static rt_err_t __suspend(void) { RT_DEBUG_LOG(RT_DEBUG_USB,("%s\n", __func__)); return RT_EOK; } static rt_err_t __wakeup(void) { RT_DEBUG_LOG(RT_DEBUG_USB,("%s\n", __func__)); return RT_EOK; } static rt_err_t __init(rt_device_t device) { int epidx = 0, epnum = 0; __dwc_hdl.status.b.state = USB_CABLE_DISCONNECT; /* clear all dep */ for (epidx = 0; epidx < 32; epidx++) { __dwc_hdl.dep[epidx] = RT_NULL; } for (epidx = 0; __ep_pool[epidx].addr != 0xFF; ++epidx) { dwc_ep *pep = RT_NULL; rt_uint8_t *pXfer = RT_NULL; if(epidx == 0) { /* EP0 is IN-OUT */ pep = (dwc_ep *) rt_malloc(sizeof(dwc_ep)); if (!pep) { rt_kprintf("ERROR: no memory for pep\n"); while (1) ; } /* malloc memory for EP */ pXfer = rt_malloc_align(__ep_pool[epidx].maxpacket * 2, 32); if (!pXfer) { rt_kprintf("ERROR: no memory for pXfer\n"); while (1) ; } /* init pep */ { pep->num = 0; pep->ep_state = EP_SETUP; pep->is_in = 0; pep->active = 0; pep->type = DWC_OTG_EP_TYPE_CONTROL; pep->maxpacket = __ep_pool[epidx].maxpacket; pep->xfer_buff = (void *)UNCACHED(pXfer); pep->xfer_len = 0; pep->xfer_count = 0; } __dwc_hdl.dep[0 + DWC_EP_IN_OFS] = pep; __dwc_hdl.dep[0 + DWC_EP_OUT_OFS] = pep; } else { pep = (dwc_ep *) rt_malloc(sizeof(dwc_ep)); if (!pep) { rt_kprintf("ERROR: no memory for pep\n"); while (1) ; } /* malloc memory for EP */ pXfer = rt_malloc_align(__ep_pool[epidx].maxpacket * 2, 32); if (!pXfer) { rt_kprintf("ERROR: no memory for pXfer\n"); while (1) ; } /* init pep */ { pep->num = __ep_pool[epidx].addr; pep->ep_state = EP_IDLE; pep->is_in = (__ep_pool[epidx].dir == USB_DIR_IN) ? 1 : 0; pep->active = 0; pep->type = __ep_pool[epidx].type; pep->maxpacket = __ep_pool[epidx].maxpacket; pep->xfer_buff = (void *)UNCACHED(pXfer); pep->xfer_len = 0; pep->xfer_count = 0; } if(__ep_pool[epidx].dir == USB_DIR_OUT) epnum = __ep_pool[epidx].addr + DWC_EP_OUT_OFS; else epnum = __ep_pool[epidx].addr + DWC_EP_IN_OFS; __dwc_hdl.dep[epnum] = pep; } } x1000_usbd_init(&__dwc_hdl); { dwc_ep *pep = __dwc_hdl.dep[18]; // rt_kprintf("18 pep->is_in = %d\n",pep->is_in); // rt_kprintf("18 xfer_buff = %08x\n",(uint32_t)pep->xfer_buff); } return RT_EOK; } static struct udcd_ops __x1000_usbd_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, }; void x1000_usbd_event_cb(uint8_t address,uint32_t event,void *arg) { switch (event) { case USB_EVT_SETUP: USBD_DBG("USB_EVT_SETUP\n"); if(address == 0) { rt_usbd_ep0_setup_handler(&__x1000_usbd, (struct urequest*)arg); } break; case USB_EVT_OUT: USBD_DBG("USB_EVT_OUT\n"); if(address == 0) rt_usbd_ep0_out_handler(&__x1000_usbd, (rt_size_t)arg); else rt_usbd_ep_out_handler(&__x1000_usbd, USB_DIR_OUT | address, 0); break; case USB_EVT_IN: USBD_DBG("USB_EVT_IN\n"); if(address == 0) rt_usbd_ep0_in_handler(&__x1000_usbd); else rt_usbd_ep_in_handler(&__x1000_usbd, USB_DIR_IN | address,__dwc_hdl.dep[DWC_EP_IN_OFS + address]->xfer_count); break; case USB_EVT_SOF: rt_usbd_sof_handler(&__x1000_usbd); break; default: break; } } int x1000_usbd_register(void) { rt_memset((void *)&__x1000_usbd, 0, sizeof(struct udcd)); __x1000_usbd.parent.type = RT_Device_Class_USBDevice; __x1000_usbd.parent.init = __init; __x1000_usbd.ops = &__x1000_usbd_ops; /* Register endpoint infomation */ __x1000_usbd.ep_pool = __ep_pool; __x1000_usbd.ep0.id = &__ep_pool[0]; rt_device_register(&__x1000_usbd.parent, "usbd", 0); rt_usb_device_init(); return RT_EOK; } INIT_ENV_EXPORT(x1000_usbd_register);