hid: Import hidmap-based drivers written by Greg V

This change includes:

hpen    - Generic / MS Windows compatible HID pen tablet driver.
hgame   - Generic game controller and joystick driver.
xb360gp - Xbox360-compatible game controller driver.

Submitted by:	Greg V <greg_unrelenting.technology>
Reviewed by:	hselasky (as part of D27993)
This commit is contained in:
Vladimir Kondratyev 2020-10-15 01:02:15 +03:00
parent afd590d9e5
commit d97d5c0ce8
13 changed files with 1036 additions and 1 deletions

View file

@ -181,6 +181,7 @@ MAN= aac.4 \
h_ertt.4 \
hconf.4 \
hcons.4 \
hgame.4 \
hidbus.4 \
hidquirk.4 \
hidraw.4 \
@ -188,6 +189,7 @@ MAN= aac.4 \
hkbd.4 \
hms.4 \
hmt.4 \
hpen.4 \
hpet.4 \
${_hpt27xx.4} \
${_hptiop.4} \
@ -592,6 +594,7 @@ MAN= aac.4 \
wmt.4 \
${_wpi.4} \
wsp.4 \
xb360gp.4 \
${_xen.4} \
xhci.4 \
xl.4 \

105
share/man/man4/hgame.4 Normal file
View file

@ -0,0 +1,105 @@
.\" Copyright (c) 2020 Vladimir Kondratyev <wulf@FreeBSD.org>
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd September 14, 2020
.Dt HGAME 4
.Os
.Sh NAME
.Nm hgame
.Nd Generic HID game controller (joystick/gamepad) driver
.Sh SYNOPSIS
To compile this driver into the kernel,
place the following lines in your
kernel configuration file:
.Bd -ragged -offset indent
.Cd "device hgame"
.Cd "device hid"
.Cd "device hidbus"
.Cd "device hidmap"
.Cd "device evdev"
.Ed
.Pp
Alternatively, to load the driver as a
module at boot time, place the following line in
.Xr loader.conf 5 :
.Bd -literal -offset indent
hgame_load="YES"
.Ed
.Sh DESCRIPTION
The
.Nm
driver provides support for generic game controllers (joysticks/gamepads)
that attach to the HID transport backend.
See
.Xr iichid 4
or
.Xr usbhid 4 .
.Pp
The
.Pa /dev/input/event*
device presents the game controller as a
.Ar evdev
type device.
.Sh SYSCTL VARIABLES
The following variable is available as both
.Xr sysctl 8
variable and
.Xr loader 8
tunable:
.Bl -tag -width indent
.It Va dev.hgame.X.debug
Debug output level, where 0 is debugging disabled and larger values increase
debug message verbosity.
Default is 0.
.El
.Pp
It's default value is set with
.Xr loader 8
tunable:
.Bl -tag -width indent
.It Va hw.hid.hgame.debug
.El
.Sh FILES
.Bl -tag -width /dev/input/event* -compact
.It Pa /dev/input/event*
input event device node.
.El
.Sh SEE ALSO
.Xr iichid 4 ,
.Xr usbhid 4
.Sh HISTORY
The
.Nm
driver first appeared in
.Fx 13.0.
.Sh AUTHORS
.An -nosplit
The
.Nm
driver was written by
.An Greg V Aq Mt greg@unrelenting.technology .
.Pp
This manual page was written by
.An Vladimir Kondratyev Aq Mt wulf@FreeBSD.org .

112
share/man/man4/hpen.4 Normal file
View file

