/*! \brief data out 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_out_transaction (usb_core_handle_struct *pudev, uint8_t endp_num) { usb_ep_struct *ep; if (0U == endp_num) { ep = &pudev->dev.out_ep[0]; if (USB_CTRL_DATA_OUT == pudev->dev.ctl_status) { if (pudev->dev.remain_len > ep->endp_mps) { pudev->dev.remain_len -= ep->endp_mps; usbd_ep_rx (pudev, 0U, ep->xfer_buff, (uint16_t)USB_MIN(pudev->dev.remain_len, ep->endp_mps)); } else { if (USB_STATUS_CONFIGURED == pudev->dev.status) { pudev->dev.class_data_handler(pudev, USB_RX, 0U); } usbd_ctlstatus_tx(pudev); } } } else if (USB_STATUS_CONFIGURED == pudev->dev.status) { pudev->dev.class_data_handler(pudev, USB_RX, endp_num); } else { /* no operation */ } return USBD_OK; }
/*! \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 initialize the HID device \param[in] pudev: pointer to USB device instance \param[in] config_index: configuration index \param[out] none \retval USB device operation status */ usbd_status_enum iap_init (void *pudev, uint8_t config_index) { /* initialize Tx endpoint */ usbd_ep_init(pudev, &(configuration_descriptor.HID_ReportINEndpoint)); /* initialize Rx endpoint */ usbd_ep_init(pudev, &(configuration_descriptor.HID_ReportOUTEndpoint)); /* unlock the internal flash */ fmc_unlock(); /* prepare receive Data */ usbd_ep_rx(pudev, IAP_OUT_EP, report_buf, IAP_OUT_PACKET); return USBD_OK; }
/*! \brief handle data stage \param[in] pudev: pointer to USB device instance \param[in] rx_tx: data transfer direction: \arg USBD_TX \arg USBD_RX \param[in] ep_id: endpoint identifier \param[out] none \retval USB device operation status */ usbd_status_enum iap_data_handler (void *pudev, usbd_dir_enum rx_tx, uint8_t ep_id) { if((USBD_TX == rx_tx) && ((IAP_IN_EP & 0x7F) == ep_id)) { return USBD_OK; } else if ((USBD_RX == rx_tx) && (IAP_OUT_EP == ep_id)) { switch (report_buf[0]) { case 0x01: switch(report_buf[1]) { case IAP_DNLOAD: iap_req_dnload(pudev); break; case IAP_ERASE: iap_req_erase(pudev); break; case IAP_OPTION_BYTE: iap_req_optionbyte(pudev); break; case IAP_LEAVE: iap_req_leave(pudev); break; case IAP_GETBIN_ADDRESS: iap_address_send(pudev); break; default: usbd_enum_error(pudev, NULL); return USBD_FAIL; } break; default: break; } usbd_ep_rx(pudev, IAP_OUT_EP, report_buf, IAP_OUT_PACKET); return USBD_OK; } return USBD_FAIL; }
/*! \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; }