/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static int sunxi_pburn_init(void) { sunxi_usb_dbg("sunxi_pburn_init\n"); memset(&trans_data, 0, sizeof(pburn_trans_set_t)); sunxi_usb_pburn_write_enable = 0; sunxi_usb_pburn_status = SUNXI_USB_PBURN_IDLE; trans_data.base_recv_buffer = (u8 *)malloc(SUNXI_PBURN_RECV_MEM_SIZE); if(!trans_data.base_recv_buffer) { printf("sunxi usb pburn err: unable to malloc memory for pburn receive\n"); return -1; } trans_data.base_send_buffer = (u8 *)malloc(SUNXI_PBURN_SEND_MEM_SIZE); if(!trans_data.base_send_buffer) { printf("sunxi usb pburn err: unable to malloc memory for pburn send\n"); free(trans_data.base_recv_buffer); return -1; } sunxi_usb_dbg("recv addr 0x%x\n", (uint)trans_data.base_recv_buffer); sunxi_usb_dbg("send addr 0x%x\n", (uint)trans_data.base_send_buffer); return 0; }
/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int sunxi_udc_set_address(uchar address) { __u32 speed_mode; /*Config New Address*/ SUSB_Dev_SetAddress(address); speed_mode = SUSB_Get_Speed_Mode(); if(speed_mode== 0x4) { sunxi_udc_source.speed = USB_SPEED_SUPER; sunxi_usb_dbg("usb speed: SS\n"); } else if(speed_mode == 0x0) { sunxi_udc_source.speed = USB_SPEED_HIGH; sunxi_usb_dbg("usb speed: HIGH\n"); } else { sunxi_udc_source.speed = USB_SPEED_FULL; sunxi_usb_dbg("usb speed: FULL\n"); } //__ep0_send_zero_package(); ep0_zero_package_flag = 1; return SUNXI_USB_REQ_SUCCESSED; }
/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static int eprx_recv_op(void) { uint old_ep_index; uint this_len; uint fifo; old_ep_index = USBC_GetActiveEp(sunxi_udc_source.usbc_hd); USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX); if (USBC_Dev_IsEpStall(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX)) { USBC_Dev_EpClearStall(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX); printf("sunxi ubs read error: usb rx ep is busy already\n"); } else { if(USBC_Dev_IsReadDataReady(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX)) { this_len = USBC_ReadLenFromFifo(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX); if(fastboot_data_flag == 1) { fifo = USBC_SelectFIFO(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX); sunxi_ubuf.rx_req_length = USBC_ReadPacket(sunxi_udc_source.usbc_hd, fifo, this_len, sunxi_ubuf.rx_req_buffer); sunxi_ubuf.rx_req_buffer += this_len; sunxi_usb_dbg("special read ep bytes 0x%x\n", sunxi_ubuf.rx_req_length); __usb_readcomplete(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX, 1); //返回状态 } else if(!sunxi_ubuf.rx_ready_for_data) { fifo = USBC_SelectFIFO(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX); memset(sunxi_ubuf.rx_req_buffer, 0, 64); sunxi_ubuf.rx_req_length = USBC_ReadPacket(sunxi_udc_source.usbc_hd, fifo, this_len, sunxi_ubuf.rx_req_buffer); sunxi_ubuf.rx_ready_for_data = 1; sunxi_usb_dbg("read ep bytes 0x%x\n", sunxi_ubuf.rx_req_length); __usb_readcomplete(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX, 1); //返回状态 } else { sunxi_usb_dbg("eprx do nothing and left it to dma\n"); } } else { sunxi_usb_dbg("sunxi usb rxdata not ready\n"); } } USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, old_ep_index); return 0; }
static int __usb_read_fifo(void *buffer, unsigned int buffer_size) { u32 old_ep_idx = 0; u32 fifo = 0; u32 transfered = 0; u32 left = 0; u32 this_len; old_ep_idx = USBC_GetActiveEp(sunxi_udc_source.usbc_hd); USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX); //选择当前EP fifo = USBC_SelectFIFO(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX); //选择fifo left = buffer_size; if(left) { while(left) { if(USBC_Dev_IsReadDataReady(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX)) { this_len = USBC_ReadLenFromFifo(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX); this_len = USBC_ReadPacket(sunxi_udc_source.usbc_hd, fifo, this_len, buffer + transfered); transfered += this_len; left -= this_len; __usb_readcomplete(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX, 1); //返回状态 } } USBC_INT_ClearEpPending(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX, SUNXI_USB_BULK_OUT_EP_INDEX); } else { if(USBC_Dev_IsReadDataReady(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX)) { this_len = USBC_ReadLenFromFifo(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX); this_len = USBC_ReadPacket(sunxi_udc_source.usbc_hd, fifo, this_len, buffer); transfered = this_len; __usb_readcomplete(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX, 1); //返回状态 } else { sunxi_usb_dbg("sunxi usb rxdata not ready\n"); } } USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, old_ep_idx); sunxi_usb_dbg("read bytes 0x%x\n", transfered); return transfered; }
/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static void __endpoint_interrupt(__u32 event_context) { switch(((event_context>>6)&0x0f)) { case SUSB_DEPEVT_XFERCOMPLETE: if(((event_context>>1)&0x1f)==0)//ep0 out { sunxi_usb_dbg("ep0 out complete\n"); __ep0_complete_out(); } else if(((event_context>>1)&0x1f)==1)//ep0 in { sunxi_usb_dbg("ep0 in complete\n"); __ep0_complete_in(); } else if(((event_context>>1)&0x1f) == (usb_mem_cfg.phy_out_ep&0x1f))//epx out
/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static int sunxi_pburn_nonstandard_req_op(uint cmd, struct usb_device_request *req, uchar *buffer, uint data_status) { int ret = SUNXI_USB_REQ_SUCCESSED; switch(req->bmRequestType) //PBURN 特有请求 { case 161: if(req->bRequest == 0xFE) { sunxi_usb_dbg("pburn ask for max lun\n"); buffer[0] = 0; sunxi_udc_send_setup(1, buffer); } else { printf("sunxi usb err: unknown ep0 req in pburn\n"); ret = SUNXI_USB_REQ_DEVICE_NOT_SUPPORTED; } break; default: printf("sunxi usb err: unknown non standard ep0 req\n"); ret = SUNXI_USB_REQ_DEVICE_NOT_SUPPORTED; break; } return ret; }
/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static void sunxi_pburn_usb_tx_dma_isr(void *p_arg) { sunxi_usb_dbg("dma int for usb tx occur\n"); #if defined(SUNXI_USB_30) sunxi_usb_pburn_status_enable = 1; #endif }
/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static void __usb_recv_by_dma_isr(void *p_arg) { u32 old_ep_idx; old_ep_idx = USBC_GetActiveEp(sunxi_udc_source.usbc_hd); USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX); //选择RXEP //选择使用IO方式搬运数据 sunxi_usb_dbg("select io mode to transfer data\n"); USBC_Dev_ClearEpDma(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX); if(usb_dma_trans_unaliged_bytes) { uint fifo, this_len; this_len = USBC_ReadLenFromFifo(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX); fifo = USBC_SelectFIFO(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX); USBC_ReadPacket(sunxi_udc_source.usbc_hd, fifo, this_len, usb_dma_trans_unaligned_buf); __usb_readcomplete(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX, 1); //返回状态 usb_dma_trans_unaliged_bytes = 0; } //如果当前dma传输的不是完整包,则需要手动清除中断 if(sunxi_ubuf.request_size % sunxi_udc_source.bulk_ep_max) { USBC_Dev_ReadDataStatus(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX, 1); //printf("clear rx pending manually\n"); } USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, old_ep_idx); sunxi_udev_active->dma_rx_isr(p_arg); }
/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static int __eps_complete_out(void) { pSUSBTRB cbw_trb; cbw_trb = (pSUSBTRB)&usb_mem_cfg.pSDEVTRBx[0]; if(sunxi_udc_source.eps_bulk_step == SUNXI_USB_BULK_CBW_BEGIN) { sunxi_udc_source.eps_bulk_step = SUNXI_USB_BULK_CBW_OK; sunxi_ubuf.rx_ready_for_data = 1; sunxi_ubuf.rx_req_length = 0x200 - (cbw_trb->size & 0x00ffffff); sunxi_usb_dbg("sunxi_ubuf.rx_req_length=0x%x\n", sunxi_ubuf.rx_req_length); if(fastboot_data_flag) { sunxi_ubuf.rx_req_buffer += sunxi_ubuf.rx_req_length; sunxi_udc_source.eps_bulk_step = SUNXI_USB_BULK_PREPARE; } } else if(sunxi_udc_source.eps_bulk_step == SUNXI_USB_BULK_CBW_OK) { sunxi_udev_active->dma_rx_isr(NULL); } return 0; }
/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int sunxi_udc_set_address(uchar address) { USBC_Dev_SetAddress(sunxi_udc_source.usbc_hd, address); if(USBC_Dev_QueryTransferMode(sunxi_udc_source.usbc_hd) == USBC_TS_MODE_HS) { sunxi_udc_source.speed = USB_SPEED_HIGH; sunxi_udc_source.fifo_size = HIGH_SPEED_EP_MAX_PACKET_SIZE; sunxi_usb_dbg("usb speed: HIGH\n"); } else { sunxi_udc_source.speed = USB_SPEED_FULL; sunxi_udc_source.fifo_size = FULL_SPEED_EP_MAX_PACKET_SIZE; sunxi_usb_dbg("usb speed: FULL\n"); } return SUNXI_USB_REQ_SUCCESSED; }
/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static int sunxi_pburn_exit(void) { sunxi_usb_dbg("sunxi_pburn_exit\n"); if(trans_data.base_recv_buffer) { free(trans_data.base_recv_buffer); } if(trans_data.base_send_buffer) { free(trans_data.base_send_buffer); } return 0; }
/* ******************************************************************************* * do_usb_req_set_interface * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static int __usb_set_interface(struct usb_device_request *req) { sunxi_usb_dbg("set interface\n"); /* Only support interface 0, alternate 0 */ if((0 == req->wIndex) && (0 == req->wValue)) { sunxi_udc_ep_reset(); } else { printf("err: invalid wIndex and wValue, (0, %d), (0, %d)\n", req->wIndex, req->wValue); return SUNXI_USB_REQ_OP_ERR; } return SUNXI_USB_REQ_SUCCESSED; }
/* ******************************************************************************* * do_usb_req_set_configuration * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static int __usb_set_configuration(struct usb_device_request *req) { sunxi_usb_dbg("set configuration\n"); /* Only support 1 configuration so nak anything else */ if (1 == req->wValue) { sunxi_udc_ep_reset(); } else { printf("err: invalid wValue, (0, %d)\n", req->wValue); return SUNXI_USB_REQ_OP_ERR; } sunxi_udc_set_configuration(req->wValue); return SUNXI_USB_REQ_SUCCESSED; }
/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static void __usb_recv_by_dma_isr(void *p_arg) { u32 old_ep_idx; old_ep_idx = USBC_GetActiveEp(sunxi_udc_source.usbc_hd); USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX); //选择RXEP //如果当前dma传输的不是完整包,则需要手动清除中断 //printf("sunxi_ubuf.request_size=0x%x\n",sunxi_ubuf.request_size); if(sunxi_ubuf.request_size % sunxi_udc_source.bulk_ep_max) { USBC_Dev_ReadDataStatus(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX, 1); //printf("clear rx pending manually\n"); } //选择使用IO方式搬运数据 sunxi_usb_dbg("select io mode to transfer data\n"); USBC_Dev_ClearEpDma(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX); USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, old_ep_idx); sunxi_udev_active->dma_rx_isr(p_arg); }
/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int sunxi_udc_start_recv_by_dma(uint mem_buf, uint length) { uint old_ep_idx; uint fifo; old_ep_idx = USBC_GetActiveEp(sunxi_udc_source.usbc_hd); USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX); //选择当前EP //usb控制器选择dma传输方式 USBC_Dev_ConfigEpDma(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX); //选择buffer fifo = USBC_SelectFIFO(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX); //刷掉cache flush_cache(mem_buf, length); //使能dma传输 sunxi_ubuf.request_size = length; sunxi_usb_dbg("dma start\n"); sunxi_dma_start(sunxi_udc_source.dma_recv_channal, fifo, mem_buf, length); //恢复EP USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, old_ep_idx); //恢复原有EP return 0; }
/* ******************************************************************************* * __usb_get_status * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static int __usb_get_status(struct usb_device_request *req, uchar *buffer) { unsigned char bLength = 0; sunxi_usb_dbg("get status\n"); if(0 == req->wLength) { /* sent zero packet */ sunxi_udc_send_setup(0, NULL); return SUNXI_USB_REQ_OP_ERR; } bLength = MIN(req->wValue, 2); buffer[0] = 1; buffer[1] = 0; sunxi_udc_send_setup(bLength, buffer); return SUNXI_USB_REQ_SUCCESSED; }
/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int sunxi_udc_start_recv_by_dma(uint mem_buf, uint length) { uint old_ep_idx; usb_dma_trans_unaliged_bytes = length & (sizeof(int) - 1); length &= ~(sizeof(int) - 1); usb_dma_trans_unaligned_buf = (uchar *)mem_buf + length; old_ep_idx = USBC_GetActiveEp(sunxi_udc_source.usbc_hd); USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX); //选择当前EP //usb控制器选择dma传输方式 USBC_Dev_ConfigEpDma(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX); //刷掉cache flush_cache(mem_buf, length); //使能dma传输 sunxi_ubuf.request_size = length; sunxi_usb_dbg("dma start 0x%x, length 0x%x\n", mem_buf, length); usb_dma_start(sunxi_udc_source.dma_recv_channal, mem_buf, length); //恢复EP USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, old_ep_idx); //恢复原有EP return 0; }
/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ void sunxi_usb_irq(void *data) { u8 misc_irq = 0; u16 tx_irq = 0; u16 rx_irq = 0; u32 old_ep_idx = 0; /* Save index */ old_ep_idx = USBC_GetActiveEp(sunxi_udc_source.usbc_hd); /* Read status registers */ misc_irq = USBC_INT_MiscPending(sunxi_udc_source.usbc_hd); tx_irq = USBC_INT_EpPending(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_TX); rx_irq = USBC_INT_EpPending(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX); /* RESET */ if(misc_irq & USBC_INTUSB_RESET) { sunxi_usb_dbg("IRQ: reset\n"); USBC_INT_ClearMiscPending(sunxi_udc_source.usbc_hd, USBC_INTUSB_RESET); __usb_clear_all_irq(); USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, 0); USBC_Dev_SetAddress_default(sunxi_udc_source.usbc_hd); sunxi_udc_source.address = 0; //default value sunxi_udc_source.speed = USB_SPEED_HIGH; //default value sunxi_dma_stop(sunxi_udc_source.dma_recv_channal); sunxi_dma_stop(sunxi_udc_source.dma_send_channal); sunxi_ubuf.rx_ready_for_data = 0; sunxi_udev_active->state_reset(); return ; } /* RESUME 暂时不处理,仅仅清理中断*/ if (misc_irq & USBC_INTUSB_RESUME) { sunxi_usb_dbg("IRQ: resume\n"); /* clear interrupt */ USBC_INT_ClearMiscPending(sunxi_udc_source.usbc_hd, USBC_INTUSB_RESUME); } /* SUSPEND */ if (misc_irq & USBC_INTUSB_SUSPEND) { sunxi_usb_dbg("IRQ: suspend\n"); /* clear interrupt */ USBC_INT_ClearMiscPending(sunxi_udc_source.usbc_hd, USBC_INTUSB_SUSPEND); } /* DISCONNECT */ if(misc_irq & USBC_INTUSB_DISCONNECT) { sunxi_usb_dbg("IRQ: disconnect\n"); USBC_INT_ClearMiscPending(sunxi_udc_source.usbc_hd, USBC_INTUSB_DISCONNECT); return ; } #if 0 /* SOF */ if(misc_irq & USBC_INTUSB_SOF) { sunxi_usb_dbg("IRQ: SOF\n"); USBC_INT_ClearMiscPending(sunxi_udc_source.usbc_hd, USBC_INTUSB_SOF); } #endif /* ep0 */ if (tx_irq & (1 << SUNXI_USB_CTRL_EP_INDEX) ) { sunxi_usb_dbg("IRQ: EP0\n"); USBC_INT_ClearEpPending(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_TX, SUNXI_USB_CTRL_EP_INDEX); //中断内完成ep0处理 ep0_recv_op(); } /* tx endpoint data transfers */ if (tx_irq & (1 << SUNXI_USB_BULK_IN_EP_INDEX)) { sunxi_usb_dbg("tx irq occur\n"); /* Clear the interrupt bit by setting it to 1 */ USBC_INT_ClearEpPending(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_TX, SUNXI_USB_BULK_IN_EP_INDEX); eptx_send_op(); } /* rx endpoint data transfers */ if (rx_irq & (1 << SUNXI_USB_BULK_OUT_EP_INDEX)) { sunxi_usb_dbg("rx irq occur\n"); /* Clear the interrupt bit by setting it to 1 */ USBC_INT_ClearEpPending(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX, SUNXI_USB_BULK_OUT_EP_INDEX); eprx_recv_op(); } USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, old_ep_idx); return ; }
/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static void sunxi_pburn_usb_rx_dma_isr(void *p_arg) { sunxi_usb_dbg("dma int for usb rx occur\n"); //通知主循环,可以写入数据 sunxi_usb_pburn_write_enable = 1; }
/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : usb初始化动作,完成后,即可开启中断后,使用中断处理程序 * * ************************************************************************************************************ */ int sunxi_usb_init(int delaytime) { sunxi_dma_setting_t usb_send_by_dma; sunxi_dma_setting_t usb_recv_by_dma; if(sunxi_udev_active->state_init()) { printf("sunxi usb err: fail to init usb device\n"); return -1; } //预先关闭usb中断 irq_disable(AW_IRQ_USB_OTG); //初始化 sunxi_udc用到的资源 memset(&sunxi_udc_source, 0, sizeof(sunxi_udc_t)); //获取控制器地址资源 sunxi_udc_source.usbc_hd = USBC_open_otg(0); if(sunxi_udc_source.usbc_hd == 0) { printf("sunxi usb err : USBC_open_otg failed\n"); return -1; } //断开usb USBC_Dev_ConectSwitch(sunxi_udc_source.usbc_hd, USBC_DEVICE_SWITCH_OFF); //预先关闭usb时钟 usb_close_clock(); //延时 delaytime ms printf("delay time %d\n", delaytime); __msdelay(delaytime); //申请DMA资源 sunxi_udc_source.dma_send_channal = sunxi_dma_request(0); if(!sunxi_udc_source.dma_send_channal) { printf("sunxi usb err : unable to request dma for usb send data\n"); goto __sunxi_usb_init_fail; } sunxi_udc_source.dma_recv_channal = sunxi_dma_request(0); if(!sunxi_udc_source.dma_recv_channal) { printf("sunxi usb err : unable to request dma for usb receive data\n"); goto __sunxi_usb_init_fail; } //配置dma资源 usb_recv_by_dma.loop_mode = 0; usb_recv_by_dma.wait_cyc = 8; usb_recv_by_dma.data_block_size = 1 * 32/8; //config recv(from usb fifo to dram) usb_recv_by_dma.cfg.src_drq_type = DMAC_CFG_SRC_TYPE_OTG_EP2; //OTG EP2 usb_recv_by_dma.cfg.src_addr_mode = DMAC_CFG_SRC_ADDR_TYPE_IO_MODE; usb_recv_by_dma.cfg.src_burst_length = DMAC_CFG_SRC_1_BURST; usb_recv_by_dma.cfg.src_data_width = DMAC_CFG_SRC_DATA_WIDTH_32BIT; usb_recv_by_dma.cfg.reserved0 = 0; usb_recv_by_dma.cfg.dst_drq_type = DMAC_CFG_DEST_TYPE_DRAM; //DRAM usb_recv_by_dma.cfg.dst_addr_mode = DMAC_CFG_DEST_ADDR_TYPE_LINEAR_MODE; usb_recv_by_dma.cfg.dst_burst_length = DMAC_CFG_DEST_1_BURST; usb_recv_by_dma.cfg.dst_data_width = DMAC_CFG_DEST_DATA_WIDTH_32BIT; usb_recv_by_dma.cfg.reserved1 = 0; //注册dma中断函数 sunxi_usb_dbg("install dma isr\n"); sunxi_dma_install_int(sunxi_udc_source.dma_recv_channal, __usb_recv_by_dma_isr, 0); //sunxi_dma_install_int(sunxi_udc_source.dma_recv_channal, __usb_recv_by_dma_isr, 0); //使能dma中断 sunxi_usb_dbg("enable dma isr\n"); sunxi_dma_enable_int(sunxi_udc_source.dma_recv_channal); //配置dma资源 usb_send_by_dma.loop_mode = 0; usb_send_by_dma.wait_cyc = 8; usb_send_by_dma.data_block_size = 1 * 32/8; //usb_send_by_dma. //config send(from dram to usb fifo) usb_send_by_dma.cfg.src_drq_type = DMAC_CFG_SRC_TYPE_DRAM; //OTG, EP2 usb_send_by_dma.cfg.src_addr_mode = DMAC_CFG_SRC_ADDR_TYPE_LINEAR_MODE; usb_send_by_dma.cfg.src_burst_length = DMAC_CFG_SRC_1_BURST; usb_send_by_dma.cfg.src_data_width = DMAC_CFG_SRC_DATA_WIDTH_32BIT; usb_send_by_dma.cfg.reserved0 = 0; usb_send_by_dma.cfg.dst_drq_type = DMAC_CFG_DEST_TYPE_OTG_EP1; //OTG EP1 usb_send_by_dma.cfg.dst_addr_mode = DMAC_CFG_DEST_ADDR_TYPE_IO_MODE; usb_send_by_dma.cfg.dst_burst_length = DMAC_CFG_DEST_1_BURST; usb_send_by_dma.cfg.dst_data_width = DMAC_CFG_DEST_DATA_WIDTH_32BIT; usb_send_by_dma.cfg.reserved1 = 0; sunxi_dma_setting(sunxi_udc_source.dma_recv_channal, &usb_recv_by_dma); sunxi_dma_setting(sunxi_udc_source.dma_send_channal, &usb_send_by_dma); //假定usb运行在高速模式下 sunxi_udc_source.address = 0; sunxi_udc_source.speed = USB_SPEED_HIGH; sunxi_udc_source.bulk_ep_max = HIGH_SPEED_EP_MAX_PACKET_SIZE; sunxi_udc_source.fifo_size = BULK_FIFOSIZE; sunxi_udc_source.bulk_in_addr = 100; sunxi_udc_source.bulk_out_addr = sunxi_udc_source.bulk_in_addr + sunxi_udc_source.fifo_size * 2; memset(&sunxi_ubuf, 0, sizeof(sunxi_ubuf_t)); sunxi_ubuf.rx_base_buffer = (uchar *)malloc(1024); if(!sunxi_ubuf.rx_base_buffer) { printf("sunxi usb err: fail to malloc memory for rx command buffer\n"); goto __sunxi_usb_init_fail; } sunxi_ubuf.rx_req_buffer = sunxi_ubuf.rx_base_buffer; usb_open_clock(); //设置为device模式 USBC_ForceId(sunxi_udc_source.usbc_hd, USBC_ID_TYPE_DEVICE); //设置VBUS为高 USBC_ForceVbusValid(sunxi_udc_source.usbc_hd, USBC_VBUS_TYPE_HIGH); USBC_Dev_ConectSwitch(sunxi_udc_source.usbc_hd, USBC_DEVICE_SWITCH_OFF); //soft connect USBC_EnableDpDmPullUp(sunxi_udc_source.usbc_hd); USBC_EnableIdPullUp(sunxi_udc_source.usbc_hd); //选择使用PIO模式搬移数据 USBC_SelectBus(sunxi_udc_source.usbc_hd, USBC_IO_TYPE_PIO, 0, 0); //映射SRAM buffer USBC_ConfigFIFO_Base(sunxi_udc_source.usbc_hd, 0, 0); // USBC_EnhanceSignal(sunxi_udc_source.usbc_hd); //默认采用高速模式传输 #ifdef CONFIG_USB_1_1_DEVICE USBC_Dev_ConfigTransferMode(sunxi_udc_source.usbc_hd, USBC_TS_TYPE_BULK, USBC_TS_MODE_FS); #else USBC_Dev_ConfigTransferMode(sunxi_udc_source.usbc_hd, USBC_TS_TYPE_BULK, USBC_TS_MODE_HS); #endif /* disable all interrupt */ USBC_INT_DisableUsbMiscAll(sunxi_udc_source.usbc_hd); USBC_INT_DisableEpAll(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX); USBC_INT_DisableEpAll(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_TX); /* 开启 reset、resume、suspend中断 */ USBC_INT_EnableUsbMiscUint(sunxi_udc_source.usbc_hd, USBC_INTUSB_SUSPEND | USBC_INTUSB_RESUME \ | USBC_INTUSB_RESET); /* enbale ep0_tx_irq */ USBC_INT_EnableEp(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_TX, SUNXI_USB_CTRL_EP_INDEX); __usb_bulk_ep_reset(); USBC_Dev_ConectSwitch(sunxi_udc_source.usbc_hd, USBC_DEVICE_SWITCH_ON); irq_install_handler(AW_IRQ_USB_OTG, sunxi_usb_irq, NULL); irq_enable(AW_IRQ_USB_OTG); return 0; __sunxi_usb_init_fail: if(sunxi_udc_source.usbc_hd) { USBC_close_otg(sunxi_udc_source.usbc_hd); } if(sunxi_udc_source.dma_send_channal) { sunxi_dma_release(sunxi_udc_source.dma_send_channal); } if(sunxi_udc_source.dma_recv_channal) { sunxi_dma_release(sunxi_udc_source.dma_recv_channal); } if(sunxi_ubuf.rx_base_buffer) { free(sunxi_ubuf.rx_base_buffer); } return -1; }
/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static int ep0_recv_op(void) { u32 old_ep_index = 0; int ret = 0; static uint ep0_stage = 0; if(!ep0_stage) { memset(&sunxi_udc_source.standard_reg, 0, sizeof(struct usb_device_request)); } old_ep_index = USBC_GetActiveEp(sunxi_udc_source.usbc_hd); USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, SUNXI_USB_CTRL_EP_INDEX); //clear stall status if(USBC_Dev_IsEpStall(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_EP0)) { printf("ERR: handle_ep0: ep0 stall\n"); USBC_Dev_EpClearStall(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_EP0); ret = -1; goto __ep0_recv_op_err; } //clear setup end if (USBC_Dev_Ctrl_IsSetupEnd(sunxi_udc_source.usbc_hd)) { USBC_Dev_Ctrl_ClearSetupEnd(sunxi_udc_source.usbc_hd); } //检查读ep0数据是否完成 if(USBC_Dev_IsReadDataReady(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_EP0)) { uint status; if(!ep0_stage) { status = __usb_read_ep0_data(&sunxi_udc_source.standard_reg, ep0_stage); } else { status = __usb_read_ep0_data(sunxi_usb_ep0_buffer, ep0_stage); } if(status!= 0) { printf("sunxi usb err: read_request failed\n"); ret = -1; goto __ep0_recv_op_err; } } else //此情况通常由于ep0发送空包引起,可以不处理 { sunxi_usb_dbg("sunxi usb msg: ep0 rx data is not ready\n"); goto __ep0_recv_op_err; } /* Check data */ if(USB_REQ_TYPE_STANDARD == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_TYPE_MASK)) { ret = SUNXI_USB_REQ_UNMATCHED_COMMAND; /* standard */ switch(sunxi_udc_source.standard_reg.bRequest) { case USB_REQ_GET_STATUS: // 0x00 { /* device-to-host */ if(USB_DIR_IN == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_DIRECTION_MASK)) { ret = sunxi_udev_active->standard_req_op(USB_REQ_GET_STATUS, &sunxi_udc_source.standard_reg, sunxi_usb_ep0_buffer); } break; } case USB_REQ_CLEAR_FEATURE: // 0x01 { /* host-to-device */ if(USB_DIR_OUT == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_DIRECTION_MASK)) { ret = sunxi_udev_active->standard_req_op(USB_REQ_CLEAR_FEATURE, &sunxi_udc_source.standard_reg, NULL); } break; } case USB_REQ_SET_FEATURE: // 0x03 { /* host-to-device */ if(USB_DIR_OUT == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_DIRECTION_MASK)) { ret = sunxi_udev_active->standard_req_op(USB_REQ_SET_FEATURE, &sunxi_udc_source.standard_reg, NULL); } break; } case USB_REQ_SET_ADDRESS: // 0x05 { /* host-to-device */ if(USB_DIR_OUT == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_DIRECTION_MASK)) { if(USB_RECIP_DEVICE == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_RECIPIENT_MASK)) { /* receiver is device */ ret = sunxi_udev_active->standard_req_op(USB_REQ_SET_ADDRESS, &sunxi_udc_source.standard_reg, NULL); } } break; } case USB_REQ_GET_DESCRIPTOR: // 0x06 { /* device-to-host */ if(USB_DIR_IN == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_DIRECTION_MASK)) { if(USB_RECIP_DEVICE == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_RECIPIENT_MASK)) { ret = sunxi_udev_active->standard_req_op(USB_REQ_GET_DESCRIPTOR, &sunxi_udc_source.standard_reg, sunxi_usb_ep0_buffer); } } break; } case USB_REQ_SET_DESCRIPTOR: // 0x07 { /* host-to-device */ if(USB_DIR_OUT == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_DIRECTION_MASK)) { if(USB_RECIP_DEVICE == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_RECIPIENT_MASK)) { //there is some problem ret = sunxi_udev_active->standard_req_op(USB_REQ_SET_DESCRIPTOR, &sunxi_udc_source.standard_reg, sunxi_usb_ep0_buffer); } } break; } case USB_REQ_GET_CONFIGURATION: // 0x08 { /* device-to-host */ if(USB_DIR_IN == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_DIRECTION_MASK)) { if(USB_RECIP_DEVICE == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_RECIPIENT_MASK)) { ret = sunxi_udev_active->standard_req_op(USB_REQ_GET_CONFIGURATION, &sunxi_udc_source.standard_reg, sunxi_usb_ep0_buffer); } } break; } case USB_REQ_SET_CONFIGURATION: // 0x09 { /* host-to-device */ if(USB_DIR_OUT == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_DIRECTION_MASK)) { if(USB_RECIP_DEVICE == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_RECIPIENT_MASK)) { ret = sunxi_udev_active->standard_req_op(USB_REQ_SET_CONFIGURATION, &sunxi_udc_source.standard_reg, NULL); } } break; } case USB_REQ_GET_INTERFACE: // 0x0a { /* device-to-host */ if(USB_DIR_IN == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_DIRECTION_MASK)) { if(USB_RECIP_DEVICE == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_RECIPIENT_MASK)) { ret = sunxi_udev_active->standard_req_op(USB_REQ_GET_INTERFACE, &sunxi_udc_source.standard_reg, sunxi_usb_ep0_buffer); } } break; } case USB_REQ_SET_INTERFACE: // 0x0b { /* host-to-device */ if(USB_DIR_OUT == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_DIRECTION_MASK)) { if(USB_RECIP_INTERFACE == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_RECIPIENT_MASK)) { ret = sunxi_udev_active->standard_req_op(USB_REQ_SET_INTERFACE, &sunxi_udc_source.standard_reg, NULL); } } break; } case USB_REQ_SYNCH_FRAME: // 0x0b { /* device-to-host */ if(USB_DIR_IN == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_DIRECTION_MASK)) { if(USB_RECIP_INTERFACE == (sunxi_udc_source.standard_reg.bmRequestType & USB_REQ_RECIPIENT_MASK)) { //there is some problem if(!ep0_stage) { ep0_stage = 1; } else { ret = sunxi_udev_active->standard_req_op(USB_REQ_SYNCH_FRAME, &sunxi_udc_source.standard_reg, NULL); ep0_stage = 0; } } } break; } default: { printf("sunxi usb err: unknown usb out request to device\n"); USBC_Dev_EpSendStall(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_EP0); ret = SUNXI_USB_REQ_DEVICE_NOT_SUPPORTED; ep0_stage = 0; break; } } } else { /* Non-Standard Req */ printf("non standard req\n"); ret = sunxi_udev_active->nonstandard_req_op(USB_REQ_GET_STATUS, &sunxi_udc_source.standard_reg, sunxi_usb_ep0_buffer, ep0_stage); if(ret == SUNXI_USB_REQ_DATA_HUNGRY) { ep0_stage = 1; } else if(ret == SUNXI_USB_REQ_SUCCESSED) { ep0_stage = 0; } else if(ret < 0) { ep0_stage = 0; printf("err: unkown bmRequestType(%d)\n", sunxi_udc_source.standard_reg.bmRequestType); USBC_Dev_EpSendStall(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_EP0); } } __ep0_recv_op_err: USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, old_ep_index); return ret; }
/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static int sunxi_pburn_state_loop(void *buffer) { static struct umass_bbb_cbw_t *cbw; static struct umass_bbb_csw_t csw; static uint pburn_flash_start = 0; //static uint pburn_flash_sectors = 0; int ret; sunxi_ubuf_t *sunxi_ubuf = (sunxi_ubuf_t *)buffer; switch(sunxi_usb_pburn_status) { case SUNXI_USB_PBURN_IDLE: if(sunxi_ubuf->rx_ready_for_data == 1) { sunxi_usb_pburn_status = SUNXI_USB_PBURN_SETUP; } break; case SUNXI_USB_PBURN_SETUP: sunxi_usb_dbg("SUNXI_USB_PBURN_SETUP\n"); if(sunxi_ubuf->rx_req_length != sizeof(struct umass_bbb_cbw_t)) { printf("sunxi usb error: received bytes 0x%x is not equal cbw struct size 0x%zx\n", sunxi_ubuf->rx_req_length, sizeof(struct umass_bbb_cbw_t)); sunxi_ubuf->rx_ready_for_data = 0; sunxi_usb_pburn_status = SUNXI_USB_PBURN_IDLE; break; } cbw = (struct umass_bbb_cbw_t *)sunxi_ubuf->rx_req_buffer; if(CBWSIGNATURE != cbw->dCBWSignature) { printf("sunxi usb error: the cbw signature 0x%x is bad, need 0x%x\n", cbw->dCBWSignature, CBWSIGNATURE); sunxi_ubuf->rx_ready_for_data = 0; sunxi_usb_pburn_status = SUNXI_USB_PBURN_IDLE; break; } csw.dCSWSignature = CSWSIGNATURE; csw.dCSWTag = cbw->dCBWTag; #if defined(SUNXI_USB_30) sunxi_usb_pburn_status_enable = 1; #endif sunxi_usb_dbg("usb cbw command = 0x%x\n", cbw->CBWCDB[0]); switch(cbw->CBWCDB[0]) { #ifdef CONFIG_SUNXI_SECURE_STORAGE case 0xf0: //自定义命令,用于烧录用户数据 sunxi_usb_dbg("usb burn secure storage data\n"); printf("usb command = %d\n", cbw->CBWCDB[1]); switch(cbw->CBWCDB[1]) { case 0: //握手 { __usb_handshake_sec_t *handshake = (__usb_handshake_sec_t *)trans_data.base_send_buffer; memset(handshake, 0, sizeof(__usb_handshake_sec_t)); strcpy(handshake->magic, "usb_burn_handshake"); sunxi_usb_pburn_status = SUNXI_USB_PBURN_SEND_DATA; trans_data.act_send_buffer = trans_data.base_send_buffer; trans_data.send_size = min(cbw->dCBWDataTransferLength, sizeof(__usb_handshake_sec_t)); sunxi_usb_burn_from_boot_setup = 1; private_data_ext_buff = (u8 *)malloc(4 * 1024 * 1024); if(private_data_ext_buff == NULL) { printf("there is no memorfy to store all user key data\n"); csw.bCSWStatus = -1; } else { csw.bCSWStatus = 0; sunxi_usb_burn_from_boot_handshake = 1; } private_data_ext_buff_step = private_data_ext_buff; } break; case 1: //小机端接收数据 { trans_data.recv_size = cbw->dCBWDataTransferLength; sunxi_usb_pburn_write_enable = 0; sunxi_udc_start_recv_by_dma(private_data_ext_buff_step, trans_data.recv_size); //start dma to receive data printf("recv_size=%d\n", trans_data.recv_size); sunxi_dump(private_data_ext_buff, trans_data.recv_size); sunxi_usb_pburn_status = SUNXI_USB_PBURN_RECEIVE_NULL; } break; case 2: //工具端声明数据传输已经完毕,要求获取烧录状态 { __usb_handshake_ext_t *handshake = (__usb_handshake_ext_t *)trans_data.base_send_buffer; memset(handshake, 0, sizeof(__usb_handshake_ext_t)); //strcpy(handshake->magic, "usb_burn_receive_data_all"); sunxi_usb_pburn_status = SUNXI_USB_PBURN_SEND_DATA; printf("recv_size=%d\n", trans_data.recv_size); sunxi_dump(private_data_ext_buff, trans_data.recv_size); int ret = __sunxi_burn_key(private_data_ext_buff, trans_data.recv_size); trans_data.act_send_buffer = trans_data.base_send_buffer; trans_data.send_size = min(cbw->dCBWDataTransferLength, sizeof(__usb_handshake_ext_t)); //开始根据数据类型进行烧录动作 if(!ret) //数据烧写成功 { strcpy(handshake->magic, "usb_burn_success"); csw.bCSWStatus = 0; } else //数据烧写失败 { strcpy(handshake->magic, "usb_burn_error"); csw.bCSWStatus = -1; } if(private_data_ext_buff) { free(private_data_ext_buff); } } break; // case 3: //小机端读取每个key // { // uint start, sectors; // uint offset; // // start = *(int *)(cbw->CBWCDB + 4); //读数据的偏移量 // sectors = *(int *)(cbw->CBWCDB + 8); //扇区数; // // trans_data.send_size = min(cbw->dCBWDataTransferLength, sectors * 512); // trans_data.act_send_buffer = (uint)trans_data.base_send_buffer; // // offset = burn_private_start; // ret = sunxi_flash_read(start + offset, sectors, trans_data.base_send_buffer); // if(!ret) // { // printf("sunxi flash read err: start,0x%x sectors 0x%x\n", start, sectors); // // csw.bCSWStatus = 1; // } // else // { // csw.bCSWStatus = 0; // } // // sunxi_usb_pburn_status = SUNXI_USB_PBURN_SEND_DATA; // } // break; case 4: //关闭usb { __usb_handshake_ext_t *handshake = (__usb_handshake_ext_t *)trans_data.base_send_buffer; memset(handshake, 0, sizeof(__usb_handshake_ext_t)); strcpy(handshake->magic, "usb_burn_finish"); trans_data.act_send_buffer = trans_data.base_send_buffer; trans_data.send_size = min(cbw->dCBWDataTransferLength, sizeof(__usb_handshake_ext_t)); sunxi_udc_send_data((void *)trans_data.act_send_buffer, trans_data.send_size); csw.bCSWStatus = 0; sunxi_usb_pburn_status = SUNXI_USB_PBURN_EXIT; } break; case 5: { __usb_handshake_ext_t *handshake = (__usb_handshake_ext_t *)trans_data.base_send_buffer; memset(handshake, 0, sizeof(__usb_handshake_ext_t)); strcpy(handshake->magic, "usb_burn_saved"); trans_data.act_send_buffer = trans_data.base_send_buffer; trans_data.send_size = min(cbw->dCBWDataTransferLength, sizeof(__usb_handshake_ext_t)); csw.bCSWStatus = 0; sunxi_usb_pburn_status = SUNXI_USB_PBURN_SEND_DATA; if(sunxi_secure_storage_write("key_burned_flag", "key_burned", strlen("key_burned"))) { printf("save burned flag err\n"); csw.bCSWStatus = -1; } sunxi_secure_storage_exit(); } break; default: break; } break; #endif case 0xf3: //自定义命令,用于烧录用户数据 sunxi_usb_dbg("usb burn private\n"); printf("usb command = %d\n", cbw->CBWCDB[1]); switch(cbw->CBWCDB[1]) { case 0: //握手 { __usb_handshake_t *handshake = (__usb_handshake_t *)trans_data.base_send_buffer; burn_private_start = sunxi_partition_get_offset_byname("private"); burn_private_len = sunxi_partition_get_size_byname("private"); if(!burn_private_start) { printf("private partition is not exist\n"); csw.bCSWStatus = -1; } else { csw.bCSWStatus = 0; } memset(handshake, 0, sizeof(__usb_handshake_t)); strcpy(handshake->magic, "usb_burn_handshake"); handshake->sizelo = burn_private_len; handshake->sizehi = 0; sunxi_usb_pburn_status = SUNXI_USB_PBURN_SEND_DATA; sunxi_usb_burn_from_boot_setup = 1; sunxi_usb_burn_from_boot_handshake = 1; trans_data.act_send_buffer = trans_data.base_send_buffer; trans_data.send_size = min(cbw->dCBWDataTransferLength, sizeof(__usb_handshake_t)); } break; case 1: //小机端接收数据 { //pburn_flash_sectors = *(int *)(cbw->CBWCDB + 8); //pburn_flash_start = *(int *)(cbw->CBWCDB + 4); memcpy(&pburn_flash_start,(cbw->CBWCDB + 4),4); trans_data.recv_size = cbw->dCBWDataTransferLength; trans_data.act_recv_buffer = trans_data.base_recv_buffer; pburn_flash_start += burn_private_start; sunxi_usb_pburn_write_enable = 0; sunxi_udc_start_recv_by_dma(trans_data.act_recv_buffer, trans_data.recv_size); //start dma to receive data sunxi_usb_pburn_status = SUNXI_USB_PBURN_RECEIVE_DATA; } break; case 3: //小机端发送数据 { uint start, sectors; //start = *(int *)(cbw->CBWCDB + 4); //读数据的偏移量 //sectors = *(int *)(cbw->CBWCDB + 8); //扇区数; memcpy(&start,(cbw->CBWCDB + 4),4); memcpy(§ors,(cbw->CBWCDB + 8),4); printf("start=%d, sectors=%d\n", start, sectors); trans_data.send_size = min(cbw->dCBWDataTransferLength, sectors * 512); trans_data.act_send_buffer = trans_data.base_send_buffer; printf("send size=%d\n", trans_data.send_size); ret = sunxi_flash_read(start + burn_private_start, sectors, trans_data.base_send_buffer); if(!ret) { printf("sunxi flash read err: start,0x%x sectors 0x%x\n", start, sectors); csw.bCSWStatus = 1; } else { csw.bCSWStatus = 0; } sunxi_usb_pburn_status = SUNXI_USB_PBURN_SEND_DATA; } break; case 4: //关闭usb { __usb_handshake_ext_t *handshake = (__usb_handshake_ext_t *)trans_data.base_send_buffer; memset(handshake, 0, sizeof(__usb_handshake_ext_t)); strcpy(handshake->magic, "usb_burn_finish"); trans_data.act_send_buffer = trans_data.base_send_buffer; trans_data.send_size = min(cbw->dCBWDataTransferLength, sizeof(__usb_handshake_ext_t)); sunxi_udc_send_data((void *)trans_data.act_send_buffer, trans_data.send_size); csw.bCSWStatus = 0; sunxi_flash_flush(); sunxi_usb_pburn_status = SUNXI_USB_PBURN_EXIT; } break; case 5: { __usb_handshake_ext_t *handshake = (__usb_handshake_ext_t *)trans_data.base_send_buffer; char buffer[512]; memset(handshake, 0, sizeof(__usb_handshake_ext_t)); strcpy(handshake->magic, "usb_burn_saved"); trans_data.act_send_buffer = trans_data.base_send_buffer; trans_data.send_size = min(cbw->dCBWDataTransferLength, sizeof(__usb_handshake_ext_t)); csw.bCSWStatus = 0; sunxi_usb_pburn_status = SUNXI_USB_PBURN_SEND_DATA; memset(buffer, 0, 512); strcpy(buffer, "key_burned"); if(!sunxi_flash_write(burn_private_start + burn_private_len - (8192+512)/512, 1, buffer)) { printf("save burned flag err\n"); csw.bCSWStatus = -1; } sunxi_flash_flush(); #ifdef CONFIG_SUNXI_SECURE_STORAGE if(sunxi_secure_storage_init()) { printf("init secure storage failed\n"); csw.bCSWStatus = -1; } else { if(sunxi_secure_storage_write("key_burned_flag", "key_burned", strlen("key_burned"))) { printf("save burned flag err\n"); csw.bCSWStatus = -1; } } sunxi_secure_storage_exit(); #endif } break; default: break; } break; default: sunxi_usb_dbg("not supported command 0x%x now\n", cbw->CBWCDB[0]); sunxi_usb_dbg("asked size 0x%x\n", cbw->dCBWDataTransferLength); csw.bCSWStatus = 1; sunxi_usb_pburn_status = SUNXI_USB_PBURN_STATUS; break; } break; case SUNXI_USB_PBURN_SEND_DATA: sunxi_usb_dbg("SUNXI_USB_SEND_DATA\n"); sunxi_usb_pburn_status = SUNXI_USB_PBURN_STATUS; printf("SUNXI_USB_SEND_DATA=%d\n", trans_data.send_size); sunxi_udc_send_data((void *)trans_data.act_send_buffer, trans_data.send_size); #if defined(SUNXI_USB_30) sunxi_usb_pburn_status_enable = 0; #endif break; case SUNXI_USB_PBURN_RECEIVE_DATA: sunxi_usb_dbg("SUNXI_USB_RECEIVE_DATA\n"); if(sunxi_usb_pburn_write_enable == 1) { sunxi_usb_dbg("write flash, start 0x%x, sectors 0x%x\n", pburn_flash_start, trans_data.recv_size/512); ret = sunxi_flash_write(pburn_flash_start, (trans_data.recv_size+511)/512, (void *)trans_data.act_recv_buffer); if(!ret) { printf("sunxi flash write err: start,0x%x sectors 0x%x\n", pburn_flash_start, (trans_data.recv_size+511)/512); csw.bCSWStatus = 1; } else { csw.bCSWStatus = 0; } sunxi_usb_pburn_write_enable = 0; sunxi_usb_pburn_status = SUNXI_USB_PBURN_STATUS; } break; case SUNXI_USB_PBURN_STATUS: sunxi_usb_dbg("SUNXI_USB_PBURN_STATUS\n"); #if defined(SUNXI_USB_30) if(sunxi_usb_pburn_status_enable) #endif { sunxi_usb_pburn_status = SUNXI_USB_PBURN_IDLE; sunxi_ubuf->rx_ready_for_data = 0; __sunxi_pburn_send_status(&csw, sizeof(struct umass_bbb_csw_t)); } break; case SUNXI_USB_PBURN_EXIT: printf("SUNXI_USB_PBURN_EXIT\n"); sunxi_usb_pburn_status = SUNXI_USB_PBURN_IDLE; sunxi_ubuf->rx_ready_for_data = 0; __sunxi_pburn_send_status(&csw, sizeof(struct umass_bbb_csw_t)); printf("Device will shutdown in 3 Secends...\n"); __msdelay(3000); return SUNXI_UPDATE_NEXT_ACTION_SHUTDOWN; case SUNXI_USB_PBURN_RECEIVE_NULL: sunxi_usb_dbg("SUNXI_USB_PBURN_RECEIVE_NULL\n"); if(sunxi_usb_pburn_write_enable == 1) { csw.bCSWStatus = 0; sunxi_usb_pburn_write_enable = 0; sunxi_usb_pburn_status = SUNXI_USB_PBURN_STATUS; } break; default: break; } return 0; }
/* ******************************************************************************* * do_usb_req_get_descriptor * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static int __usb_get_descriptor(struct usb_device_request *req, uchar *buffer) { int ret = SUNXI_USB_REQ_SUCCESSED; //获取描述符 switch(req->wValue >> 8) { case USB_DT_DEVICE: //设备描述符 { struct usb_device_descriptor *dev_dscrptr; sunxi_usb_dbg("get device descriptor\n"); dev_dscrptr = (struct usb_device_descriptor *)buffer; memset((void *)dev_dscrptr, 0, sizeof(struct usb_device_descriptor)); dev_dscrptr->bLength = MIN(req->wLength, sizeof (struct usb_device_descriptor)); dev_dscrptr->bDescriptorType = USB_DT_DEVICE; #ifdef CONFIG_USB_1_1_DEVICE dev_dscrptr->bcdUSB = 0x110; #else dev_dscrptr->bcdUSB = 0x200; #endif dev_dscrptr->bDeviceClass = 0xff; //设备类:大容量存储 dev_dscrptr->bDeviceSubClass = 0xff; dev_dscrptr->bDeviceProtocol = 0xff; dev_dscrptr->bMaxPacketSize0 = 0x40; dev_dscrptr->idVendor = DEVICE_VENDOR_ID; dev_dscrptr->idProduct = DEVICE_PRODUCT_ID; dev_dscrptr->bcdDevice = DEVICE_BCD; dev_dscrptr->iManufacturer = SUNXI_FASTBOOT_DEVICE_STRING_MANUFACTURER_INDEX; dev_dscrptr->iProduct = SUNXI_FASTBOOT_DEVICE_STRING_PRODUCT_INDEX; dev_dscrptr->iSerialNumber = SUNXI_FASTBOOT_DEVICE_STRING_SERIAL_NUMBER_INDEX; dev_dscrptr->bNumConfigurations = 1; sunxi_udc_send_setup(dev_dscrptr->bLength, buffer); } break; case USB_DT_CONFIG: //配置描述符 { struct usb_configuration_descriptor *config_dscrptr; struct usb_interface_descriptor *inter_dscrptr; struct usb_endpoint_descriptor *ep_in, *ep_out; unsigned char bytes_remaining = req->wLength; unsigned char bytes_total = 0; sunxi_usb_dbg("get config descriptor\n"); bytes_total = sizeof (struct usb_configuration_descriptor) + \ sizeof (struct usb_interface_descriptor) + \ sizeof (struct usb_endpoint_descriptor) + \ sizeof (struct usb_endpoint_descriptor); memset(buffer, 0, bytes_total); config_dscrptr = (struct usb_configuration_descriptor *)(buffer + 0); inter_dscrptr = (struct usb_interface_descriptor *)(buffer + \ sizeof(struct usb_configuration_descriptor)); ep_in = (struct usb_endpoint_descriptor *)(buffer + \ sizeof(struct usb_configuration_descriptor) + \ sizeof(struct usb_interface_descriptor)); ep_out = (struct usb_endpoint_descriptor *)(buffer + \ sizeof(struct usb_configuration_descriptor) + \ sizeof(struct usb_interface_descriptor) + \ sizeof(struct usb_endpoint_descriptor)); /* configuration */ config_dscrptr->bLength = MIN(bytes_remaining, sizeof (struct usb_configuration_descriptor)); config_dscrptr->bDescriptorType = USB_DT_CONFIG; config_dscrptr->wTotalLength = bytes_total; config_dscrptr->bNumInterfaces = 1; config_dscrptr->bConfigurationValue = 1; config_dscrptr->iConfiguration = SUNXI_FASTBOOT_DEVICE_STRING_CONFIG_INDEX; config_dscrptr->bmAttributes = 0xC0; config_dscrptr->bMaxPower = 0xFA; //最大电流500ms(0xfa * 2) bytes_remaining -= config_dscrptr->bLength; /* interface */ inter_dscrptr->bLength = MIN (bytes_remaining, sizeof(struct usb_interface_descriptor)); inter_dscrptr->bDescriptorType = USB_DT_INTERFACE; inter_dscrptr->bInterfaceNumber = 0x00; inter_dscrptr->bAlternateSetting = 0x00; inter_dscrptr->bNumEndpoints = 0x02; inter_dscrptr->bInterfaceClass = 0xff; //fastboot storage inter_dscrptr->bInterfaceSubClass = FASTBOOT_INTERFACE_SUB_CLASS; inter_dscrptr->bInterfaceProtocol = FASTBOOT_INTERFACE_PROTOCOL; inter_dscrptr->iInterface = SUNXI_FASTBOOT_DEVICE_STRING_INTERFACE_INDEX; bytes_remaining -= inter_dscrptr->bLength; /* ep_in */ ep_in->bLength = MIN (bytes_remaining, sizeof (struct usb_endpoint_descriptor)); ep_in->bDescriptorType = USB_DT_ENDPOINT; ep_in->bEndpointAddress = sunxi_udc_get_ep_in_type(); /* IN */ ep_in->bmAttributes = USB_ENDPOINT_XFER_BULK; ep_in->wMaxPacketSize = sunxi_udc_get_ep_max(); ep_in->bInterval = 0x00; bytes_remaining -= ep_in->bLength; /* ep_out */ ep_out->bLength = MIN (bytes_remaining, sizeof (struct usb_endpoint_descriptor)); ep_out->bDescriptorType = USB_DT_ENDPOINT; ep_out->bEndpointAddress = sunxi_udc_get_ep_out_type(); /* OUT */ ep_out->bmAttributes = USB_ENDPOINT_XFER_BULK; ep_out->wMaxPacketSize = sunxi_udc_get_ep_max(); ep_out->bInterval = 0x00; bytes_remaining -= ep_out->bLength; sunxi_udc_send_setup(MIN(req->wLength, bytes_total), buffer); } break; case USB_DT_STRING: { unsigned char bLength = 0; unsigned char string_index = req->wValue & 0xff; sunxi_usb_dbg("get string descriptor\n"); /* Language ID */ if(string_index == 0) { bLength = MIN(4, req->wLength); sunxi_udc_send_setup(bLength, (void *)sunxi_usb_fastboot_dev[0]); } else if(string_index < SUNXI_USB_FASTBOOT_DEV_MAX) { /* Size of string in chars */ unsigned char i = 0; unsigned char str_length = strlen ((const char *)sunxi_usb_fastboot_dev[string_index]); unsigned char bLength = 2 + (2 * str_length); buffer[0] = bLength; /* length */ buffer[1] = USB_DT_STRING; /* descriptor = string */ /* Copy device string to fifo, expand to simple unicode */ for(i = 0; i < str_length; i++) { buffer[2+ 2*i + 0] = sunxi_usb_fastboot_dev[string_index][i]; buffer[2+ 2*i + 1] = 0; } bLength = MIN(bLength, req->wLength); sunxi_udc_send_setup(bLength, buffer); } else { printf("sunxi usb err: string line %d is not supported\n", string_index); } } break; case USB_DT_DEVICE_QUALIFIER: { #ifdef CONFIG_USB_1_1_DEVICE /* This is an invalid request for usb 1.1, nak it */ USBC_Dev_EpSendStall(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_EP0); #else struct usb_qualifier_descriptor *qua_dscrpt; sunxi_usb_dbg("get qualifier descriptor\n"); qua_dscrpt = (struct usb_qualifier_descriptor *)buffer; memset(&buffer, 0, sizeof(struct usb_qualifier_descriptor)); qua_dscrpt->bLength = MIN(req->wLength, sizeof(sizeof(struct usb_qualifier_descriptor))); qua_dscrpt->bDescriptorType = USB_DT_DEVICE_QUALIFIER; qua_dscrpt->bcdUSB = 0x200; qua_dscrpt->bDeviceClass = 0xff; qua_dscrpt->bDeviceSubClass = 0xff; qua_dscrpt->bDeviceProtocol = 0xff; qua_dscrpt->bMaxPacketSize0 = 0x40; qua_dscrpt->bNumConfigurations = 1; qua_dscrpt->bRESERVED = 0; sunxi_udc_send_setup(qua_dscrpt->bLength, buffer); #endif } break; default: printf("err: unkown wValue(%d)\n", req->wValue); ret = SUNXI_USB_REQ_OP_ERR; } return ret; }
/* ******************************************************************************* * do_usb_req_get_descriptor * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static int __usb_get_descriptor(struct usb_device_request *req, uchar *buffer) { int ret = SUNXI_USB_REQ_SUCCESSED; //获取描述符 switch(req->wValue >> 8) { case USB_DT_DEVICE: //设备描述符 { struct usb_device_descriptor *dev_dscrptr; sunxi_usb_dbg("get device descriptor\n"); dev_dscrptr = (struct usb_device_descriptor *)buffer; memset((void *)dev_dscrptr, 0, sizeof(struct usb_device_descriptor)); dev_dscrptr->bLength = MIN(req->wLength, sizeof (struct usb_device_descriptor)); dev_dscrptr->bDescriptorType = USB_DT_DEVICE; #ifdef CONFIG_USB_1_1_DEVICE dev_dscrptr->bcdUSB = 0x110; #else dev_dscrptr->bcdUSB = 0x200; #endif dev_dscrptr->bDeviceClass = 0; dev_dscrptr->bDeviceSubClass = 0; dev_dscrptr->bDeviceProtocol = 0; dev_dscrptr->bMaxPacketSize0 = 0x40; dev_dscrptr->idVendor = DRIVER_VENDOR_ID; dev_dscrptr->idProduct = DRIVER_PRODUCT_ID; dev_dscrptr->bcdDevice = 0xffff; //ignored //dev_dscrptr->iManufacturer = SUNXI_USB_STRING_IMANUFACTURER; //dev_dscrptr->iProduct = SUNXI_USB_STRING_IPRODUCT; //dev_dscrptr->iSerialNumber = SUNXI_USB_STRING_ISERIALNUMBER; dev_dscrptr->iManufacturer = 0; dev_dscrptr->iProduct = 0; dev_dscrptr->iSerialNumber = 0; dev_dscrptr->bNumConfigurations = 1; sunxi_udc_send_setup(dev_dscrptr->bLength, buffer); } break; case USB_DT_CONFIG: //配置描述符 { struct usb_configuration_descriptor *config_dscrptr; struct usb_interface_descriptor *inter_dscrptr; struct usb_endpoint_descriptor *ep_in, *ep_out; unsigned char bytes_remaining = req->wLength; unsigned char bytes_total = 0; sunxi_usb_dbg("get config descriptor\n"); bytes_total = sizeof (struct usb_configuration_descriptor) + \ sizeof (struct usb_interface_descriptor) + \ sizeof (struct usb_endpoint_descriptor) + \ sizeof (struct usb_endpoint_descriptor); memset(buffer, 0, bytes_total); config_dscrptr = (struct usb_configuration_descriptor *)(buffer + 0); inter_dscrptr = (struct usb_interface_descriptor *)(buffer + \ sizeof(struct usb_configuration_descriptor)); ep_in = (struct usb_endpoint_descriptor *)(buffer + \ sizeof(struct usb_configuration_descriptor) + \ sizeof(struct usb_interface_descriptor)); ep_out = (struct usb_endpoint_descriptor *)(buffer + \ sizeof(struct usb_configuration_descriptor) + \ sizeof(struct usb_interface_descriptor) + \ sizeof(struct usb_endpoint_descriptor)); /* configuration */ config_dscrptr->bLength = MIN(bytes_remaining, sizeof (struct usb_configuration_descriptor)); config_dscrptr->bDescriptorType = USB_DT_CONFIG; config_dscrptr->wTotalLength = bytes_total; config_dscrptr->bNumInterfaces = 1; config_dscrptr->bConfigurationValue = 1; config_dscrptr->iConfiguration = 0; config_dscrptr->bmAttributes = 0x80; //not self powered config_dscrptr->bMaxPower = 0xFA; //最大电流500ms(0xfa * 2) bytes_remaining -= config_dscrptr->bLength; /* interface */ inter_dscrptr->bLength = MIN (bytes_remaining, sizeof(struct usb_interface_descriptor)); inter_dscrptr->bDescriptorType = USB_DT_INTERFACE; inter_dscrptr->bInterfaceNumber = 0x00; inter_dscrptr->bAlternateSetting = 0x00; inter_dscrptr->bNumEndpoints = 0x02; inter_dscrptr->bInterfaceClass = 0xff; inter_dscrptr->bInterfaceSubClass = 0xff; inter_dscrptr->bInterfaceProtocol = 0xff; inter_dscrptr->iInterface = 0; bytes_remaining -= inter_dscrptr->bLength; /* ep_in */ ep_in->bLength = MIN (bytes_remaining, sizeof (struct usb_endpoint_descriptor)); ep_in->bDescriptorType = USB_DT_ENDPOINT; ep_in->bEndpointAddress = sunxi_udc_get_ep_in_type(); /* IN */ ep_in->bmAttributes = USB_ENDPOINT_XFER_BULK; ep_in->wMaxPacketSize = sunxi_udc_get_ep_max(); ep_in->bInterval = 0x00; bytes_remaining -= ep_in->bLength; /* ep_out */ ep_out->bLength = MIN (bytes_remaining, sizeof (struct usb_endpoint_descriptor)); ep_out->bDescriptorType = USB_DT_ENDPOINT; ep_out->bEndpointAddress = sunxi_udc_get_ep_out_type(); /* OUT */ ep_out->bmAttributes = USB_ENDPOINT_XFER_BULK; ep_out->wMaxPacketSize = sunxi_udc_get_ep_max(); ep_out->bInterval = 0x00; bytes_remaining -= ep_out->bLength; sunxi_udc_send_setup(MIN(req->wLength, bytes_total), buffer); } break; case USB_DT_STRING: { unsigned char bLength = 0; unsigned char string_index = req->wValue & 0xff; sunxi_usb_dbg("get string descriptor\n"); /* Language ID */ if(string_index == 0) { bLength = MIN(4, req->wLength); buffer[0] = bLength; buffer[1] = USB_DT_STRING; buffer[2] = 9; buffer[3] = 4; sunxi_udc_send_setup(bLength, (void *)buffer); } else { printf("sunxi usb err: string line %d is not supported\n", string_index); } } break; case USB_DT_DEVICE_QUALIFIER: { #ifdef CONFIG_USB_1_1_DEVICE /* This is an invalid request for usb 1.1, nak it */ USBC_Dev_EpSendStall(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_EP0); #else struct usb_qualifier_descriptor *qua_dscrpt; sunxi_usb_dbg("get qualifier descriptor\n"); qua_dscrpt = (struct usb_qualifier_descriptor *)buffer; memset(&buffer, 0, sizeof(struct usb_qualifier_descriptor)); qua_dscrpt->bLength = MIN(req->wLength, sizeof(sizeof(struct usb_qualifier_descriptor))); qua_dscrpt->bDescriptorType = USB_DT_DEVICE_QUALIFIER; qua_dscrpt->bcdUSB = 0x200; qua_dscrpt->bDeviceClass = 0xff; qua_dscrpt->bDeviceSubClass = 0xff; qua_dscrpt->bDeviceProtocol = 0xff; qua_dscrpt->bMaxPacketSize0 = 0x40; qua_dscrpt->bNumConfigurations = 1; qua_dscrpt->breserved = 0; sunxi_udc_send_setup(qua_dscrpt->bLength, buffer); #endif } break; default: printf("err: unkown wValue(%d)\n", req->wValue); ret = SUNXI_USB_REQ_OP_ERR; } return ret; }
/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : usb初始化动作,完成后,即可开启中断后,使用中断处理程序 * * ************************************************************************************************************ */ int sunxi_usb_init(int delaytime) { if(sunxi_udev_active->state_init()) { printf("sunxi usb err: fail to init usb device\n"); return -1; } //预先关闭usb中断 irq_disable(AW_IRQ_USB_OTG); //初始化 sunxi_udc用到的资源 memset(&sunxi_udc_source, 0, sizeof(sunxi_udc_t)); //获取控制器地址资源 sunxi_udc_source.usbc_hd = USBC_open_otg(0); if(sunxi_udc_source.usbc_hd == 0) { printf("sunxi usb err : USBC_open_otg failed\n"); return -1; } usb_dma_init(sunxi_udc_source.usbc_hd); //断开usb USBC_Dev_ConectSwitch(sunxi_udc_source.usbc_hd, USBC_DEVICE_SWITCH_OFF); //预先关闭usb时钟 usb_close_clock(); //延时 delaytime ms printf("delay time %d\n", delaytime); __msdelay(delaytime); //申请DMA资源 sunxi_udc_source.dma_send_channal = usb_dma_request(); if(!sunxi_udc_source.dma_send_channal) { printf("sunxi usb err : unable to request dma for usb send data\n"); goto __sunxi_usb_init_fail; } sunxi_usb_dbg("dma send ch %d\n", sunxi_udc_source.dma_send_channal); sunxi_udc_source.dma_recv_channal = usb_dma_request(); if(!sunxi_udc_source.dma_recv_channal) { printf("sunxi usb err : unable to request dma for usb receive data\n"); goto __sunxi_usb_init_fail; } sunxi_usb_dbg("dma recv ch %d\n", sunxi_udc_source.dma_recv_channal); sunxi_udc_source.address = 0; sunxi_udc_source.speed = USB_SPEED_HIGH; sunxi_udc_source.bulk_ep_max = HIGH_SPEED_EP_MAX_PACKET_SIZE; sunxi_udc_source.fifo_size = BULK_FIFOSIZE; sunxi_udc_source.bulk_in_addr = 100; sunxi_udc_source.bulk_out_addr = sunxi_udc_source.bulk_in_addr + sunxi_udc_source.fifo_size * 2; //内存资源 memset(&sunxi_ubuf, 0, sizeof(sunxi_ubuf_t)); sunxi_ubuf.rx_base_buffer = (uchar *)malloc(1024); if(!sunxi_ubuf.rx_base_buffer) { printf("sunxi usb err: fail to malloc memory for rx command buffer\n"); goto __sunxi_usb_init_fail; } sunxi_ubuf.rx_req_buffer = sunxi_ubuf.rx_base_buffer; usb_open_clock(); //设置为device模式 USBC_ForceId(sunxi_udc_source.usbc_hd, USBC_ID_TYPE_DEVICE); //设置VBUS为高 USBC_ForceVbusValid(sunxi_udc_source.usbc_hd, USBC_VBUS_TYPE_HIGH); USBC_Dev_ConectSwitch(sunxi_udc_source.usbc_hd, USBC_DEVICE_SWITCH_OFF); //soft connect USBC_EnableDpDmPullUp(sunxi_udc_source.usbc_hd); USBC_EnableIdPullUp(sunxi_udc_source.usbc_hd); //选择使用PIO模式搬移数据 USBC_SelectBus(sunxi_udc_source.usbc_hd, USBC_IO_TYPE_PIO, 0, 0); //映射SRAM buffer USBC_ConfigFIFO_Base(sunxi_udc_source.usbc_hd, 0, 0); // USBC_EnhanceSignal(sunxi_udc_source.usbc_hd); //默认采用高速模式传输 #ifdef CONFIG_USB_1_1_DEVICE USBC_Dev_ConfigTransferMode(sunxi_udc_source.usbc_hd, USBC_TS_TYPE_BULK, USBC_TS_MODE_FS); #else USBC_Dev_ConfigTransferMode(sunxi_udc_source.usbc_hd, USBC_TS_TYPE_BULK, USBC_TS_MODE_HS); #endif //配置发送端dma资源 usb_dma_setting(sunxi_udc_source.dma_send_channal, USB_DMA_FROM_DRAM_TO_HOST, SUNXI_USB_BULK_IN_EP_INDEX); usb_dma_set_pktlen(sunxi_udc_source.dma_send_channal, HIGH_SPEED_EP_MAX_PACKET_SIZE); //配置接收端dma资源 usb_dma_setting(sunxi_udc_source.dma_recv_channal, USB_DMA_FROM_HOST_TO_DRAM, SUNXI_USB_BULK_OUT_EP_INDEX); usb_dma_set_pktlen(sunxi_udc_source.dma_recv_channal, HIGH_SPEED_EP_MAX_PACKET_SIZE); /* disable all interrupt */ USBC_INT_DisableUsbMiscAll(sunxi_udc_source.usbc_hd); USBC_INT_DisableEpAll(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX); USBC_INT_DisableEpAll(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_TX); /* 开启 reset、resume、suspend中断 */ USBC_INT_EnableUsbMiscUint(sunxi_udc_source.usbc_hd, USBC_INTUSB_SUSPEND | USBC_INTUSB_RESUME \ | USBC_INTUSB_RESET | USBC_INTUSB_SOF); /* enbale ep0_tx_irq */ USBC_INT_EnableEp(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_TX, SUNXI_USB_CTRL_EP_INDEX); __usb_bulk_ep_reset(); USBC_Dev_ConectSwitch(sunxi_udc_source.usbc_hd, USBC_DEVICE_SWITCH_ON); irq_install_handler(AW_IRQ_USB_OTG, sunxi_usb_irq, NULL); irq_enable(AW_IRQ_USB_OTG); return 0; __sunxi_usb_init_fail: if(sunxi_udc_source.dma_send_channal) { usb_dma_release(sunxi_udc_source.dma_send_channal); } if(sunxi_udc_source.dma_recv_channal) { usb_dma_release(sunxi_udc_source.dma_recv_channal); } if(sunxi_udc_source.usbc_hd) { USBC_close_otg(sunxi_udc_source.usbc_hd); } if(sunxi_ubuf.rx_base_buffer) { free(sunxi_ubuf.rx_base_buffer); } return -1; }