/* ************************************************************************************************************ * * 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; }
/* ************************************************************************************************************ * * 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; }