aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/hid/hidraw.c93
-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
6 files changed, 321 insertions, 10 deletions
diff --git a/sys/dev/hid/hidraw.c b/sys/dev/hid/hidraw.c
index e71b2e2c7d5d..f359fe3e7e6f 100644
--- a/sys/dev/hid/hidraw.c
+++ b/sys/dev/hid/hidraw.c
@@ -41,6 +41,9 @@ __FBSDID("$FreeBSD$");
#include "opt_hid.h"
#include <sys/param.h>
+#ifdef COMPAT_FREEBSD32
+#include <sys/abi_compat.h>
+#endif
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/fcntl.h>
@@ -115,6 +118,31 @@ struct hidraw_softc {
struct cdev *dev;
};
+#ifdef COMPAT_FREEBSD32
+struct hidraw_gen_descriptor32 {
+ uint32_t hgd_data; /* void * */
+ uint16_t hgd_lang_id;
+ uint16_t hgd_maxlen;
+ uint16_t hgd_actlen;
+ uint16_t hgd_offset;
+ uint8_t hgd_config_index;
+ uint8_t hgd_string_index;
+ uint8_t hgd_iface_index;
+ uint8_t hgd_altif_index;
+ uint8_t hgd_endpt_index;
+ uint8_t hgd_report_type;
+ uint8_t reserved[8];
+};
+#define HIDRAW_GET_REPORT_DESC32 \
+ _IOC_NEWTYPE(HIDRAW_GET_REPORT_DESC, struct hidraw_gen_descriptor32)
+#define HIDRAW_GET_REPORT32 \
+ _IOC_NEWTYPE(HIDRAW_GET_REPORT, struct hidraw_gen_descriptor32)
+#define HIDRAW_SET_REPORT_DESC32 \
+ _IOC_NEWTYPE(HIDRAW_SET_REPORT_DESC, struct hidraw_gen_descriptor32)
+#define HIDRAW_SET_REPORT32 \
+ _IOC_NEWTYPE(HIDRAW_SET_REPORT, struct hidraw_gen_descriptor32)
+#endif
+
static d_open_t hidraw_open;
static d_read_t hidraw_read;
static d_write_t hidraw_write;
@@ -507,11 +535,35 @@ hidraw_write(struct cdev *dev, struct uio *uio, int flag)
return (error);
}
+#ifdef COMPAT_FREEBSD32
+static void
+update_hgd32(const struct hidraw_gen_descriptor *hgd,
+ struct hidraw_gen_descriptor32 *hgd32)
+{
+ /* Don't update hgd_data pointer */
+ CP(*hgd, *hgd32, hgd_lang_id);
+ CP(*hgd, *hgd32, hgd_maxlen);
+ CP(*hgd, *hgd32, hgd_actlen);
+ CP(*hgd, *hgd32, hgd_offset);
+ CP(*hgd, *hgd32, hgd_config_index);
+ CP(*hgd, *hgd32, hgd_string_index);
+ CP(*hgd, *hgd32, hgd_iface_index);
+ CP(*hgd, *hgd32, hgd_altif_index);
+ CP(*hgd, *hgd32, hgd_endpt_index);
+ CP(*hgd, *hgd32, hgd_report_type);
+ /* Don't update reserved */
+}
+#endif
+
static int
hidraw_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
struct thread *td)
{
uint8_t local_buf[HIDRAW_LOCAL_BUFSIZE];
+#ifdef COMPAT_FREEBSD32
+ struct hidraw_gen_descriptor local_hgd;
+ struct hidraw_gen_descriptor32 *hgd32 = NULL;
+#endif
void *buf;
struct hidraw_softc *sc;
struct hidraw_gen_descriptor *hgd;
@@ -527,6 +579,32 @@ hidraw_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
if (sc == NULL)
return (EIO);
+#ifdef COMPAT_FREEBSD32
+ hgd = (struct hidraw_gen_descriptor *)addr;
+ switch (cmd) {
+ case HIDRAW_GET_REPORT_DESC32:
+ case HIDRAW_GET_REPORT32:
+ case HIDRAW_SET_REPORT_DESC32:
+ case HIDRAW_SET_REPORT32:
+ cmd = _IOC_NEWTYPE(cmd, struct hidraw_gen_descriptor);
+ hgd32 = (struct hidraw_gen_descriptor32 *)addr;
+ hgd = &local_hgd;
+ PTRIN_CP(*hgd32, *hgd, hgd_data);
+ CP(*hgd32, *hgd, hgd_lang_id);
+ CP(*hgd32, *hgd, hgd_maxlen);
+ CP(*hgd32, *hgd, hgd_actlen);
+ CP(*hgd32, *hgd, hgd_offset);
+ CP(*hgd32, *hgd, hgd_config_index);
+ CP(*hgd32, *hgd, hgd_string_index);
+ CP(*hgd32, *hgd, hgd_iface_index);
+ CP(*hgd32, *hgd, hgd_altif_index);
+ CP(*hgd32, *hgd, hgd_endpt_index);
+ CP(*hgd32, *hgd, hgd_report_type);
+ /* Don't copy reserved */
+ break;
+ }
+#endif
+
/* fixed-length ioctls handling */
switch (cmd) {
case FIONBIO:
@@ -562,15 +640,19 @@ hidraw_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
mtx_lock(&sc->sc_mtx);
sc->sc_state.uhid = true;
mtx_unlock(&sc->sc_mtx);
- hgd = (struct hidraw_gen_descriptor *)addr;
if (sc->sc_rdesc->len > hgd->hgd_maxlen) {
size = hgd->hgd_maxlen;
} else {
size = sc->sc_rdesc->len;
}
hgd->hgd_actlen = size;
+#ifdef COMPAT_FREEBSD32
+ if (hgd32 != NULL)
+ update_hgd32(hgd, hgd32);
+#endif
if (hgd->hgd_data == NULL)
return (0); /* descriptor length only */
+
return (copyout(sc->sc_rdesc->data, hgd->hgd_data, size));
@@ -593,7 +675,6 @@ hidraw_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
if (error != 0)
return(error);
- hgd = (struct hidraw_gen_descriptor *)addr;
buf = HIDRAW_LOCAL_ALLOC(local_buf, hgd->hgd_maxlen);
copyin(hgd->hgd_data, buf, hgd->hgd_maxlen);
/* Lock newbus around set_report_descr call */
@@ -640,7 +721,6 @@ hidraw_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
case HIDRAW_GET_REPORT:
if (!(sc->sc_fflags & FREAD))
return (EPERM);
- hgd = (struct hidraw_gen_descriptor *)addr;
switch (hgd->hgd_report_type) {
case HID_INPUT_REPORT:
size = sc->sc_rdesc->isize;
@@ -666,12 +746,17 @@ hidraw_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
if (!error)
error = copyout(buf, hgd->hgd_data, size);
HIDRAW_LOCAL_FREE(local_buf, buf);
+#ifdef COMPAT_FREEBSD32
+ /*
+ * HIDRAW_GET_REPORT is declared _IOWR, but hgd is not written
+ * so we don't call update_hgd32().
+ */
+#endif
return (error);
case HIDRAW_SET_REPORT:
if (!(sc->sc_fflags & FWRITE))
return (EPERM);
- hgd = (struct hidraw_gen_descriptor *)addr;
switch (hgd->hgd_report_type) {
case HID_INPUT_REPORT:
size = sc->sc_rdesc->isize;
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_ */