FreeBSD Bugzilla – Attachment 255239 Details for
Bug 282790
hidraw(4) - Regression in documented behavior of HIDRAW_GET_REPORT.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch to hidraw.c, uhid.c correcting the defect.
hid.patch (text/plain), 7.33 KB, created by
Matthew.Nygard.Dodd
on 2024-11-17 16:32:08 UTC
(
hide
)
Description:
Patch to hidraw.c, uhid.c correcting the defect.
Filename:
MIME Type:
Creator:
Matthew.Nygard.Dodd
Created:
2024-11-17 16:32:08 UTC
Size:
7.33 KB
patch
obsolete
>diff --git a/sys/dev/hid/hidraw.c b/sys/dev/hid/hidraw.c >index 6a05b633cfc8..5fc553699b6f 100644 >--- a/sys/dev/hid/hidraw.c >+++ b/sys/dev/hid/hidraw.c >@@ -530,85 +530,85 @@ hidraw_write(struct cdev *dev, struct uio *uio, int flag) > error = hid_write(sc->sc_dev, buf, size); > HIDRAW_LOCAL_FREE(local_buf, buf); > > 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_device_info *hdi; > struct hidraw_gen_descriptor *hgd; > struct hidraw_report_descriptor *hrd; > struct hidraw_devinfo *hd; > const char *devname; >- uint32_t size; >+ uint32_t size, actsize; > int id, len; > int error = 0; > > DPRINTFN(2, "cmd=%lx\n", cmd); > > sc = dev->si_drv1; > if (sc == NULL) > return (EIO); > > hgd = (struct hidraw_gen_descriptor *)addr; > > #ifdef COMPAT_FREEBSD32 > 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: > /* All handled in the upper FS layer. */ > return (0); > >@@ -708,94 +708,94 @@ hidraw_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, > error = hid_get_report(sc->sc_dev, buf, size, NULL, > HID_INPUT_REPORT, sc->sc_rdesc->iid); > HIDRAW_LOCAL_FREE(local_buf, buf); > if (error) > return (EOPNOTSUPP); > > mtx_lock(&sc->sc_mtx); > sc->sc_state.immed = true; > mtx_unlock(&sc->sc_mtx); > } else { > mtx_lock(&sc->sc_mtx); > sc->sc_state.immed = false; > mtx_unlock(&sc->sc_mtx); > } > return (0); > > case HIDRAW_GET_REPORT: > if (!(sc->sc_fflags & FREAD)) > return (EPERM); > switch (hgd->hgd_report_type) { > case HID_INPUT_REPORT: > size = sc->sc_rdesc->isize; > id = sc->sc_rdesc->iid; > break; > case HID_OUTPUT_REPORT: > size = sc->sc_rdesc->osize; > id = sc->sc_rdesc->oid; > break; > case HID_FEATURE_REPORT: > size = sc->sc_rdesc->fsize; > id = sc->sc_rdesc->fid; > break; > default: > return (EINVAL); > } > if (id != 0) { > error = copyin(hgd->hgd_data, &id, 1); > if (error != 0) > return (error); > } > size = MIN(hgd->hgd_maxlen, size); > buf = HIDRAW_LOCAL_ALLOC(local_buf, size); >- error = hid_get_report(sc->sc_dev, buf, size, NULL, >+ actsize = 0; >+ error = hid_get_report(sc->sc_dev, buf, size, &actsize, > hgd->hgd_report_type, id); > if (!error) >- error = copyout(buf, hgd->hgd_data, size); >+ error = copyout(buf, hgd->hgd_data, actsize); > HIDRAW_LOCAL_FREE(local_buf, buf); >+ hgd->hgd_actlen = actsize; > #ifdef COMPAT_FREEBSD32 >- /* >- * HIDRAW_GET_REPORT is declared _IOWR, but hgd is not written >- * so we don't call update_hgd32(). >- */ >+ if (hgd32 != NULL) >+ update_hgd32(hgd, hgd32); > #endif > return (error); > > case HIDRAW_SET_REPORT: > if (!(sc->sc_fflags & FWRITE)) > return (EPERM); > switch (hgd->hgd_report_type) { > case HID_INPUT_REPORT: > size = sc->sc_rdesc->isize; > id = sc->sc_rdesc->iid; > break; > case HID_OUTPUT_REPORT: > size = sc->sc_rdesc->osize; > id = sc->sc_rdesc->oid; > break; > case HID_FEATURE_REPORT: > size = sc->sc_rdesc->fsize; > id = sc->sc_rdesc->fid; > break; > default: > return (EINVAL); > } > size = MIN(hgd->hgd_maxlen, size); > buf = HIDRAW_LOCAL_ALLOC(local_buf, size); > error = copyin(hgd->hgd_data, buf, size); > if (error == 0) { > if (id != 0) > id = *(uint8_t *)buf; > error = hid_set_report(sc->sc_dev, buf, size, > hgd->hgd_report_type, id); > } > HIDRAW_LOCAL_FREE(local_buf, buf); > return (error); > > case HIDRAW_GET_REPORT_ID: > *(int *)addr = 0; /* XXX: we only support reportid 0? */ > return (0); > > case HIDRAW_GET_DEVICEINFO: > hdi = (struct hidraw_device_info *)addr; > bzero(hdi, sizeof(struct hidraw_device_info)); > hdi->hdi_product = sc->sc_hw->idProduct; >diff --git a/sys/dev/usb/input/uhid.c b/sys/dev/usb/input/uhid.c >index 863e04f4e52b..098ec4364df7 100644 >--- a/sys/dev/usb/input/uhid.c >+++ b/sys/dev/usb/input/uhid.c >@@ -594,89 +594,91 @@ uhid_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr, > error = EPERM; > break; > } > if (*(int *)addr) { > /* do a test read */ > > error = uhid_get_report(sc, UHID_INPUT_REPORT, > sc->sc_iid, NULL, NULL, sc->sc_isize); > if (error) { > break; > } > mtx_lock(&sc->sc_mtx); > sc->sc_flags |= UHID_FLAG_IMMED; > mtx_unlock(&sc->sc_mtx); > } else { > mtx_lock(&sc->sc_mtx); > sc->sc_flags &= ~UHID_FLAG_IMMED; > mtx_unlock(&sc->sc_mtx); > } > break; > > case USB_GET_REPORT: > if (!(fflags & FREAD)) { > error = EPERM; > break; > } > switch (ugd->ugd_report_type) { > case UHID_INPUT_REPORT: > size = sc->sc_isize; > id = sc->sc_iid; > break; > case UHID_OUTPUT_REPORT: > size = sc->sc_osize; > id = sc->sc_oid; > break; > case UHID_FEATURE_REPORT: > size = sc->sc_fsize; > id = sc->sc_fid; > break; > default: > return (EINVAL); > } >+ size = imin(ugd->ugd_maxlen, size); > if (id != 0) > error = copyin(ugd->ugd_data, &id, 1); > if (error == 0) > error = uhid_get_report(sc, ugd->ugd_report_type, id, >- NULL, ugd->ugd_data, imin(ugd->ugd_maxlen, size)); >+ NULL, ugd->ugd_data, size); >+ ugd->ugd_actlen = size; > break; > > case USB_SET_REPORT: > if (!(fflags & FWRITE)) { > error = EPERM; > break; > } > switch (ugd->ugd_report_type) { > case UHID_INPUT_REPORT: > size = sc->sc_isize; > id = sc->sc_iid; > break; > case UHID_OUTPUT_REPORT: > size = sc->sc_osize; > id = sc->sc_oid; > break; > case UHID_FEATURE_REPORT: > size = sc->sc_fsize; > id = sc->sc_fid; > break; > default: > return (EINVAL); > } > if (id != 0) > error = copyin(ugd->ugd_data, &id, 1); > if (error == 0) > error = uhid_set_report(sc, ugd->ugd_report_type, id, > NULL, ugd->ugd_data, imin(ugd->ugd_maxlen, size)); > break; > > case USB_GET_REPORT_ID: > *(int *)addr = 0; /* XXX: we only support reportid 0? */ > break; > > default: > error = ENOIOCTL; > break; > } > #ifdef COMPAT_FREEBSD32 > if (ugd32 != NULL) > update_usb_gen_descriptor32(ugd32, ugd); > #endif
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 282790
:
255207
|
255223
| 255239