svn commit: r306134 - in head/sys: dev/usb/input modules/usb/ums

Oleksandr Tymoshenko gonzo at FreeBSD.org
Wed Sep 21 18:52:04 UTC 2016


Author: gonzo
Date: Wed Sep 21 18:52:03 2016
New Revision: 306134
URL: https://svnweb.freebsd.org/changeset/base/306134

Log:
  Add evdev support to ums(4)
  
  event generation is disabled by default in favour of sysmouse. This
  behavoiur is controlled by kern.evdev.rcpt_mask sysctl, bit 2 should
  be set to give priority to hw over sysmouse
  
  Submitted by:	Vladimir Kondratiev <wulf at cicgroup.ru>
  Reviewed by:	hans
  Differential Revision:	https://reviews.freebsd.org/D7863

Modified:
  head/sys/dev/usb/input/ums.c
  head/sys/modules/usb/ums/Makefile

Modified: head/sys/dev/usb/input/ums.c
==============================================================================
--- head/sys/dev/usb/input/ums.c	Wed Sep 21 18:50:11 2016	(r306133)
+++ head/sys/dev/usb/input/ums.c	Wed Sep 21 18:52:03 2016	(r306134)
@@ -35,6 +35,8 @@ __FBSDID("$FreeBSD$");
  * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf
  */
 
+#include "opt_evdev.h"
+
 #include <sys/stdint.h>
 #include <sys/stddef.h>
 #include <sys/param.h>
@@ -68,6 +70,11 @@ __FBSDID("$FreeBSD$");
 
 #include <dev/usb/quirk/usb_quirk.h>
 
+#ifdef EVDEV
+#include <dev/evdev/input.h>
+#include <dev/evdev/evdev.h>
+#endif
+
 #include <sys/ioccom.h>
 #include <sys/filio.h>
 #include <sys/tty.h>
@@ -135,10 +142,18 @@ struct ums_softc {
 
 	int sc_pollrate;
 	int sc_fflags;
+#ifdef EVDEV
+	int sc_evflags;
+#define	UMS_EVDEV_OPENED	1
+#endif
 
 	uint8_t	sc_buttons;
 	uint8_t	sc_iid;
 	uint8_t	sc_temp[64];
+
+#ifdef EVDEV
+	struct evdev_dev *sc_evdev;
+#endif
 };
 
 static void ums_put_queue_timeout(void *__sc);
@@ -149,25 +164,39 @@ static device_probe_t ums_probe;
 static device_attach_t ums_attach;
 static device_detach_t ums_detach;
 
-static usb_fifo_cmd_t ums_start_read;
-static usb_fifo_cmd_t ums_stop_read;
-static usb_fifo_open_t ums_open;
-static usb_fifo_close_t ums_close;
-static usb_fifo_ioctl_t ums_ioctl;
+static usb_fifo_cmd_t ums_fifo_start_read;
+static usb_fifo_cmd_t ums_fifo_stop_read;
+static usb_fifo_open_t ums_fifo_open;
+static usb_fifo_close_t ums_fifo_close;
+static usb_fifo_ioctl_t ums_fifo_ioctl;
+
+#ifdef EVDEV
+static evdev_open_t ums_ev_open;
+static evdev_close_t ums_ev_close;
+#endif
 
+static void	ums_start_rx(struct ums_softc *);
+static void	ums_stop_rx(struct ums_softc *);
 static void	ums_put_queue(struct ums_softc *, int32_t, int32_t,
 		    int32_t, int32_t, int32_t);
 static int	ums_sysctl_handler_parseinfo(SYSCTL_HANDLER_ARGS);
 
 static struct usb_fifo_methods ums_fifo_methods = {
-	.f_open = &ums_open,
-	.f_close = &ums_close,
-	.f_ioctl = &ums_ioctl,
-	.f_start_read = &ums_start_read,
-	.f_stop_read = &ums_stop_read,
+	.f_open = &ums_fifo_open,
+	.f_close = &ums_fifo_close,
+	.f_ioctl = &ums_fifo_ioctl,
+	.f_start_read = &ums_fifo_start_read,
+	.f_stop_read = &ums_fifo_stop_read,
 	.basename[0] = "ums",
 };
 
