/** * This is called by the interrupt handler */ void usb_handle_transaction(struct usb_xfer_info *info) { enum usb_tok_pid pid = usb_get_xfer_pid(info); struct usbd_ep_state_t *eps = &usb.ep_state[usb_get_xfer_ep(info)]; struct usbd_ep_pipe_state_t *s = &eps->pipe[usb_get_xfer_dir(info)]; switch (pid) { case USB_PID_SETUP: case USB_PID_OUT: /** * If we receive a SETUP transaction, but don't expect * it (callback set to somewhere else), stall the EP. */ if (pid == USB_PID_SETUP && s->callback != usb_handle_control) usb_handle_control_status(1); else usb_rx_next(s); if (pid == USB_PID_SETUP) usb_enable_xfers(); break; case USB_PID_IN: usb_tx_next(s); break; default: break; } }
static void submit_tx(struct usbd_ep_pipe_state_t *s) { /* usb_tx_next() flips the data toggle, so invert this here. */ s->data01 ^= 1; usb_tx_next(s); }
/** * send USB data (IN device transaction) * * So far this function is specialized for EP 0 only. * * Returns: size to be transfered, or -1 on error. */ int usb_tx(struct usbd_ep_pipe_state_t *s, const void *buf, size_t len, size_t reqlen, ep_callback_t cb, void *cb_data) { s->data_buf = (void *)buf; s->transfer_size = len; s->pos = 0; s->callback = cb; s->callback_data = cb_data; if (s->transfer_size > reqlen) s->transfer_size = reqlen; if (s->transfer_size < reqlen && s->transfer_size % s->ep_maxsize == 0) s->short_transfer = 1; else s->short_transfer = 0; /* usb_tx_next() flips the data toggle, so invert this here. */ s->data01 ^= 1; usb_tx_next(s); return (s->transfer_size); }