aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/usb
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/usb')
-rw-r--r--sys/dev/usb/input/uhid.c25
-rw-r--r--sys/dev/usb/input/uhid_snes.c26
-rw-r--r--sys/dev/usb/usb_dev.c12
-rw-r--r--sys/dev/usb/usb_generic.c118
-rw-r--r--sys/dev/usb/usb_ioctl.h57
5 files changed, 232 insertions, 6 deletions
diff --git a/sys/dev/usb/input/uhid.c b/sys/dev/usb/input/uhid.c
index 97f9b1c8edea..1cad7af222ac 100644
--- a/sys/dev/usb/input/uhid.c
+++ b/sys/dev/usb/input/uhid.c
@@ -550,13 +550,30 @@ uhid_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr,
{
struct uhid_softc *sc = usb_fifo_softc(fifo);
struct usb_gen_descriptor *ugd;
+#ifdef COMPAT_FREEBSD32
+ struct usb_gen_descriptor local_ugd;
+ struct usb_gen_descriptor32 *ugd32 = NULL;
+#endif
uint32_t size;
int error = 0;
uint8_t id;
+ ugd = addr;
+#ifdef COMPAT_FREEBSD32
+ switch (cmd) {
+ case USB_GET_REPORT_DESC32:
+ case USB_GET_REPORT32:
+ case USB_SET_REPORT32:
+ ugd32 = addr;
+ ugd = &local_ugd;
+ usb_gen_descriptor_from32(ugd, ugd32);
+ cmd = _IOC_NEWTYPE(cmd, struct usb_gen_descriptor);
+ break;
+ }
+#endif
+
switch (cmd) {
case USB_GET_REPORT_DESC:
- ugd = addr;
if (sc->sc_repdesc_size > ugd->ugd_maxlen) {
size = ugd->ugd_maxlen;
} else {
@@ -596,7 +613,6 @@ uhid_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr,
error = EPERM;
break;
}
- ugd = addr;
switch (ugd->ugd_report_type) {
case UHID_INPUT_REPORT:
size = sc->sc_isize;
@@ -624,7 +640,6 @@ uhid_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr,
error = EPERM;
break;
}
- ugd = addr;
switch (ugd->ugd_report_type) {
case UHID_INPUT_REPORT:
size = sc->sc_isize;
@@ -655,6 +670,10 @@ uhid_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr,
error = ENOIOCTL;
break;
}
+#ifdef COMPAT_FREEBSD32
+ if (ugd32 != NULL)
+ update_usb_gen_descriptor32(ugd32, ugd);
+#endif
return (error);
}
diff --git a/sys/dev/usb/input/uhid_snes.c b/sys/dev/usb/input/uhid_snes.c
index 181e38eba7b1..9bce3d10941f 100644
--- a/sys/dev/usb/input/uhid_snes.c
+++ b/sys/dev/usb/input/uhid_snes.c
@@ -281,13 +281,30 @@ uhid_snes_ioctl(struct usb_fifo *fifo, u_long cmd, void *data, int fflags)
{
struct uhid_snes_softc *sc = usb_fifo_softc(fifo);
struct usb_gen_descriptor *ugd;
+#ifdef COMPAT_FREEBSD32
+ struct usb_gen_descriptor local_ugd;
+ struct usb_gen_descriptor32 *ugd32 = NULL;
+#endif
uint32_t size;
int error = 0;
uint8_t id;
+ ugd = data;
+#ifdef COMPAT_FREEBSD32
+ switch (cmd) {
+ case USB_GET_REPORT_DESC32:
+ case USB_GET_REPORT32:
+ case USB_SET_REPORT32:
+ ugd32 = data;
+ ugd = &local_ugd;
+ usb_gen_descriptor_from32(ugd, ugd32);
+ cmd = _IOC_NEWTYPE(cmd, struct usb_gen_descriptor);
+ break;
+ }
+#endif
+
switch (cmd) {
case USB_GET_REPORT_DESC:
- ugd = data;
if (sc->sc_repdesc_size > ugd->ugd_maxlen) {
size = ugd->ugd_maxlen;
} else {
@@ -328,7 +345,6 @@ uhid_snes_ioctl(struct usb_fifo *fifo, u_long cmd, void *data, int fflags)
error = EPERM;
break;
}
- ugd = data;
switch (ugd->ugd_report_type) {
case UHID_INPUT_REPORT:
size = sc->sc_isize;
@@ -356,7 +372,6 @@ uhid_snes_ioctl(struct usb_fifo *fifo, u_long cmd, void *data, int fflags)
error = EPERM;
break;
}
- ugd = data;
switch (ugd->ugd_report_type) {
case UHID_INPUT_REPORT:
size = sc->sc_isize;
@@ -388,6 +403,11 @@ uhid_snes_ioctl(struct usb_fifo *fifo, u_long cmd, void *data, int fflags)
error = EINVAL;
break;
}
+
+#ifdef COMPAT_FREEBSD32
+ if (ugd32 != NULL)
+ update_usb_gen_descriptor32(ugd32, ugd);
+#endif
return (error);
}
diff --git a/sys/dev/usb/usb_dev.c b/sys/dev/usb/usb_dev.c
index 99b243464f6c..4811d280562c 100644
--- a/sys/dev/usb/usb_dev.c
+++ b/sys/dev/usb/usb_dev.c
@@ -32,6 +32,9 @@
#ifdef USB_GLOBAL_INCLUDE_FILE
#include USB_GLOBAL_INCLUDE_FILE
#else
+#ifdef COMPAT_FREEBSD32
+#include <sys/abi_compat.h>
+#endif
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -1650,6 +1653,9 @@ usb_static_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
{
union {
struct usb_read_dir *urd;
+#ifdef COMPAT_FREEBSD32
+ struct usb_read_dir32 *urd32;
+#endif
void* data;
} u;
int err;
@@ -1660,6 +1666,12 @@ usb_static_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
err = usb_read_symlink(u.urd->urd_data,
u.urd->urd_startentry, u.urd->urd_maxlen);
break;
+#ifdef COMPAT_FREEBSD32
+ case USB_READ_DIR32:
+ err = usb_read_symlink(PTRIN(u.urd32->urd_data),
+ u.urd32->urd_startentry, u.urd32->urd_maxlen);
+ break;
+#endif
case USB_DEV_QUIRK_GET:
case USB_QUIRK_NAME_GET:
case USB_DEV_QUIRK_ADD:
diff --git a/sys/dev/usb/usb_generic.c b/sys/dev/usb/usb_generic.c
index 65af2bd6979d..746a843baf09 100644
--- a/sys/dev/usb/usb_generic.c
+++ b/sys/dev/usb/usb_generic.c
@@ -29,6 +29,9 @@
#ifdef USB_GLOBAL_INCLUDE_FILE
#include USB_GLOBAL_INCLUDE_FILE
#else
+#ifdef COMPAT_FREEBSD32
+#include <sys/abi_compat.h>
+#endif
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -109,6 +112,9 @@ static int ugen_set_interface(struct usb_fifo *, uint8_t, uint8_t);
static int ugen_get_cdesc(struct usb_fifo *, struct usb_gen_descriptor *);
static int ugen_get_sdesc(struct usb_fifo *, struct usb_gen_descriptor *);
static int ugen_get_iface_driver(struct usb_fifo *f, struct usb_gen_descriptor *ugd);
+#ifdef COMPAT_FREEBSD32
+static int ugen_get32(u_long cmd, struct usb_fifo *f, struct usb_gen_descriptor32 *ugd32);
+#endif
static int ugen_re_enumerate(struct usb_fifo *);
static int ugen_iface_ioctl(struct usb_fifo *, u_long, void *, int);
static uint8_t ugen_fs_get_complete(struct usb_fifo *, uint8_t *);
@@ -943,6 +949,31 @@ ugen_do_request(struct usb_fifo *f, struct usb_ctl_request *ur)
return (error);
}
+#ifdef COMPAT_FREEBSD32
+static int
+ugen_do_request32(struct usb_fifo *f, struct usb_ctl_request32 *ur32)
+{
+ struct usb_ctl_request ur;
+ int error;
+
+ PTRIN_CP(*ur32, ur, ucr_data);
+ CP(*ur32, ur, ucr_flags);
+ CP(*ur32, ur, ucr_actlen);
+ CP(*ur32, ur, ucr_addr);
+ CP(*ur32, ur, ucr_request);
+
+ error = ugen_do_request(f, &ur);
+
+ /* Don't update ucr_data pointer */
+ CP(ur, *ur32, ucr_flags);
+ CP(ur, *ur32, ucr_actlen);
+ CP(ur, *ur32, ucr_addr);
+ CP(ur, *ur32, ucr_request);
+
+ return (error);
+}
+#endif
+
/*------------------------------------------------------------------------
* ugen_re_enumerate
*------------------------------------------------------------------------*/
@@ -2192,6 +2223,14 @@ ugen_ioctl_post(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
error = ugen_get_iface_driver(f, addr);
break;
+#ifdef COMPAT_FREEBSD32
+ case USB_GET_FULL_DESC32:
+ case USB_GET_STRING_DESC32:
+ case USB_GET_IFACE_DRIVER32:
+ error = ugen_get32(cmd, f, addr);
+ break;
+#endif
+
case USB_REQUEST:
case USB_DO_REQUEST:
if (!(fflags & FWRITE)) {
@@ -2201,6 +2240,17 @@ ugen_ioctl_post(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
error = ugen_do_request(f, addr);
break;
+#ifdef COMPAT_FREEBSD32
+ case USB_REQUEST32:
+ case USB_DO_REQUEST32:
+ if (!(fflags & FWRITE)) {
+ error = EPERM;
+ break;
+ }
+ error = ugen_do_request32(f, addr);
+ break;
+#endif
+
case USB_DEVICEINFO:
case USB_GET_DEVICEINFO:
error = ugen_fill_deviceinfo(f, addr);
@@ -2363,4 +2413,72 @@ ugen_ctrl_fs_callback(struct usb_xfer *xfer, usb_error_t error)
break;
}
}
+
+#ifdef COMPAT_FREEBSD32
+void
+usb_gen_descriptor_from32(struct usb_gen_descriptor *ugd,
+ const struct usb_gen_descriptor32 *ugd32)
+{
+ PTRIN_CP(*ugd32, *ugd, ugd_data);
+ CP(*ugd32, *ugd, ugd_lang_id);
+ CP(*ugd32, *ugd, ugd_maxlen);
+ CP(*ugd32, *ugd, ugd_actlen);
+ CP(*ugd32, *ugd, ugd_offset);
+ CP(*ugd32, *ugd, ugd_config_index);
+ CP(*ugd32, *ugd, ugd_string_index);
+ CP(*ugd32, *ugd, ugd_iface_index);
+ CP(*ugd32, *ugd, ugd_altif_index);
+ CP(*ugd32, *ugd, ugd_endpt_index);
+ CP(*ugd32, *ugd, ugd_report_type);
+ /* Don't copy reserved */
+}
+
+void
+update_usb_gen_descriptor32(struct usb_gen_descriptor32 *ugd32,
+ struct usb_gen_descriptor *ugd)
+{
+ /* Don't update ugd_data pointer */
+ CP(*ugd32, *ugd, ugd_lang_id);
+ CP(*ugd32, *ugd, ugd_maxlen);
+ CP(*ugd32, *ugd, ugd_actlen);
+ CP(*ugd32, *ugd, ugd_offset);
+ CP(*ugd32, *ugd, ugd_config_index);
+ CP(*ugd32, *ugd, ugd_string_index);
+ CP(*ugd32, *ugd, ugd_iface_index);
+ CP(*ugd32, *ugd, ugd_altif_index);
+ CP(*ugd32, *ugd, ugd_endpt_index);
+ CP(*ugd32, *ugd, ugd_report_type);
+ /* Don't update reserved */
+}
+
+static int
+ugen_get32(u_long cmd, struct usb_fifo *f, struct usb_gen_descriptor32 *ugd32)
+{
+ struct usb_gen_descriptor ugd;
+ int error;
+
+ usb_gen_descriptor_from32(&ugd, ugd32);
+ switch (cmd) {
+ case USB_GET_FULL_DESC32:
+ error = ugen_get_cdesc(f, &ugd);
+ break;
+
+ case USB_GET_STRING_DESC32:
+ error = ugen_get_sdesc(f, &ugd);
+ break;
+
+ case USB_GET_IFACE_DRIVER32:
+ error = ugen_get_iface_driver(f, &ugd);
+ break;
+ default:
+ /* Can't happen except by programmer error */
+ panic("%s: called with invalid cmd %lx", __func__, cmd);
+ }
+ update_usb_gen_descriptor32(ugd32, &ugd);
+
+ return (error);
+}
+
+#endif /* COMPAT_FREEBSD32 */
+
#endif /* USB_HAVE_UGEN */
diff --git a/sys/dev/usb/usb_ioctl.h b/sys/dev/usb/usb_ioctl.h
index 39783305ca6b..9d35588f1138 100644
--- a/sys/dev/usb/usb_ioctl.h
+++ b/sys/dev/usb/usb_ioctl.h
@@ -346,4 +346,61 @@ struct usb_gen_quirk {
#define USB_DEV_QUIRK_ADD _IOW ('Q', 2, struct usb_gen_quirk)
#define USB_DEV_QUIRK_REMOVE _IOW ('Q', 3, struct usb_gen_quirk)
+#ifdef _KERNEL
+#ifdef COMPAT_FREEBSD32
+
+struct usb_read_dir32 {
+ uint32_t urd_data;
+ uint32_t urd_startentry;
+ uint32_t urd_maxlen;
+};
+#define USB_READ_DIR32 \
+ _IOC_NEWTYPE(USB_READ_DIR, struct usb_read_dir32)
+
+struct usb_ctl_request32 {
+ uint32_t ucr_data;
+ uint16_t ucr_flags;
+ uint16_t ucr_actlen;
+ uint8_t ucr_addr;
+ struct usb_device_request ucr_request;
+};
+#define USB_REQUEST32 _IOC_NEWTYPE(USB_REQUEST, struct usb_ctl_request32)
+#define USB_DO_REQUEST32 _IOC_NEWTYPE(USB_DO_REQUEST, struct usb_ctl_request32)
+
+struct usb_gen_descriptor32 {
+ uint32_t ugd_data; /* void * */
+ uint16_t ugd_lang_id;
+ uint16_t ugd_maxlen;
+ uint16_t ugd_actlen;
+ uint16_t ugd_offset;
+ uint8_t ugd_config_index;
+ uint8_t ugd_string_index;
+ uint8_t ugd_iface_index;
+ uint8_t ugd_altif_index;
+ uint8_t ugd_endpt_index;
+ uint8_t ugd_report_type;
+ uint8_t reserved[8];
+};
+
+#define USB_GET_REPORT_DESC32 \
+ _IOC_NEWTYPE(USB_GET_REPORT_DESC, struct usb_gen_descriptor32)
+#define USB_GET_REPORT32 \
+ _IOC_NEWTYPE(USB_GET_REPORT, struct usb_gen_descriptor32)
+#define USB_SET_REPORT32 \
+ _IOC_NEWTYPE(USB_SET_REPORT, struct usb_gen_descriptor32)
+#define USB_GET_FULL_DESC32 \
+ _IOC_NEWTYPE(USB_GET_FULL_DESC, struct usb_gen_descriptor32)
+#define USB_GET_STRING_DESC32 \
+ _IOC_NEWTYPE(USB_GET_STRING_DESC, struct usb_gen_descriptor32)
+#define USB_GET_IFACE_DRIVER32 \
+ _IOC_NEWTYPE(USB_GET_IFACE_DRIVER, struct usb_gen_descriptor32)
+
+void usb_gen_descriptor_from32(struct usb_gen_descriptor *ugd,
+ const struct usb_gen_descriptor32 *ugd32);
+void update_usb_gen_descriptor32(struct usb_gen_descriptor32 *ugd32,
+ struct usb_gen_descriptor *ugd);
+
+#endif /* COMPAT_FREEBSD32 */
+#endif /* _KERNEL */
+
#endif /* _USB_IOCTL_H_ */