drivers/usb/gadget/udc/aspeed-vhub/ep0.c

Source file repositories/reference/linux-study-clean/drivers/usb/gadget/udc/aspeed-vhub/ep0.c

File Facts

System
Linux kernel
Corpus path
drivers/usb/gadget/udc/aspeed-vhub/ep0.c
Extension
.c
Size
13618 bytes
Lines
522
Domain
Driver Families
Bucket
drivers/usb
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (req) {
			dev_warn(dev, "request present while in TOKEN state\n");
			ast_vhub_nuke(ep, -EINVAL);
		}
		dev_warn(dev, "ack while in TOKEN state\n");
		stall = true;
		break;
	case ep0_state_data:
		/* Check the state bits corresponding to our direction */
		if ((ep->ep0.dir_in && (stat & VHUB_EP0_TX_BUFF_RDY)) ||
		    (!ep->ep0.dir_in && (stat & VHUB_EP0_RX_BUFF_RDY)) ||
		    (ep->ep0.dir_in != in_ack)) {
			/* In that case, ignore interrupt */
			dev_warn(dev, "irq state mismatch");
			break;
		}
		/*
		 * We are in data phase and there's no request, something is
		 * wrong, stall
		 */
		if (!req) {
			dev_warn(dev, "data phase, no request\n");
			stall = true;
			break;
		}

		/* We have a request, handle data transfers */
		if (ep->ep0.dir_in)
			ast_vhub_ep0_do_send(ep, req);
		else
			ast_vhub_ep0_do_receive(ep, req, VHUB_EP0_RX_LEN(stat));
		return;
	case ep0_state_status:
		/* Nuke stale requests */
		if (req) {
			dev_warn(dev, "request present while in STATUS state\n");
			ast_vhub_nuke(ep, -EINVAL);
		}

		/*
		 * If the status phase completes with the wrong ack, stall
		 * the endpoint just in case, to abort whatever the host
		 * was doing.
		 */
		if (ep->ep0.dir_in == in_ack) {
			dev_warn(dev, "status direction mismatch\n");
			stall = true;
		}
		break;
	case ep0_state_stall:
		/*
		 * There shouldn't be any request left, but nuke just in case
		 * otherwise the stale request will block subsequent ones
		 */
		ast_vhub_nuke(ep, -EIO);
		break;
	}

	/* Reset to token state or stall */
	if (stall) {
		writel(VHUB_EP0_CTRL_STALL, ep->ep0.ctlstat);
		ep->ep0.state = ep0_state_stall;
	} else
		ep->ep0.state = ep0_state_token;
}

static int ast_vhub_ep0_queue(struct usb_ep* u_ep, struct usb_request *u_req,
			      gfp_t gfp_flags)
{
	struct ast_vhub_req *req = to_ast_req(u_req);
	struct ast_vhub_ep *ep = to_ast_ep(u_ep);
	struct ast_vhub *vhub = ep->vhub;
	struct device *dev = &vhub->pdev->dev;
	unsigned long flags;

	/* Paranoid cheks */
	if (!u_req || (!u_req->complete && !req->internal)) {
		dev_warn(dev, "Bogus EP0 request ! u_req=%p\n", u_req);
		if (u_req) {
			dev_warn(dev, "complete=%p internal=%d\n",
				 u_req->complete, req->internal);
		}
		return -EINVAL;
	}

	/* Not endpoint 0 ? */
	if (WARN_ON(ep->d_idx != 0))
		return -EINVAL;

	/* Disabled device */

Annotation

Implementation Notes