The branch main has been updated by wulf:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=8d73071c47ff1f911bdaec6356f37feb4e3b7cb5

commit 8d73071c47ff1f911bdaec6356f37feb4e3b7cb5
Author:     Vladimir Kondratyev <w...@freebsd.org>
AuthorDate: 2021-08-24 23:01:42 +0000
Commit:     Vladimir Kondratyev <w...@freebsd.org>
CommitDate: 2021-08-24 23:01:42 +0000

    wsp(4): Add evdev support.
    
    Reviewed by:    hselasky
    Tested by:      Greg V, Constantin Furst<constantin_AT_fuersten_DOT_info>
    MFC after:      2 weeks
    PR:             252236
    Differential revision:  https://reviews.freebsd.org/D31653
---
 sys/dev/usb/input/wsp.c      | 305 ++++++++++++++++++++++++++++++++++++++++---
 sys/modules/usb/wsp/Makefile |   4 +-
 2 files changed, 287 insertions(+), 22 deletions(-)

diff --git a/sys/dev/usb/input/wsp.c b/sys/dev/usb/input/wsp.c
index cc99c4678633..2c70b24d1f89 100644
--- a/sys/dev/usb/input/wsp.c
+++ b/sys/dev/usb/input/wsp.c
@@ -29,6 +29,8 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include "opt_evdev.h"
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
@@ -56,6 +58,11 @@ __FBSDID("$FreeBSD$");
 #define        USB_DEBUG_VAR wsp_debug
 #include <dev/usb/usb_debug.h>
 
+#ifdef EVDEV_SUPPORT
+#include <dev/evdev/input.h>
+#include <dev/evdev/evdev.h>
+#endif
+
 #include <sys/mouse.h>
 
 #define        WSP_DRIVER_NAME "wsp"
@@ -288,9 +295,14 @@ struct tp_finger {
 } __packed;
 
 /* trackpad finger data size, empirically at least ten fingers */
+#ifdef EVDEV_SUPPORT
+#define        MAX_FINGERS             MAX_MT_SLOTS
+#else
 #define        MAX_FINGERS             16
+#endif
 #define        SIZEOF_FINGER           sizeof(struct tp_finger)
 #define        SIZEOF_ALL_FINGERS      (MAX_FINGERS * SIZEOF_FINGER)
+#define        MAX_FINGER_ORIENTATION  16384
 
 #if (WSP_BUFFER_MAX < ((MAX_FINGERS * FSIZE_TYPE4) + FINGER_TYPE4))
 #error "WSP_BUFFER_MAX is too small"
@@ -313,50 +325,147 @@ enum {
        WSP_FLAG_MAX,
 };
 
+/* device-specific parameters */
+struct wsp_param {
+       int snratio;                    /* signal-to-noise ratio */
+       int min;                        /* device minimum reading */
+       int max;                        /* device maximum reading */
+       int size;                       /* physical size, mm */
+};
+
 /* device-specific configuration */
 struct wsp_dev_params {
        const struct wsp_tp* tp;
+       struct wsp_param p;             /* finger pressure limits */
+       struct wsp_param w;             /* finger width limits */
+       struct wsp_param x;             /* horizontal limits */
+       struct wsp_param y;             /* vertical limits */
+       struct wsp_param o;             /* orientation limits */
 };
 
