hidraw(4): Implement HIDRAW_GET_DEVICEINFO ioctl

In commit c77bfaa750 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
MFC after:	1 month
Requested by:	grembo
This commit is contained in:
Vladimir Kondratyev 2023-08-06 14:51:08 +03:00
parent 12f5f11477
commit f1d955be2a
4 changed files with 44 additions and 7 deletions

View File

@ -29,7 +29,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd July 1, 2018
.Dd August 6, 2023
.Dt HIDRAW 4
.Os
.Sh NAME
@ -147,6 +147,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

View File

@ -566,9 +566,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;
@ -788,6 +789,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);
@ -813,10 +831,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);
}

View File

@ -51,6 +51,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];
@ -69,6 +83,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)

View File

@ -120,7 +120,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];