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; } } }
bool udd_ep_set_halt(udd_ep_id_t ep) { uint8_t index = ep & USB_EP_ADDR_MASK; if (USB_DEVICE_MAX_EP < index) return false; if (Is_udd_bank_interrupt_enabled(index)) { // Wait end of transfer (= no busy bank) before stall endpoint udd_ep_job[index - 1].stall_requested = true; } else { // Stall endpoint udd_enable_stall_handshake(index); udd_reset_data_toggle(index); } udd_ep_abort_job(ep); return true; }