+/* logical signal quality */
+#define        SN_PRESSURE     45              /* pressure signal-to-noise 
ratio */
+#define        SN_WIDTH        25              /* width signal-to-noise ratio 
*/
+#define        SN_COORD        250             /* coordinate signal-to-noise 
ratio */
+#define        SN_ORIENT       10              /* orientation signal-to-noise 
ratio */
+
 static const struct wsp_dev_params wsp_dev_params[WSP_FLAG_MAX] = {
        [WSP_FLAG_WELLSPRING1] = {
                .tp = wsp_tp + TYPE1,
+               .p = { SN_PRESSURE, 0, 256, 0 },
+               .w = { SN_WIDTH, 0, 2048, 0 },
+               .x = { SN_COORD, -4824, 5342, 105 },
+               .y = { SN_COORD, -172, 5820, 75 },
+               .o = { SN_ORIENT,
+                   -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
        },
        [WSP_FLAG_WELLSPRING2] = {
                .tp = wsp_tp + TYPE1,
+               .p = { SN_PRESSURE, 0, 256, 0 },
+               .w = { SN_WIDTH, 0, 2048, 0 },
+               .x = { SN_COORD, -4824, 4824, 105 },
+               .y = { SN_COORD, -172, 4290, 75 },
+               .o = { SN_ORIENT,
+                   -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
        },
        [WSP_FLAG_WELLSPRING3] = {
                .tp = wsp_tp + TYPE2,
+               .p = { SN_PRESSURE, 0, 300, 0 },
+               .w = { SN_WIDTH, 0, 2048, 0 },
+               .x = { SN_COORD, -4460, 5166, 105 },
+               .y = { SN_COORD, -75, 6700, 75 },
+               .o = { SN_ORIENT,
+                   -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
        },
        [WSP_FLAG_WELLSPRING4] = {
                .tp = wsp_tp + TYPE2,
+               .p = { SN_PRESSURE, 0, 300, 0 },
+               .w = { SN_WIDTH, 0, 2048, 0 },
+               .x = { SN_COORD, -4620, 5140, 105 },
+               .y = { SN_COORD, -150, 6600, 75 },
+               .o = { SN_ORIENT,
+                   -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
        },
        [WSP_FLAG_WELLSPRING4A] = {
                .tp = wsp_tp + TYPE2,
+               .p = { SN_PRESSURE, 0, 300, 0 },
+               .w = { SN_WIDTH, 0, 2048, 0 },
+               .x = { SN_COORD, -4616, 5112, 105 },
+               .y = { SN_COORD, -142, 5234, 75 },
+               .o = { SN_ORIENT,
+                   -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
        },
        [WSP_FLAG_WELLSPRING5] = {
                .tp = wsp_tp + TYPE2,
+               .p = { SN_PRESSURE, 0, 300, 0 },
+               .w = { SN_WIDTH, 0, 2048, 0 },
+               .x = { SN_COORD, -4415, 5050, 105 },
+               .y = { SN_COORD, -55, 6680, 75 },
+               .o = { SN_ORIENT,
+                   -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
        },
        [WSP_FLAG_WELLSPRING6] = {
                .tp = wsp_tp + TYPE2,
+               .p = { SN_PRESSURE, 0, 300, 0 },
+               .w = { SN_WIDTH, 0, 2048, 0 },
+               .x = { SN_COORD, -4620, 5140, 105 },
+               .y = { SN_COORD, -150, 6600, 75 },
+               .o = { SN_ORIENT,
+                   -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
        },
        [WSP_FLAG_WELLSPRING5A] = {
                .tp = wsp_tp + TYPE2,
+               .p = { SN_PRESSURE, 0, 300, 0 },
+               .w = { SN_WIDTH, 0, 2048, 0 },
+               .x = { SN_COORD, -4750, 5280, 105 },
+               .y = { SN_COORD, -150, 6730, 75 },
+               .o = { SN_ORIENT,
+                   -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
        },
        [WSP_FLAG_WELLSPRING6A] = {
                .tp = wsp_tp + TYPE2,
+               .p = { SN_PRESSURE, 0, 300, 0 },
+               .w = { SN_WIDTH, 0, 2048, 0 },
+               .x = { SN_COORD, -4620, 5140, 105 },
+               .y = { SN_COORD, -150, 6600, 75 },
+               .o = { SN_ORIENT,
+                   -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
        },
        [WSP_FLAG_WELLSPRING7] = {
                .tp = wsp_tp + TYPE2,
+               .p = { SN_PRESSURE, 0, 300, 0 },
+               .w = { SN_WIDTH, 0, 2048, 0 },
+               .x = { SN_COORD, -4750, 5280, 105 },
+               .y = { SN_COORD, -150, 6730, 75 },
+               .o = { SN_ORIENT,
+                   -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
        },
        [WSP_FLAG_WELLSPRING7A] = {
                .tp = wsp_tp + TYPE2,
+               .p = { SN_PRESSURE, 0, 300, 0 },
+               .w = { SN_WIDTH, 0, 2048, 0 },
+               .x = { SN_COORD, -4750, 5280, 105 },
+               .y = { SN_COORD, -150, 6730, 75 },
+               .o = { SN_ORIENT,
+                   -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
        },
        [WSP_FLAG_WELLSPRING8] = {
                .tp = wsp_tp + TYPE3,
+               .p = { SN_PRESSURE, 0, 300, 0 },
+               .w = { SN_WIDTH, 0, 2048, 0 },
+               .x = { SN_COORD, -4620, 5140, 105 },
+               .y = { SN_COORD, -150, 6600, 75 },
+               .o = { SN_ORIENT,
+                   -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
        },
        [WSP_FLAG_WELLSPRING9] = {
                .tp = wsp_tp + TYPE4,
+               .p = { SN_PRESSURE, 0, 300, 0 },
+               .w = { SN_WIDTH, 0, 2048, 0 },
+               .x = { SN_COORD, -4828, 5345, 105 },
+               .y = { SN_COORD, -203, 6803, 75 },
+               .o = { SN_ORIENT,
+                   -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
        },
 };
 #define        WSP_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, 
i) }
@@ -445,12 +554,17 @@ struct wsp_softc {
 
        const struct wsp_dev_params *sc_params; /* device configuration */
 
+#ifdef EVDEV_SUPPORT
+       struct evdev_dev *sc_evdev;
+#endif
        mousehw_t sc_hw;
        mousemode_t sc_mode;
        u_int   sc_pollrate;
        mousestatus_t sc_status;
+       int     sc_fflags;
        u_int   sc_state;
-#define        WSP_ENABLED            0x01
+#define        WSP_ENABLED             0x01
+#define        WSP_EVDEV_OPENED        0x02
 
        struct tp_finger *index[MAX_FINGERS];   /* finger index data */
        int16_t pos_x[MAX_FINGERS];     /* position array */
@@ -491,8 +605,8 @@ struct wsp_softc {
 /*
  * function prototypes
  */
-static usb_fifo_cmd_t wsp_start_read;
-static usb_fifo_cmd_t wsp_stop_read;
+static usb_fifo_cmd_t wsp_fifo_start_read;
+static usb_fifo_cmd_t wsp_fifo_stop_read;
 static usb_fifo_open_t wsp_open;
 static usb_fifo_close_t wsp_close;
 static usb_fifo_ioctl_t wsp_ioctl;
@@ -501,11 +615,20 @@ static struct usb_fifo_methods wsp_fifo_methods = {
        .f_open = &wsp_open,
        .f_close = &wsp_close,
        .f_ioctl = &wsp_ioctl,
-       .f_start_read = &wsp_start_read,
-       .f_stop_read = &wsp_stop_read,
+       .f_start_read = &wsp_fifo_start_read,
+       .f_stop_read = &wsp_fifo_stop_read,
        .basename[0] = WSP_DRIVER_NAME,
 };
 
+#ifdef EVDEV_SUPPORT
+static evdev_open_t wsp_ev_open;
+static evdev_close_t wsp_ev_close;
+static const struct evdev_methods wsp_evdev_methods = {
+       .ev_open = &wsp_ev_open,
+       .ev_close = &wsp_ev_close,
+};
+#endif
+
 /* device initialization and shutdown */
 static int wsp_enable(struct wsp_softc *sc);
 static void wsp_disable(struct wsp_softc *sc);
@@ -714,6 +837,56 @@ wsp_attach(device_t dev)
        sc->sc_touch = WSP_UNTOUCH;
        sc->scr_mode = WSP_SCR_NONE;
 
+#ifdef EVDEV_SUPPORT
+       sc->sc_evdev = evdev_alloc();
+       evdev_set_name(sc->sc_evdev, device_get_desc(dev));
+       evdev_set_phys(sc->sc_evdev, device_get_nameunit(dev));
+       evdev_set_id(sc->sc_evdev, BUS_USB, uaa->info.idVendor,
+           uaa->info.idProduct, 0);
+       evdev_set_serial(sc->sc_evdev, usb_get_serial(uaa->device));
+       evdev_set_methods(sc->sc_evdev, sc, &wsp_evdev_methods);
+       evdev_support_prop(sc->sc_evdev, INPUT_PROP_POINTER);
+       evdev_support_event(sc->sc_evdev, EV_SYN);
+       evdev_support_event(sc->sc_evdev, EV_ABS);
+       evdev_support_event(sc->sc_evdev, EV_KEY);
+
+#define WSP_SUPPORT_ABS(evdev, code, param)                            \
+       evdev_support_abs((evdev), (code), (param).min, (param).max,    \
+       ((param).max - (param).min) / (param).snratio, 0,               \
+       (param).size != 0 ? ((param).max - (param).min) / (param).size : 0);
+
+       /* finger position */
+       WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_POSITION_X, sc->sc_params->x);
+       WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_POSITION_Y, sc->sc_params->y);
+       /* finger pressure */
+       WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_PRESSURE, sc->sc_params->p);
+       /* finger touch area */
+       WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_TOUCH_MAJOR, sc->sc_params->w);
+       WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_TOUCH_MINOR, sc->sc_params->w);
+       /* finger approach area */
+       WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_WIDTH_MAJOR, sc->sc_params->w);
+       WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_WIDTH_MINOR, sc->sc_params->w);
+       /* finger orientation */
+       WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_ORIENTATION, sc->sc_params->o);
+       /* button properties */
+       evdev_support_key(sc->sc_evdev, BTN_LEFT);
+       if ((sc->sc_params->tp->caps & HAS_INTEGRATED_BUTTON) != 0)
+               evdev_support_prop(sc->sc_evdev, INPUT_PROP_BUTTONPAD);
+       /* Enable automatic touch assignment for type B MT protocol */
+       evdev_support_abs(sc->sc_evdev, ABS_MT_SLOT,
+           0, MAX_FINGERS - 1, 0, 0, 0);
+       evdev_support_abs(sc->sc_evdev, ABS_MT_TRACKING_ID,
+           -1, MAX_FINGERS - 1, 0, 0, 0);
+       evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_TRACK);
+       evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_AUTOREL);
+       /* Synaptics compatibility events */
+       evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_STCOMPAT);
+
+       err = evdev_register(sc->sc_evdev);
+       if (err)
+               goto detach;
+#endif
+
        return (0);
 
 detach:
@@ -735,6 +908,10 @@ wsp_detach(device_t dev)
 
        usb_fifo_detach(&sc->sc_fifo);
 
+#ifdef EVDEV_SUPPORT
+       evdev_free(sc->sc_evdev);
+#endif
+
        usbd_transfer_unsetup(sc->sc_xfer, WSP_N_TRANSFER);
 
        mtx_destroy(&sc->sc_mutex);
@@ -761,6 +938,9 @@ wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error)
        int rdz = 0;
        int len;
        int i;
+#ifdef EVDEV_SUPPORT
+       int slot = 0;
+#endif
 
        wsp_runing_rangecheck(&tun);
 
@@ -829,8 +1009,31 @@ wsp_intr_callback(struct usb_xfer *xfer, usb_error_t 
error)
                        sc->pos_x[i] = f->abs_x;
                        sc->pos_y[i] = -f->abs_y;
                        sc->index[i] = f;
+#ifdef EVDEV_SUPPORT
+                       if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE && 
f->touch_major != 0) {
+                               union evdev_mt_slot slot_data = {
+                                       .id = slot,
+                                       .x = f->abs_x,
+                                       .y = params->y.min + params->y.max - 
f->abs_y,
+                                       .p = f->pressure,
+                                       .maj = f->touch_major << 1,
+                                       .min = f->touch_minor << 1,
+                                       .w_maj = f->tool_major << 1,
+                                       .w_min = f->tool_minor << 1,
+                                       .ori = params->o.max - f->orientation,
+                               };
+                               evdev_mt_push_slot(sc->sc_evdev, slot, 
&slot_data);
+                               slot++;
+                       }
+#endif
                }
 
