summaryrefslogtreecommitdiffstats
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.c200
1 files changed, 124 insertions, 76 deletions
diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c
index 58fd877..10b0b9c 100644
--- a/sys/dev/usb/usb_transfer.c
+++ b/sys/dev/usb/usb_transfer.c
@@ -50,45 +50,7 @@ struct usb2_std_packet_size {
uint16_t fixed[4];
};
-/*
- * This table stores the all the allowed packet sizes based on
- * endpoint type and USB speed:
- */
-static const struct usb2_std_packet_size
- usb2_std_packet_size[4][USB_SPEED_MAX] = {
-
- [UE_INTERRUPT] = {
- [USB_SPEED_LOW] = {.range = {0, 8}},
- [USB_SPEED_FULL] = {.range = {0, 64}},
- [USB_SPEED_HIGH] = {.range = {0, 1024}},
- [USB_SPEED_VARIABLE] = {.range = {0, 1024}},
- [USB_SPEED_SUPER] = {.range = {0, 1024}},
- },
-
- [UE_CONTROL] = {
- [USB_SPEED_LOW] = {.fixed = {8, 8, 8, 8}},
- [USB_SPEED_FULL] = {.fixed = {8, 16, 32, 64}},
- [USB_SPEED_HIGH] = {.fixed = {64, 64, 64, 64}},
- [USB_SPEED_VARIABLE] = {.fixed = {512, 512, 512, 512}},
- [USB_SPEED_SUPER] = {.fixed = {512, 512, 512, 512}},
- },
-
- [UE_BULK] = {
- [USB_SPEED_LOW] = {.fixed = {0, 0, 0, 0}}, /* invalid */
- [USB_SPEED_FULL] = {.fixed = {8, 16, 32, 64}},
- [USB_SPEED_HIGH] = {.fixed = {512, 512, 512, 512}},
- [USB_SPEED_VARIABLE] = {.fixed = {512, 512, 1024, 1536}},
- [USB_SPEED_SUPER] = {.fixed = {1024, 1024, 1024, 1024}},
- },
-
- [UE_ISOCHRONOUS] = {
- [USB_SPEED_LOW] = {.fixed = {0, 0, 0, 0}}, /* invalid */
- [USB_SPEED_FULL] = {.range = {0, 1023}},
- [USB_SPEED_HIGH] = {.range = {0, 1024}},
- [USB_SPEED_VARIABLE] = {.range = {0, 3584}},
- [USB_SPEED_SUPER] = {.range = {0, 1024}},
- },
-};
+static usb2_callback_t usb2_request_callback;
static const struct usb2_config usb2_control_ep_cfg[USB_DEFAULT_XFER_MAX] = {
@@ -98,12 +60,10 @@ static const struct usb2_config usb2_control_ep_cfg[USB_DEFAULT_XFER_MAX] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control endpoint */
.direction = UE_DIR_ANY,
- .mh.bufsize = USB_EP0_BUFSIZE, /* bytes */
- .mh.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,},
- .mh.callback = &usb2_do_request_callback,
- .md.bufsize = USB_EP0_BUFSIZE, /* bytes */
- .md.flags = {.proxy_buffer = 1,.short_xfer_ok = 0,},
- .md.callback = &usb2_handle_request_callback,
+ .bufsize = USB_EP0_BUFSIZE, /* bytes */
+ .flags = {.proxy_buffer = 1,},
+ .callback = &usb2_request_callback,
+ .usb_mode = USB_MODE_MAX, /* both modes */
},
/* This transfer is used for generic clear stall only */
@@ -112,10 +72,11 @@ static const struct usb2_config usb2_control_ep_cfg[USB_DEFAULT_XFER_MAX] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request),
- .mh.callback = &usb2_do_clear_stall_callback,
- .mh.timeout = 1000, /* 1 second */
- .mh.interval = 50, /* 50ms */
+ .bufsize = sizeof(struct usb2_device_request),
+ .callback = &usb2_do_clear_stall_callback,
+ .timeout = 1000, /* 1 second */
+ .interval = 50, /* 50ms */
+ .usb_mode = USB_MODE_HOST,
},
};
@@ -131,6 +92,20 @@ static void usb2_callback_wrapper(struct usb2_xfer_queue *);
static void usb2_dma_delay_done_cb(void *);
static void usb2_transfer_start_cb(void *);
static uint8_t usb2_callback_wrapper_sub(struct usb2_xfer *);
+static void usb2_get_std_packet_size(struct usb2_std_packet_size *ptr,
+ uint8_t type, uint8_t usb_speed);
+
+/*------------------------------------------------------------------------*
+ * usb2_request_callback
+ *------------------------------------------------------------------------*/
+static void
+usb2_request_callback(struct usb2_xfer *xfer)
+{
+ if (xfer->flags_int.usb2_mode == USB_MODE_DEVICE)
+ usb2_handle_request_callback(xfer);
+ else
+ usb2_do_request_callback(xfer);
+}
/*------------------------------------------------------------------------*
* usb2_update_max_frame_size
@@ -320,7 +295,7 @@ usb2_transfer_setup_sub(struct usb2_setup_params *parm)
MIN_PKT = 8,
};
struct usb2_xfer *xfer = parm->curr_xfer;
- const struct usb2_config_sub *setup_sub = parm->curr_setup_sub;
+ const struct usb2_config *setup = parm->curr_setup;
struct usb2_endpoint_descriptor *edesc;
struct usb2_std_packet_size std_size;
usb2_frcount_t n_frlengths;
@@ -343,18 +318,18 @@ usb2_transfer_setup_sub(struct usb2_setup_params *parm)
type = (edesc->bmAttributes & UE_XFERTYPE);
- xfer->flags = setup_sub->flags;
- xfer->nframes = setup_sub->frames;
- xfer->timeout = setup_sub->timeout;
- xfer->callback = setup_sub->callback;
- xfer->interval = setup_sub->interval;
+ xfer->flags = setup->flags;
+ xfer->nframes = setup->frames;
+ xfer->timeout = setup->timeout;
+ xfer->callback = setup->callback;
+ xfer->interval = setup->interval;
xfer->endpoint = edesc->bEndpointAddress;
xfer->max_packet_size = UGETW(edesc->wMaxPacketSize);
xfer->max_packet_count = 1;
/* make a shadow copy: */
xfer->flags_int.usb2_mode = parm->udev->flags.usb2_mode;
- parm->bufsize = setup_sub->bufsize;
+ parm->bufsize = setup->bufsize;
if (parm->speed == USB_SPEED_HIGH) {
xfer->max_packet_count += (xfer->max_packet_size >> 11) & 3;
@@ -373,7 +348,7 @@ usb2_transfer_setup_sub(struct usb2_setup_params *parm)
}
/* filter "wMaxPacketSize" according to standard sizes */
- std_size = usb2_std_packet_size[type][parm->speed];
+ usb2_get_std_packet_size(&std_size, type, parm->speed);
if (std_size.range.min || std_size.range.max) {
@@ -779,13 +754,11 @@ usb2_transfer_setup(struct usb2_device *udev,
/* sanity checks */
for (setup = setup_start, n = 0;
setup != setup_end; setup++, n++) {
- if ((setup->mh.bufsize == (usb2_frlength_t)-1) ||
- (setup->md.bufsize == (usb2_frlength_t)-1)) {
+ if (setup->bufsize == (usb2_frlength_t)-1) {
parm.err = USB_ERR_BAD_BUFSIZE;
DPRINTF("invalid bufsize\n");
}
- if ((setup->mh.callback == NULL) &&
- (setup->md.callback == NULL)) {
+ if (setup->callback == NULL) {
parm.err = USB_ERR_NO_CALLBACK;
DPRINTF("no callback\n");
}
@@ -865,14 +838,8 @@ usb2_transfer_setup(struct usb2_device *udev,
for (setup = setup_start, n = 0;
setup != setup_end; setup++, n++) {
- /* select mode specific structure */
- if (udev->flags.usb2_mode == USB_MODE_HOST) {
- parm.curr_setup_sub = &setup->mh;
- } else {
- parm.curr_setup_sub = &setup->md;
- }
/* skip USB transfers without callbacks: */
- if (parm.curr_setup_sub->callback == NULL) {
+ if (setup->callback == NULL) {
continue;
}
/* see if there is a matching endpoint */
@@ -880,18 +847,21 @@ usb2_transfer_setup(struct usb2_device *udev,
ifaces[setup->if_index], setup);
if (!pipe) {
- if (parm.curr_setup_sub->flags.no_pipe_ok) {
+ if (setup->flags.no_pipe_ok)
+ continue;
+ if ((setup->usb_mode != USB_MODE_MAX) &&
+ (setup->usb_mode != udev->flags.usb2_mode))
continue;
- }
parm.err = USB_ERR_NO_PIPE;
goto done;
}
- /* store current setup pointer */
- parm.curr_setup = setup;
/* align data properly */
parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
+ /* store current setup pointer */
+ parm.curr_setup = setup;
+
if (buf) {
/*
* Common initialization of the
@@ -1418,9 +1388,10 @@ usb2_start_hardware(struct usb2_xfer *xfer)
/* set "transferring" flag */
xfer->flags_int.transferring = 1;
+#if USB_HAVE_POWERD
/* increment power reference */
usb2_transfer_power_ref(xfer, 1);
-
+#endif
/*
* Check if the transfer is waiting on a queue, most
* frequently the "done_q":
@@ -1945,9 +1916,10 @@ usb2_callback_wrapper(struct usb2_xfer_queue *pq)
USB_BUS_LOCK(xfer->xroot->bus);
goto done;
}
+#if USB_HAVE_POWERD
/* decrement power reference */
usb2_transfer_power_ref(xfer, -1);
-
+#endif
xfer->flags_int.transferring = 0;
if (xfer->error) {
@@ -2669,8 +2641,9 @@ usb2_clear_data_toggle(struct usb2_device *udev, struct usb2_pipe *pipe)
* .direction = UE_DIR_ANY,
* .interval = 50, //50 milliseconds
* .bufsize = sizeof(struct usb2_device_request),
- * .mh.timeout = 1000, //1.000 seconds
- * .mh.callback = &my_clear_stall_callback, // **
+ * .timeout = 1000, //1.000 seconds
+ * .callback = &my_clear_stall_callback, // **
+ * .usb_mode = USB_MODE_HOST,
* };
*
* ** "my_clear_stall_callback" calls "usb2_clear_stall_callback"
@@ -2749,3 +2722,78 @@ usb2_do_poll(struct usb2_xfer **ppxfer, uint16_t max)
"not supported!\n");
}
}
+
+static void
+usb2_get_std_packet_size(struct usb2_std_packet_size *ptr,
+ uint8_t type, uint8_t usb_speed)
+{
+ static const uint16_t intr_range_max[USB_SPEED_MAX] = {
+ [USB_SPEED_LOW] = 8,
+ [USB_SPEED_FULL] = 64,
+ [USB_SPEED_HIGH] = 1024,
+ [USB_SPEED_VARIABLE] = 1024,
+ [USB_SPEED_SUPER] = 1024,
+ };
+
+ static const uint16_t isoc_range_max[USB_SPEED_MAX] = {
+ [USB_SPEED_LOW] = 0, /* invalid */
+ [USB_SPEED_FULL] = 1023,
+ [USB_SPEED_HIGH] = 1024,
+ [USB_SPEED_VARIABLE] = 3584,
+ [USB_SPEED_SUPER] = 1024,
+ };
+
+ static const uint16_t control_min[USB_SPEED_MAX] = {
+ [USB_SPEED_LOW] = 8,
+ [USB_SPEED_FULL] = 8,
+ [USB_SPEED_HIGH] = 64,
+ [USB_SPEED_VARIABLE] = 512,
+ [USB_SPEED_SUPER] = 512,
+ };
+
+ static const uint16_t bulk_min[USB_SPEED_MAX] = {
+ [USB_SPEED_LOW] = 0, /* not supported */
+ [USB_SPEED_FULL] = 8,
+ [USB_SPEED_HIGH] = 512,
+ [USB_SPEED_VARIABLE] = 512,
+ [USB_SPEED_SUPER] = 1024,
+ };
+
+ uint16_t temp;
+
+ memset(ptr, 0, sizeof(*ptr));
+
+ switch (type) {
+ case UE_INTERRUPT:
+ ptr->range.max = intr_range_max[usb_speed];
+ break;
+ case UE_ISOCHRONOUS:
+ ptr->range.max = isoc_range_max[usb_speed];
+ break;
+ default:
+ if (type == UE_BULK)
+ temp = bulk_min[usb_speed];
+ else /* UE_CONTROL */
+ temp = control_min[usb_speed];
+
+ /* default is fixed */
+ ptr->fixed[0] = temp;
+ ptr->fixed[1] = temp;
+ ptr->fixed[2] = temp;
+ ptr->fixed[3] = temp;
+
+ if (usb_speed == USB_SPEED_FULL) {
+ /* multiple sizes */
+ ptr->fixed[1] = 16;
+ ptr->fixed[2] = 32;
+ ptr->fixed[3] = 64;
+ }
+ if ((usb_speed == USB_SPEED_VARIABLE) &&
+ (type == UE_BULK)) {
+ /* multiple sizes */
+ ptr->fixed[2] = 1024;
+ ptr->fixed[3] = 1536;
+ }
+ break;
+ }
+}
OpenPOWER on IntegriCloud