Commit 5bef4a9d authored by Mathieu CHOPLAIN's avatar Mathieu CHOPLAIN Committed by Henrik Brix Andersen
Browse files

drivers: usb: udc: skeleton: handle special case of set_halt() for EP0

The UDC stack assumes that 'halt' on control endpoints is automatically
cleared by device drivers and never calls udc_ep_clear_halt() for such
endpoints. In practice, most controllers do perform this automatic clear
in hardware, but this requires special handling in udc_ep_set_halt() for
control endpoints (EP0), as setting the 'halted' bit on such endpoints will
lead to the software getting out-of-sync with the hardware.

Update the UDC skeleton driver to handle this edge case and add a comment
documenting the stack's behavior, along with the hardware behavior expected
by the code added to the skeleton driver for it to be functional.

Co-authored-by: default avatarJohann Fischer <johann.fischer@nordicsemi.no>
Signed-off-by: default avatarMathieu CHOPLAIN <mathieu.choplain-ext@st.com>
parent 32c67762
Loading
Loading
Loading
Loading
+20 −0
Changes for drivers/usb/udc/udc_skeleton.c: 20 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -160,7 +160,27 @@ static int udc_skeleton_ep_set_halt(const struct device *dev,
{
	LOG_DBG("Set halt ep 0x%02x", cfg->addr);

	/*
	 * NOTE: udc_ep_clear_halt() is not called for control endpoints.
	 *
	 * When an endpoint is halted or a control pipe request is not
	 * supported, endpoint responds with a STALL handshake packet. The
	 * specification distinguishes between a functional stall and a
	 * protocol stall. The stack calls udc_ep_set_halt() to set a
	 * functional or protocol stall. A protocol stall is unique to control
	 * pipes and terminates at the beginning of the next control transfer.
	 * Although a control pipe may support functional stall, it is not
	 * recommended by the specification. The stack does not call
	 * udc_ep_clear_halt() for control endpoints.
	 *
	 * How a driver clears a protocol stall depends on the implementation.
	 * Some controllers automatically clear the protocol stall condition
	 * when the next setup packet arrives, while others require software
	 * intervention.
	 */
	if (USB_EP_GET_IDX(cfg->addr) != 0U) {
		cfg->stat.halted = true;
	}

	return 0;
}