+#ifdef EVDEV_SUPPORT
+               if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE) {
+                       evdev_push_key(sc->sc_evdev, BTN_LEFT, ibt);
+                       evdev_sync(sc->sc_evdev);
+               }
+#endif
                sc->sc_status.flags &= ~MOUSE_POSCHANGED;
                sc->sc_status.flags &= ~MOUSE_STDBUTTONSCHANGED;
                sc->sc_status.obutton = sc->sc_status.button;
@@ -1135,9 +1338,8 @@ wsp_reset_buf(struct wsp_softc *sc)
 }
 
 static void
-wsp_start_read(struct usb_fifo *fifo)
+wsp_start_read(struct wsp_softc *sc)
 {
-       struct wsp_softc *sc = usb_fifo_softc(fifo);
        int rate;
 
        /* Check if we should override the default polling interval */
@@ -1158,49 +1360,109 @@ wsp_start_read(struct usb_fifo *fifo)
 }
 
 static void
-wsp_stop_read(struct usb_fifo *fifo)
+wsp_stop_read(struct wsp_softc *sc)
 {
-       struct wsp_softc *sc = usb_fifo_softc(fifo);
-
        usbd_transfer_stop(sc->sc_xfer[WSP_INTR_DT]);
 }
 
 static int
 wsp_open(struct usb_fifo *fifo, int fflags)
 {
-       DPRINTFN(WSP_LLEVEL_INFO, "\n");
+       struct wsp_softc *sc = usb_fifo_softc(fifo);
+       int rc = 0;
 
-       if (fflags & FREAD) {
-               struct wsp_softc *sc = usb_fifo_softc(fifo);
-               int rc;
+       DPRINTFN(WSP_LLEVEL_INFO, "\n");
 
-               if (sc->sc_state & WSP_ENABLED)
-                       return (EBUSY);
+       if (sc->sc_fflags & fflags)
+               return (EBUSY);
 
+       if (fflags & FREAD) {
                if (usb_fifo_alloc_buffer(fifo,
                    WSP_FIFO_BUF_SIZE, WSP_FIFO_QUEUE_MAXLEN)) {
                        return (ENOMEM);
                }
-               rc = wsp_enable(sc);
+#ifdef EVDEV_SUPPORT
+               if ((sc->sc_state & WSP_EVDEV_OPENED) == 0)
+#endif
+                       rc = wsp_enable(sc);
                if (rc != 0) {
                        usb_fifo_free_buffer(fifo);
                        return (rc);
                }
        }
+       sc->sc_fflags |= fflags & (FREAD | FWRITE);
        return (0);
 }
 
 static void
 wsp_close(struct usb_fifo *fifo, int fflags)
 {
-       if (fflags & FREAD) {
-               struct wsp_softc *sc = usb_fifo_softc(fifo);
+       struct wsp_softc *sc = usb_fifo_softc(fifo);
 
-               wsp_disable(sc);
+       if (fflags & FREAD) {
+#ifdef EVDEV_SUPPORT
+               if ((sc->sc_state & WSP_EVDEV_OPENED) == 0)
+#endif
+                       wsp_disable(sc);
                usb_fifo_free_buffer(fifo);
        }
+
+       sc->sc_fflags &= ~(fflags & (FREAD | FWRITE));
+}
+
+static void
+wsp_fifo_start_read(struct usb_fifo *fifo)
+{
+       struct wsp_softc *sc = usb_fifo_softc(fifo);
+
+       wsp_start_read(sc);
+}
+
+static void
+wsp_fifo_stop_read(struct usb_fifo *fifo)
+{
+       struct wsp_softc *sc = usb_fifo_softc(fifo);
+
+#ifdef EVDEV_SUPPORT
+       if ((sc->sc_state & WSP_EVDEV_OPENED) == 0)
+#endif
+               wsp_stop_read(sc);
 }
 
+#ifdef EVDEV_SUPPORT
+static int
+wsp_ev_open(struct evdev_dev *evdev)
+{
+       struct wsp_softc *sc = evdev_get_softc(evdev);
+       int rc = 0;
+
+       mtx_lock(&sc->sc_mutex);
+       if (sc->sc_fflags == 0)
+               rc = wsp_enable(sc);
+       if (rc == 0) {
+               wsp_start_read(sc);
+               sc->sc_state |= WSP_EVDEV_OPENED;
+       }
+       mtx_unlock(&sc->sc_mutex);
+
+       return (rc);
+}
+
+static int
+wsp_ev_close(struct evdev_dev *evdev)
+{
+       struct wsp_softc *sc = evdev_get_softc(evdev);
+
+       mtx_lock(&sc->sc_mutex);
+       sc->sc_state &= ~WSP_EVDEV_OPENED;
+       if (sc->sc_fflags == 0)
+               wsp_stop_read(sc);
+       mtx_unlock(&sc->sc_mutex);
+
+       return (0);
+}
+#endif
+
 int
 wsp_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr, int fflags)
 {
@@ -1312,5 +1574,8 @@ static devclass_t wsp_devclass;
 DRIVER_MODULE(wsp, uhub, wsp_driver, wsp_devclass, NULL, 0);
 MODULE_DEPEND(wsp, usb, 1, 1, 1);
 MODULE_DEPEND(wsp, hid, 1, 1, 1);
+#ifdef EVDEV_SUPPORT
+MODULE_DEPEND(wsp, evdev, 1, 1, 1);
+#endif
 MODULE_VERSION(wsp, 1);
 USB_PNP_HOST_INFO(wsp_devs);
diff --git a/sys/modules/usb/wsp/Makefile b/sys/modules/usb/wsp/Makefile
index a5215c0150f5..73a289a09544 100644
--- a/sys/modules/usb/wsp/Makefile
+++ b/sys/modules/usb/wsp/Makefile
@@ -30,7 +30,7 @@ S=     ${SRCTOP}/sys
 .PATH: $S/dev/usb/input
 
 KMOD=  wsp
-SRCS=  opt_bus.h opt_usb.h device_if.h bus_if.h usb_if.h vnode_if.h usbdevs.h \
-       wsp.c
+SRCS=  opt_bus.h opt_evdev.h opt_usb.h device_if.h bus_if.h usb_if.h \
+       vnode_if.h usbdevs.h wsp.c
 
 .include <bsd.kmod.mk>
_______________________________________________
dev-commits-src-main@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-main
To unsubscribe, send any mail to "dev-commits-src-main-unsubscr...@freebsd.org"

Reply via email to