git: 2e009b460fe5 - stable/13 - hidraw(4): Implement HIDRAW_GET_DEVICEINFO ioctl

From: Vladimir Kondratyev <wulf_at_FreeBSD.org>
Date: Fri, 09 Feb 2024 21:03:05 UTC
The branch stable/13 has been updated by wulf:

URL: https://cgit.FreeBSD.org/src/commit/?id=2e009b460fe5ddbac96e12a9c3ca05bae11817bf

commit 2e009b460fe5ddbac96e12a9c3ca05bae11817bf
Author:     Vladimir Kondratyev <wulf@FreeBSD.org>
AuthorDate: 2023-08-06 11:51:08 +0000
Commit:     Vladimir Kondratyev <wulf@FreeBSD.org>
CommitDate: 2024-02-09 20:59:37 +0000

    hidraw(4): Implement HIDRAW_GET_DEVICEINFO ioctl
    
    In commit c77bfaa75051 uhid(4) gained support for ioctl from
    USB_GET_DEVICEINFO. This is used in libraries like libfido2 to
    retrieve information about a device.
    
    This commit adds binary compatible version to hidraw(4).
    
    PR:             264843
    
    (cherry picked from commit f1d955be2a7367ef755d70257c381f83b8367288)
---
 share/man/man4/hidraw.4 |  5 ++++-
 sys/dev/hid/hidraw.c    | 28 +++++++++++++++++++++++-----
 sys/dev/hid/hidraw.h    | 15 +++++++++++++++
 sys/dev/usb/usb_ioctl.h |  3 ++-
 4 files changed, 44 insertions(+), 7 deletions(-)

diff --git a/share/man/man4/hidraw.4 b/share/man/man4/hidraw.4
index 92e01a8c9a0a..9749277bca51 100644
--- a/share/man/man4/hidraw.4
+++ b/share/man/man4/hidraw.4
@@ -27,7 +27,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd July 1, 2018
+.Dd August 6, 2023
 .Dt HIDRAW 4
 .Os
 .Sh NAME
@@ -145,6 +145,9 @@ The report data begins from the second byte.
 For devices which do not use numbered reports, the report data begins at the
 first byte.
 This call may fail if the device does not support this feature.
+.It Dv HIDRAW_GET_DEVICEINFO Pq Vt "struct hidraw_device_info"
+Returns information about the device, like vendor ID and product ID.
+This call will not issue any hardware transfers.
 .El
 .Pp
 Linux
diff --git a/sys/dev/hid/hidraw.c b/sys/dev/hid/hidraw.c
index c47a1445f7af..703e16d8bf8f 100644
--- a/sys/dev/hid/hidraw.c
+++ b/sys/dev/hid/hidraw.c
@@ -564,9 +564,10 @@ hidraw_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
 #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 *hdi;
+	struct hidraw_devinfo *hd;
 	const char *devname;
 	uint32_t size;
 	int id, len;
@@ -795,6 +796,23 @@ hidraw_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
 		*(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;
+		hdi->hdi_vendor = sc->sc_hw->idVendor;
+		hdi->hdi_version = sc->sc_hw->idVersion;
+		hdi->hdi_bustype = sc->sc_hw->idBus;
+		strlcpy(hdi->hdi_name, sc->sc_hw->name,
+		    sizeof(hdi->hdi_name));
+		strlcpy(hdi->hdi_phys, device_get_nameunit(sc->sc_dev),
+		    sizeof(hdi->hdi_phys));
+		strlcpy(hdi->hdi_uniq, sc->sc_hw->serial,
+		    sizeof(hdi->hdi_uniq));
+		snprintf(hdi->hdi_release, sizeof(hdi->hdi_release), "%x.%02x",
+		    sc->sc_hw->idVersion >> 8, sc->sc_hw->idVersion & 0xff);
+		return(0);
+
 	case HIDIOCGRDESCSIZE:
 		*(int *)addr = sc->sc_hw->rdescsize;
 		return (0);
@@ -820,10 +838,10 @@ hidraw_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
 		return (error);
 
 	case HIDIOCGRAWINFO:
-		hdi = (struct hidraw_devinfo *)addr;
-		hdi->bustype = sc->sc_hw->idBus;
-		hdi->vendor = sc->sc_hw->idVendor;
-		hdi->product = sc->sc_hw->idProduct;
+		hd = (struct hidraw_devinfo *)addr;
+		hd->bustype = sc->sc_hw->idBus;
+		hd->vendor = sc->sc_hw->idVendor;
+		hd->product = sc->sc_hw->idProduct;
 		return (0);
 	}
 
diff --git a/sys/dev/hid/hidraw.h b/sys/dev/hid/hidraw.h
index 5e46597be453..4095ddb388bb 100644
--- a/sys/dev/hid/hidraw.h
+++ b/sys/dev/hid/hidraw.h
@@ -49,6 +49,20 @@ struct hidraw_gen_descriptor {
 	uint8_t reserved[8];
 };
 
+/* Compatible with usb_device_info structure */
+struct hidraw_device_info {
+	uint16_t	hdi_product;
+	uint16_t	hdi_vendor;
+	uint16_t	hdi_version;
+	uint8_t		occupied[18];	/* by usb_device_info */
+	uint16_t	hdi_bustype;
+	uint8_t		reserved[14];	/* leave space for the future */
+	char		hdi_name[128];
+	char		hdi_phys[128];
+	char		hdi_uniq[64];
+	char		hdi_release[8];	/* decrypted USB bcdDevice */
+};
+
 struct hidraw_report_descriptor {
 	uint32_t	size;
 	uint8_t		value[HID_MAX_DESCRIPTOR_SIZE];
@@ -67,6 +81,7 @@ struct hidraw_devinfo {
 #define	HIDRAW_SET_REPORT	_IOW ('U', 24, struct hidraw_gen_descriptor)
 #define	HIDRAW_GET_REPORT_ID	_IOR ('U', 25, int)
 #define	HIDRAW_SET_REPORT_DESC	_IOW ('U', 26, struct hidraw_gen_descriptor)
+#define	HIDRAW_GET_DEVICEINFO	_IOR ('U', 112, struct hidraw_device_info)
 
 /* Linux hidraw-compatible ioctl interface */
 #define	HIDIOCGRDESCSIZE	_IOR('U', 30, int)
diff --git a/sys/dev/usb/usb_ioctl.h b/sys/dev/usb/usb_ioctl.h
index ba6e5f18d0bb..6d9184723816 100644
--- a/sys/dev/usb/usb_ioctl.h
+++ b/sys/dev/usb/usb_ioctl.h
@@ -119,7 +119,8 @@ struct usb_device_info {
 	uint8_t	udi_hubport;		/* parent HUB port */
 	uint8_t	udi_power_mode;		/* see "USB_POWER_MODE_XXX" */
 	uint8_t	udi_suspended;		/* set if device is suspended */
-	uint8_t	udi_reserved[16];	/* leave space for the future */
+	uint16_t udi_bustypeNo;
+	uint8_t	udi_reserved[14];	/* leave space for the future */
 	char	udi_product[128];
 	char	udi_vendor[128];
 	char	udi_serial[64];