static bool udd_ep_interrupt(void) { udd_ep_id_t ep; udd_ep_job_t *ptr_job; // For each endpoint different of control endpoint (0) for (ep = 1; ep <= USB_DEVICE_MAX_EP; ep++) { // Get job corresponding at endpoint ptr_job = &udd_ep_job[ep - 1]; // Check DMA event if (Is_udd_endpoint_dma_interrupt_enabled(ep) && Is_udd_endpoint_dma_interrupt(ep)) { uint32_t nb_remaining; if( udd_endpoint_dma_get_status(ep) & AVR32_USBB_UDDMA1_STATUS_CH_EN_MASK) { return true; // Ignore EOT_STA interrupt } udd_disable_endpoint_dma_interrupt(ep); // Save number of data no transfered nb_remaining = (udd_endpoint_dma_get_status(ep) & AVR32_USBB_UDDMA1_STATUS_CH_BYTE_CNT_MASK) >> AVR32_USBB_UDDMA1_STATUS_CH_BYTE_CNT_OFFSET; if (nb_remaining) { // Transfer no complete (short packet or ZLP) then: // Update number of data transfered ptr_job->nb_trans -= nb_remaining; // Set transfer complete to stop the transfer ptr_job->buf_size = ptr_job->nb_trans; } udd_ep_trans_done(ep); return true; } // Check empty bank interrupt event if (Is_udd_endpoint_interrupt_enabled(ep)) { if (Is_udd_in_send_interrupt_enabled(ep) && Is_udd_in_send(ep)) { udd_disable_in_send_interrupt(ep); // One bank is free then send a ZLP udd_ack_in_send(ep); udd_ack_fifocon(ep); udd_ep_finish_job(ptr_job, false, ep); return true; } if (Is_udd_bank_interrupt_enabled(ep) && (0 == udd_nb_busy_bank(ep))) { // End of background transfer on IN endpoint udd_disable_bank_interrupt(ep); udd_disable_endpoint_interrupt(ep); Assert(ptr_job->stall_requested); // A stall has been requested during background transfer ptr_job->stall_requested = false; udd_disable_endpoint_bank_autoswitch(ep); udd_enable_stall_handshake(ep); udd_reset_data_toggle(ep); return true; } } }
/** * \brief Waits a DATA IN packets on control endpoint * * \param payload RAM buffer to store data received * \param size Size of RAM buffer waiting */ static void main_usb_send_in(uint8_t *payload, uint8_t size) { uint8_t *ptr_dest; do { while (!Is_udd_in_send(0)); // Fill buffer of endpoint control ptr_dest = (uint8_t *) & udd_get_endpoint_fifo_access(0, 8); // Write quickly the IN data for (uint8_t i = 0; (i<udd_get_endpoint_size(0)) && size; i++) { *ptr_dest++ = *payload++; size--; } // Validate and send the data available in the control endpoint buffer udd_ack_in_send(0); } while (size); while (!Is_udd_in_send(0)); }
static void udd_ctrl_overflow(void) { if (Is_udd_in_send(0)) return; // overflow ignored if IN data is received // The case of UDD_EPCTRL_DATA_IN is not managed // because the OUT endpoint is already free and OUT ZLP accepted if (UDD_EPCTRL_HANDSHAKE_WAIT_IN_ZLP == udd_ep_control_state) { // A IN handshake is waiting by device, // but host want extra OUT data then stall extra OUT data udd_enable_stall_handshake(0); } }
static bool udd_ctrl_interrupt(void) { if (!Is_udd_endpoint_interrupt(0)) { return false; // No interrupt events on control endpoint } dbg_print("0: "); // By default disable overflow and underflow interrupt udd_disable_nak_in_interrupt(0); udd_disable_nak_out_interrupt(0); // Search event on control endpoint if (Is_udd_setup_received(0)) { dbg_print("stup "); // SETUP packet received udd_ctrl_setup_received(); return true; } if (Is_udd_in_send(0) && Is_udd_in_send_interrupt_enabled(0)) { dbg_print("in "); // IN packet sent udd_ctrl_in_sent(); return true; } if (Is_udd_out_received(0)) { dbg_print("out "); // OUT packet received udd_ctrl_out_received(); return true; } if (Is_udd_nak_out(0)) { dbg_print("nako "); // Overflow on OUT packet udd_ack_nak_out(0); udd_ctrl_overflow(); return true; } if (Is_udd_nak_in(0)) { dbg_print("naki "); // Underflow on IN packet udd_ack_nak_in(0); udd_ctrl_underflow(); return true; } dbg_print("n%x ", (int)UHDP_ARRAY(UOTGHS_DEVEPTISR[0], 0)); return false; }
static bool udd_ctrl_interrupt(void) { if (!Is_udd_endpoint_interrupt(0)) return false; // No interrupt events on control endpoint // By default disable overflow and underflow interrupt udd_disable_nak_in_interrupt(0); udd_disable_nak_out_interrupt(0); // Search event on control endpoint if (Is_udd_setup_received(0)) { // SETUP packet received udd_ctrl_setup_received(); return true; } if (Is_udd_in_send(0) && Is_udd_in_send_interrupt_enabled(0)) { // IN packet sent udd_ctrl_in_sent(); return true; } if (Is_udd_out_received(0)) { // OUT packet received udd_ctrl_out_received(); return true; } if (Is_udd_nak_out(0)) { // Overflow on OUT packet udd_ack_nak_out(0); udd_ctrl_overflow(); return true; } if (Is_udd_nak_in(0)) { // Underflow on IN packet udd_ack_nak_in(0); udd_ctrl_underflow(); return true; } return false; }