Skip to content

Commit fd6690e

Browse files
committed
hidraw(4): Add additional hidraw input/output report ioctls
to Linux hidraw compatibility API. Respective Linux commit f43d3870cafa made by Dean Camera message is: Currently the hidraw module can only read and write feature HID reports on demand, via dedicated ioctls. Input reports are read from the device through the read() interface, while output reports are written through the write interface(). This is insufficient; it is desirable in many situations to be able to read and write input and output reports through the control interface to cover additional scenarios: - Reading an input report by its report ID, to get initial state - Writing an input report, to set initial input state in the device - Reading an output report by its report ID, to obtain current state - Writing an output report by its report ID, out of band This patch adds these missing ioctl requests to read and write the remaining HID report types. Note that not all HID backends will neccesarily support this (e.g. while the USB link layer supports setting Input reports, others may not). FreeBSD native uhid(4) compatible API already has similar ioctls. MFC after: 3 days
1 parent 5959703 commit fd6690e

File tree

4 files changed

+47
-9
lines changed

4 files changed

+47
-9
lines changed

share/man/man4/hidraw.4

+8-4
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2828
.\" POSSIBILITY OF SUCH DAMAGE.
2929
.\"
30-
.Dd August 6, 2023
30+
.Dd April 27, 2025
3131
.Dt HIDRAW 4
3232
.Os
3333
.Sh NAME
@@ -206,10 +206,12 @@ into the memory
206206
specified by
207207
.Va buf .
208208
.It Dv HIDIOCGFEATURE(len) Pq Vt "void[] buf"
209-
Get a feature report from the device.
209+
.It Dv HIDIOCGINPUT(len) Pq Vt "void[] buf"
210+
.It Dv HIDIOCGOUTPUT(len) Pq Vt "void[] buf"
211+
Get respectively a feature, input or output report from the device.
210212
Copies a maximum of
211213
.Va len
212-
bytes of the feature report data into the memory specified by
214+
bytes of the report data into the memory specified by
213215
.Va buf .
214216
The first byte of the supplied buffer should be set to the report
215217
number of the requested report.
@@ -218,7 +220,9 @@ The report will be returned starting at the first byte of the buffer
218220
(ie: the report number is not returned).
219221
This call may fail if the device does not support this feature.
220222
.It Dv HIDIOCSFEATURE(len) Pq Vt "void[] buf"
221-
Set a feature Report in the device.
223+
.It Dv HIDIOCSINPUT(len) Pq Vt "void[] buf"
224+
.It Dv HIDIOCSOUTPUT(len) Pq Vt "void[] buf"
225+
Set respectively a feature, input or output Report in the device.
222226
The value of the report is specified by the
223227
.Va buf
224228
and the

sys/dev/hid/hidraw.c

+34-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Copyright (c) 1998 The NetBSD Foundation, Inc.
55
* All rights reserved.
6-
* Copyright (c) 2020 Vladimir Kondratyev <[email protected]>
6+
* Copyright (c) 2020, 2025 Vladimir Kondratyev <[email protected]>
77
*
88
* This code is derived from software contributed to The NetBSD Foundation
99
* by Lennart Augustsson ([email protected]) at
@@ -573,6 +573,7 @@ hidraw_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
573573
hid_size_t actsize;
574574
int id, len;
575575
int error = 0;
576+
uint8_t reptype;
576577

577578
DPRINTFN(2, "cmd=%lx\n", cmd);
578579

@@ -860,6 +861,8 @@ hidraw_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
860861
return (0);
861862

862863
case HIDIOCSFEATURE(0):
864+
case HIDIOCSINPUT(0):
865+
case HIDIOCSOUTPUT(0):
863866
if (!(sc->sc_fflags & FWRITE))
864867
return (EPERM);
865868
if (len < 2)
@@ -869,10 +872,24 @@ hidraw_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
869872
addr = (uint8_t *)addr + 1;
870873
len--;
871874
}
872-
return (hid_set_report(sc->sc_dev, addr, len,
873-
HID_FEATURE_REPORT, id));
875+
switch (IOCBASECMD(cmd)) {
876+
case HIDIOCSFEATURE(0):
877+
reptype = HID_FEATURE_REPORT;
878+
break;
879+
case HIDIOCSINPUT(0):
880+
reptype = HID_INPUT_REPORT;
881+
break;
882+
case HIDIOCSOUTPUT(0):
883+
reptype = HID_OUTPUT_REPORT;
884+
break;
885+
default:
886+
panic("Invalid report type");
887+
}
888+
return (hid_set_report(sc->sc_dev, addr, len, reptype, id));
874889

875890
case HIDIOCGFEATURE(0):
891+
case HIDIOCGINPUT(0):
892+
case HIDIOCGOUTPUT(0):
876893
if (!(sc->sc_fflags & FREAD))
877894
return (EPERM);
878895
if (len < 2)
@@ -882,8 +899,21 @@ hidraw_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
882899
addr = (uint8_t *)addr + 1;
883900
len--;
884901
}
902+
switch (IOCBASECMD(cmd)) {
903+
case HIDIOCGFEATURE(0):
904+
reptype = HID_FEATURE_REPORT;
905+
break;
906+
case HIDIOCGINPUT(0):
907+
reptype = HID_INPUT_REPORT;
908+
break;
909+
case HIDIOCGOUTPUT(0):
910+
reptype = HID_OUTPUT_REPORT;
911+
break;
912+
default:
913+
panic("Invalid report type");
914+
}
885915
return (hid_get_report(sc->sc_dev, addr, len, NULL,
886-
HID_FEATURE_REPORT, id));
916+
reptype, id));
887917

888918
case HIDIOCGRAWUNIQ(0):
889919
strlcpy(addr, sc->sc_hw->serial, len);

sys/dev/hid/hidraw.h

+4
Original file line numberDiff line numberDiff line change
@@ -92,5 +92,9 @@ struct hidraw_devinfo {
9292
#define HIDIOCSFEATURE(len) _IOC(IOC_IN, 'U', 35, len)
9393
#define HIDIOCGFEATURE(len) _IOC(IOC_INOUT, 'U', 36, len)
9494
#define HIDIOCGRAWUNIQ(len) _IOC(IOC_OUT, 'U', 37, len)
95+
#define HIDIOCSINPUT(len) _IOC(IOC_IN, 'U', 38, len)
96+
#define HIDIOCGINPUT(len) _IOC(IOC_INOUT, 'U', 39, len)
97+
#define HIDIOCSOUTPUT(len) _IOC(IOC_IN, 'U', 40, len)
98+
#define HIDIOCGOUTPUT(len) _IOC(IOC_INOUT, 'U', 41, len)
9599

96100
#endif /* _HID_HIDRAW_H */

sys/dev/usb/usb_ioctl.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ struct usb_gen_quirk {
239239
#define USB_DEVICESTATS _IOR ('U', 5, struct usb_device_stats)
240240
#define USB_DEVICEENUMERATE _IOW ('U', 6, int)
241241

242-
/* Generic HID device. Numbers 26 and 30-39 are occupied by hidraw. */
242+
/* Generic HID device. Numbers 26 and 30-49 are occupied by hidraw. */
243243
#define USB_GET_REPORT_DESC _IOWR('U', 21, struct usb_gen_descriptor)
244244
#define USB_SET_IMMED _IOW ('U', 22, int)
245245
#define USB_GET_REPORT _IOWR('U', 23, struct usb_gen_descriptor)

0 commit comments

Comments
 (0)