+#ifdef EVDEV
+static struct evdev_methods ums_evdev_methods = {
+	.ev_open = &ums_ev_open,
+	.ev_close = &ums_ev_close,
+};
+#endif
+
 static void
 ums_put_queue_timeout(void *__sc)
 {
@@ -327,11 +356,17 @@ ums_intr_callback(struct usb_xfer *xfer,
 	case USB_ST_SETUP:
 tr_setup:
 		/* check if we can put more data into the FIFO */
-		if (usb_fifo_put_bytes_max(
-		    sc->sc_fifo.fp[USB_FIFO_RX]) != 0) {
-			usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
-			usbd_transfer_submit(xfer);
+		if (usb_fifo_put_bytes_max(sc->sc_fifo.fp[USB_FIFO_RX]) == 0) {
+#ifdef EVDEV
+			if (sc->sc_evflags == 0)
+				break;
+#else
+			break;
+#endif
 		}
+
+		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
+		usbd_transfer_submit(xfer);
 		break;
 
 	default:			/* Error */
@@ -655,6 +690,41 @@ ums_attach(device_t dev)
 	if (err)
 		goto detach;
 
+#ifdef EVDEV
+	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, &ums_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_REL);
+	evdev_support_event(sc->sc_evdev, EV_KEY);
+
+	info = &sc->sc_info[0];
+
+	if (info->sc_flags & UMS_FLAG_X_AXIS)
+		evdev_support_rel(sc->sc_evdev, REL_X);
+
+	if (info->sc_flags & UMS_FLAG_Y_AXIS)
+		evdev_support_rel(sc->sc_evdev, REL_Y);
+
+	if (info->sc_flags & UMS_FLAG_Z_AXIS)
+		evdev_support_rel(sc->sc_evdev, REL_WHEEL);
+
+	if (info->sc_flags & UMS_FLAG_T_AXIS)
+		evdev_support_rel(sc->sc_evdev, REL_HWHEEL);
+
+	for (i = 0; i < info->sc_buttons; i++)
+		evdev_support_key(sc->sc_evdev, BTN_MOUSE + i);
+
+	err = evdev_register(sc->sc_evdev);
+	if (err)
+		goto detach;
+#endif
+
 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
 	    OID_AUTO, "parseinfo", CTLTYPE_STRING|CTLFLAG_RD,
@@ -680,6 +750,10 @@ ums_detach(device_t self)
 
 	usb_fifo_detach(&sc->sc_fifo);
 
+#ifdef EVDEV
+	evdev_free(sc->sc_evdev);
+#endif
+
 	usbd_transfer_unsetup(sc->sc_xfer, UMS_N_TRANSFER);
 
 	usb_callout_drain(&sc->sc_callout);
@@ -690,9 +764,44 @@ ums_detach(device_t self)
 }
 
 static void
-ums_start_read(struct usb_fifo *fifo)
+ums_reset(struct ums_softc *sc)
+{
+
+	/* reset all USB mouse parameters */
+
+	if (sc->sc_buttons > MOUSE_MSC_MAXBUTTON)
+		sc->sc_hw.buttons = MOUSE_MSC_MAXBUTTON;
+	else
+		sc->sc_hw.buttons = sc->sc_buttons;
+
+	sc->sc_hw.iftype = MOUSE_IF_USB;
+	sc->sc_hw.type = MOUSE_MOUSE;
+	sc->sc_hw.model = MOUSE_MODEL_GENERIC;
+	sc->sc_hw.hwid = 0;
+
+	sc->sc_mode.protocol = MOUSE_PROTO_MSC;
+	sc->sc_mode.rate = -1;
+	sc->sc_mode.resolution = MOUSE_RES_UNKNOWN;
+	sc->sc_mode.accelfactor = 0;
+	sc->sc_mode.level = 0;
+	sc->sc_mode.packetsize = MOUSE_MSC_PACKETSIZE;
+	sc->sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK;
+	sc->sc_mode.syncmask[1] = MOUSE_MSC_SYNC;
+
+	/* reset status */
+
+	sc->sc_status.flags = 0;
+	sc->sc_status.button = 0;
+	sc->sc_status.obutton = 0;
+	sc->sc_status.dx = 0;
+	sc->sc_status.dy = 0;
+	sc->sc_status.dz = 0;
+	/* sc->sc_status.dt = 0; */
+}
+
+static void
+ums_start_rx(struct ums_softc *sc)
 {
-	struct ums_softc *sc = usb_fifo_softc(fifo);
 	int rate;
 
 	/* Check if we should override the default polling interval */
@@ -715,14 +824,28 @@ ums_start_read(struct usb_fifo *fifo)
 }
 
 static void
-ums_stop_read(struct usb_fifo *fifo)
+ums_stop_rx(struct ums_softc *sc)
 {
-	struct ums_softc *sc = usb_fifo_softc(fifo);
-
 	usbd_transfer_stop(sc->sc_xfer[UMS_INTR_DT]);
 	usb_callout_stop(&sc->sc_callout);
 }
 
+static void
+ums_fifo_start_read(struct usb_fifo *fifo)
+{
+	struct ums_softc *sc = usb_fifo_softc(fifo);
+
+	ums_start_rx(sc);
+}
+
+static void
+ums_fifo_stop_read(struct usb_fifo *fifo)
+{
+	struct ums_softc *sc = usb_fifo_softc(fifo);
+
+	ums_stop_rx(sc);
+}
+
 
 #if ((MOUSE_SYS_PACKETSIZE != 8) || \
      (MOUSE_MSC_PACKETSIZE != 5))
