diff options
Diffstat (limited to 'sys/dev/usb/usb_transfer.c')
-rw-r--r-- | sys/dev/usb/usb_transfer.c | 228 |
1 files changed, 195 insertions, 33 deletions
diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c index bad72d4..ae70539 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; + } +} |