aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/usb/usb_transfer.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/usb/usb_transfer.c')
-rw-r--r--sys/dev/usb/usb_transfer.c228
1 files changed, 195 insertions, 33 deletions
diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c
index bad72d4ee617..ae705396554b 100644
--- a/sys/dev/usb/usb_transfer.c
+++ b/sys/dev/usb/usb_transfer.c
@@ -24,9 +24,29 @@
* SUCH DAMAGE.
*/
-#include <dev/usb/usb_mfunc.h>
-#include <dev/usb/usb_error.h>
+#include <sys/stdint.h>
+#include <sys/stddef.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/linker_set.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/sysctl.h>
+#include <sys/sx.h>
+#include <sys/unistd.h>
+#include <sys/callout.h>
+#include <sys/malloc.h>
+#include <sys/priv.h>
+
#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
#define USB_DEBUG_VAR usb_debug
@@ -85,7 +105,7 @@ static const struct usb_config usb_control_ep_cfg[USB_DEFAULT_XFER_MAX] = {
static void usbd_update_max_frame_size(struct usb_xfer *);
static void usbd_transfer_unsetup_sub(struct usb_xfer_root *, uint8_t);
static void usbd_control_transfer_init(struct usb_xfer *);
-static uint8_t usbd_start_hardware_sub(struct usb_xfer *);
+static int usbd_setup_ctrl_transfer(struct usb_xfer *);
static void usb_callback_proc(struct usb_proc_msg *);
static void usbd_callback_ss_done_defer(struct usb_xfer *);
static void usbd_callback_wrapper(struct usb_xfer_queue *);
@@ -99,12 +119,12 @@ static void usbd_get_std_packet_size(struct usb_std_packet_size *ptr,
* usb_request_callback
*------------------------------------------------------------------------*/
static void
-usb_request_callback(struct usb_xfer *xfer)
+usb_request_callback(struct usb_xfer *xfer, usb_error_t error)
{
if (xfer->flags_int.usb_mode == USB_MODE_DEVICE)
- usb_handle_request_callback(xfer);
+ usb_handle_request_callback(xfer, error);
else
- usbd_do_request_callback(xfer);
+ usbd_do_request_callback(xfer, error);
}
/*------------------------------------------------------------------------*
@@ -575,17 +595,16 @@ usbd_transfer_setup_sub(struct usb_setup_params *parm)
xfer->max_data_length -= REQ_SIZE;
}
/* setup "frlengths" */
-
xfer->frlengths = parm->xfer_length_ptr;
-
parm->xfer_length_ptr += n_frlengths;
/* setup "frbuffers" */
-
xfer->frbuffers = parm->xfer_page_cache_ptr;
-
parm->xfer_page_cache_ptr += n_frbuffers;
+ /* initialize max frame count */
+ xfer->max_frame_count = xfer->nframes;
+
/*
* check if we need to setup
* a local buffer:
@@ -601,10 +620,10 @@ usbd_transfer_setup_sub(struct usb_setup_params *parm)
xfer->local_buffer =
USB_ADD_BYTES(parm->buf, parm->size[0]);
- usbd_set_frame_offset(xfer, 0, 0);
+ usbd_xfer_set_frame_offset(xfer, 0, 0);
if ((type == UE_CONTROL) && (n_frbuffers > 1)) {
- usbd_set_frame_offset(xfer, REQ_SIZE, 1);
+ usbd_xfer_set_frame_offset(xfer, REQ_SIZE, 1);
}
}
parm->size[0] += parm->bufsize;
@@ -662,9 +681,6 @@ usbd_transfer_setup_sub(struct usb_setup_params *parm)
parm->err = USB_ERR_INVAL;
goto done;
}
- /* initialize max frame count */
-
- xfer->max_frame_count = xfer->nframes;
/* initialize frame buffers */
@@ -1209,7 +1225,7 @@ usbd_control_transfer_init(struct usb_xfer *xfer)
}
/*------------------------------------------------------------------------*
- * usbd_start_hardware_sub
+ * usbd_setup_ctrl_transfer
*
* This function handles initialisation of control transfers. Control
* transfers are special in that regard that they can both transmit
@@ -1219,8 +1235,8 @@ usbd_control_transfer_init(struct usb_xfer *xfer)
* 0: Success
* Else: Failure
*------------------------------------------------------------------------*/
-static uint8_t
-usbd_start_hardware_sub(struct usb_xfer *xfer)
+static int
+usbd_setup_ctrl_transfer(struct usb_xfer *xfer)
{
usb_frlength_t len;
@@ -1495,7 +1511,7 @@ usbd_transfer_submit(struct usb_xfer *xfer)
if (xfer->flags_int.control_xfr) {
- if (usbd_start_hardware_sub(xfer)) {
+ if (usbd_setup_ctrl_transfer(xfer)) {
USB_BUS_LOCK(bus);
usbd_transfer_done(xfer, USB_ERR_STALLED);
USB_BUS_UNLOCK(bus);
@@ -1780,8 +1796,24 @@ usbd_transfer_drain(struct usb_xfer *xfer)
USB_XFER_UNLOCK(xfer);
}
+struct usb_page_cache *
+usbd_xfer_get_frame(struct usb_xfer *xfer, usb_frcount_t frindex)
+{
+ KASSERT(frindex < xfer->max_frame_count, ("frame index overflow"));
+
+ return (&xfer->frbuffers[frindex]);
+}
+
+usb_frlength_t
+usbd_xfer_get_frame_len(struct usb_xfer *xfer, usb_frcount_t frindex)
+{
+ KASSERT(frindex < xfer->max_frame_count, ("frame index overflow"));
+
+ return (xfer->frlengths[frindex]);
+}
+
/*------------------------------------------------------------------------*
- * usbd_set_frame_data
+ * usbd_xfer_set_frame_data
*
* This function sets the pointer of the buffer that should
* loaded directly into DMA for the given USB frame. Passing "ptr"
@@ -1789,30 +1821,106 @@ usbd_transfer_drain(struct usb_xfer *xfer)
* than zero gives undefined results!
*------------------------------------------------------------------------*/
void
-usbd_set_frame_data(struct usb_xfer *xfer, void *ptr, usb_frcount_t frindex)
+usbd_xfer_set_frame_data(struct usb_xfer *xfer, usb_frcount_t frindex,
+ void *ptr, usb_frlength_t len)
{
+ KASSERT(frindex < xfer->max_frame_count, ("frame index overflow"));
+
/* set virtual address to load and length */
xfer->frbuffers[frindex].buffer = ptr;
+ usbd_xfer_set_frame_len(xfer, frindex, len);
+}
+
+void
+usbd_xfer_get_frame_data(struct usb_xfer *xfer, usb_frcount_t frindex,
+ void **ptr, int *len)
+{
+ KASSERT(frindex < xfer->max_frame_count, ("frame index overflow"));
+
+ if (ptr != NULL)
+ *ptr = xfer->frbuffers[frindex].buffer;
+ if (len != NULL)
+ *len = xfer->frlengths[frindex];
+}
+
+void
+usbd_xfer_status(struct usb_xfer *xfer, int *actlen, int *sumlen, int *aframes,
+ int *nframes)
+{
+ if (actlen != NULL)
+ *actlen = xfer->actlen;
+ if (sumlen != NULL)
+ *sumlen = xfer->sumlen;
+ if (aframes != NULL)
+ *aframes = xfer->aframes;
+ if (nframes != NULL)
+ *nframes = xfer->nframes;
}
/*------------------------------------------------------------------------*
- * usbd_set_frame_offset
+ * usbd_xfer_set_frame_offset
*
* This function sets the frame data buffer offset relative to the beginning
* of the USB DMA buffer allocated for this USB transfer.
*------------------------------------------------------------------------*/
void
-usbd_set_frame_offset(struct usb_xfer *xfer, usb_frlength_t offset,
+usbd_xfer_set_frame_offset(struct usb_xfer *xfer, usb_frlength_t offset,
usb_frcount_t frindex)
{
- USB_ASSERT(!xfer->flags.ext_buffer, ("Cannot offset data frame "
+ KASSERT(!xfer->flags.ext_buffer, ("Cannot offset data frame "
"when the USB buffer is external!\n"));
+ KASSERT(frindex < xfer->max_frame_count, ("frame index overflow"));
/* set virtual address to load */
xfer->frbuffers[frindex].buffer =
USB_ADD_BYTES(xfer->local_buffer, offset);
}
+void
+usbd_xfer_set_interval(struct usb_xfer *xfer, int i)
+{
+ xfer->interval = i;
+}
+
+void
+usbd_xfer_set_timeout(struct usb_xfer *xfer, int t)
+{
+ xfer->timeout = t;
+}
+
+void
+usbd_xfer_set_frames(struct usb_xfer *xfer, usb_frcount_t n)
+{
+ xfer->nframes = n;
+}
+
+usb_frcount_t
+usbd_xfer_max_frames(struct usb_xfer *xfer)
+{
+ return (xfer->max_frame_count);
+}
+
+usb_frlength_t
+usbd_xfer_max_len(struct usb_xfer *xfer)
+{
+ return (xfer->max_data_length);
+}
+
+usb_frlength_t
+usbd_xfer_max_framelen(struct usb_xfer *xfer)
+{
+ return (xfer->max_frame_size);
+}
+
+void
+usbd_xfer_set_frame_len(struct usb_xfer *xfer, usb_frcount_t frindex,
+ usb_frlength_t len)
+{
+ KASSERT(frindex < xfer->max_frame_count, ("frame index overflow"));
+
+ xfer->frlengths[frindex] = len;
+}
+
/*------------------------------------------------------------------------*
* usb_callback_proc - factored out code
*
@@ -1963,7 +2071,7 @@ usbd_callback_wrapper(struct usb_xfer_queue *pq)
}
/* call processing routine */
- (xfer->callback) (xfer);
+ (xfer->callback) (xfer, xfer->error);
/* pickup the USB mutex again */
USB_BUS_LOCK(info->bus);
@@ -2157,13 +2265,13 @@ usbd_transfer_start_cb(void *arg)
}
/*------------------------------------------------------------------------*
- * usbd_transfer_set_stall
+ * usbd_xfer_set_stall
*
* This function is used to set the stall flag outside the
* callback. This function is NULL safe.
*------------------------------------------------------------------------*/
void
-usbd_transfer_set_stall(struct usb_xfer *xfer)
+usbd_xfer_set_stall(struct usb_xfer *xfer)
{
if (xfer == NULL) {
/* tearing down */
@@ -2173,12 +2281,16 @@ usbd_transfer_set_stall(struct usb_xfer *xfer)
/* avoid any races by locking the USB mutex */
USB_BUS_LOCK(xfer->xroot->bus);
-
xfer->flags.stall_pipe = 1;
-
USB_BUS_UNLOCK(xfer->xroot->bus);
}
+int
+usbd_xfer_is_stalled(struct usb_xfer *xfer)
+{
+ return (xfer->endpoint->is_stalled);
+}
+
/*------------------------------------------------------------------------*
* usbd_transfer_clear_stall
*
@@ -2411,7 +2523,7 @@ usbd_callback_wrapper_sub(struct usb_xfer *xfer)
* of frames transferred, "xfer->aframes":
*/
for (; x < xfer->nframes; x++) {
- xfer->frlengths[x] = 0;
+ usbd_xfer_set_frame_len(xfer, x, 0);
}
/* check actual length */
@@ -2425,7 +2537,7 @@ usbd_callback_wrapper_sub(struct usb_xfer *xfer)
xfer->actlen = xfer->sumlen;
}
}
- DPRINTFN(6, "xfer=%p endpoint=%p sts=%d alen=%d, slen=%d, afrm=%d, nfrm=%d\n",
+ DPRINTFN(1, "xfer=%p endpoint=%p sts=%d alen=%d, slen=%d, afrm=%d, nfrm=%d\n",
xfer, xfer->endpoint, xfer->error, xfer->actlen, xfer->sumlen,
xfer->aframes, xfer->nframes);
@@ -2734,13 +2846,13 @@ usbd_clear_stall_callback(struct usb_xfer *xfer1,
}
void
-usbd_do_poll(struct usb_xfer **ppxfer, uint16_t max)
+usbd_transfer_poll(struct usb_xfer **ppxfer, uint16_t max)
{
static uint8_t once = 0;
/* polling is currently not supported */
if (!once) {
once = 1;
- printf("usbd_do_poll: USB polling is "
+ printf("usbd_transfer_poll: USB polling is "
"not supported!\n");
}
}
@@ -2819,3 +2931,53 @@ usbd_get_std_packet_size(struct usb_std_packet_size *ptr,
break;
}
}
+
+void *
+usbd_xfer_softc(struct usb_xfer *xfer)
+{
+ return (xfer->priv_sc);
+}
+
+void *
+usbd_xfer_get_priv(struct usb_xfer *xfer)
+{
+ return (xfer->priv_fifo);
+}
+
+void
+usbd_xfer_set_priv(struct usb_xfer *xfer, void *ptr)
+{
+ xfer->priv_fifo = ptr;
+}
+
+uint8_t
+usbd_xfer_state(struct usb_xfer *xfer)
+{
+ return (xfer->usb_state);
+}
+
+void
+usbd_xfer_set_flag(struct usb_xfer *xfer, int flag)
+{
+ switch (flag) {
+ case USB_FORCE_SHORT_XFER:
+ xfer->flags.force_short_xfer = 1;
+ break;
+ case USB_SHORT_XFER_OK:
+ xfer->flags.short_xfer_ok = 1;
+ break;
+ }
+}
+
+void
+usbd_xfer_clr_flag(struct usb_xfer *xfer, int flag)
+{
+ switch (flag) {
+ case USB_FORCE_SHORT_XFER:
+ xfer->flags.force_short_xfer = 0;
+ break;
+ case USB_SHORT_XFER_OK:
+ xfer->flags.short_xfer_ok = 0;
+ break;
+ }
+}