@ -0,0 +1,112 @@
.\" Copyright (c) 2020 Vladimir Kondratyev <wulf@FreeBSD.org>
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd September 14, 2020
.Dt HPEN 4
.Os
.Sh NAME
.Nm hpen
.Nd MS Windows compatible HID pen tablet driver
.Sh SYNOPSIS
To compile this driver into the kernel,
place the following lines in your
kernel configuration file:
.Bd -ragged -offset indent
.Cd "device hpen"
.Cd "device hid"
.Cd "device hidbus"
.Cd "device hidmap"
.Cd "device evdev"
.Ed
.Pp
Alternatively, to load the driver as a
module at boot time, place the following line in
.Xr loader.conf 5 :
.Bd -literal -offset indent
hpen_load="YES"
.Ed
.Sh DESCRIPTION
The
.Nm
driver provides support for generic MS Windows compatible HID pen tablet
and digitizer that attach to the HID transport backend.
See
.Xr iichid 4
or
.Xr usbhid 4 .
.Pp
The
.Pa /dev/input/event*
device presents the pen as a
.Ar evdev
type device.
.Sh SYSCTL VARIABLES
The following variable is available as both
.Xr sysctl 8
variable and
.Xr loader 8
tunable:
.Bl -tag -width indent
.It Va dev.hpen.X.debug
Debug output level, where 0 is debugging disabled and larger values increase
debug message verbosity.
Default is 0.
.El
.Pp
It's default value is set with
.Xr loader 8
tunable:
.Bl -tag -width indent
.It Va hw.hid.hpen.debug
.El
.Sh FILES
.Bl -tag -width /dev/input/event* -compact
.It Pa /dev/input/event*
input event device node.
.El
.Sh SEE ALSO
.Xr iichid 4 ,
.Xr usbhid 4 ,
.Xr xorg.conf 5 Pq Pa ports/x11/xorg
.Sh BUGS
.Nm
cannot act like
.Xr sysmouse 4 .
.Pp
Pen battery charge level reporting is not supported.
.Sh HISTORY
The
.Nm
driver first appeared in
.Fx 13.0.
.Sh AUTHORS
.An -nosplit
The
.Nm
driver was written by
.An Greg V Aq Mt greg@unrelenting.technology .
.Pp
This manual page was written by
.An Vladimir Kondratyev Aq Mt wulf@FreeBSD.org .

98
share/man/man4/xb360gp.4 Normal file
View file

@ -0,0 +1,98 @@
.\" Copyright (c) 2020 Vladimir Kondratyev <wulf@FreeBSD.org>
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd September 16, 2020
.Dt XB360GP 4
.Os
.Sh NAME
.Nm xb360gp
.Nd XBox 360 gamepad driver
.Sh SYNOPSIS
To compile this driver into the kernel,
place the following lines in your
kernel configuration file:
.Bd -ragged -offset indent
.Cd "device xb360gp"
.Cd "device hgame"
.Cd "device hid"
.Cd "device hidbus"
.Cd "device hidmap"
.Cd "device evdev"
.Ed
.Pp
Alternatively, to load the driver as a
module at boot time, place the following line in
.Xr loader.conf 5 :
.Bd -literal -offset indent
xb360gp_load="YES"
.Ed
.Sh DESCRIPTION
The
.Nm
driver provides support for XBox 360 gamepad driver.
.Pp
The
.Pa /dev/input/event*
device presents the game controller as a
.Ar evdev
type device.
.Sh SYSCTL VARIABLES
The following variable is available as both
.Xr sysctl 8
variable and
.Xr loader 8
tunable:
.Bl -tag -width indent
.It Va dev.xb360gp.X.debug
Debug output level, where 0 is debugging disabled and larger values increase
debug message verbosity.
Default is 0.
.El
.Pp
It's default value is set with
.Xr loader 8
tunable:
.Bl -tag -width indent
.It Va hw.hid.xb360gp.debug
.El
.Sh FILES
.Bl -tag -width /dev/input/event* -compact
.It Pa /dev/input/event*
input event device node.
.El
.Sh HISTORY
The
.Nm
driver first appeared in
.Fx 13.0.
.Sh AUTHORS
.An -nosplit
The
.Nm
driver was written by
.An Greg V Aq Mt greg@unrelenting.technology .
.Pp
This manual page was written by
.An Vladimir Kondratyev Aq Mt wulf@FreeBSD.org .

View file

