static void udd_ctrl_setup_received(void)
{
	if (UDD_EPCTRL_SETUP != udd_ep_control_state) {
		if ((UDD_EPCTRL_HANDSHAKE_WAIT_IN_ZLP == udd_ep_control_state)
				|| (UDD_EPCTRL_HANDSHAKE_WAIT_OUT_ZLP == udd_ep_control_state)) {
			// Accept that ZLP event can be hidden by setup packet event
			// in case of setup packet sending quickly after a ZLP
			udd_ctrl_endofrequest();
		}
		// Reinitializes control endpoint management
		udd_ctrl_init();
	}
	// Fill setup request structure
	if (8 != udd_control_out_get_bytecnt())
		return; // Error data number don't correspond to SETUP packet
	memcpy((uint8_t *) & udd_g_ctrlreq.req, udd_ctrl_buffer, 8);

	// To detect a protocol error on setup, enable nak interrupt on IN/OUT of control endpoint
	udd_enable_overflow_interrupt();
	udd_enable_underflow_interrupt();

	// Decode setup request
	if (udc_process_setup() == false) {
		// Setup request unknown then stall it
		udd_ctrl_stall_data();
		return;
	}

	if (Udd_setup_is_in()) {
		udd_ctrl_prev_payload_nb_trans = 0;
		udd_ctrl_payload_nb_trans = 0;
		udd_ep_control_state = UDD_EPCTRL_DATA_IN;
		udd_ctrl_in_sent(); // Send first data transfer
	} else {
		if (0 == udd_g_ctrlreq.req.wLength) {
			// No data phase requested
			// Send IN ZLP to ACK setup request
			udd_ctrl_send_zlp_in();
			return;
		}
		// OUT data phase requested
		udd_ctrl_prev_payload_nb_trans = 0;
		udd_ctrl_payload_nb_trans = 0;
		udd_ep_control_state = UDD_EPCTRL_DATA_OUT;
		// Clear packet to receive first packet
		udd_control_out_clear_NACK0();
		udd_control_out_ack_tc();
	}
}
예제 #2
0
static void udd_ctrl_send_zlp_out(void)
{
	udd_ep_control_state = UDD_EPCTRL_HANDSHAKE_WAIT_OUT_ZLP;
	// Valid reception of OUT packet on control endpoint
	udd_control_out_clear_NACK0();
}
예제 #3
0
static void udd_ctrl_out_received(void)
{
	uint16_t nb_data;

	if (UDD_EPCTRL_HANDSHAKE_WAIT_OUT_ZLP == udd_ep_control_state) {
		// Valid end of setup request
		udd_ctrl_endofrequest();
		// Reinitializes control endpoint management
		udd_ctrl_init();
		return;
	}
	Assert(udd_ep_control_state == UDD_EPCTRL_DATA_OUT);

	// Read data received during OUT phase
	nb_data = udd_control_out_get_bytecnt();

	if (udd_g_ctrlreq.payload_size < (udd_ctrl_payload_nb_trans + nb_data)) {
		// Payload buffer too small, ignore data remaining
		nb_data = udd_g_ctrlreq.payload_size - udd_ctrl_payload_nb_trans;
	}

	memcpy((uint8_t *) (udd_g_ctrlreq.payload + udd_ctrl_payload_nb_trans),
			udd_ctrl_buffer, nb_data);
	udd_ctrl_payload_nb_trans += nb_data;

	if ((USB_DEVICE_EP_CTRL_SIZE != nb_data) || (udd_g_ctrlreq.req.wLength
			<= (udd_ctrl_prev_payload_nb_trans
			+ udd_ctrl_payload_nb_trans))) {
		// End of reception because it is a short packet
		// or all data are transfered

		// Before send ZLP, call intermediate callback
		// in case of data receive generate a stall
		udd_g_ctrlreq.payload_size = udd_ctrl_payload_nb_trans;
		if (NULL != udd_g_ctrlreq.over_under_run) {
			if (!udd_g_ctrlreq.over_under_run()) {
				// Stall ZLP
				udd_ctrl_stall_data();
				return;
			}
		}
		// Send IN ZLP to ACK setup request
		udd_ctrl_send_zlp_in();
		return;
	}

	if (udd_g_ctrlreq.payload_size == udd_ctrl_payload_nb_trans) {
		// Overrun then request a new payload buffer
		if (!udd_g_ctrlreq.over_under_run) {
			// No callback available to request a new payload buffer
			udd_ctrl_stall_data();
			return;
		}
		if (!udd_g_ctrlreq.over_under_run()) {
			// No new payload buffer delivered
			udd_ctrl_stall_data();
			return;
		}
		// New payload buffer available
		// Update number of total data received
		udd_ctrl_prev_payload_nb_trans += udd_ctrl_payload_nb_trans;
		// Reinit reception on payload buffer
		udd_ctrl_payload_nb_trans = 0;
	}
	// Free buffer of OUT control endpoint to authorize next reception
	udd_control_out_clear_NACK0();
}