aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/usb
diff options
context:
space:
mode:
authorHans Petter Selasky <hselasky@FreeBSD.org>2013-05-03 11:10:04 +0000
committerHans Petter Selasky <hselasky@FreeBSD.org>2013-05-03 11:10:04 +0000
commit2c79a775ed2daeee80f5a665e947648f501bf40e (patch)
treeda34869305f7442f6ba4ce940376c157aa9705e3 /sys/dev/usb
parent5d0b98f2c3b1859dd31c4481cc2db94c7f2431ef (diff)
Notes
Diffstat (limited to 'sys/dev/usb')
-rw-r--r--sys/dev/usb/template/usb_template.c11
-rw-r--r--sys/dev/usb/usb_device.c4
-rw-r--r--sys/dev/usb/usb_device.h4
-rw-r--r--sys/dev/usb/usb_dynamic.c9
-rw-r--r--sys/dev/usb/usb_freebsd.h3
-rw-r--r--sys/dev/usb/usb_freebsd_loader.h3
-rw-r--r--sys/dev/usb/usb_generic.c17
-rw-r--r--sys/dev/usb/usb_hub.c26
-rw-r--r--sys/dev/usb/usb_hub.h4
-rw-r--r--sys/dev/usb/usb_request.c48
-rw-r--r--sys/dev/usb/usb_request.h5
11 files changed, 99 insertions, 35 deletions
diff --git a/sys/dev/usb/template/usb_template.c b/sys/dev/usb/template/usb_template.c
index b815161e898e..73ca73b079e3 100644
--- a/sys/dev/usb/template/usb_template.c
+++ b/sys/dev/usb/template/usb_template.c
@@ -69,6 +69,7 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#include <dev/usb/usb_request.h>
#include <dev/usb/template/usb_template.h>
#endif /* USB_GLOBAL_INCLUDE_FILE */
@@ -1267,7 +1268,7 @@ usb_temp_setup(struct usb_device *udev,
goto done;
}
/* allocate zeroed memory */
- uts->buf = malloc(uts->size, M_USB, M_WAITOK | M_ZERO);
+ uts->buf = usbd_alloc_config_desc(udev, uts->size);
/*
* Allow malloc() to return NULL regardless of M_WAITOK flag.
* This helps when porting the software to non-FreeBSD
@@ -1336,12 +1337,8 @@ done:
void
usb_temp_unsetup(struct usb_device *udev)
{
- if (udev->usb_template_ptr) {
-
- free(udev->usb_template_ptr, M_USB);
-
- udev->usb_template_ptr = NULL;
- }
+ usbd_free_config_desc(udev, udev->usb_template_ptr);
+ udev->usb_template_ptr = NULL;
}
static usb_error_t
diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c
index b1770cee11e5..b88a0e1cea5d 100644
--- a/sys/dev/usb/usb_device.c
+++ b/sys/dev/usb/usb_device.c
@@ -493,7 +493,7 @@ usb_unconfigure(struct usb_device *udev, uint8_t flag)
/* free "cdesc" after "ifaces" and "endpoints", if any */
if (udev->cdesc != NULL) {
if (udev->flags.usb_mode != USB_MODE_DEVICE)
- free(udev->cdesc, M_USB);
+ usbd_free_config_desc(udev, udev->cdesc);
udev->cdesc = NULL;
}
/* set unconfigured state */
@@ -552,7 +552,7 @@ usbd_set_config_index(struct usb_device *udev, uint8_t index)
} else {
/* normal request */
err = usbd_req_get_config_desc_full(udev,
- NULL, &cdp, M_USB, index);
+ NULL, &cdp, index);
}
if (err) {
goto done;
diff --git a/sys/dev/usb/usb_device.h b/sys/dev/usb/usb_device.h
index 89dff364c8fe..06b931fb0b26 100644
--- a/sys/dev/usb/usb_device.h
+++ b/sys/dev/usb/usb_device.h
@@ -267,6 +267,10 @@ struct usb_device {
uint32_t clear_stall_errors; /* number of clear-stall failures */
union usb_device_scratch scratch;
+
+#if (USB_HAVE_FIXED_CONFIG != 0)
+ uint32_t config_data[(USB_CONFIG_MAX + 3) / 4];
+#endif
};
/* globals */
diff --git a/sys/dev/usb/usb_dynamic.c b/sys/dev/usb/usb_dynamic.c
index 58deb4e2cf32..d08e7f84afd8 100644
--- a/sys/dev/usb/usb_dynamic.c
+++ b/sys/dev/usb/usb_dynamic.c
@@ -53,6 +53,7 @@
#include <dev/usb/usb_process.h>
#include <dev/usb/usb_device.h>
#include <dev/usb/usb_dynamic.h>
+#include <dev/usb/usb_request.h>
#endif /* USB_GLOBAL_INCLUDE_FILE */
/* function prototypes */
@@ -98,12 +99,8 @@ usb_temp_get_desc_w(struct usb_device *udev, struct usb_device_request *req, con
static void
usb_temp_unsetup_w(struct usb_device *udev)
{
- if (udev->usb_template_ptr) {
-
- free(udev->usb_template_ptr, M_USB);
-
- udev->usb_template_ptr = NULL;
- }
+ usbd_free_config_desc(udev, udev->usb_template_ptr);
+ udev->usb_template_ptr = NULL;
}
void
diff --git a/sys/dev/usb/usb_freebsd.h b/sys/dev/usb/usb_freebsd.h
index 10f412e91ec5..870e869e714d 100644
--- a/sys/dev/usb/usb_freebsd.h
+++ b/sys/dev/usb/usb_freebsd.h
@@ -47,6 +47,8 @@
#define USB_HAVE_PER_BUS_PROCESS 1
#define USB_HAVE_FIXED_ENDPOINT 0
#define USB_HAVE_FIXED_IFACE 0
+#define USB_HAVE_FIXED_CONFIG 0
+#define USB_HAVE_FIXED_PORT 0
#define USB_TD_GET_PROC(td) (td)->td_proc
#define USB_PROC_GET_GID(td) (td)->p_pgid
@@ -68,6 +70,7 @@
#define USB_FIFO_MAX 128 /* units */
#define USB_MAX_EP_STREAMS 8 /* units */
#define USB_MAX_EP_UNITS 32 /* units */
+#define USB_MAX_PORTS 255 /* units */
#define USB_MAX_FS_ISOC_FRAMES_PER_XFER (120) /* units */
#define USB_MAX_HS_ISOC_FRAMES_PER_XFER (8*120) /* units */
diff --git a/sys/dev/usb/usb_freebsd_loader.h b/sys/dev/usb/usb_freebsd_loader.h
index 10ee06374d67..2a1e1044bcfb 100644
--- a/sys/dev/usb/usb_freebsd_loader.h
+++ b/sys/dev/usb/usb_freebsd_loader.h
@@ -47,6 +47,8 @@
#define USB_HAVE_PER_BUS_PROCESS 0
#define USB_HAVE_FIXED_ENDPOINT 0
#define USB_HAVE_FIXED_IFACE 0
+#define USB_HAVE_FIXED_CONFIG 0
+#define USB_HAVE_FIXED_PORT 0
#define USB_TD_GET_PROC(td) (td)->td_proc
#define USB_PROC_GET_GID(td) (td)->p_pgid
@@ -68,6 +70,7 @@
#define USB_FIFO_MAX 128 /* units */
#define USB_MAX_EP_UNITS 32 /* units */
#define USB_MAX_EP_STREAMS 8 /* units */
+#define USB_MAX_PORTS 255 /* units */
#define USB_MAX_FS_ISOC_FRAMES_PER_XFER (120) /* units */
#define USB_MAX_HS_ISOC_FRAMES_PER_XFER (8*120) /* units */
diff --git a/sys/dev/usb/usb_generic.c b/sys/dev/usb/usb_generic.c
index 013210aa7e05..8e1033e4a9ca 100644
--- a/sys/dev/usb/usb_generic.c
+++ b/sys/dev/usb/usb_generic.c
@@ -688,18 +688,21 @@ ugen_get_cdesc(struct usb_fifo *f, struct usb_gen_descriptor *ugd)
if ((ugd->ugd_config_index == USB_UNCONFIG_INDEX) ||
(ugd->ugd_config_index == udev->curr_config_index)) {
cdesc = usbd_get_config_descriptor(udev);
- if (cdesc == NULL) {
+ if (cdesc == NULL)
return (ENXIO);
- }
free_data = 0;
} else {
+#if (USB_HAVE_FIXED_CONFIG == 0)
if (usbd_req_get_config_desc_full(udev,
- NULL, &cdesc, M_USBDEV,
- ugd->ugd_config_index)) {
+ NULL, &cdesc, ugd->ugd_config_index)) {
return (ENXIO);
}
free_data = 1;
+#else
+ /* configuration descriptor data is shared */
+ return (EINVAL);
+#endif
}
len = UGETW(cdesc->wTotalLength);
@@ -713,9 +716,9 @@ ugen_get_cdesc(struct usb_fifo *f, struct usb_gen_descriptor *ugd)
error = copyout(cdesc, ugd->ugd_data, len);
- if (free_data) {
- free(cdesc, M_USBDEV);
- }
+ if (free_data)
+ usbd_free_config_desc(udev, cdesc);
+
return (error);
}
diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c
index a359ee252937..227f31730f6c 100644
--- a/sys/dev/usb/usb_hub.c
+++ b/sys/dev/usb/usb_hub.c
@@ -100,6 +100,9 @@ struct uhub_current_state {
struct uhub_softc {
struct uhub_current_state sc_st;/* current state */
+#if (USB_HAVE_FIXED_PORT != 0)
+ struct usb_hub sc_hub;
+#endif
device_t sc_dev; /* base device */
struct mtx sc_mtx; /* our mutex */
struct usb_device *sc_udev; /* USB device */
@@ -922,8 +925,8 @@ uhub_attach(device_t dev)
struct usb_hub_descriptor hubdesc20;
struct usb_hub_ss_descriptor hubdesc30;
uint16_t pwrdly;
+ uint16_t nports;
uint8_t x;
- uint8_t nports;
uint8_t portno;
uint8_t removable;
uint8_t iface_index;
@@ -1067,12 +1070,19 @@ uhub_attach(device_t dev)
DPRINTFN(0, "portless HUB\n");
goto error;
}
+ if (nports > USB_MAX_PORTS) {
+ DPRINTF("Port limit exceeded\n");
+ goto error;
+ }
+#if (USB_HAVE_FIXED_PORT == 0)
hub = malloc(sizeof(hub[0]) + (sizeof(hub->ports[0]) * nports),
M_USBDEV, M_WAITOK | M_ZERO);
- if (hub == NULL) {
+ if (hub == NULL)
goto error;
- }
+#else
+ hub = &sc->sc_hub;
+#endif
udev->hub = hub;
/* initialize HUB structure */
@@ -1197,10 +1207,10 @@ uhub_attach(device_t dev)
error:
usbd_transfer_unsetup(sc->sc_xfer, UHUB_N_TRANSFER);
- if (udev->hub) {
- free(udev->hub, M_USBDEV);
- udev->hub = NULL;
- }
+#if (USB_HAVE_FIXED_PORT == 0)
+ free(udev->hub, M_USBDEV);
+#endif
+ udev->hub = NULL;
mtx_destroy(&sc->sc_mtx);
@@ -1240,7 +1250,9 @@ uhub_detach(device_t dev)
usb_free_device(child, 0);
}
+#if (USB_HAVE_FIXED_PORT == 0)
free(hub, M_USBDEV);
+#endif
sc->sc_udev->hub = NULL;
mtx_destroy(&sc->sc_mtx);
diff --git a/sys/dev/usb/usb_hub.h b/sys/dev/usb/usb_hub.h
index 23a1fa4f1c5c..4a48f747c782 100644
--- a/sys/dev/usb/usb_hub.h
+++ b/sys/dev/usb/usb_hub.h
@@ -48,7 +48,11 @@ struct usb_hub {
uint16_t portpower; /* mA per USB port */
uint8_t isoc_last_time;
uint8_t nports;
+#if (USB_HAVE_FIXED_PORT == 0)
struct usb_port ports[0];
+#else
+ struct usb_port ports[USB_MAX_PORTS];
+#endif
};
/* function prototypes */
diff --git a/sys/dev/usb/usb_request.c b/sys/dev/usb/usb_request.c
index cc7765624e46..0a82462148d9 100644
--- a/sys/dev/usb/usb_request.c
+++ b/sys/dev/usb/usb_request.c
@@ -1260,10 +1260,49 @@ done:
}
/*------------------------------------------------------------------------*
+ * usbd_alloc_config_desc
+ *
+ * This function is used to allocate a zeroed configuration
+ * descriptor.
+ *
+ * Returns:
+ * NULL: Failure
+ * Else: Success
+ *------------------------------------------------------------------------*/
+void *
+usbd_alloc_config_desc(struct usb_device *udev, uint32_t size)
+{
+ if (size > USB_CONFIG_MAX) {
+ DPRINTF("Configuration descriptor too big\n");
+ return (NULL);
+ }
+#if (USB_HAVE_FIXED_CONFIG == 0)
+ return (malloc(size, M_USBDEV, M_ZERO | M_WAITOK));
+#else
+ memset(udev->config_data, 0, sizeof(udev->config_data));
+ return (udev->config_data);
+#endif
+}
+
+/*------------------------------------------------------------------------*
+ * usbd_alloc_config_desc
+ *
+ * This function is used to free a configuration descriptor.
+ *------------------------------------------------------------------------*/
+void
+usbd_free_config_desc(struct usb_device *udev, void *ptr)
+{
+#if (USB_HAVE_FIXED_CONFIG == 0)
+ free(ptr, M_USBDEV);
+#endif
+}
+
+/*------------------------------------------------------------------------*
* usbd_req_get_config_desc_full
*
* This function gets the complete USB configuration descriptor and
- * ensures that "wTotalLength" is correct.
+ * ensures that "wTotalLength" is correct. The returned configuration
+ * descriptor is freed by calling "usbd_free_config_desc()".
*
* Returns:
* 0: Success
@@ -1271,8 +1310,7 @@ done:
*------------------------------------------------------------------------*/
usb_error_t
usbd_req_get_config_desc_full(struct usb_device *udev, struct mtx *mtx,
- struct usb_config_descriptor **ppcd, struct malloc_type *mtype,
- uint8_t index)
+ struct usb_config_descriptor **ppcd, uint8_t index)
{
struct usb_config_descriptor cd;
struct usb_config_descriptor *cdesc;
@@ -1296,13 +1334,13 @@ usbd_req_get_config_desc_full(struct usb_device *udev, struct mtx *mtx,
DPRINTF("Configuration descriptor was truncated\n");
len = USB_CONFIG_MAX;
}
- cdesc = malloc(len, mtype, M_WAITOK);
+ cdesc = usbd_alloc_config_desc(udev, len);
if (cdesc == NULL)
return (USB_ERR_NOMEM);
err = usbd_req_get_desc(udev, mtx, NULL, cdesc, len, len, 0,
UDESC_CONFIG, index, 3);
if (err) {
- free(cdesc, mtype);
+ usbd_free_config_desc(udev, cdesc);
return (err);
}
/* make sure that the device is not fooling us: */
diff --git a/sys/dev/usb/usb_request.h b/sys/dev/usb/usb_request.h
index 5fcedd5e5247..9f0a4e644d55 100644
--- a/sys/dev/usb/usb_request.h
+++ b/sys/dev/usb/usb_request.h
@@ -44,7 +44,7 @@ usb_error_t usbd_req_get_config_desc(struct usb_device *udev, struct mtx *mtx,
struct usb_config_descriptor *d, uint8_t conf_index);
usb_error_t usbd_req_get_config_desc_full(struct usb_device *udev,
struct mtx *mtx, struct usb_config_descriptor **ppcd,
- struct malloc_type *mtype, uint8_t conf_index);
+ uint8_t conf_index);
usb_error_t usbd_req_get_desc(struct usb_device *udev, struct mtx *mtx,
uint16_t *actlen, void *desc, uint16_t min_len,
uint16_t max_len, uint16_t id, uint8_t type,
@@ -94,4 +94,7 @@ usb_error_t usbd_req_set_port_link_state(struct usb_device *udev,
usb_error_t usbd_req_set_lpm_info(struct usb_device *udev, struct mtx *mtx,
uint8_t port, uint8_t besl, uint8_t addr, uint8_t rwe);
+void * usbd_alloc_config_desc(struct usb_device *, uint32_t);
+void usbd_free_config_desc(struct usb_device *, void *);
+
#endif /* _USB_REQUEST_H_ */