handle_ep0(9)
π handle_ep0(9) β bestie edition
okay so this is handle_ep0(9) from the Kernel API Manual and honestly? it's a whole moment. sit down, grab a strawberry drink π, we're learning how the control endpoint moves data around.
β¨ NAME β¨
handle_ep0 β literally the function that handles control endpoint data transfers π
πΈ SYNOPSIS πΈ
void handle_ep0 (struct pxa_udc *udc , int fifo_irq , int opc_irq );
like, that's the whole signature, no notes π
π¦ ARGUMENTS π¦
udcβ the udc device itself, the main character of this whole operation πfifo_irqβ1if we got triggered by a fifo service type irqopc_irqβ1if we got triggered by an output packet complete type irq
π CONTEXT π
interrupt handler β¨ (yes, interrupt handler, we're in the fast lane, no sleeping on the job)
π₯ DESCRIPTION π₯
okay so what does it actually do? it tries to transfer all pending request data into the endpoint and/or transfer all pending data in the endpoint into usb requests. both directions, she's flexible like that π«Ά. and it handles the states of the ep0 automata β the state machine, the vibe check enforcer.
so, PXA27x hardware is out here handling several standard usb control requests without even notifying the driver. she's independent, we love that for her. the requests fully handled by hardware are:
SET_ADDRESS, SET_FEATURE, CLEAR_FEATURE, GET_CONFIGURATION, GET_INTERFACE, GET_STATUS
then there's the requests handled by hardware, but with irq notification:
SYNCH_FRAME, SET_CONFIGURATION, SET_INTERFACE
and the remaining standard requests really handled by handle_ep0 are:
GET_DESCRIPTOR, SET_DESCRIPTOR, specific requests.
requests standardized outside of USB 2.0 chapter 9 are handled more uniformly, by gadget drivers. iykyk π
π¨ real talk: the control endpoint state machine is _not_ USB spec compliant. it's even hardly compliant with Intel PXA270 developers guide. like, not even close, bestie π
the key points which inferred this state machine are:
- on every setup token, bit
UDCCSR0_SAis raised and held until cleared by software. - on every OUT packet received,
UDCCSR0_OPCis raised and held until cleared by software. - clearing
UDCCSR0_OPCalways flushes ep0. If in setup stage, never do it before reading ep0. This is true only for PXA27x. This is not true anymore for PXA3xx family (check Back-to-Back setup packet in developers guide). β οΈ - irq can be called on a "packet complete" event (
opc_irq=1), whileUDCCSR0_OPCis not yet raised (delta can be as big as 100ms from experimentation). yeah. 100ms. we timed it. π - as
UDCCSR0_SAcan be activated while in irq handling, and clearingUDCCSR0_OPCwould flush the setup data, we almost never clearUDCCSR0_OPC=> we never actually read the "status stage" packet of an IN data stage => this is not documented in Intel documentation. iconic behaviour honestly π - hardware as no idea of STATUS STAGE, it only handle SETUP STAGE and DATA STAGE. The driver add STATUS STAGE to send last zero length packet in
OUT_STATUS_STAGE. - special attention was needed for
IN_STATUS_STAGE. If a packet complete event is detected, we terminate the status stage without ackowledging the packet (not to risk to loose a potential SETUP packet) β
π SEE ALSO π
Kernel file ./drivers/usb/gadget/udc/pxa27x_udc.c is where the whole friend group lives, and it's also is_match_usb_pxa(9), find_pxa_ep(9), update_pxa_ep_matches(9), pio_irq_enable(9), pio_irq_disable(9), udc_set_mask_UDCCR(9), udc_clear_mask_UDCCR(9), ep_write_UDCCSR(9), ep_count_bytes_remain(9), ep_is_empty(9), ep_is_full(9), epout_has_pkt(9), set_ep0state(9), ep0_idle(9), inc_ep_stats_reqs(9), inc_ep_stats_bytes(9), pxa_ep_setup(9), pxa_eps_setup(9), pxa_ep_alloc_request(9), pxa_ep_free_request(9), ep_add_request(9), ep_del_request(9), req_done(9), ep_end_out_req(9), ep0_end_out_req(9), ep_end_in_req(9), ep0_end_in_req(9), nuke(9), read_packet(9), write_packet(9), read_fifo(9), write_fifo(9), read_ep0_fifo(9), write_ep0_fifo(9), pxa_ep_queue(9), pxa_ep_dequeue(9), pxa_ep_set_halt(9), pxa_ep_fifo_status(9), pxa_ep_fifo_flush(9), pxa_ep_enable(9), pxa_ep_disable(9), dplus_pullup(9), pxa_udc_get_frame(9), pxa_udc_wakeup(9), should_enable_udc(9),
should_disable_udc(9), pxa_udc_pullup(9), pxa_udc_vbus_session(9), pxa_udc_vbus_draw(9), pxa_udc_phy_event(9), udc_disable(9), udc_init_data(9), udc_enable(9), pxa27x_udc_start(9), stop_activity(9), pxa27x_udc_stop(9), handle_ep0_ctrl_req(9), handle_ep(9), pxa27x_change_configuration(9), pxa27x_change_interface(9), irq_udc_suspend(9), irq_udc_resume(9), irq_udc_reconfig(9), irq_udc_reset(9), pxa_udc_irq(9), pxa_udc_probe(9), pxa_udc_remove(9), pxa_udc_suspend(9), pxa_udc_resume(9)
that's the whole page bestie, go read the source, slay πβ¨
sign-off time π β this gorgeous little doc lives under ./drivers/usb/gadget/udc, dated October 2026, and it's serving handle_ep0(9) energy only. periodt. π
π¦ where this page comes from
- nixpkgs unstable: linux-manual 7.3.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms