/*! \brief handle USB device class request \param[in] pudev: pointer to USB device instance \param[in] req: pointer to USB device class request \param[out] none \retval USB device operation status */ static usbd_status_enum usbd_device_class_request (usb_core_handle_struct *pudev, usb_device_req_struct *req) { usbd_status_enum ret = USBD_OK; switch (pudev->dev.status) { case USB_STATUS_CONFIGURED: if (LOWBYTE(req->wIndex) <= USBD_ITF_MAX_NUM) { ret = (usbd_status_enum)(pudev->dev.class_req_handler(pudev, req)); if ((0U == req->wLength) && (USBD_OK == ret)) { /* no data stage */ usbd_ctlstatus_tx(pudev); } } else { usbd_enum_error(pudev, req); } break; default: usbd_enum_error(pudev, req); break; } return ret; }
/*! \brief handle USB Get_Descriptor request \param[in] pudev: pointer to USB device instance \param[in] req: pointer to USB device request \param[out] none \retval none */ static void usbd_getdescriptor (usb_core_handle_struct *pudev, usb_device_req_struct *req) { if (USB_REQTYPE_DEVICE == (req->bmRequestType & USB_REQTYPE_MASK)) { uint8_t desc_index = (uint8_t)(req->wValue >> 8U); if (desc_index <= 0x03U) { uint16_t len; uint8_t *pbuf; /* call corresponding descriptor get function */ pbuf = standard_descriptor_get[desc_index - 1U](pudev, (uint8_t)(req->wValue) & 0xFFU, &len); if ((0U != len) && (0U != req->wLength)) { len = USB_MIN(len, req->wLength); if ((1U == desc_index) && (64U == req->wLength)) { len = 8U; } usbd_ctltx(pudev, pbuf, len); } } else { usbd_enum_error(pudev, req); } } else if (USB_REQTYPE_INTERFACE == (req->bmRequestType & USB_REQTYPE_MASK)) {
/*! \brief handle USB Set_Address request \param[in] pudev: pointer to USB device instance \param[in] req: pointer to USB device request \param[out] none \retval none */ static void usbd_setaddress (usb_core_handle_struct *pudev, usb_device_req_struct *req) { uint8_t DevAddr; if ((0U == req->wIndex) && (0U == req->wLength)) { DevAddr = (uint8_t)(req->wValue) & 0x7FU; if (USB_STATUS_CONFIGURED == pudev->dev.status) { usbd_enum_error(pudev, req); } else { USB_SET_DEVADDR((uint32_t)DevAddr); usbd_ctlstatus_tx(pudev); if (0U != DevAddr) { pudev->dev.status = USB_STATUS_ADDRESSED; } else { pudev->dev.status = USB_STATUS_DEFAULT; } } } else { usbd_enum_error(pudev, req); } }
/*! \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; }
/*! \brief handle USB Set_Feature request \param[in] pudev: pointer to USB device instance \param[in] req: pointer to USB device request \param[out] none \retval none */ static void usbd_setfeature (usb_core_handle_struct *pudev, usb_device_req_struct *req) { uint8_t ep_addr = 0U; __IO uint32_t DctlrStatus; switch (req->bmRequestType & USB_REQ_MASK) { case USB_REQTYPE_DEVICE: switch (pudev->dev.status) { case USB_STATUS_ADDRESSED: case USB_STATUS_CONFIGURED: if (USB_FEATURE_REMOTE_WAKEUP == req->wValue) { pudev->dev.remote_wakeup = 1U; pudev->dev.class_req_handler(pudev, req); usbd_ctlstatus_tx(pudev); } else if ((req->wValue == USB_FEATURE_TEST_MODE) && (0U == (req->wIndex & 0xFFU))) { DctlrStatus = USB_DCTL; usbd_ctlstatus_tx(pudev); } else { /* no operation */ } break; default: break; } break; case USB_REQTYPE_INTERFACE: switch (pudev->dev.status) { case USB_STATUS_ADDRESSED: usbd_enum_error(pudev, req); break; case USB_STATUS_CONFIGURED: if (LOWBYTE(req->wIndex) <= USBD_ITF_MAX_NUM) { /* no operation */ } else { usbd_enum_error(pudev, req); } break; default: break; } break; case USB_REQTYPE_ENDPOINT: switch (pudev->dev.status) { case USB_STATUS_ADDRESSED: if (IS_NOT_EP0(ep_addr)) { usbd_ep_stall(pudev, ep_addr); } break; case USB_STATUS_CONFIGURED: if (USB_FEATURE_ENDP_HALT == req->wValue) { if (IS_NOT_EP0(ep_addr)) { usbd_ep_stall(pudev, ep_addr); } } pudev->dev.class_req_handler(pudev, req); usbd_ctlstatus_tx(pudev); break; default: break; } break; default: usbd_enum_error(pudev, req); break; } }
/*! \brief handle USB Clear_Feature request \param[in] pudev: pointer to USB device instance \param[in] req: USB device request \param[out] none \retval none */ static void usbd_clrfeature (usb_core_handle_struct *pudev, usb_device_req_struct *req) { uint8_t ep_addr = 0U; switch (req->bmRequestType & USB_REQTYPE_MASK) { case USB_REQTYPE_DEVICE: switch (pudev->dev.status) { case USB_STATUS_ADDRESSED: case USB_STATUS_CONFIGURED: if (USB_FEATURE_REMOTE_WAKEUP == req->wValue) { pudev->dev.remote_wakeup = 0U; pudev->dev.class_req_handler(pudev, req); usbd_ctlstatus_tx(pudev); } break; default: usbd_enum_error(pudev, req); break; } break; case USB_REQTYPE_INTERFACE: switch (pudev->dev.status) { case USB_STATUS_ADDRESSED: usbd_enum_error(pudev, req); break; case USB_STATUS_CONFIGURED: if (LOWBYTE(req->wIndex) <= USBD_ITF_MAX_NUM) { /* no operation */ } else { usbd_enum_error(pudev, req); } break; default: break; } break; case USB_REQTYPE_ENDPOINT: ep_addr = LOWBYTE(req->wIndex); switch (pudev->dev.status) { case USB_STATUS_ADDRESSED: if (IS_NOT_EP0(ep_addr)) { usbd_ep_stall(pudev, ep_addr); } break; case USB_STATUS_CONFIGURED: if (USB_FEATURE_ENDP_HALT == req->wValue) { if (IS_NOT_EP0(ep_addr)) { usbd_ep_clear_stall(pudev, ep_addr); pudev->dev.class_req_handler(pudev, req); } } usbd_ctlstatus_tx(pudev); break; default: break; } break; default: usbd_enum_error(pudev, req); break; } }