Пример #1
0
bool udd_ep_set_halt(udd_ep_id_t ep)
{
	udd_ep_job_t *ptr_job;
	uint8_t index = ep & USB_EP_ADDR_MASK;

	if (USB_DEVICE_MAX_EP < index) {
		return false;
	}

	ptr_job = &udd_ep_job[index - 1];

	if (Is_udd_endpoint_stall_requested(index) // Endpoint stalled
			|| ptr_job->stall_requested) { // Endpoint stall is requested
		return true; // Already STALL
	}

	if (ptr_job->busy == true) {
		return false; // Job on going, stall impossible
	}

	if ((ep & USB_EP_DIR_IN) && (0 != udd_nb_busy_bank(index))) {
			// Delay the stall after the end of IN transfer on USB line
			ptr_job->stall_requested = true;
			udd_enable_bank_interrupt(index);
			udd_enable_endpoint_interrupt(index);
			return true;
	}
	
	// Stall endpoint immediately
	udd_disable_endpoint_bank_autoswitch(index);
	udd_ack_stall(index);
	udd_enable_stall_handshake(index);
	return true;
}
Пример #2
0
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++) {
		// Check DMA event
		if (Is_udd_endpoint_dma_interrupt_enabled(ep)
				&& Is_udd_endpoint_dma_interrupt(ep)) {
			uint32_t nb_remaining;
			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;
			// Get job corresponding at endpoint
			ptr_job = &udd_ep_job[ep - 1];
			// Update number of data transfered
			ptr_job->buf_size -= nb_remaining;

			if (!Is_udd_endpoint_in(ep)) {
				// Disable autoswitch bank on OUT
				udd_disable_endpoint_bank_autoswitch(ep);
			} else {
				// Wait end of background transfer on IN endpoint before disabled autoswitch bank
				udd_enable_endpoint_interrupt(ep);
				udd_enable_bank_interrupt(ep);
			}
			// Call callback to signal end of transfer
			udd_ep_finish_job(&udd_ep_job[ep - 1], false);
			return true;
		}
		// Check empty bank interrupt event
		if (Is_udd_endpoint_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);
			// If no new transfer running then disable autoswitch bank
			if (!udd_ep_job[ep - 1].busy) {
				udd_disable_endpoint_bank_autoswitch(ep);
			}
			// If a stall has been requested during backgound transfer then execute it
			if (udd_ep_job[ep - 1].stall_requested) {
				udd_ep_job[ep - 1].stall_requested = false;
				udd_enable_stall_handshake(ep);
				udd_reset_data_toggle(ep);
			}
			return true;
		}
	}