static void udd_ctrl_send_zlp_in(void) { udd_ep_control_state = UDD_EPCTRL_HANDSHAKE_WAIT_IN_ZLP; // Valid and sent empty IN packet on control endpoint udd_control_in_set_bytecnt(0); udd_control_in_clear_NACK0(); }
static void udd_ctrl_in_sent(void) { static bool b_shortpacket = false; uint16_t nb_remain; if (UDD_EPCTRL_HANDSHAKE_WAIT_IN_ZLP == udd_ep_control_state) { // ZLP on IN is sent, then valid end of setup request udd_ctrl_endofrequest(); // Reinitializes control endpoint management udd_ctrl_init(); return; } Assert(udd_ep_control_state == UDD_EPCTRL_DATA_IN); nb_remain = udd_g_ctrlreq.payload_size - udd_ctrl_payload_nb_trans; if (0 == nb_remain) { // Update number of total data sending by previous playload buffer udd_ctrl_prev_payload_nb_trans += udd_ctrl_payload_nb_trans; if ((udd_g_ctrlreq.req.wLength == udd_ctrl_prev_payload_nb_trans) || b_shortpacket) { // All data requested are transfered or a short packet has been sent // then it is the end of data phase. // Generate an OUT ZLP for handshake phase. udd_ctrl_send_zlp_out(); return; } // Need of new buffer because the data phase is not complete if ((!udd_g_ctrlreq.over_under_run) || (!udd_g_ctrlreq.over_under_run())) { // Underrun then send zlp on IN // nb_remain == 0 allows to send a IN ZLP } else { // A new payload buffer is given udd_ctrl_payload_nb_trans = 0; nb_remain = udd_g_ctrlreq.payload_size; } } // Continue transfer an send next data if (nb_remain >= USB_DEVICE_EP_CTRL_SIZE) { nb_remain = USB_DEVICE_EP_CTRL_SIZE; b_shortpacket = false; } else { b_shortpacket = true; } udd_control_in_set_bytecnt(nb_remain); // Link payload buffer directly on USB hardware udd_control_in_set_buf(udd_g_ctrlreq.payload + udd_ctrl_payload_nb_trans); udd_ctrl_payload_nb_trans += nb_remain; // Valid and sent the data available in control endpoint buffer udd_control_in_clear_NACK0(); }
static void udd_ctrl_init(void) { udd_disable_overflow_interrupt(); udd_disable_underflow_interrupt(); // Clear status flag from control endpoints // Mandatory for ATxmega128A1 Rev. K udd_control_in_set_NACK0(); udd_control_in_set_bytecnt(0); udd_control_in_ack_tc(); udd_control_ack_in_underflow(); udd_control_ack_out_overflow(); udd_g_ctrlreq.callback = NULL; udd_g_ctrlreq.over_under_run = NULL; udd_g_ctrlreq.payload_size = 0; udd_ep_control_state = UDD_EPCTRL_SETUP; }