- Add more defines to limit USB memory usage and number of allocations
in reduced memory systems. - Split allocation and freeing of the configuration descriptor into a separate function, so that the configuration descriptor can be made fixed size to save memory allocations. This applies for both device and host mode.
This commit is contained in:
parent
bf0ecb6670
commit
fad53c9a9b
@ -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 @@ usb_temp_setup(struct usb_device *udev,
|
||||
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
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -1259,11 +1259,50 @@ usbd_req_get_config_desc(struct usb_device *udev, struct mtx *mtx,
|
||||
return (err);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* 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 @@ usbd_req_get_config_desc(struct usb_device *udev, struct mtx *mtx,
|
||||
*------------------------------------------------------------------------*/
|
||||
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: */
|
||||
|
@ -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_ */
|
||||
|
Loading…
Reference in New Issue
Block a user