summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/boot/usb/bsd_global.h2
-rw-r--r--sys/dev/usb/template/usb_template.c65
-rw-r--r--sys/dev/usb/usb_bus.h10
-rw-r--r--sys/dev/usb/usb_controller.h45
-rw-r--r--sys/dev/usb/usb_device.c85
-rw-r--r--sys/dev/usb/usb_device.h73
-rw-r--r--sys/dev/usb/usb_generic.c11
-rw-r--r--sys/dev/usb/usb_handle_request.c9
-rw-r--r--sys/dev/usb/usb_msctest.c9
-rw-r--r--sys/dev/usb/usb_transfer.c167
-rw-r--r--sys/dev/usb/usb_util.c22
11 files changed, 269 insertions, 229 deletions
diff --git a/sys/boot/usb/bsd_global.h b/sys/boot/usb/bsd_global.h
index 80cbd63..2fb0dcc 100644
--- a/sys/boot/usb/bsd_global.h
+++ b/sys/boot/usb/bsd_global.h
@@ -39,6 +39,7 @@
#include <dev/usb/usb_process.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_dynamic.h>
+#include <dev/usb/usb_transfer.h>
#include <dev/usb/usb_device.h>
#include <dev/usb/usb_hub.h>
#include <dev/usb/usb_controller.h>
@@ -52,7 +53,6 @@
#include <dev/usb/usb_pf.h>
#include <dev/usb/usb_request.h>
#include <dev/usb/usb_util.h>
-#include <dev/usb/usb_transfer.h>
#include <dev/usb/usb_compat_linux.h>
#include <dev/usb/usbhid.h>
#include <dev/usb/usb_ioctl.h>
diff --git a/sys/dev/usb/template/usb_template.c b/sys/dev/usb/template/usb_template.c
index 36c11d9..b815161 100644
--- a/sys/dev/usb/template/usb_template.c
+++ b/sys/dev/usb/template/usb_template.c
@@ -849,20 +849,20 @@ usb_hw_ep_resolve(struct usb_device *udev,
struct usb_device_descriptor *dd;
uint16_t mps;
- if (desc == NULL) {
+ if (desc == NULL)
return (USB_ERR_INVAL);
- }
+
/* get bus methods */
methods = udev->bus->methods;
- if (methods->get_hw_ep_profile == NULL) {
+ if (methods->get_hw_ep_profile == NULL)
return (USB_ERR_INVAL);
- }
+
if (desc->bDescriptorType == UDESC_DEVICE) {
- if (desc->bLength < sizeof(*dd)) {
+ if (desc->bLength < sizeof(*dd))
return (USB_ERR_INVAL);
- }
+
dd = (void *)desc;
/* get HW control endpoint 0 profile */
@@ -909,13 +909,12 @@ usb_hw_ep_resolve(struct usb_device *udev,
}
return (0); /* success */
}
- if (desc->bDescriptorType != UDESC_CONFIG) {
+ if (desc->bDescriptorType != UDESC_CONFIG)
return (USB_ERR_INVAL);
- }
- if (desc->bLength < sizeof(*(ues->cd))) {
+ if (desc->bLength < sizeof(*(ues->cd)))
return (USB_ERR_INVAL);
- }
- ues = udev->bus->scratch[0].hw_ep_scratch;
+
+ ues = udev->scratch.hw_ep_scratch;
memset(ues, 0, sizeof(*ues));
@@ -1236,13 +1235,18 @@ usb_temp_setup(struct usb_device *udev,
{
struct usb_temp_setup *uts;
void *buf;
+ usb_error_t error;
uint8_t n;
+ uint8_t do_unlock;
- if (tdd == NULL) {
- /* be NULL safe */
+ /* be NULL safe */
+ if (tdd == NULL)
return (0);
- }
- uts = udev->bus->scratch[0].temp_setup;
+
+ /* Protect scratch area */
+ do_unlock = usbd_enum_lock(udev);
+
+ uts = udev->scratch.temp_setup;
memset(uts, 0, sizeof(*uts));
@@ -1255,17 +1259,24 @@ usb_temp_setup(struct usb_device *udev,
if (uts->err) {
/* some error happened */
- return (uts->err);
+ goto done;
}
/* sanity check */
if (uts->size == 0) {
- return (USB_ERR_INVAL);
+ uts->err = USB_ERR_INVAL;
+ goto done;
}
/* allocate zeroed memory */
uts->buf = malloc(uts->size, M_USB, M_WAITOK | M_ZERO);
+ /*
+ * Allow malloc() to return NULL regardless of M_WAITOK flag.
+ * This helps when porting the software to non-FreeBSD
+ * systems.
+ */
if (uts->buf == NULL) {
/* could not allocate memory */
- return (USB_ERR_NOMEM);
+ uts->err = USB_ERR_NOMEM;
+ goto done;
}
/* second pass */
@@ -1280,7 +1291,7 @@ usb_temp_setup(struct usb_device *udev,
if (uts->err) {
/* some error happened during second pass */
- goto error;
+ goto done;
}
/*
* Resolve all endpoint addresses !
@@ -1291,7 +1302,7 @@ usb_temp_setup(struct usb_device *udev,
DPRINTFN(0, "Could not resolve endpoints for "
"Device Descriptor, error = %s\n",
usbd_errstr(uts->err));
- goto error;
+ goto done;
}
for (n = 0;; n++) {
@@ -1304,14 +1315,16 @@ usb_temp_setup(struct usb_device *udev,
DPRINTFN(0, "Could not resolve endpoints for "
"Config Descriptor %u, error = %s\n", n,
usbd_errstr(uts->err));
- goto error;
+ goto done;
}
}
- return (uts->err);
-
-error:
- usb_temp_unsetup(udev);
- return (uts->err);
+done:
+ error = uts->err;
+ if (error)
+ usb_temp_unsetup(udev);
+ if (do_unlock)
+ usbd_enum_unlock(udev);
+ return (error);
}
/*------------------------------------------------------------------------*
diff --git a/sys/dev/usb/usb_bus.h b/sys/dev/usb/usb_bus.h
index dea15f8..2898eee 100644
--- a/sys/dev/usb/usb_bus.h
+++ b/sys/dev/usb/usb_bus.h
@@ -113,16 +113,6 @@ struct usb_bus {
uint8_t devices_max; /* maximum number of USB devices */
uint8_t do_probe; /* set if USB should be re-probed */
uint8_t no_explore; /* don't explore USB ports */
-
- /*
- * The scratch area can only be used inside the explore thread
- * belonging to the give serial bus.
- */
- union {
- struct usb_hw_ep_scratch hw_ep_scratch[1];
- struct usb_temp_setup temp_setup[1];
- uint8_t data[255];
- } scratch[1];
};
#endif /* _USB_BUS_H_ */
diff --git a/sys/dev/usb/usb_controller.h b/sys/dev/usb/usb_controller.h
index 6c14454..3ee6f04 100644
--- a/sys/dev/usb/usb_controller.h
+++ b/sys/dev/usb/usb_controller.h
@@ -40,7 +40,6 @@ struct usb_page_cache;
struct usb_setup_params;
struct usb_hw_ep_profile;
struct usb_fs_isoc_schedule;
-struct usb_config_descriptor;
struct usb_endpoint_descriptor;
/* typedefs */
@@ -186,50 +185,6 @@ struct usb_hw_ep_profile {
uint8_t support_out:1; /* OUT-token is supported */
};
-/*
- * The following structure is used when trying to allocate hardware
- * endpoints for an USB configuration in USB device side mode.
- */
-struct usb_hw_ep_scratch_sub {
- const struct usb_hw_ep_profile *pf;
- uint16_t max_frame_size;
- uint8_t hw_endpoint_out;
- uint8_t hw_endpoint_in;
- uint8_t needs_ep_type;
- uint8_t needs_in:1;
- uint8_t needs_out:1;
-};
-
-/*
- * The following structure is used when trying to allocate hardware
- * endpoints for an USB configuration in USB device side mode.
- */
-struct usb_hw_ep_scratch {
- struct usb_hw_ep_scratch_sub ep[USB_EP_MAX];
- struct usb_hw_ep_scratch_sub *ep_max;
- struct usb_config_descriptor *cd;
- struct usb_device *udev;
- struct usb_bus_methods *methods;
- uint8_t bmOutAlloc[(USB_EP_MAX + 15) / 16];
- uint8_t bmInAlloc[(USB_EP_MAX + 15) / 16];
-};
-
-/*
- * The following structure is used when generating USB descriptors
- * from USB templates.
- */
-struct usb_temp_setup {
- void *buf;
- usb_size_t size;
- enum usb_dev_speed usb_speed;
- uint8_t self_powered;
- uint8_t bNumEndpoints;
- uint8_t bInterfaceNumber;
- uint8_t bAlternateSetting;
- uint8_t bConfigurationValue;
- usb_error_t err;
-};
-
/* prototypes */
void usb_bus_mem_flush_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb);
diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c
index a9aab53..fdc734c 100644
--- a/sys/dev/usb/usb_device.c
+++ b/sys/dev/usb/usb_device.c
@@ -460,13 +460,8 @@ usb_unconfigure(struct usb_device *udev, uint8_t flag)
{
uint8_t do_unlock;
- /* automatic locking */
- if (usbd_enum_is_locked(udev)) {
- do_unlock = 0;
- } else {
- do_unlock = 1;
- usbd_enum_lock(udev);
- }
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
/* detach all interface drivers */
usb_detach_device(udev, USB_IFACE_INDEX_ANY, flag);
@@ -529,13 +524,8 @@ usbd_set_config_index(struct usb_device *udev, uint8_t index)
DPRINTFN(6, "udev=%p index=%d\n", udev, index);
- /* automatic locking */
- if (usbd_enum_is_locked(udev)) {
- do_unlock = 0;
- } else {
- do_unlock = 1;
- usbd_enum_lock(udev);
- }
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
usb_unconfigure(udev, 0);
@@ -888,13 +878,9 @@ usbd_set_alt_interface_index(struct usb_device *udev,
usb_error_t err;
uint8_t do_unlock;
- /* automatic locking */
- if (usbd_enum_is_locked(udev)) {
- do_unlock = 0;
- } else {
- do_unlock = 1;
- usbd_enum_lock(udev);
- }
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
+
if (iface == NULL) {
err = USB_ERR_INVAL;
goto done;
@@ -931,7 +917,6 @@ usbd_set_alt_interface_index(struct usb_device *udev,
done:
if (do_unlock)
usbd_enum_unlock(udev);
-
return (err);
}
@@ -1310,13 +1295,8 @@ usb_probe_and_attach(struct usb_device *udev, uint8_t iface_index)
DPRINTF("udev == NULL\n");
return (USB_ERR_INVAL);
}
- /* automatic locking */
- if (usbd_enum_is_locked(udev)) {
- do_unlock = 0;
- } else {
- do_unlock = 1;
- usbd_enum_lock(udev);
- }
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
if (udev->curr_config_index == USB_UNCONFIG_INDEX) {
/* do nothing - no configuration has been set */
@@ -1403,7 +1383,6 @@ usb_probe_and_attach(struct usb_device *udev, uint8_t iface_index)
done:
if (do_unlock)
usbd_enum_unlock(udev);
-
return (0);
}
@@ -1532,6 +1511,7 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus,
uint8_t config_index;
uint8_t config_quirk;
uint8_t set_config_failed;
+ uint8_t do_unlock;
DPRINTF("parent_dev=%p, bus=%p, parent_hub=%p, depth=%u, "
"port_index=%u, port_no=%u, speed=%u, usb_mode=%u\n",
@@ -1750,7 +1730,11 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus,
* device descriptor. If no strings are present there we
* simply disable all USB strings.
*/
- scratch_ptr = udev->bus->scratch[0].data;
+
+ /* Protect scratch area */
+ do_unlock = usbd_enum_lock(udev);
+
+ scratch_ptr = udev->scratch.data;
if (udev->ddesc.iManufacturer ||
udev->ddesc.iProduct ||
@@ -1775,7 +1759,7 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus,
mask = usb_lang_mask;
/* align length correctly */
- scratch_ptr[0] &= ~1;
+ scratch_ptr[0] &= ~1U;
/* fix compiler warning */
langid = 0;
@@ -1796,6 +1780,9 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus,
udev->langid = langid;
}
+ if (do_unlock)
+ usbd_enum_unlock(udev);
+
/* assume 100mA bus powered for now. Changed when configured. */
udev->power = USB_MIN_POWER;
/* fetch the vendor and product strings from the device */
@@ -2295,9 +2282,13 @@ usbd_set_device_strings(struct usb_device *udev)
size_t temp_size;
uint16_t vendor_id;
uint16_t product_id;
+ uint8_t do_unlock;
- temp_ptr = (char *)udev->bus->scratch[0].data;
- temp_size = sizeof(udev->bus->scratch[0].data);
+ /* Protect scratch area */
+ do_unlock = usbd_enum_lock(udev);
+
+ temp_ptr = (char *)udev->scratch.data;
+ temp_size = sizeof(udev->scratch.data);
vendor_id = UGETW(udd->idVendor);
product_id = UGETW(udd->idProduct);
@@ -2352,6 +2343,9 @@ usbd_set_device_strings(struct usb_device *udev)
snprintf(temp_ptr, temp_size, "product 0x%04x", product_id);
udev->product = strdup(temp_ptr, M_USB);
}
+
+ if (do_unlock)
+ usbd_enum_unlock(udev);
}
/*
@@ -2664,11 +2658,17 @@ usbd_device_attached(struct usb_device *udev)
return (udev->state > USB_STATE_DETACHED);
}
-/* The following function locks enumerating the given USB device. */
-
-void
+/*
+ * The following function locks enumerating the given USB device. If
+ * the lock is already grabbed this function returns zero. Else a
+ * non-zero value is returned.
+ */
+uint8_t
usbd_enum_lock(struct usb_device *udev)
{
+ if (sx_xlocked(&udev->enum_sx))
+ return (0);
+
sx_xlock(&udev->enum_sx);
sx_xlock(&udev->sr_sx);
/*
@@ -2677,6 +2677,7 @@ usbd_enum_lock(struct usb_device *udev)
* locked multiple times.
*/
mtx_lock(&Giant);
+ return (1);
}
/* The following function unlocks enumerating the given USB device. */
@@ -2783,13 +2784,8 @@ usbd_set_endpoint_mode(struct usb_device *udev, struct usb_endpoint *ep,
usb_error_t error;
uint8_t do_unlock;
- /* automatic locking */
- if (usbd_enum_is_locked(udev)) {
- do_unlock = 0;
- } else {
- do_unlock = 1;
- usbd_enum_lock(udev);
- }
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
if (udev->bus->methods->set_endpoint_mode != NULL) {
error = (udev->bus->methods->set_endpoint_mode) (
@@ -2805,7 +2801,6 @@ usbd_set_endpoint_mode(struct usb_device *udev, struct usb_endpoint *ep,
if (do_unlock)
usbd_enum_unlock(udev);
-
return (error);
}
diff --git a/sys/dev/usb/usb_device.h b/sys/dev/usb/usb_device.h
index 4eaadc7..22a4652 100644
--- a/sys/dev/usb/usb_device.h
+++ b/sys/dev/usb/usb_device.h
@@ -27,9 +27,18 @@
#ifndef _USB_DEVICE_H_
#define _USB_DEVICE_H_
-struct usb_symlink; /* UGEN */
+#ifndef USB_GLOBAL_INCLUDE_FILE
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_transfer.h>
+#endif
+
+struct usb_bus_methods;
+struct usb_config_descriptor;
struct usb_device; /* linux compat */
struct usb_fs_privdata;
+struct usb_hw_ep_profile;
+struct usb_symlink; /* UGEN */
#define USB_CTRL_XFER_MAX 2
@@ -108,6 +117,64 @@ struct usb_power_save {
};
/*
+ * The following structure is used when trying to allocate hardware
+ * endpoints for an USB configuration in USB device side mode.
+ */
+struct usb_hw_ep_scratch_sub {
+ const struct usb_hw_ep_profile *pf;
+ uint16_t max_frame_size;
+ uint8_t hw_endpoint_out;
+ uint8_t hw_endpoint_in;
+ uint8_t needs_ep_type;
+ uint8_t needs_in:1;
+ uint8_t needs_out:1;
+};
+
+/*
+ * The following structure is used when trying to allocate hardware
+ * endpoints for an USB configuration in USB device side mode.
+ */
+struct usb_hw_ep_scratch {
+ struct usb_hw_ep_scratch_sub ep[USB_EP_MAX];
+ struct usb_hw_ep_scratch_sub *ep_max;
+ struct usb_config_descriptor *cd;
+ struct usb_device *udev;
+ struct usb_bus_methods *methods;
+ uint8_t bmOutAlloc[(USB_EP_MAX + 15) / 16];
+ uint8_t bmInAlloc[(USB_EP_MAX + 15) / 16];
+};
+
+/*
+ * The following structure is used when generating USB descriptors
+ * from USB templates.
+ */
+struct usb_temp_setup {
+ void *buf;
+ usb_size_t size;
+ enum usb_dev_speed usb_speed;
+ uint8_t self_powered;
+ uint8_t bNumEndpoints;
+ uint8_t bInterfaceNumber;
+ uint8_t bAlternateSetting;
+ uint8_t bConfigurationValue;
+ usb_error_t err;
+};
+
+/*
+ * The scratch area for USB devices. Access to this structure is
+ * protected by the enumeration SX lock.
+ */
+union usb_device_scratch {
+ struct usb_hw_ep_scratch hw_ep_scratch[1];
+ struct usb_temp_setup temp_setup[1];
+ struct {
+ struct usb_xfer dummy;
+ struct usb_setup_params parm;
+ } xfer_setup[1];
+ uint8_t data[255];
+};
+
+/*
* The following structure defines an USB device. There exists one of
* these structures for every USB device.
*/
@@ -191,6 +258,8 @@ struct usb_device {
#endif
uint32_t clear_stall_errors; /* number of clear-stall failures */
+
+ union usb_device_scratch scratch;
};
/* globals */
@@ -227,7 +296,7 @@ struct usb_endpoint *usb_endpoint_foreach(struct usb_device *udev, struct usb_en
void usb_set_device_state(struct usb_device *, enum usb_dev_state);
enum usb_dev_state usb_get_device_state(struct usb_device *);
-void usbd_enum_lock(struct usb_device *);
+uint8_t usbd_enum_lock(struct usb_device *);
void usbd_enum_unlock(struct usb_device *);
void usbd_sr_lock(struct usb_device *);
void usbd_sr_unlock(struct usb_device *);
diff --git a/sys/dev/usb/usb_generic.c b/sys/dev/usb/usb_generic.c
index 13f5bd6..34b7778 100644
--- a/sys/dev/usb/usb_generic.c
+++ b/sys/dev/usb/usb_generic.c
@@ -719,13 +719,20 @@ ugen_get_cdesc(struct usb_fifo *f, struct usb_gen_descriptor *ugd)
return (error);
}
+/*
+ * This function is called having the enumeration SX locked which
+ * protects the scratch area used.
+ */
static int
ugen_get_sdesc(struct usb_fifo *f, struct usb_gen_descriptor *ugd)
{
- void *ptr = f->udev->bus->scratch[0].data;
- uint16_t size = sizeof(f->udev->bus->scratch[0].data);
+ void *ptr;
+ uint16_t size;
int error;
+ ptr = f->udev->scratch.data;
+ size = sizeof(f->udev->scratch.data);
+
if (usbd_req_get_string_desc(f->udev, NULL, ptr,
size, ugd->ugd_lang_id, ugd->ugd_string_index)) {
error = EINVAL;
diff --git a/sys/dev/usb/usb_handle_request.c b/sys/dev/usb/usb_handle_request.c
index 13fff91..a775d67 100644
--- a/sys/dev/usb/usb_handle_request.c
+++ b/sys/dev/usb/usb_handle_request.c
@@ -191,13 +191,8 @@ usb_check_alt_setting(struct usb_device *udev,
uint8_t do_unlock;
usb_error_t err = 0;
- /* automatic locking */
- if (usbd_enum_is_locked(udev)) {
- do_unlock = 0;
- } else {
- do_unlock = 1;
- usbd_enum_lock(udev);
- }
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
if (alt_index >= usbd_get_no_alts(udev->cdesc, iface->idesc))
err = USB_ERR_INVAL;
diff --git a/sys/dev/usb/usb_msctest.c b/sys/dev/usb/usb_msctest.c
index a1bc5fc..1f0598a 100644
--- a/sys/dev/usb/usb_msctest.c
+++ b/sys/dev/usb/usb_msctest.c
@@ -505,13 +505,8 @@ bbb_attach(struct usb_device *udev, uint8_t iface_index)
usb_error_t err;
uint8_t do_unlock;
- /* automatic locking */
- if (usbd_enum_is_locked(udev)) {
- do_unlock = 0;
- } else {
- do_unlock = 1;
- usbd_enum_lock(udev);
- }
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
/*
* Make sure any driver which is hooked up to this interface,
diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c
index edcc596..f2acf70 100644
--- a/sys/dev/usb/usb_transfer.c
+++ b/sys/dev/usb/usb_transfer.c
@@ -22,7 +22,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- */
+ */
#ifdef USB_GLOBAL_INCLUDE_FILE
#include USB_GLOBAL_INCLUDE_FILE
@@ -855,20 +855,17 @@ usbd_transfer_setup(struct usb_device *udev,
const struct usb_config *setup_start, uint16_t n_setup,
void *priv_sc, struct mtx *xfer_mtx)
{
- struct usb_xfer dummy;
- struct usb_setup_params parm;
const struct usb_config *setup_end = setup_start + n_setup;
const struct usb_config *setup;
+ struct usb_setup_params *parm;
struct usb_endpoint *ep;
struct usb_xfer_root *info;
struct usb_xfer *xfer;
void *buf = NULL;
+ usb_error_t error = 0;
uint16_t n;
uint16_t refcount;
-
- parm.err = 0;
- refcount = 0;
- info = NULL;
+ uint8_t do_unlock;
WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
"usbd_transfer_setup can sleep!");
@@ -887,31 +884,40 @@ usbd_transfer_setup(struct usb_device *udev,
DPRINTFN(6, "using global lock\n");
xfer_mtx = &Giant;
}
- /* sanity checks */
+
+ /* more sanity checks */
+
for (setup = setup_start, n = 0;
setup != setup_end; setup++, n++) {
if (setup->bufsize == (usb_frlength_t)-1) {
- parm.err = USB_ERR_BAD_BUFSIZE;
+ error = USB_ERR_BAD_BUFSIZE;
DPRINTF("invalid bufsize\n");
}
if (setup->callback == NULL) {
- parm.err = USB_ERR_NO_CALLBACK;
+ error = USB_ERR_NO_CALLBACK;
DPRINTF("no callback\n");
}
ppxfer[n] = NULL;
}
- if (parm.err) {
- goto done;
- }
- memset(&parm, 0, sizeof(parm));
+ if (error)
+ return (error);
- parm.udev = udev;
- parm.speed = usbd_get_speed(udev);
- parm.hc_max_packet_count = 1;
+ /* Protect scratch area */
+ do_unlock = usbd_enum_lock(udev);
- if (parm.speed >= USB_SPEED_MAX) {
- parm.err = USB_ERR_INVAL;
+ refcount = 0;
+ info = NULL;
+
+ parm = &udev->scratch.xfer_setup[0].parm;
+ memset(parm, 0, sizeof(*parm));
+
+ parm->udev = udev;
+ parm->speed = usbd_get_speed(udev);
+ parm->hc_max_packet_count = 1;
+
+ if (parm->speed >= USB_SPEED_MAX) {
+ parm->err = USB_ERR_INVAL;
goto done;
}
/* setup all transfers */
@@ -926,22 +932,22 @@ usbd_transfer_setup(struct usb_device *udev,
info = USB_ADD_BYTES(buf, 0);
info->memory_base = buf;
- info->memory_size = parm.size[0];
+ info->memory_size = parm->size[0];
#if USB_HAVE_BUSDMA
- info->dma_page_cache_start = USB_ADD_BYTES(buf, parm.size[4]);
- info->dma_page_cache_end = USB_ADD_BYTES(buf, parm.size[5]);
+ info->dma_page_cache_start = USB_ADD_BYTES(buf, parm->size[4]);
+ info->dma_page_cache_end = USB_ADD_BYTES(buf, parm->size[5]);
#endif
- info->xfer_page_cache_start = USB_ADD_BYTES(buf, parm.size[5]);
- info->xfer_page_cache_end = USB_ADD_BYTES(buf, parm.size[2]);
+ info->xfer_page_cache_start = USB_ADD_BYTES(buf, parm->size[5]);
+ info->xfer_page_cache_end = USB_ADD_BYTES(buf, parm->size[2]);
cv_init(&info->cv_drain, "WDRAIN");
info->xfer_mtx = xfer_mtx;
#if USB_HAVE_BUSDMA
usb_dma_tag_setup(&info->dma_parent_tag,
- parm.dma_tag_p, udev->bus->dma_parent_tag[0].tag,
- xfer_mtx, &usb_bdma_done_event, 32, parm.dma_tag_max);
+ parm->dma_tag_p, udev->bus->dma_parent_tag[0].tag,
+ xfer_mtx, &usb_bdma_done_event, 32, parm->dma_tag_max);
#endif
info->bus = udev->bus;
@@ -976,9 +982,9 @@ usbd_transfer_setup(struct usb_device *udev,
}
/* reset sizes */
- parm.size[0] = 0;
- parm.buf = buf;
- parm.size[0] += sizeof(info[0]);
+ parm->size[0] = 0;
+ parm->buf = buf;
+ parm->size[0] += sizeof(info[0]);
for (setup = setup_start, n = 0;
setup != setup_end; setup++, n++) {
@@ -1010,22 +1016,22 @@ usbd_transfer_setup(struct usb_device *udev,
if ((setup->usb_mode != USB_MODE_DUAL) &&
(setup->usb_mode != udev->flags.usb_mode))
continue;
- parm.err = USB_ERR_NO_PIPE;
+ parm->err = USB_ERR_NO_PIPE;
goto done;
}
/* align data properly */
- parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
+ parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
/* store current setup pointer */
- parm.curr_setup = setup;
+ parm->curr_setup = setup;
if (buf) {
/*
* Common initialization of the
* "usb_xfer" structure.
*/
- xfer = USB_ADD_BYTES(buf, parm.size[0]);
+ xfer = USB_ADD_BYTES(buf, parm->size[0]);
xfer->address = udev->address;
xfer->priv_sc = priv_sc;
xfer->xroot = info;
@@ -1040,8 +1046,8 @@ usbd_transfer_setup(struct usb_device *udev,
* before we have allocated any
* memory:
*/
- xfer = &dummy;
- memset(&dummy, 0, sizeof(dummy));
+ xfer = &udev->scratch.xfer_setup[0].dummy;
+ memset(xfer, 0, sizeof(*xfer));
refcount++;
}
@@ -1051,18 +1057,18 @@ usbd_transfer_setup(struct usb_device *udev,
/* set transfer stream ID */
xfer->stream_id = setup->stream_id;
- parm.size[0] += sizeof(xfer[0]);
- parm.methods = xfer->endpoint->methods;
- parm.curr_xfer = xfer;
+ parm->size[0] += sizeof(xfer[0]);
+ parm->methods = xfer->endpoint->methods;
+ parm->curr_xfer = xfer;
/*
* Call the Host or Device controller transfer
* setup routine:
*/
- (udev->bus->methods->xfer_setup) (&parm);
+ (udev->bus->methods->xfer_setup) (parm);
/* check for error */
- if (parm.err)
+ if (parm->err)
goto done;
if (buf) {
@@ -1077,7 +1083,7 @@ usbd_transfer_setup(struct usb_device *udev,
*/
USB_BUS_LOCK(info->bus);
if (xfer->endpoint->refcount_alloc >= USB_EP_REF_MAX)
- parm.err = USB_ERR_INVAL;
+ parm->err = USB_ERR_INVAL;
xfer->endpoint->refcount_alloc++;
@@ -1100,22 +1106,22 @@ usbd_transfer_setup(struct usb_device *udev,
}
/* check for error */
- if (parm.err)
+ if (parm->err)
goto done;
}
- if (buf || parm.err) {
+ if (buf != NULL || parm->err != 0)
goto done;
- }
- if (refcount == 0) {
- /* no transfers - nothing to do ! */
+
+ /* if no transfers, nothing to do */
+ if (refcount == 0)
goto done;
- }
+
/* align data properly */
- parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
+ parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
/* store offset temporarily */
- parm.size[1] = parm.size[0];
+ parm->size[1] = parm->size[0];
/*
* The number of DMA tags required depends on
@@ -1126,72 +1132,72 @@ usbd_transfer_setup(struct usb_device *udev,
* 2) for allocating memory
* 3) for fixing memory [UHCI]
*/
- parm.dma_tag_max += 3 * MIN(n_setup, USB_EP_MAX);
+ parm->dma_tag_max += 3 * MIN(n_setup, USB_EP_MAX);
/*
* DMA tags for QH, TD, Data and more.
*/
- parm.dma_tag_max += 8;
+ parm->dma_tag_max += 8;
- parm.dma_tag_p += parm.dma_tag_max;
+ parm->dma_tag_p += parm->dma_tag_max;
- parm.size[0] += ((uint8_t *)parm.dma_tag_p) -
+ parm->size[0] += ((uint8_t *)parm->dma_tag_p) -
((uint8_t *)0);
/* align data properly */
- parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
+ parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
/* store offset temporarily */
- parm.size[3] = parm.size[0];
+ parm->size[3] = parm->size[0];
- parm.size[0] += ((uint8_t *)parm.dma_page_ptr) -
+ parm->size[0] += ((uint8_t *)parm->dma_page_ptr) -
((uint8_t *)0);
/* align data properly */
- parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
+ parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
/* store offset temporarily */
- parm.size[4] = parm.size[0];
+ parm->size[4] = parm->size[0];
- parm.size[0] += ((uint8_t *)parm.dma_page_cache_ptr) -
+ parm->size[0] += ((uint8_t *)parm->dma_page_cache_ptr) -
((uint8_t *)0);
/* store end offset temporarily */
- parm.size[5] = parm.size[0];
+ parm->size[5] = parm->size[0];
- parm.size[0] += ((uint8_t *)parm.xfer_page_cache_ptr) -
+ parm->size[0] += ((uint8_t *)parm->xfer_page_cache_ptr) -
((uint8_t *)0);
/* store end offset temporarily */
- parm.size[2] = parm.size[0];
+ parm->size[2] = parm->size[0];
/* align data properly */
- parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
+ parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
- parm.size[6] = parm.size[0];
+ parm->size[6] = parm->size[0];
- parm.size[0] += ((uint8_t *)parm.xfer_length_ptr) -
+ parm->size[0] += ((uint8_t *)parm->xfer_length_ptr) -
((uint8_t *)0);
/* align data properly */
- parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
+ parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
/* allocate zeroed memory */
- buf = malloc(parm.size[0], M_USB, M_WAITOK | M_ZERO);
+ buf = malloc(parm->size[0], M_USB, M_WAITOK | M_ZERO);
if (buf == NULL) {
- parm.err = USB_ERR_NOMEM;
+ parm->err = USB_ERR_NOMEM;
DPRINTFN(0, "cannot allocate memory block for "
"configuration (%d bytes)\n",
- parm.size[0]);
+ parm->size[0]);
goto done;
}
- parm.dma_tag_p = USB_ADD_BYTES(buf, parm.size[1]);
- parm.dma_page_ptr = USB_ADD_BYTES(buf, parm.size[3]);
- parm.dma_page_cache_ptr = USB_ADD_BYTES(buf, parm.size[4]);
- parm.xfer_page_cache_ptr = USB_ADD_BYTES(buf, parm.size[5]);
- parm.xfer_length_ptr = USB_ADD_BYTES(buf, parm.size[6]);
+ parm->dma_tag_p = USB_ADD_BYTES(buf, parm->size[1]);
+ parm->dma_page_ptr = USB_ADD_BYTES(buf, parm->size[3]);
+ parm->dma_page_cache_ptr = USB_ADD_BYTES(buf, parm->size[4]);
+ parm->xfer_page_cache_ptr = USB_ADD_BYTES(buf, parm->size[5]);
+ parm->xfer_length_ptr = USB_ADD_BYTES(buf, parm->size[6]);
}
done:
@@ -1207,10 +1213,17 @@ done:
usbd_transfer_unsetup_sub(info, 0);
}
}
- if (parm.err) {
+
+ /* check if any errors happened */
+ if (parm->err)
usbd_transfer_unsetup(ppxfer, n_setup);
- }
- return (parm.err);
+
+ error = parm->err;
+
+ if (do_unlock)
+ usbd_enum_unlock(udev);
+
+ return (error);
}
/*------------------------------------------------------------------------*
diff --git a/sys/dev/usb/usb_util.c b/sys/dev/usb/usb_util.c
index f9fec76..ffd005b 100644
--- a/sys/dev/usb/usb_util.c
+++ b/sys/dev/usb/usb_util.c
@@ -75,6 +75,7 @@ device_set_usb_desc(device_t dev)
struct usb_interface *iface;
char *temp_p;
usb_error_t err;
+ uint8_t do_unlock;
if (dev == NULL) {
/* should not happen */
@@ -96,19 +97,26 @@ device_set_usb_desc(device_t dev)
err = 0;
}
- temp_p = (char *)udev->bus->scratch[0].data;
+ /* Protect scratch area */
+ do_unlock = usbd_enum_lock(udev);
- if (!err) {
+ temp_p = (char *)udev->scratch.data;
+
+ if (err == 0) {
/* try to get the interface string ! */
- err = usbd_req_get_string_any
- (udev, NULL, temp_p,
- sizeof(udev->bus->scratch), iface->idesc->iInterface);
+ err = usbd_req_get_string_any(udev, NULL, temp_p,
+ sizeof(udev->scratch.data),
+ iface->idesc->iInterface);
}
- if (err) {
+ if (err != 0) {
/* use default description */
usb_devinfo(udev, temp_p,
- sizeof(udev->bus->scratch));
+ sizeof(udev->scratch.data));
}
+
+ if (do_unlock)
+ usbd_enum_unlock(udev);
+
device_set_desc_copy(dev, temp_p);
device_printf(dev, "<%s> on %s\n", temp_p,
device_get_nameunit(udev->bus->bdev));
OpenPOWER on IntegriCloud