diff options
-rw-r--r-- | sys/dev/hid/hidraw.c | 93 | ||||
-rw-r--r-- | sys/dev/usb/input/uhid.c | 25 | ||||
-rw-r--r-- | sys/dev/usb/input/uhid_snes.c | 26 | ||||
-rw-r--r-- | sys/dev/usb/usb_dev.c | 12 | ||||
-rw-r--r-- | sys/dev/usb/usb_generic.c | 118 | ||||
-rw-r--r-- | sys/dev/usb/usb_ioctl.h | 57 |
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_ */ |