@@ -769,6 +892,21 @@ ums_put_queue(struct ums_softc *sc, int3
 		usb_fifo_put_data_linear(sc->sc_fifo.fp[USB_FIFO_RX], buf,
 		    sc->sc_mode.packetsize, 1);
 
+#ifdef EVDEV
+		if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE) {
+			/* Push evdev event */
+			evdev_push_event(sc->sc_evdev, EV_REL, REL_X, dx);
+			evdev_push_event(sc->sc_evdev, EV_REL, REL_Y, -dy);
+			evdev_push_event(sc->sc_evdev, EV_REL, REL_WHEEL, -dz);
+			evdev_push_event(sc->sc_evdev, EV_REL, REL_HWHEEL, dt);
+			evdev_push_mouse_btn(sc->sc_evdev,
+			    (buttons & ~MOUSE_STDBUTTONS) |
+			    (buttons & (1 << 2) ? MOUSE_BUTTON1DOWN : 0) |
+			    (buttons & (1 << 1) ? MOUSE_BUTTON2DOWN : 0) |
+			    (buttons & (1 << 0) ? MOUSE_BUTTON3DOWN : 0));
+			evdev_sync(sc->sc_evdev);
+		}
+#endif
 	} else {
 		DPRINTF("Buffer full, discarded packet\n");
 	}
@@ -781,8 +919,44 @@ ums_reset_buf(struct ums_softc *sc)
 	usb_fifo_reset(sc->sc_fifo.fp[USB_FIFO_RX]);
 }
 
+#ifdef EVDEV
+static int
+ums_ev_open(struct evdev_dev *evdev, void *ev_softc)
+{
+	struct ums_softc *sc = (struct ums_softc *)ev_softc;
+
+	mtx_lock(&sc->sc_mtx);
+
+	sc->sc_evflags = UMS_EVDEV_OPENED;
+
+	if (sc->sc_fflags == 0) {
+		ums_reset(sc);
+		ums_start_rx(sc);
+	}
+
+	mtx_unlock(&sc->sc_mtx);
+
+	return (0);
+}
+
+static void
+ums_ev_close(struct evdev_dev *evdev, void *ev_softc)
+{
+	struct ums_softc *sc = (struct ums_softc *)ev_softc;
+
+	mtx_lock(&sc->sc_mtx);
+
+	sc->sc_evflags = 0;
+
+	if (sc->sc_fflags == 0)
+		ums_stop_rx(sc);
+
+	mtx_unlock(&sc->sc_mtx);
+}
+#endif
+
 static int
