Re: git: 82e38b012cc8 - main - usbhid(4): Implement USB_REQUEST command in hid_ioctl method

From: Hans Petter Selasky <hps_at_selasky.org>
Date: Thu, 03 Mar 2022 08:47:12 UTC
On 3/3/22 00:36, Vladimir Kondratyev wrote:
> The branch main has been updated by wulf:
> 
> URL: https://cgit.FreeBSD.org/src/commit/?id=82e38b012cc832651ba195f5443e7f9fb64ce5d3
> 
> commit 82e38b012cc832651ba195f5443e7f9fb64ce5d3
> Author:     Vladimir Kondratyev <wulf@FreeBSD.org>
> AuthorDate: 2022-03-02 23:35:23 +0000
> Commit:     Vladimir Kondratyev <wulf@FreeBSD.org>
> CommitDate: 2022-03-02 23:35:23 +0000
> 
>      usbhid(4): Implement USB_REQUEST command in hid_ioctl method
>      
>      This command is intended to be compatible with USB_REQUEST ioctl.
>      It is required to perform arbitrary control endpoint requests by device
>      drivers which can switch between HID and native non-HID modes.
>      
>      MFC after:      2 month
> ---
>   sys/dev/usb/input/usbhid.c | 31 +++++++++++++++++++++++++++++++
>   1 file changed, 31 insertions(+)
> 
> diff --git a/sys/dev/usb/input/usbhid.c b/sys/dev/usb/input/usbhid.c
> index c6f2a1f24303..ed76f6291a11 100644
> --- a/sys/dev/usb/input/usbhid.c
> +++ b/sys/dev/usb/input/usbhid.c
> @@ -68,6 +68,7 @@ __FBSDID("$FreeBSD$");
>   #include <dev/usb/usbdi_util.h>
>   #include <dev/usb/usbhid.h>
>   #include <dev/usb/usb_core.h>
> +#include <dev/usb/usb_ioctl.h>
>   
>   #define	USB_DEBUG_VAR usbhid_debug
>   #include <dev/usb/usb_debug.h>
> @@ -677,6 +678,35 @@ usbhid_set_protocol(device_t dev, uint16_t protocol)
>   	return (usbhid_sync_xfer(sc, USBHID_CTRL_DT, &req, NULL));
>   }
>   

You may also want to add a call to:

static int
ugen_check_request(struct usb_device *udev, struct usb_device_request *req)
{

so that non-root drivers won't and can't do damaging commands to the device!

--HPS

> +static int
> +usbhid_ioctl(device_t dev, unsigned long cmd, uintptr_t data)
> +{
> +	struct usbhid_softc* sc = device_get_softc(dev);
> +	struct usb_ctl_request *ucr;
> +	union usbhid_device_request req;
> +	int error;
> +
> +	switch (cmd) {
> +	case USB_REQUEST:
> +		ucr = (struct usb_ctl_request *)data;
> +		req.ctrl = ucr->ucr_request;
> +		error = usbhid_xfer_check_len(
> +		    sc, USBHID_CTRL_DT, UGETW(req.ctrl.wLength));
> +		if (error)
> +			break;
> +
> +		error = usbhid_sync_xfer(
> +		    sc, USBHID_CTRL_DT, &req, ucr->ucr_data);
> +		if (error == 0)
> +			ucr->ucr_actlen = UGETW(req.ctrl.wLength);
> +		break;
> +	default:
> +		error = EINVAL;
> +	}
> +
> +	return (error);
> +}
> +
>   static void
>   usbhid_init_device_info(struct usb_attach_arg *uaa, struct hid_device_info *hw)
>   {
> @@ -848,6 +878,7 @@ static device_method_t usbhid_methods[] = {
>   	DEVMETHOD(hid_set_report,	usbhid_set_report),
>   	DEVMETHOD(hid_set_idle,		usbhid_set_idle),
>   	DEVMETHOD(hid_set_protocol,	usbhid_set_protocol),
> +	DEVMETHOD(hid_ioctl,		usbhid_ioctl),
>   
>   	DEVMETHOD_END
>   };
>