/** \brief Internal function used for the very similar \ref SET_FEATURE and \ref CLEAR_FEATURE requests * * This function either sets or clears the specified feature on the specified recipient. * * \param[in] set * When TRUE, the feature is set. When FALSE, the feature is cleared. * * \return * TRUE if the selected feature is supported by the USB library. FALSE to indicate that * \ref usbsrHookClearFeature() or \ref usbsrHookSetFeature() must be called. */ static uint8 ChangeFeature(uint8 set) { uint8 endpoint; // Sanity check if (usbSetupHeader.length || (usbfwData.usbState != DEV_CONFIGURED) && (usbSetupHeader.index != 0)) { usbfwData.ep0Status = EP_STALL; // Handle based on recipient } else { switch (usbSetupHeader.requestType & RT_MASK_RECIP) { // Device case RT_RECIP_DEV: // Sanity check if (LO_UINT16(usbSetupHeader.value) != DEVICE_REMOTE_WAKEUP) { return FALSE; } else { usbfwData.remoteWakeup = set; usbsrHookProcessEvent(set ? USBSR_EVENT_REMOTE_WAKEUP_ENABLED : USBSR_EVENT_REMOTE_WAKEUP_DISABLED, 0); } break; // Endpoint case RT_RECIP_IF: return FALSE; // Endpoint case RT_RECIP_EP: endpoint = LO_UINT16(usbSetupHeader.index) & 0x7F; // Sanity check if (LO_UINT16(usbSetupHeader.value) != ENDPOINT_HALT) { return FALSE; } else if (endpoint > 5) { usbfwData.ep0Status = EP_STALL; } else { USBFW_SELECT_ENDPOINT(endpoint); // IN if (LO_UINT16(usbSetupHeader.index) & 0x80) { USBCSIL = set ? USBCSIL_SEND_STALL : USBCSIL_CLR_DATA_TOG; usbfwData.pEpInStatus[endpoint - 1] = set ? EP_HALT : EP_IDLE; usbsrHookProcessEvent(set ? USBSR_EVENT_EPIN_STALL_SET : USBSR_EVENT_EPIN_STALL_CLEARED, endpoint); // OUT } else { USBCSOL = set ? USBCSOL_SEND_STALL : USBCSOL_CLR_DATA_TOG; usbfwData.pEpOutStatus[endpoint - 1] = set ? EP_HALT : EP_IDLE; usbsrHookProcessEvent(set ? USBSR_EVENT_EPOUT_STALL_SET : USBSR_EVENT_EPOUT_STALL_CLEARED, endpoint); } USBFW_SELECT_ENDPOINT(0); } break; default: usbfwData.ep0Status = EP_STALL; break; } } return TRUE; } // ChangeFeature
/** \brief Internal function used for the very similar \c SET_FEATURE and \c CLEAR_FEATURE requests * * This function either sets or clears the specified feature on the specified recipient. * * \param[in] set * When TRUE, the feature is set. When FALSE, the feature is cleared. * * \return * TRUE if the selected feature is supported by the USB library. FALSE to indicate that * \ref usbsrHookClearFeature() or \ref usbsrHookSetFeature() must be called. */ static uint8_t usbsrChangeFeature(uint8_t set) { uint8_t endpoint; // // Sanity check // if(usbSetupHeader.length || ((usbfwData.usbState != DEV_CONFIGURED) && (usbSetupHeader.index != 0))) { usbfwData.ep0Status = EP_STALL; // // Handle based on recipient // } else { switch(usbSetupHeader.requestType & RT_MASK_RECIP) { // // Device // case RT_RECIP_DEV: // // Sanity check // if(usbSetupHeader.valueLsb != USBSR_FEATSEL_DEVICE_REMOTE_WAKEUP) { return false; } else { usbfwData.remoteWakeup = set; usbsrHookProcessEvent(set ? USBSR_EVENT_REMOTE_WAKEUP_ENABLED : USBSR_EVENT_REMOTE_WAKEUP_DISABLED, 0); } break; // // Interface // case RT_RECIP_IF: return false; // // Endpoint // case RT_RECIP_EP: endpoint = usbSetupHeader.indexLsb & 0x7F; // // Sanity check // if(usbSetupHeader.valueLsb != USBSR_FEATSEL_ENDPOINT_HALT) { return false; } else if(endpoint > 5) { usbfwData.ep0Status = EP_STALL; } else { USBFW_SELECT_ENDPOINT(endpoint); // // IN // if(usbSetupHeader.indexLsb & 0x80) { HWREG(USB_CS0_CSIL) = set ? USB_CSIL_SENDSTALL_M : USB_CSIL_CLRDATATOG_M; usbfwData.pEpInStatus[endpoint - 1] = set ? EP_HALT : EP_IDLE; usbsrHookProcessEvent(set ? USBSR_EVENT_EPIN_STALL_SET : USBSR_EVENT_EPIN_STALL_CLEARED, endpoint); // // OUT // } else { HWREG(USB_CSOL) = set ? USB_CSOL_SENDSTALL_M : USB_CSOL_CLRDATATOG_M; usbfwData.pEpOutStatus[endpoint - 1] = set ? EP_HALT : EP_IDLE; usbsrHookProcessEvent(set ? USBSR_EVENT_EPOUT_STALL_SET : USBSR_EVENT_EPOUT_STALL_CLEARED, endpoint); } USBFW_SELECT_ENDPOINT(0); } break; default: usbfwData.ep0Status = EP_STALL; break; } } return true; }