diff options
Diffstat (limited to 'sys/dev/usb/usb_generic.c')
-rw-r--r-- | sys/dev/usb/usb_generic.c | 118 |
1 files changed, 118 insertions, 0 deletions
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 */ |