-ums_open(struct usb_fifo *fifo, int fflags)
+ums_fifo_open(struct usb_fifo *fifo, int fflags)
 {
 	struct ums_softc *sc = usb_fifo_softc(fifo);
 
@@ -793,39 +967,13 @@ ums_open(struct usb_fifo *fifo, int ffla
 		return (EBUSY);
 
 	/* check for first open */
-	if (sc->sc_fflags == 0) {
-
-		/* reset all USB mouse parameters */
-
-		if (sc->sc_buttons > MOUSE_MSC_MAXBUTTON)
-			sc->sc_hw.buttons = MOUSE_MSC_MAXBUTTON;
-		else
-			sc->sc_hw.buttons = sc->sc_buttons;
-
-		sc->sc_hw.iftype = MOUSE_IF_USB;
-		sc->sc_hw.type = MOUSE_MOUSE;
-		sc->sc_hw.model = MOUSE_MODEL_GENERIC;
-		sc->sc_hw.hwid = 0;
-
-		sc->sc_mode.protocol = MOUSE_PROTO_MSC;
-		sc->sc_mode.rate = -1;
-		sc->sc_mode.resolution = MOUSE_RES_UNKNOWN;
-		sc->sc_mode.accelfactor = 0;
-		sc->sc_mode.level = 0;
-		sc->sc_mode.packetsize = MOUSE_MSC_PACKETSIZE;
-		sc->sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK;
-		sc->sc_mode.syncmask[1] = MOUSE_MSC_SYNC;
-
-		/* reset status */
-
-		sc->sc_status.flags = 0;
-		sc->sc_status.button = 0;
-		sc->sc_status.obutton = 0;
-		sc->sc_status.dx = 0;
-		sc->sc_status.dy = 0;
-		sc->sc_status.dz = 0;
-		/* sc->sc_status.dt = 0; */
-	}
+#ifdef EVDEV
+	if (sc->sc_fflags == 0 && sc->sc_evflags == 0)
+		ums_reset(sc);
+#else
+	if (sc->sc_fflags == 0)
+		ums_reset(sc);
+#endif
 
 	if (fflags & FREAD) {
 		/* allocate RX buffer */
@@ -840,7 +988,7 @@ ums_open(struct usb_fifo *fifo, int ffla
 }
 
 static void
-ums_close(struct usb_fifo *fifo, int fflags)
+ums_fifo_close(struct usb_fifo *fifo, int fflags)
 {
 	struct ums_softc *sc = usb_fifo_softc(fifo);
 
@@ -853,7 +1001,7 @@ ums_close(struct usb_fifo *fifo, int ffl
 }
 
 static int
-ums_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr, int fflags)
+ums_fifo_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr, int fflags)
 {
 	struct ums_softc *sc = usb_fifo_softc(fifo);
 	mousemode_t mode;

Modified: head/sys/modules/usb/ums/Makefile
==============================================================================
--- head/sys/modules/usb/ums/Makefile	Wed Sep 21 18:50:11 2016	(r306133)
+++ head/sys/modules/usb/ums/Makefile	Wed Sep 21 18:52:03 2016	(r306134)
@@ -30,7 +30,7 @@ S=     ${.CURDIR}/../../..
 .PATH: $S/dev/usb/input
 
 KMOD=	ums
-SRCS=	opt_bus.h opt_usb.h device_if.h bus_if.h usb_if.h vnode_if.h usbdevs.h \
-	ums.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 ums.c
 
 .include <bsd.kmod.mk>


More information about the svn-src-all mailing list