hid: Add Sony DualSense gamepad driver

Add a driver for the Sony PS5 DualSense controller (054c:0ce6)
providing gamepad input via evdev, lightbar RGB LED control, and
player indicator LEDs through sysctl.

Signed-off-by:	Christos Longros <[email protected]>
Reviewed by:	ziaee, wulf
MFC after:	1 month
Differential Revision:	https://reviews.freebsd.org/D56345
This commit is contained in:
Christos Longros authored and Vladimir Kondratyev committed 2026-09-11 18:49:22 +03:00
1 parent b7e91f238c
commit d8e315ba97
7 files changed
+629

No files matched your search

+1
View File
@@ -496,6 +496,7 @@ MAN= aac.4 \
procfs.4 \
proto.4 \
ps4dshock.4 \
ps5dsense.4 \
psm.4 \
pst.4 \
pt.4 \
+145
View File
@@ -0,0 +1,145 @@
.\"
.\" Copyright (c) 2026 Christos Longros <[email protected]>
.\"
.\" SPDX-License-Identifier: BSD-2-Clause
.\"
.Dd August 29, 2026
.Dt PS5DSENSE 4
.Os
.Sh NAME
.Nm ps5dsense
.Nd Sony PlayStation 5 DualSense gamepad driver
.Sh SYNOPSIS
.Cd device ps5dsense
.Cd device hid
.Cd device hidbus
.Cd device hidmap
.Cd device evdev
.Pp
In
.Xr sysctl.conf 5 :
.Cd dev.ps5dsense.%d.led_state
.Cd dev.ps5dsense.%d.led_color_r
.Cd dev.ps5dsense.%d.led_color_g
.Cd dev.ps5dsense.%d.led_color_b
.Cd dev.ps5dsense.%d.player_leds
.Pp
In
.Xr loader.conf 5 :
.Cd hw.hid.ps5dsense.debug
.Cd ps5dsense_load
.Sh DESCRIPTION
The
.Nm
driver supports the Sony PlayStation 5 DualSense gamepad
connected over USB,
and presents it to applications over the
.Sy evdev
interface.
.Pp
If the appropriate hardware is detected,
the driver will be loaded automatically by
.Xr devmatch 8 .
To load the driver manually at boot time, set the
.Va ps5dsense_load
variable to
.Ar YES
at the
.Xr loader 8
prompt, or add it to
.Xr loader.conf 5 .
.Pp
To give user applications access to the game controller,
allow user access to the
.Pa /dev/input/event*
nodes with inclusion of user in the
.Em games
group,
or with a
.Xr devfs.rules 5
ruleset.
.Pp
The microphone mute button is reported as
.Dv KEY_MICMUTE ;
unlike the vendor driver on other systems,
.Nm
does not mute the built-in microphone itself.
.Sh HARDWARE
The
.Nm
driver supports the following devices:
.Pp
.Bl -bullet -compact
.It
Sony DualSense wireless controller
.Pq USB product ID 0x0ce6
.El
.Sh SYSCTL VARIABLES
The following variables are available as
.Xr sysctl 8
variables:
.Bl -tag -width indent
.It Va dev.ps5dsense.%d.led_state
Lightbar state,
where 0 is off and
1 is on.
.It Va dev.ps5dsense.%d.led_color_r
Lightbar color,
red component.
.It Va dev.ps5dsense.%d.led_color_g
Lightbar color,
green component.
.It Va dev.ps5dsense.%d.led_color_b
Lightbar color,
blue component.
.It Va dev.ps5dsense.%d.player_leds
Player indicator LEDs,
where -1 is off and
0 to 4 select the player number.
.El
.Pp
The following variable is available as both
.Xr sysctl 8
variable and
.Xr loader 8
tunable:
.Bl -tag -width indent
.It Va hw.hid.ps5dsense.debug
Debug output level,
where 0 is debugging disabled and
larger values increase debug message verbosity.
Default is 0.
.El
.Sh FILES
.Bl -tag -width "/dev/input/event*" -compact
.It Pa /dev/input/event*
input event device
.Pq Sy evdev
node
.El
.Sh SEE ALSO
.Xr hgame 4 ,
.Xr ps4dshock 4 ,
.Xr usbhid 4 ,
.Xr devfs.rules 5
.Sh HISTORY
The
.Nm
driver first appeared in
.Fx 16.0 .
.Sh AUTHORS
.An -nosplit
The
.Nm
driver was written by
.An Christos Longros Aq Mt [email protected] .
.Sh BUGS
The
.Nm
driver does not support force-feedback events, haptic feedback or the
adaptive triggers.
.Pp
The touchpad and the motion sensors are not decoded.
The touchpad click is therefore not reported at all.
.Pp
Bluetooth operation is not supported.
+1
View File
@@ -2441,6 +2441,7 @@ device hpen # Generic pen driver
device hrfkill # RFKILL driver
device hsctrl # System controls
device ps4dshock # Sony PS4 DualShock 4 gamepad driver
device ps5dsense # Sony PS5 DualSense gamepad driver
device u2f # FIDO/U2F authenticator
options U2F_DROP_UHID_ALIAS # Do not install /dev/uhid alias for
# /dev/u2f/ and rename driver from uhid to u2f
+1
View File
@@ -1816,6 +1816,7 @@ dev/hid/hrfkill.c optional hrfkill
dev/hid/hsctrl.c optional hsctrl
dev/hid/ietp.c optional ietp
dev/hid/ps4dshock.c optional ps4dshock
dev/hid/ps5dsense.c optional ps5dsense
dev/hid/u2f.c optional u2f
dev/hid/xb360gp.c optional xb360gp
dev/hptiop/hptiop.c optional hptiop scbus
+472
View File
@@ -0,0 +1,472 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2020 Vladimir Kondratyev <wulf@FreeBSD.org>
* Copyright (c) 2026 Christos Longros <chris.longros@gmail.com>
*
* 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.
*/
/*
* Sony PS5 DualSense driver
* https://controllers.fandom.com/wiki/Sony_DualSense
* https://github.com/torvalds/linux/blob/master/drivers/hid/hid-playstation.c
*
* Touchpad and motion sensors are not supported yet.
*/
#include "opt_hid.h"
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/stat.h>
#include <sys/sx.h>
#include <sys/sysctl.h>
#include <dev/evdev/input.h>
#include <dev/evdev/evdev.h>
#define HID_DEBUG_VAR ps5ds_debug
#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>
#include "usbdevs.h"
#ifdef HID_DEBUG
static int ps5ds_debug = 1;
static SYSCTL_NODE(_hw_hid, OID_AUTO, ps5dsense, CTLFLAG_RW, 0,
"Sony PS5 DualSense Gamepad");
SYSCTL_INT(_hw_hid_ps5dsense, OID_AUTO, debug, CTLFLAG_RWTUN,
&ps5ds_debug, 0, "Debug level");
#endif
/*
* Fixed HID report descriptor. Output is 62 bytes, not 47: shorter reports
* are ignored.
*/
static const uint8_t ps5ds_rdesc[] = {
0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */
0x09, 0x05, /* Usage (Game Pad) */
0xA1, 0x01, /* Collection (Application) */
0x85, 0x01, /* Report ID (1) */
0x09, 0x30, /* Usage (X) - left stick X */
0x09, 0x31, /* Usage (Y) - left stick Y */
0x09, 0x33, /* Usage (Rx) - right stick X */
0x09, 0x34, /* Usage (Ry) - right stick Y */
0x15, 0x00, /* Logical Minimum (0) */
0x26, 0xFF, 0x00, /* Logical Maximum (255) */
0x75, 0x08, /* Report Size (8) */
0x95, 0x04, /* Report Count (4) */
0x81, 0x02, /* Input (Data,Var,Abs) */
0x09, 0x32, /* Usage (Z) - L2 trigger */
0x09, 0x35, /* Usage (Rz) - R2 trigger */
0x15, 0x00, /* Logical Minimum (0) */
0x26, 0xFF, 0x00, /* Logical Maximum (255) */
0x75, 0x08, /* Report Size (8) */
0x95, 0x02, /* Report Count (2) */
0x81, 0x02, /* Input (Data,Var,Abs) */
0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined 0xFF00) */
0x09, 0x20, /* Usage (0x20) */
0x15, 0x00, /* Logical Minimum (0) */
0x26, 0xFF, 0x00, /* Logical Maximum (255) */
0x75, 0x08, /* Report Size (8) */
0x95, 0x01, /* Report Count (1) */
0x81, 0x02, /* Input (Data,Var,Abs) - counter */
0x05, 0x01, /* Usage Page (Generic Desktop) */
0x09, 0x39, /* Usage (Hat switch) */
0x15, 0x00, /* Logical Minimum (0) */
0x25, 0x07, /* Logical Maximum (7) */
0x35, 0x00, /* Physical Minimum (0) */
0x46, 0x3B, 0x01, /* Physical Maximum (315) */
0x65, 0x14, /* Unit (Eng Rot: Degree) */
0x75, 0x04, /* Report Size (4) */
0x95, 0x01, /* Report Count (1) */
0x81, 0x42, /* Input (Data,Var,Abs,Null State) */
0x65, 0x00, /* Unit (None) */
0x45, 0x00, /* Physical Maximum (0) */
0x05, 0x09, /* Usage Page (Button) */
0x19, 0x01, /* Usage Minimum (0x01) */
0x29, 0x0F, /* Usage Maximum (0x0F) */
0x15, 0x00, /* Logical Minimum (0) */
0x25, 0x01, /* Logical Maximum (1) */
0x75, 0x01, /* Report Size (1) */
0x95, 0x0F, /* Report Count (15) */
0x81, 0x02, /* Input (Data,Var,Abs) */
0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined 0xFF00) */
0x09, 0x21, /* Usage (0x21) */
0x75, 0x01, /* Report Size (1) */
0x95, 0x0D, /* Report Count (13) */
0x81, 0x03, /* Input (Const) - unused button bits */
0x09, 0x22, /* Usage (0x22) */
0x15, 0x00, /* Logical Minimum (0) */
0x26, 0xFF, 0x00, /* Logical Maximum (255) */
0x75, 0x08, /* Report Size (8) */
0x95, 0x34, /* Report Count (52) */
0x81, 0x03, /* Input (Const) - sensors, touchpad */
/* Output report (63 bytes total) for LED and rumble control */
0x85, 0x02, /* Report ID (2) */
0x09, 0x23, /* Usage (0x23) */
0x75, 0x08, /* Report Size (8) */
0x95, 0x3E, /* Report Count (62) */
0x91, 0x02, /* Output (Data,Var,Abs) */
0xC0, /* End Collection */
};
#define PS5DS_OUTPUT_REPORT2_SIZE 63
struct ps5ds_out2 {
uint8_t valid_flag0;
uint8_t valid_flag1;
uint8_t rumble_right;
uint8_t rumble_left;
uint8_t reserved1[4];
uint8_t mute_button_led;
uint8_t power_save_control;
uint8_t reserved2[28];
uint8_t valid_flag2;
uint8_t reserved3[2];
uint8_t lightbar_setup;
uint8_t led_brightness;
uint8_t player_leds;
uint8_t led_color_r;
uint8_t led_color_g;
uint8_t led_color_b;
} __attribute__((packed));
#define PS5DS_FLAG1_LIGHTBAR 0x04
#define PS5DS_FLAG1_PLAYER_LEDS 0x10
#define PS5DS_FLAG2_LIGHTBAR_SETUP 0x02
#define PS5DS_LIGHTBAR_FADE_OUT 0x02
static const uint8_t ps5ds_player_leds[] = {
0x04, /* Player 1: --x-- */
0x0A, /* Player 2: -x-x- */
0x15, /* Player 3: x-x-x */
0x1B, /* Player 4: xx-xx */
0x1F, /* Player 5: xxxxx */
};
static const struct ps5ds_led {
int r;
int g;
int b;
} ps5ds_leds[] = {
/* The first 4 entries match the PS4, other from Linux driver */
{ 0x00, 0x00, 0x40 }, /* Blue */
{ 0x40, 0x00, 0x00 }, /* Red */
{ 0x00, 0x40, 0x00 }, /* Green */
{ 0x20, 0x00, 0x20 }, /* Pink */
{ 0x02, 0x01, 0x00 }, /* Orange */
{ 0x00, 0x01, 0x01 }, /* Teal */
{ 0x01, 0x01, 0x01 } /* White */
};
enum ps5ds_led_state {
PS5DS_LED_OFF,
PS5DS_LED_ON,
PS5DS_LED_CNT,
};
struct ps5ds_softc {
struct hidmap hm;
struct sx lock;
enum ps5ds_led_state led_state;
struct ps5ds_led led_color;
int player_leds; /* 0-4: player number, -1: off */
};
#define PS5DS_OFFSET(field) offsetof(struct ps5ds_softc, field)
enum {
PS5DS_SYSCTL_LED_STATE = PS5DS_OFFSET(led_state),
PS5DS_SYSCTL_LED_COLOR_R = PS5DS_OFFSET(led_color.r),
PS5DS_SYSCTL_LED_COLOR_G = PS5DS_OFFSET(led_color.g),
PS5DS_SYSCTL_LED_COLOR_B = PS5DS_OFFSET(led_color.b),
PS5DS_SYSCTL_PLAYER_LEDS = PS5DS_OFFSET(player_leds),
#define PS5DS_SYSCTL_LAST PS5DS_SYSCTL_PLAYER_LEDS
};
#define PS5DS_MAP_BTN(number, code) \
{ HIDMAP_KEY(HUP_BUTTON, number, code) }
#define PS5DS_MAP_ABS(usage, code) \
{ HIDMAP_ABS(HUP_GENERIC_DESKTOP, HUG_##usage, code) }
#define PS5DS_MAP_FLT(usage, code) \
{ HIDMAP_ABS(HUP_GENERIC_DESKTOP, HUG_##usage, code), .flat = 15 }
#define PS5DS_MAP_GCB(usage, callback) \
{ HIDMAP_ANY_CB(HUP_GENERIC_DESKTOP, HUG_##usage, callback) }
#define PS5DS_FINALCB(cb) \
{ HIDMAP_FINAL_CB(&cb) }
static hidmap_cb_t ps5ds_final_cb;
static const struct hidmap_item ps5ds_map[] = {
PS5DS_MAP_FLT(X, ABS_X),
PS5DS_MAP_FLT(Y, ABS_Y),
PS5DS_MAP_ABS(Z, ABS_Z),
PS5DS_MAP_ABS(RZ, ABS_RZ),
PS5DS_MAP_FLT(RX, ABS_RX),
PS5DS_MAP_FLT(RY, ABS_RY),
PS5DS_MAP_BTN(1, BTN_WEST),
PS5DS_MAP_BTN(2, BTN_SOUTH),
PS5DS_MAP_BTN(3, BTN_EAST),
PS5DS_MAP_BTN(4, BTN_NORTH),
PS5DS_MAP_BTN(5, BTN_TL),
PS5DS_MAP_BTN(6, BTN_TR),
PS5DS_MAP_BTN(7, BTN_TL2),
PS5DS_MAP_BTN(8, BTN_TR2),
PS5DS_MAP_BTN(9, BTN_SELECT),
PS5DS_MAP_BTN(10, BTN_START),
PS5DS_MAP_BTN(11, BTN_THUMBL),
PS5DS_MAP_BTN(12, BTN_THUMBR),
PS5DS_MAP_BTN(13, BTN_MODE),
/* Click button is handled by touchpad driver */
/* PS5DS_MAP_BTN(14, BTN_LEFT), */
/* Linux mutes the microphone in hardware and emits no event */
PS5DS_MAP_BTN(15, KEY_MICMUTE),
PS5DS_MAP_GCB(HAT_SWITCH, hgame_hat_switch_cb),
PS5DS_FINALCB( ps5ds_final_cb),
};
static const struct hid_device_id ps5ds_devs[] = {
{ HID_BVP(BUS_USB, USB_VENDOR_SONY, 0x0ce6),
HID_TLC(HUP_GENERIC_DESKTOP, HUG_GAME_PAD) },
};
static int
ps5ds_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);
evdev_set_cdev_mode(evdev, UID_ROOT, GID_GAMES,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
}
/* Do not execute callback at interrupt handler and detach */
return (ENOSYS);
}
static int
ps5ds_write(struct ps5ds_softc *sc)
{
uint8_t buf[PS5DS_OUTPUT_REPORT2_SIZE];
bool led_on;
sx_assert(&sc->lock, SA_XLOCKED);
memset(buf, 0, sizeof(buf));
buf[0] = 0x02;
led_on = sc->led_state != PS5DS_LED_OFF;
*(struct ps5ds_out2 *)(buf + 1) = (struct ps5ds_out2) {
.valid_flag1 = PS5DS_FLAG1_LIGHTBAR | PS5DS_FLAG1_PLAYER_LEDS,
.player_leds = sc->player_leds < 0 ?
0 : ps5ds_player_leds[sc->player_leds],
.led_color_r = led_on ? sc->led_color.r : 0,
.led_color_g = led_on ? sc->led_color.g : 0,
.led_color_b = led_on ? sc->led_color.b : 0,
};
return (hid_write(sc->hm.dev, buf, sizeof(buf)));
}
static int
ps5ds_blank(struct ps5ds_softc *sc)
{
uint8_t buf[PS5DS_OUTPUT_REPORT2_SIZE];
memset(buf, 0, sizeof(buf));
buf[0] = 0x02;
*(struct ps5ds_out2 *)(buf + 1) = (struct ps5ds_out2) {
.valid_flag1 = PS5DS_FLAG1_LIGHTBAR | PS5DS_FLAG1_PLAYER_LEDS,
.valid_flag2 = PS5DS_FLAG2_LIGHTBAR_SETUP,
.lightbar_setup = PS5DS_LIGHTBAR_FADE_OUT,
};
return (hid_write(sc->hm.dev, buf, sizeof(buf)));
}
static int
ps5ds_sysctl(SYSCTL_HANDLER_ARGS)
{
struct ps5ds_softc *sc;
int error, arg;
if (oidp->oid_arg1 == NULL || oidp->oid_arg2 < 0 ||
oidp->oid_arg2 > PS5DS_SYSCTL_LAST)
return (EINVAL);
sc = oidp->oid_arg1;
sx_xlock(&sc->lock);
arg = *(int *)((char *)sc + oidp->oid_arg2);
error = sysctl_handle_int(oidp, &arg, 0, req);
if (error || !req->newptr)
goto unlock;
switch (oidp->oid_arg2) {
case PS5DS_SYSCTL_LED_STATE:
if (arg < 0 || arg >= PS5DS_LED_CNT)
error = EINVAL;
break;
case PS5DS_SYSCTL_LED_COLOR_R:
case PS5DS_SYSCTL_LED_COLOR_G:
case PS5DS_SYSCTL_LED_COLOR_B:
if (arg < 0 || arg > UINT8_MAX)
error = EINVAL;
break;
case PS5DS_SYSCTL_PLAYER_LEDS:
if (arg < -1 || arg >= (int)nitems(ps5ds_player_leds))
error = EINVAL;
break;
default:
error = EINVAL;
}
if (error == 0) {
*(int *)((char *)sc + oidp->oid_arg2) = arg;
ps5ds_write(sc);
}
unlock:
sx_unlock(&sc->lock);
return (error);
}
static void
ps5ds_identify(driver_t *driver, device_t parent)
{
/* Replace the gamepad's rudimentary report descriptor */
if (HIDBUS_LOOKUP_ID(parent, ps5ds_devs) != NULL)
hid_set_report_descr(parent, ps5ds_rdesc,
sizeof(ps5ds_rdesc));
}
static int
ps5ds_probe(device_t dev)
{
struct ps5ds_softc *sc = device_get_softc(dev);
hidmap_set_debug_var(&sc->hm, &HID_DEBUG_VAR);
return (
HIDMAP_PROBE(&sc->hm, dev, ps5ds_devs, ps5ds_map, NULL)
);
}
static int
ps5ds_attach(device_t dev)
{
struct ps5ds_softc *sc = device_get_softc(dev);
struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev);
struct sysctl_oid *tree = device_get_sysctl_tree(dev);
int error, unit;
sx_init(&sc->lock, "ps5dsense");
unit = device_get_unit(dev);
sc->led_state = PS5DS_LED_ON;
sc->led_color = ps5ds_leds[unit % nitems(ps5ds_leds)];
sc->player_leds = unit < (int)nitems(ps5ds_player_leds) ? unit : -1;
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"led_state", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc,
PS5DS_SYSCTL_LED_STATE, ps5ds_sysctl, "I",
"LED state: 0 - off, 1 - on.");
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"led_color_r", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc,
PS5DS_SYSCTL_LED_COLOR_R, ps5ds_sysctl, "I",
"Lightbar color. Red component.");
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"led_color_g", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc,
PS5DS_SYSCTL_LED_COLOR_G, ps5ds_sysctl, "I",
"Lightbar color. Green component.");
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"led_color_b", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc,
PS5DS_SYSCTL_LED_COLOR_B, ps5ds_sysctl, "I",
"Lightbar color. Blue component.");
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"player_leds", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc,
PS5DS_SYSCTL_PLAYER_LEDS, ps5ds_sysctl, "I",
"Player indicator LEDs: -1 - off, 0-4 - player number.");
error = hidmap_attach(&sc->hm);
if (error) {
sx_destroy(&sc->lock);
return (error);
}
sx_xlock(&sc->lock);
ps5ds_write(sc);
sx_xunlock(&sc->lock);
return (0);
}
static int
ps5ds_detach(device_t dev)
{
struct ps5ds_softc *sc = device_get_softc(dev);
int error;
error = hidmap_detach(&sc->hm);
if (error)
return (error);
ps5ds_blank(sc);
sx_destroy(&sc->lock);
return (0);
}
static device_method_t ps5ds_methods[] = {
DEVMETHOD(device_identify, ps5ds_identify),
DEVMETHOD(device_probe, ps5ds_probe),
DEVMETHOD(device_attach, ps5ds_attach),
DEVMETHOD(device_detach, ps5ds_detach),
DEVMETHOD_END
};
DEFINE_CLASS_0(ps5dsense, ps5ds_driver, ps5ds_methods,
sizeof(struct ps5ds_softc));
DRIVER_MODULE(ps5dsense, hidbus, ps5ds_driver, NULL, NULL);
MODULE_DEPEND(ps5dsense, hid, 1, 1, 1);
MODULE_DEPEND(ps5dsense, hidbus, 1, 1, 1);
MODULE_DEPEND(ps5dsense, hidmap, 1, 1, 1);
MODULE_DEPEND(ps5dsense, hgame, 1, 1, 1);
MODULE_DEPEND(ps5dsense, evdev, 1, 1, 1);
MODULE_VERSION(ps5dsense, 1);
HID_PNP_INFO(ps5ds_devs);
+1
View File
@@ -20,6 +20,7 @@ SUBDIR += \
hsctrl \
ietp \
ps4dshock \
ps5dsense \
u2f \
xb360gp
+8
View File
@@ -0,0 +1,8 @@
.PATH: ${SRCTOP}/sys/dev/hid
KMOD= ps5dsense
SRCS= ps5dsense.c
SRCS+= opt_hid.h opt_kbd.h
SRCS+= bus_if.h device_if.h usbdevs.h
.include <bsd.kmod.mk>