@ -1817,6 +1817,7 @@ dev/gpio/gpiopps.c optional gpiopps fdt
dev/gpio/ofw_gpiobus.c optional fdt gpio
dev/hid/hconf.c optional hconf
dev/hid/hcons.c optional hcons
dev/hid/hgame.c optional hgame
dev/hid/hid.c optional hid
dev/hid/hid_if.m optional hid
dev/hid/hidbus.c optional hidbus
@ -1826,8 +1827,10 @@ dev/hid/hidraw.c optional hidraw
dev/hid/hkbd.c optional hkbd
dev/hid/hms.c optional hms
dev/hid/hmt.c optional hmt hconf
dev/hid/hpen.c optional hpen
dev/hid/hsctrl.c optional hsctrl
dev/hid/ps4dshock.c optional ps4dshock
dev/hid/xb360gp.c optional xb360gp
dev/hifn/hifn7751.c optional hifn
dev/hptiop/hptiop.c optional hptiop scbus
dev/hwpmc/hwpmc_logging.c optional hwpmc

200
sys/dev/hid/hgame.c Normal file
View file

@ -0,0 +1,200 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2020 Vladimir Kondratyev <wulf@FreeBSD.org>
* Copyright (c) 2020 Greg V <greg@unrelenting.technology>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* Generic HID game controller (joystick/gamepad) driver,
*/
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/sysctl.h>
#include <dev/evdev/input.h>
#include <dev/evdev/evdev.h>
#include <dev/hid/hgame.h>
#include <dev/hid/hid.h>
#include <dev/hid/hidbus.h>
#include <dev/hid/hidquirk.h>
#include <dev/hid/hidmap.h>
#define HGAME_MAP_BRG(number_from, number_to, code) \
{ HIDMAP_KEY_RANGE(HUP_BUTTON, number_from, number_to, code) }
#define HGAME_MAP_ABS(usage, code) \
{ HIDMAP_ABS(HUP_GENERIC_DESKTOP, HUG_##usage, code) }
#define HGAME_MAP_CRG(usage_from, usage_to, callback) \
{ HIDMAP_ANY_CB_RANGE(HUP_GENERIC_DESKTOP, \
HUG_##usage_from, HUG_##usage_to, callback) }
#define HGAME_FINALCB(cb) \
{ HIDMAP_FINAL_CB(&cb) }
static const struct hidmap_item hgame_map[] = {
HGAME_MAP_BRG(1, 16, BTN_TRIGGER),
HGAME_MAP_ABS(X, ABS_X),
HGAME_MAP_ABS(Y, ABS_Y),
HGAME_MAP_ABS(Z, ABS_Z),
HGAME_MAP_ABS(RX, ABS_RX),
HGAME_MAP_ABS(RY, ABS_RY),
HGAME_MAP_ABS(RZ, ABS_RZ),
HGAME_MAP_ABS(HAT_SWITCH, ABS_HAT0X),
HGAME_MAP_CRG(D_PAD_UP, D_PAD_LEFT, hgame_dpad_cb),
HGAME_MAP_BRG(17, 57, BTN_TRIGGER_HAPPY),
HGAME_FINALCB( hgame_final_cb),
};
static const struct hid_device_id hgame_devs[] = {
{ HID_TLC(HUP_GENERIC_DESKTOP, HUG_JOYSTICK),
HID_DRIVER_INFO(HUG_JOYSTICK) },
{ HID_TLC(HUP_GENERIC_DESKTOP, HUG_GAME_PAD),
HID_DRIVER_INFO(HUG_GAME_PAD) },
};
/*
* Emulate the hat switch report via the D-pad usages
* found on XInput/XBox style devices
*/
int
hgame_dpad_cb(HIDMAP_CB_ARGS)
{
struct hgame_softc *sc = HIDMAP_CB_GET_SOFTC();
struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV();
int32_t data;
switch (HIDMAP_CB_GET_STATE()) {
case HIDMAP_CB_IS_ATTACHING:
HIDMAP_CB_UDATA64 = HID_GET_USAGE(ctx.hi->usage);
evdev_support_event(evdev, EV_ABS);
evdev_support_abs(evdev, ABS_HAT0X, -1, 1, 0, 0, 0);
evdev_support_abs(evdev, ABS_HAT0Y, -1, 1, 0, 0, 0);
break;
case HIDMAP_CB_IS_RUNNING:
data = ctx.data;
switch (HIDMAP_CB_UDATA64) {
case HUG_D_PAD_UP:
if (sc->dpad_down)
return (ENOMSG);
evdev_push_abs(evdev, ABS_HAT0Y, (data == 0) ? 0 : -1);
sc->dpad_up = (data != 0);
break;
case HUG_D_PAD_DOWN:
if (sc->dpad_up)
return (ENOMSG);
evdev_push_abs(evdev, ABS_HAT0Y, (data == 0) ? 0 : 1);
sc->dpad_down = (data != 0);
break;
case HUG_D_PAD_RIGHT:
if (sc->dpad_left)
return (ENOMSG);
evdev_push_abs(evdev, ABS_HAT0X, (data == 0) ? 0 : 1);
sc->dpad_right = (data != 0);
break;
case HUG_D_PAD_LEFT:
if (sc->dpad_right)
return (ENOMSG);
evdev_push_abs(evdev, ABS_HAT0X, (data == 0) ? 0 : -1);
sc->dpad_left = (data != 0);
break;
}
}
return (0);
}
int
hgame_final_cb(HIDMAP_CB_ARGS)
{
struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV();
if (HIDMAP_CB_GET_STATE() == HIDMAP_CB_IS_ATTACHING)
evdev_support_prop(evdev, INPUT_PROP_DIRECT);
/* Do not execute callback at interrupt handler and detach */
return (ENOSYS);
}
static int
hgame_probe(device_t dev)
{
const struct hid_device_info *hw = hid_get_device_info(dev);
struct hgame_softc *sc = device_get_softc(dev);
int error;
if (hid_test_quirk(hw, HQ_IS_XBOX360GP))
return(ENXIO);
error = HIDMAP_PROBE(&sc->hm, dev, hgame_devs, hgame_map, NULL);
if (error > 0)
return (error);
hidbus_set_desc(dev, hidbus_get_driver_info(dev) == HUG_GAME_PAD ?
"Gamepad" : "Joystick");
return (BUS_PROBE_GENERIC);
}
static int
hgame_attach(device_t dev)
{
struct hgame_softc *sc = device_get_softc(dev);
return (hidmap_attach(&sc->hm));
}
static int
hgame_detach(device_t dev)
{
struct hgame_softc *sc = device_get_softc(dev);
return (hidmap_detach(&sc->hm));
}
static devclass_t hgame_devclass;
static device_method_t hgame_methods[] = {
DEVMETHOD(device_probe, hgame_probe),
DEVMETHOD(device_attach, hgame_attach),
DEVMETHOD(device_detach, hgame_detach),
DEVMETHOD_END
};
DEFINE_CLASS_0(hgame, hgame_driver, hgame_methods, sizeof(struct hgame_softc));
DRIVER_MODULE(hgame, hidbus, hgame_driver, hgame_devclass, NULL, 0);
MODULE_DEPEND(hgame, hid, 1, 1, 1);
MODULE_DEPEND(hgame, hidbus, 1, 1, 1);
MODULE_DEPEND(hgame, hidmap, 1, 1, 1);
MODULE_DEPEND(hgame, evdev, 1, 1, 1);
MODULE_VERSION(hgame, 1);
HID_PNP_INFO(hgame_devs);

45
sys/dev/hid/hgame.h Normal file
View file

@ -0,0 +1,45 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2020 Vladimir Kondratyev <wulf@FreeBSD.org>
* Copyright (c) 2020 Greg V <greg@unrelenting.technology>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _HID_HGAME_H_
#define _HID_HGAME_H_
#include <dev/hid/hidmap.h>
hidmap_cb_t hgame_dpad_cb;
hidmap_cb_t hgame_final_cb;
struct hgame_softc {
struct hidmap hm;
bool dpad_up;
bool dpad_down;
bool dpad_right;
bool dpad_left;
};
#endif /* !_HGAME_H_ */

256
sys/dev/hid/hpen.c Normal file
View file

@ -0,0 +1,256 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2019 Vladimir Kondratyev <wulf@FreeBSD.org>
* Copyright (c) 2019 Greg V <greg@unrelenting.technology>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* Generic / MS Windows compatible HID pen tablet driver:
* https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/required-hid-top-level-collections
*
* Tested on: Wacom WCOM50C1 (Google Pixelbook "eve")
*/
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/sysctl.h>
#include <dev/evdev/input.h>
#include <dev/evdev/evdev.h>
#include <dev/hid/hid.h>
#include <dev/hid/hidbus.h>
#include <dev/hid/hidmap.h>
#include <dev/hid/hidrdesc.h>
#include "usbdevs.h"
static const uint8_t hpen_graphire_report_descr[] =
{ HID_GRAPHIRE_REPORT_DESCR() };
static const uint8_t hpen_graphire3_4x5_report_descr[] =
{ HID_GRAPHIRE3_4X5_REPORT_DESCR() };
static hidmap_cb_t hpen_battery_strenght_cb;
static hidmap_cb_t hpen_final_digi_cb;
static hidmap_cb_t hpen_final_pen_cb;
#define HPEN_MAP_BUT(usage, code) \
HIDMAP_KEY(HUP_DIGITIZERS, HUD_##usage, code)
#define HPEN_MAP_ABS(usage, code) \
HIDMAP_ABS(HUP_DIGITIZERS, HUD_##usage, code)
#define HPEN_MAP_ABS_GD(usage, code) \
HIDMAP_ABS(HUP_GENERIC_DESKTOP, HUG_##usage, code)
#define HPEN_MAP_ABS_CB(usage, cb) \
HIDMAP_ABS_CB(HUP_DIGITIZERS, HUD_##usage, &cb)
/* Generic map digitizer page map according to hut1_12v2.pdf */
static const struct hidmap_item hpen_map_digi[] = {
{ HPEN_MAP_ABS_GD(X, ABS_X), .required = true },
{ HPEN_MAP_ABS_GD(Y, ABS_Y), .required = true },
{ HPEN_MAP_ABS( TIP_PRESSURE, ABS_PRESSURE) },
{ HPEN_MAP_ABS( X_TILT, ABS_TILT_X) },
{ HPEN_MAP_ABS( Y_TILT, ABS_TILT_Y) },
{ HPEN_MAP_ABS_CB(BATTERY_STRENGTH, hpen_battery_strenght_cb) },
{ HPEN_MAP_BUT( TOUCH, BTN_TOUCH) },
{ HPEN_MAP_BUT( TIP_SWITCH, BTN_TOUCH) },
{ HPEN_MAP_BUT( SEC_TIP_SWITCH, BTN_TOUCH) },
{ HPEN_MAP_BUT( IN_RANGE, BTN_TOOL_PEN) },
{ HPEN_MAP_BUT( BARREL_SWITCH, BTN_STYLUS) },
{ HPEN_MAP_BUT( INVERT, BTN_TOOL_RUBBER) },
{ HPEN_MAP_BUT( ERASER, BTN_TOUCH) },
{ HPEN_MAP_BUT( TABLET_PICK, BTN_STYLUS2) },
{ HPEN_MAP_BUT( SEC_BARREL_SWITCH,BTN_STYLUS2) },
{ HIDMAP_FINAL_CB( &hpen_final_digi_cb) },
};
/* Microsoft-standardized pen support */
static const struct hidmap_item hpen_map_pen[] = {
{ HPEN_MAP_ABS_GD(X, ABS_X), .required = true },
{ HPEN_MAP_ABS_GD(Y, ABS_Y), .required = true },
{ HPEN_MAP_ABS( TIP_PRESSURE, ABS_PRESSURE), .required = true },
{ HPEN_MAP_ABS( X_TILT, ABS_TILT_X) },
{ HPEN_MAP_ABS( Y_TILT, ABS_TILT_Y) },
{ HPEN_MAP_ABS_CB(BATTERY_STRENGTH, hpen_battery_strenght_cb) },
{ HPEN_MAP_BUT( TIP_SWITCH, BTN_TOUCH), .required = true },
{ HPEN_MAP_BUT( IN_RANGE, BTN_TOOL_PEN), .required = true },
{ HPEN_MAP_BUT( BARREL_SWITCH, BTN_STYLUS) },
{ HPEN_MAP_BUT( INVERT, BTN_TOOL_RUBBER), .required = true },
{ HPEN_MAP_BUT( ERASER, BTN_TOUCH), .required = true },
{ HIDMAP_FINAL_CB( &hpen_final_pen_cb) },
};
static const struct hid_device_id hpen_devs[] = {
{ HID_TLC(HUP_DIGITIZERS, HUD_DIGITIZER) },
{ HID_TLC(HUP_DIGITIZERS, HUD_PEN) },
};
static int
hpen_battery_strenght_cb(HIDMAP_CB_ARGS)
{
struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV();
int32_t data;
switch (HIDMAP_CB_GET_STATE()) {
case HIDMAP_CB_IS_ATTACHING:
evdev_support_event(evdev, EV_PWR);
/* TODO */
break;
case HIDMAP_CB_IS_RUNNING:
data = ctx.data;
/* TODO */
}
return (0);
}
static int
hpen_final_digi_cb(HIDMAP_CB_ARGS)
{
struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV();
if (HIDMAP_CB_GET_STATE() == HIDMAP_CB_IS_ATTACHING)
evdev_support_prop(evdev, INPUT_PROP_POINTER);
/* Do not execute callback at interrupt handler and detach */
return (ENOSYS);
}
static int
hpen_final_pen_cb(HIDMAP_CB_ARGS)
{
struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV();
if (HIDMAP_CB_GET_STATE() == HIDMAP_CB_IS_ATTACHING)
evdev_support_prop(evdev, INPUT_PROP_DIRECT);
/* Do not execute callback at interrupt handler and detach */
return (ENOSYS);
}
static void
hpen_identify(driver_t *driver, device_t parent)
{
const struct hid_device_info *hw = hid_get_device_info(parent);
/* the report descriptor for the Wacom Graphire is broken */
if (hw->idBus == BUS_USB && hw->idVendor == USB_VENDOR_WACOM) {
switch (hw->idProduct) {
case USB_PRODUCT_WACOM_GRAPHIRE:
hid_set_report_descr(parent,
hpen_graphire_report_descr,
sizeof(hpen_graphire_report_descr));
break;
case USB_PRODUCT_WACOM_GRAPHIRE3_4X5:
hid_set_report_descr(parent,
hpen_graphire3_4x5_report_descr,
sizeof(hpen_graphire3_4x5_report_descr));
break;
}
}
}
static int
hpen_probe(device_t dev)
{
struct hidmap *hm = device_get_softc(dev);
int error;
bool is_pen;
error = HIDBUS_LOOKUP_DRIVER_INFO(dev, hpen_devs);
if (error != 0)
return (error);
hidmap_set_dev(hm, dev);
/* Check if report descriptor belongs to a HID tablet device */
is_pen = hidbus_get_usage(dev) == HID_USAGE2(HUP_DIGITIZERS, HUD_PEN);
error = is_pen
? HIDMAP_ADD_MAP(hm, hpen_map_pen, NULL)
: HIDMAP_ADD_MAP(hm, hpen_map_digi, NULL);
if (error != 0)
return (error);
hidbus_set_desc(dev, is_pen ? "Pen" : "Digitizer");
return (BUS_PROBE_DEFAULT);
}
static int
hpen_attach(device_t dev)
{
const struct hid_device_info *hw = hid_get_device_info(dev);
struct hidmap *hm = device_get_softc(dev);
int error;
if (hw->idBus == BUS_USB && hw->idVendor == USB_VENDOR_WACOM &&
hw->idProduct == USB_PRODUCT_WACOM_GRAPHIRE3_4X5) {
/*
* The Graphire3 needs 0x0202 to be written to
* feature report ID 2 before it'll start
* returning digitizer data.
*/
static const uint8_t reportbuf[3] = {2, 2, 2};
error = hid_set_report(dev, reportbuf, sizeof(reportbuf),
HID_FEATURE_REPORT, reportbuf[0]);
if (error)
device_printf(dev, "set feature report failed, "
"error=%d (ignored)\n", error);
}
return (hidmap_attach(hm));
}
static int
hpen_detach(device_t dev)
{
return (hidmap_detach(device_get_softc(dev)));
}
static devclass_t hpen_devclass;
static device_method_t hpen_methods[] = {
DEVMETHOD(device_identify, hpen_identify),
DEVMETHOD(device_probe, hpen_probe),
DEVMETHOD(device_attach, hpen_attach),
DEVMETHOD(device_detach, hpen_detach),
DEVMETHOD_END
};
DEFINE_CLASS_0(hpen, hpen_driver, hpen_methods, sizeof(struct hidmap));
DRIVER_MODULE(hpen, hidbus, hpen_driver, hpen_devclass, NULL, 0);
MODULE_DEPEND(hpen, hid, 1, 1, 1);
MODULE_DEPEND(hpen, hidbus, 1, 1, 1);
MODULE_DEPEND(hpen, hidmap, 1, 1, 1);
MODULE_DEPEND(hpen, evdev, 1, 1, 1);
MODULE_VERSION(hpen, 1);
HID_PNP_INFO(hpen_devs);

183
sys/dev/hid/xb360gp.c Normal file
View file

@ -0,0 +1,183 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2020 Vladimir Kondratyev <wulf@FreeBSD.org>
* Copyright (c) 2020 Greg V <greg@unrelenting.technology>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* XBox 360 gamepad driver thanks to the custom descriptor in usbhid.
*
* Tested on: SVEN GC-5070 in both XInput (XBox 360) and DirectInput modes
*/
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/sysctl.h>
#include <dev/evdev/input.h>
#include <dev/evdev/evdev.h>
#include <dev/hid/hgame.h>
#include <dev/hid/hid.h>
#include <dev/hid/hidbus.h>
#include <dev/hid/hidmap.h>
#include <dev/hid/hidquirk.h>
#include <dev/hid/hidrdesc.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
static const uint8_t xb360gp_rdesc[] = {HID_XB360GP_REPORT_DESCR()};
#define XB360GP_MAP_BUT(number, code) \
{ HIDMAP_KEY(HUP_BUTTON, number, code) }
#define XB360GP_MAP_ABS(usage, code) \
{ HIDMAP_ABS(HUP_GENERIC_DESKTOP, HUG_##usage, code) }
#define XB360GP_MAP_ABS_FLT(usage, code) \
{ HIDMAP_ABS(HUP_GENERIC_DESKTOP, HUG_##usage, code), \
.fuzz = 16, .flat = 128 }
#define XB360GP_MAP_ABS_INV(usage, code) \
{ HIDMAP_ABS(HUP_GENERIC_DESKTOP, HUG_##usage, code), \
.fuzz = 16, .flat = 128, .invert_value = true }
#define XB360GP_MAP_CRG(usage_from, usage_to, callback) \
{ HIDMAP_ANY_CB_RANGE(HUP_GENERIC_DESKTOP, \
HUG_##usage_from, HUG_##usage_to, callback) }
#define XB360GP_FINALCB(cb) \
{ HIDMAP_FINAL_CB(&cb) }
/* Customized to match usbhid's XBox 360 descriptor */
static const struct hidmap_item xb360gp_map[] = {
XB360GP_MAP_BUT(1, BTN_SOUTH),
XB360GP_MAP_BUT(2, BTN_EAST),
XB360GP_MAP_BUT(3, BTN_WEST),
XB360GP_MAP_BUT(4, BTN_NORTH),
XB360GP_MAP_BUT(5, BTN_TL),
XB360GP_MAP_BUT(6, BTN_TR),
XB360GP_MAP_BUT(7, BTN_SELECT),
XB360GP_MAP_BUT(8, BTN_START),
XB360GP_MAP_BUT(9, BTN_THUMBL),
XB360GP_MAP_BUT(10, BTN_THUMBR),
XB360GP_MAP_BUT(11, BTN_MODE),
XB360GP_MAP_CRG(D_PAD_UP, D_PAD_LEFT, hgame_dpad_cb),
XB360GP_MAP_ABS_FLT(X, ABS_X),
XB360GP_MAP_ABS_INV(Y, ABS_Y),
XB360GP_MAP_ABS(Z, ABS_Z),
XB360GP_MAP_ABS_FLT(RX, ABS_RX),
XB360GP_MAP_ABS_INV(RY, ABS_RY),
XB360GP_MAP_ABS(RZ, ABS_RZ),
XB360GP_FINALCB( hgame_final_cb),
};
static const STRUCT_USB_HOST_ID xb360gp_devs[] = {
/* the Xbox 360 gamepad doesn't use the HID class */
{USB_IFACE_CLASS(UICLASS_VENDOR),
USB_IFACE_SUBCLASS(UISUBCLASS_XBOX360_CONTROLLER),
USB_IFACE_PROTOCOL(UIPROTO_XBOX360_GAMEPAD),},
};
static void
xb360gp_identify(driver_t *driver, device_t parent)
{
const struct hid_device_info *hw = hid_get_device_info(parent);
/* the Xbox 360 gamepad has no report descriptor */
if (hid_test_quirk(hw, HQ_IS_XBOX360GP))
hid_set_report_descr(parent, xb360gp_rdesc,
sizeof(xb360gp_rdesc));
}
static int
xb360gp_probe(device_t dev)
{
struct hgame_softc *sc = device_get_softc(dev);
const struct hid_device_info *hw = hid_get_device_info(dev);
int error;
if (!hid_test_quirk(hw, HQ_IS_XBOX360GP))
return (ENXIO);
hidmap_set_dev(&sc->hm, dev);
error = HIDMAP_ADD_MAP(&sc->hm, xb360gp_map, NULL);
if (error != 0)
return (error);
device_set_desc(dev, "XBox 360 Gamepad");
return (BUS_PROBE_DEFAULT);
}
static int
xb360gp_attach(device_t dev)
{
struct hgame_softc *sc = device_get_softc(dev);
int error;
/*
* Turn off the four LEDs on the gamepad which
* are blinking by default:
*/
static const uint8_t reportbuf[3] = {1, 3, 0};
error = hid_set_report(dev, reportbuf, sizeof(reportbuf),
HID_OUTPUT_REPORT, 0);
if (error)
device_printf(dev, "set output report failed, error=%d "
"(ignored)\n", error);
return (hidmap_attach(&sc->hm));
}
static int
xb360gp_detach(device_t dev)
{
struct hgame_softc *sc = device_get_softc(dev);
return (hidmap_detach(&sc->hm));
}
static devclass_t xb360gp_devclass;
static device_method_t xb360gp_methods[] = {
DEVMETHOD(device_identify, xb360gp_identify),
DEVMETHOD(device_probe, xb360gp_probe),
DEVMETHOD(device_attach, xb360gp_attach),
DEVMETHOD(device_detach, xb360gp_detach),
DEVMETHOD_END
};
DEFINE_CLASS_0(xb360gp, xb360gp_driver, xb360gp_methods,
sizeof(struct hgame_softc));
DRIVER_MODULE(xb360gp, hidbus, xb360gp_driver, xb360gp_devclass, NULL, 0);
MODULE_DEPEND(xb360gp, hid, 1, 1, 1);
MODULE_DEPEND(xb360gp, hidbus, 1, 1, 1);
MODULE_DEPEND(xb360gp, hidmap, 1, 1, 1);
MODULE_DEPEND(xb360gp, hgame, 1, 1, 1);
MODULE_DEPEND(xb360gp, evdev, 1, 1, 1);
MODULE_VERSION(xb360gp, 1);
USB_PNP_HOST_INFO(xb360gp_devs);

View file

@ -10,10 +10,13 @@ SUBDIR = \
SUBDIR += \
hconf \
hcons \
hgame \
hkbd \
hms \
hmt \
hpen \
hsctrl \
ps4dshock
ps4dshock \
xb360gp
.include <bsd.subdir.mk>

View file

@ -0,0 +1,9 @@
# $FreeBSD$
.PATH: ${SRCTOP}/sys/dev/hid
KMOD= hgame
SRCS= hgame.c
SRCS+= bus_if.h device_if.h
.include <bsd.kmod.mk>

View file

@ -0,0 +1,9 @@
# $FreeBSD$
.PATH: ${SRCTOP}/sys/dev/hid
KMOD= hpen
SRCS= hpen.c
SRCS+= bus_if.h device_if.h usbdevs.h
.include <bsd.kmod.mk>

View file

@ -0,0 +1,9 @@
# $FreeBSD$
.PATH: ${SRCTOP}/sys/dev/hid
KMOD= xb360gp
SRCS= xb360gp.c
SRCS+= bus_if.h device_if.h opt_usb.h
.include <bsd.kmod.mk>