/*! \brief data in stage processing \param[in] pudev: pointer to USB device instance \param[in] ep_id: endpoint identifier(0..7) \param[out] none \retval USB device operation status */ usbd_status_enum usbd_in_transaction (usb_core_handle_struct *pudev, uint8_t endp_num) { usb_ep_struct *ep; if (0U == endp_num) { ep = &pudev->dev.in_ep[0]; if (USB_CTRL_DATA_IN == pudev->dev.ctl_status) { if (pudev->dev.remain_len > ep->endp_mps) { pudev->dev.remain_len -= ep->endp_mps; usbd_ep_tx (pudev, 0U, ep->xfer_buff, pudev->dev.remain_len); usbd_ep_rx (pudev, 0U, NULL, 0U); } else { /* last packet is MPS multiple, so send ZLP packet */ if ((pudev->dev.sum_len % ep->endp_mps == 0U) && (pudev->dev.sum_len >= ep->endp_mps) && (pudev->dev.sum_len < pudev->dev.ctl_len)) { usbd_ep_tx (pudev, 0U, NULL, 0U); pudev->dev.ctl_len = 0U; usbd_ep_rx (pudev, 0U, NULL, 0U); } else { if (USB_STATUS_CONFIGURED == pudev->dev.status) { pudev->dev.class_data_handler(pudev, USB_TX, 0U); } usbd_ctlstatus_rx(pudev); } } } } else if (USB_STATUS_CONFIGURED == pudev->dev.status) { pudev->dev.class_data_handler(pudev, USB_TX, endp_num); } else { /* no operation */ } return USBD_OK; }
/*! \brief handle the IAP_ERASE request \param[in] pudev: pointer to usb device instance \param[out] none \retval none */ static void iap_req_erase(void *pudev) { uint32_t i, addr = 0; /* get base address to erase */ base_address = report_buf[2]; base_address |= report_buf[3] << 8; base_address |= report_buf[4] << 16; base_address |= report_buf[5] << 24; page_count = report_buf[6]; /* get file length */ file_length = report_buf[7]; file_length |= report_buf[8] << 8; file_length |= report_buf[9] << 16; file_length |= report_buf[10] << 24; if (0 == (file_length % TRANSFER_SIZE)) { transfer_times = file_length / TRANSFER_SIZE; } else { transfer_times = file_length / TRANSFER_SIZE + 1; } /* check if the address is in protected area */ if (IS_PROTECTED_AREA(base_address)) { return; } addr = base_address; for (i = 0; i < page_count; i ++) { /* call the standard flash erase-page function */ fmc_page_erase(addr); addr += PAGE_SIZE; } device_status[0] = 0x02; device_status[1] = 0x01; usbd_ep_tx(pudev, IAP_IN_EP, device_status, IAP_IN_PACKET); }
/*! \brief send iap report \param[in] pudev: pointer to USB device instance \param[in] report: pointer to HID report \param[in] len: data length \param[out] none \retval USB device operation status */ uint8_t iap_report_send (usbd_core_handle_struct *pudev, uint8_t *report, uint16_t len) { usbd_ep_tx (pudev, IAP_IN_EP, report, len); return USBD_OK; }
/*! \brief handle the HID class-specific requests \param[in] pudev: pointer to USB device instance \param[in] req: device class-specific request \param[out] none \retval USB device operation status */ usbd_status_enum iap_req_handler (void *pudev, usb_device_req_struct *req) { uint16_t len = 0; uint8_t *pbuf = NULL; uint8_t USBD_CUSTOMHID_Report_LENGTH = 0; switch (req->bmRequestType & USB_REQ_MASK) { case USB_CLASS_REQ: switch (req->bRequest) { case GET_REPORT: /* no use for this driver */ break; case GET_IDLE: usbd_ep_tx (pudev, EP0_IN, (uint8_t *)&usbd_customhid_idlestate, 1); break; case GET_PROTOCOL: usbd_ep_tx (pudev, EP0_IN, (uint8_t *)&usbd_customhid_protocol, 1); break; case SET_REPORT: flag = 1; usbd_customhid_report_id = (uint8_t)(req->wValue); USBD_CUSTOMHID_Report_LENGTH = (uint8_t)(req->wLength); usbd_ep_rx (pudev, EP0_OUT, report_buf, USBD_CUSTOMHID_Report_LENGTH); break; case SET_IDLE: usbd_customhid_idlestate = (uint8_t)(req->wValue >> 8); break; case SET_PROTOCOL: usbd_customhid_protocol = (uint8_t)(req->wValue); break; default: usbd_enum_error (pudev, req); return USBD_FAIL; } break; case USB_STANDARD_REQ: /* standard device request */ switch(req->bRequest) { case USBREQ_GET_DESCRIPTOR: switch(req->wValue >> 8) { case HID_REPORT_DESCTYPE: len = MIN(IAP_REPORT_DESC_SIZE, req->wLength); pbuf = (uint8_t *)iap_report_descriptor; break; case HID_DESCTYPE: len = MIN(IAP_CONFIG_DESC_SIZE, req->wLength); pbuf = (uint8_t *)(&(configuration_descriptor.HID_VendorHID)); break; default: break; } usbd_ep_tx (pudev, EP0_IN, pbuf, len); break; case USBREQ_GET_INTERFACE: usbd_ep_tx (pudev, EP0_IN, (uint8_t *)&usbd_customhid_altset, 1); break; case USBREQ_SET_INTERFACE: usbd_customhid_altset = (uint8_t)(req->wValue); break; default: break; } break; } return USBD_OK; }