diff options
Diffstat (limited to 'sys/dev/usb/controller/uss820dci.c')
-rw-r--r-- | sys/dev/usb/controller/uss820dci.c | 62 |
1 files changed, 38 insertions, 24 deletions
diff --git a/sys/dev/usb/controller/uss820dci.c b/sys/dev/usb/controller/uss820dci.c index 8d8e0e4..0b0a074 100644 --- a/sys/dev/usb/controller/uss820dci.c +++ b/sys/dev/usb/controller/uss820dci.c @@ -836,8 +836,8 @@ uss820dci_setup_standard_chain(struct usb2_xfer *xfer) temp.td = NULL; temp.td_next = xfer->td_start[0]; - temp.setup_alt_next = xfer->flags_int.short_frames_ok; temp.offset = 0; + temp.setup_alt_next = xfer->flags_int.short_frames_ok; sc = USS820_DCI_BUS2SC(xfer->xroot->bus); ep_no = (xfer->endpoint & UE_ADDR); @@ -851,6 +851,12 @@ uss820dci_setup_standard_chain(struct usb2_xfer *xfer) temp.len = xfer->frlengths[0]; temp.pc = xfer->frbuffers + 0; temp.short_pkt = temp.len ? 1 : 0; + /* check for last frame */ + if (xfer->nframes == 1) { + /* no STATUS stage yet, SETUP is last */ + if (xfer->flags_int.control_act) + temp.setup_alt_next = 0; + } uss820dci_setup_standard_chain_sub(&temp); } @@ -878,7 +884,13 @@ uss820dci_setup_standard_chain(struct usb2_xfer *xfer) x++; if (x == xfer->nframes) { - temp.setup_alt_next = 0; + if (xfer->flags_int.control_xfr) { + if (xfer->flags_int.control_act) { + temp.setup_alt_next = 0; + } + } else { + temp.setup_alt_next = 0; + } } if (temp.len == 0) { @@ -903,37 +915,39 @@ uss820dci_setup_standard_chain(struct usb2_xfer *xfer) } } - /* always setup a valid "pc" pointer for status and sync */ - temp.pc = xfer->frbuffers + 0; - - /* check if we should append a status stage */ - - if (xfer->flags_int.control_xfr && - !xfer->flags_int.control_act) { + /* check for control transfer */ + if (xfer->flags_int.control_xfr) { uint8_t need_sync; - /* - * Send a DATA1 message and invert the current - * endpoint direction. - */ - if (xfer->endpoint & UE_DIR_IN) { - temp.func = &uss820dci_data_rx; - need_sync = 0; - } else { - temp.func = &uss820dci_data_tx; - need_sync = 1; - } + /* always setup a valid "pc" pointer for status and sync */ + temp.pc = xfer->frbuffers + 0; temp.len = 0; temp.short_pkt = 0; + temp.setup_alt_next = 0; - uss820dci_setup_standard_chain_sub(&temp); - if (need_sync) { - /* we need a SYNC point after TX */ - temp.func = &uss820dci_data_tx_sync; + /* check if we should append a status stage */ + if (!xfer->flags_int.control_act) { + + /* + * Send a DATA1 message and invert the current + * endpoint direction. + */ + if (xfer->endpoint & UE_DIR_IN) { + temp.func = &uss820dci_data_rx; + need_sync = 0; + } else { + temp.func = &uss820dci_data_tx; + need_sync = 1; + } temp.len = 0; temp.short_pkt = 0; uss820dci_setup_standard_chain_sub(&temp); + if (need_sync) { + /* we need a SYNC point after TX */ + temp.func = &uss820dci_data_tx_sync; + uss820dci_setup_standard_chain_sub(&temp); + } } } /* must have at least one frame! */ |