Exemplo n.º 1
0
static void udd_ctrl_setup_received(void)
{
	irqflags_t flags;

	if (UDD_EPCTRL_SETUP != udd_ep_control_state) {
		// May be a hidden DATA or ZLP phase
		// or protocol abort
		udd_ctrl_endofrequest();

		// Reinitializes control endpoint management
		udd_ctrl_init();
	}
	// Fill setup request structure
	if (8 != udd_udesc_get_buf0_ctn(0)) {
		udd_ctrl_stall_data();
		udd_ack_setup_received(0);
		return; // Error data number doesn't correspond to SETUP packet
	}
	memcpy((uint8_t *) & udd_g_ctrlreq.req, udd_ctrl_buffer, 8);

	// Manage LSB/MSB to fit with CPU usage
	udd_g_ctrlreq.req.wValue = le16_to_cpu(udd_g_ctrlreq.req.wValue);
	udd_g_ctrlreq.req.wIndex = le16_to_cpu(udd_g_ctrlreq.req.wIndex);
	udd_g_ctrlreq.req.wLength = le16_to_cpu(udd_g_ctrlreq.req.wLength);

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

	if (Udd_setup_is_in()) {
		// IN data phase requested
		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;

		// To detect a protocol error, enable nak interrupt on data IN phase
		udd_ack_nak_in(0);
		flags = cpu_irq_save();
		udd_enable_nak_in_interrupt(0);
		cpu_irq_restore(flags);
	}
}
static void udd_ctrl_setup_received(void)
{
	uint8_t i;

	if (UDD_EPCTRL_SETUP != udd_ep_control_state) {
		// May be a hidden DATA or ZLP phase
		// or protocol abort
		udd_ctrl_endofrequest();

		// Reinitializes control endpoint management
		udd_ctrl_init();
	}
	// Fill setup request structure
	if (8 != udd_byte_count(0)) {
		udd_ack_setup_received(0);
		udd_ctrl_stall_data();
		return; // Error data number doesn't correspond to SETUP packet
	}
	for (i = 0; i < 8; i++) {
		((uint8_t *) & udd_g_ctrlreq.req)[i] =
			udd_endpoint_fifo_read(0);
	}
	// Manage LSB/MSB to fit with CPU usage
	udd_g_ctrlreq.req.wValue = le16_to_cpu(udd_g_ctrlreq.req.wValue);
	udd_g_ctrlreq.req.wIndex = le16_to_cpu(udd_g_ctrlreq.req.wIndex);
	udd_g_ctrlreq.req.wLength = le16_to_cpu(udd_g_ctrlreq.req.wLength);

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

	if (Udd_setup_is_in()) {
		// Set DIR
		udd_set_endpoint_direction_in(0);
		udd_ack_setup_received(0);
		// IN data phase requested
		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 {
		udd_ack_setup_received(0);
		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;
	}
}
bool udi_cdc_comm_setup(void)
{
	uint8_t port = udi_cdc_setup_to_port();

	if (Udd_setup_is_in()) {
		// GET Interface Requests
		if (Udd_setup_type() == USB_REQ_TYPE_CLASS) {
			// Requests Class Interface Get
			switch (udd_g_ctrlreq.req.bRequest) {
			case USB_REQ_CDC_GET_LINE_CODING:
				// Get configuration of CDC line
				if (sizeof(usb_cdc_line_coding_t) !=
						udd_g_ctrlreq.req.wLength)
					return false; // Error for USB host
				udd_g_ctrlreq.payload =
						(uint8_t *) &
						udi_cdc_line_coding[port];
				udd_g_ctrlreq.payload_size =
						sizeof(usb_cdc_line_coding_t);
				return true;
			}
		}
	}
	if (Udd_setup_is_out()) {
		// SET Interface Requests
		if (Udd_setup_type() == USB_REQ_TYPE_CLASS) {
			// Requests Class Interface Set
			switch (udd_g_ctrlreq.req.bRequest) {
			case USB_REQ_CDC_SET_LINE_CODING:
				// Change configuration of CDC line
				if (sizeof(usb_cdc_line_coding_t) !=
						udd_g_ctrlreq.req.wLength)
					return false; // Error for USB host
				udd_g_ctrlreq.callback =
						udi_cdc_line_coding_received;
				udd_g_ctrlreq.payload =
						(uint8_t *) &
						udi_cdc_line_coding[port];
				udd_g_ctrlreq.payload_size =
						sizeof(usb_cdc_line_coding_t);
				return true;
			case USB_REQ_CDC_SET_CONTROL_LINE_STATE:
				// According cdc spec 1.1 chapter 6.2.14
				UDI_CDC_SET_DTR_EXT(port, (0 !=
						(udd_g_ctrlreq.req.wValue
						 & CDC_CTRL_SIGNAL_DTE_PRESENT)));
				UDI_CDC_SET_RTS_EXT(port, (0 !=
						(udd_g_ctrlreq.req.wValue
						 & CDC_CTRL_SIGNAL_ACTIVATE_CARRIER)));
				return true;
			}
		}
	}
	return false;  // request Not supported
}
Exemplo n.º 4
0
bool udi_vendor_setup(void)
{
	if (Udd_setup_is_in()) {
		if (Udd_setup_type() == USB_REQ_TYPE_VENDOR) {
			return UDI_VENDOR_SETUP_IN_RECEIVED();
		}
	}
	if (Udd_setup_is_out()) {
		if (Udd_setup_type() == USB_REQ_TYPE_VENDOR) {
			return UDI_VENDOR_SETUP_OUT_RECEIVED();
		}
	}
	return false; // Not supported request
}
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();
	}
}
Exemplo n.º 6
0
bool udi_vendor_setup(void)
{
	if (Udd_setup_is_in()) {
		if ((Udd_setup_type() == USB_REQ_TYPE_VENDOR)
				&& (udd_g_ctrlreq.req.bRequest == 0)) {
			return UDI_VENDOR_SETUP_IN_RECEIVED();
		}
	}
	if (Udd_setup_is_out()) {
		if ((Udd_setup_type() == USB_REQ_TYPE_VENDOR)
				&& (udd_g_ctrlreq.req.bRequest == 0)
				&& (0 != udd_g_ctrlreq.req.wLength)) {
			return UDI_VENDOR_SETUP_OUT_RECEIVED();
		}
	}
	return false; // Not supported request
}
Exemplo n.º 7
0
static void udd_ctrl_setup_received(void)
{
	irqflags_t flags;
	uint8_t i;

	if (UDD_EPCTRL_SETUP != udd_ep_control_state) {
		// May be a hidden DATA or ZLP phase
		// or protocol abort
		udd_ctrl_endofrequest();
		// Reinitializes control endpoint management
		udd_ctrl_init();
	}
	// Fill setup request structure
	if (8 != udd_byte_count(0)) {
		udd_ctrl_stall_data();
		udd_ack_setup_received(0);
		return;	// Error data number doesn't correspond to SETUP packet
	}
	uint32_t *ptr = (uint32_t *) & udd_get_endpoint_fifo_access(0, 32);
	for (i = 0; i < 8 / 4; i++) {
		((uint32_t *) & udd_g_ctrlreq.req)[i] = *ptr++;
	}
	// Manage LSB/MSB to fit with CPU usage
	udd_g_ctrlreq.req.wValue = le16_to_cpu(udd_g_ctrlreq.req.wValue);
	udd_g_ctrlreq.req.wIndex = le16_to_cpu(udd_g_ctrlreq.req.wIndex);
	udd_g_ctrlreq.req.wLength = le16_to_cpu(udd_g_ctrlreq.req.wLength);

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

	if (Udd_setup_is_in()) {
		// Compute if an IN ZLP must be send after IN data
		udd_ctrl_payload_need_in_zlp =
				((udd_g_ctrlreq.payload_size %
						USB_DEVICE_EP_CTRL_SIZE) == 0);
		// IN data phase requested
		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;
		// To detect a protocol error, enable nak interrupt on data IN phase
		udd_ack_nak_in(0);
		flags = cpu_irq_save();
		udd_enable_nak_in_interrupt(0);
		cpu_irq_restore(flags);
	}
}
bool udc_dfu_setup(void)
{

	//** Interface requests
	if (Udd_setup_type() != USB_REQ_TYPE_CLASS) {
		return false;	// Only class request decoded
	}
// TODO: use state of DFU specification
	if (Udd_setup_is_in()) {
		// Requests Class Interface Get
		switch (udd_g_ctrlreq.req.bRequest) {
		case USB_REQ_DFU_GETSTATUS:
			if (0 != udd_g_ctrlreq.req.wValue)
				break;
			if (sizeof(udi_dfu_status) !=
					udd_g_ctrlreq.req.wLength)
				break;
			udd_g_ctrlreq.payload =
					(uint8_t *) & udi_dfu_status;
			udd_g_ctrlreq.payload_size =
					sizeof(udi_dfu_status);
			return true;

		case USB_REQ_DFU_GETSTATE:
			if (0 != udd_g_ctrlreq.req.wValue)
				break;
			if (sizeof(udi_dfu_status.bState) !=
					udd_g_ctrlreq.req.wLength)
				break;
			udd_g_ctrlreq.payload =
					(uint8_t *) &
					(udi_dfu_status.bState);
			udd_g_ctrlreq.payload_size =
					sizeof(udi_dfu_status.bState);
			return true;

		case USB_REQ_DFU_UPLOAD:
			break;
		}
	}


	if (Udd_setup_is_out()) {
		// Requests Class Interface Set
		switch (udd_g_ctrlreq.req.bRequest) {
		case USB_REQ_DFU_ABORT:
			break;
		case USB_REQ_DFU_CLRSTATUS:
			if (0 != udd_g_ctrlreq.req.wValue)
				break;
			if (0 != udd_g_ctrlreq.req.wLength)
				break;
			udi_dfu_clear_status();
			return true;

		case USB_REQ_DFU_DNLOAD:
			break;
		}
	}
	// Unknown request
	udi_dfu_status.bStatus = DFU_STATUS_ERRSTALLEDPK;
	udi_dfu_status.bState = DFU_STATE_DFUERROR;
	return false;
}