svn commit: r268768 - user/jceel/soc2014_evdev/head/sys/dev/terasic/mtl
Jakub Wojciech Klama
jceel at FreeBSD.org
Wed Jul 16 16:30:31 UTC 2014
Author: jceel
Date: Wed Jul 16 16:30:30 2014
New Revision: 268768
URL: http://svnweb.freebsd.org/changeset/base/268768
Log:
Add Terasic MTL multitouch driver.
Added:
user/jceel/soc2014_evdev/head/sys/dev/terasic/mtl/terasic_mtl_touch.c (contents, props changed)
Modified:
user/jceel/soc2014_evdev/head/sys/dev/terasic/mtl/terasic_mtl.c
user/jceel/soc2014_evdev/head/sys/dev/terasic/mtl/terasic_mtl.h
Modified: user/jceel/soc2014_evdev/head/sys/dev/terasic/mtl/terasic_mtl.c
==============================================================================
--- user/jceel/soc2014_evdev/head/sys/dev/terasic/mtl/terasic_mtl.c Wed Jul 16 15:57:17 2014 (r268767)
+++ user/jceel/soc2014_evdev/head/sys/dev/terasic/mtl/terasic_mtl.c Wed Jul 16 16:30:30 2014 (r268768)
@@ -80,6 +80,9 @@ terasic_mtl_attach(struct terasic_mtl_so
error = terasic_mtl_text_attach(sc);
if (error)
goto error;
+ error = terasic_mtl_touch_attach(sc);
+ if (error)
+ goto error;
/*
* XXXRW: Once we've attached syscons, we can't detach it, so do it
* last.
Modified: user/jceel/soc2014_evdev/head/sys/dev/terasic/mtl/terasic_mtl.h
==============================================================================
--- user/jceel/soc2014_evdev/head/sys/dev/terasic/mtl/terasic_mtl.h Wed Jul 16 15:57:17 2014 (r268767)
+++ user/jceel/soc2014_evdev/head/sys/dev/terasic/mtl/terasic_mtl.h Wed Jul 16 16:30:30 2014 (r268768)
@@ -33,6 +33,16 @@
#ifndef _DEV_TERASIC_MTL_H_
#define _DEV_TERASIC_MTL_H_
+struct terasic_mtl_touch_state
+{
+ int x1;
+ int y1;
+ int x2;
+ int y2;
+ uint16_t gesture;
+ uint32_t touchpoints;
+};
+
struct terasic_mtl_softc {
/*
* syscons requires that its video_adapter_t be at the front of the
@@ -76,6 +86,14 @@ struct terasic_mtl_softc {
struct resource *mtl_text_res;
int mtl_text_rid;
uint16_t *mtl_text_soft;
+
+ /*
+ * evdev device
+ */
+ struct evdev_dev *mtl_evdev;
+ struct terasic_mtl_touch_state mtl_evdev_state;
+ struct callout mtl_evdev_callout;
+ bool mtl_evdev_opened;
};
#define TERASIC_MTL_LOCK(sc) mtx_lock(&(sc)->mtl_lock)
@@ -154,6 +172,35 @@ struct terasic_mtl_softc {
#define TERASIC_MTL_ALPHA_OPAQUE 255
/*
+ * Driver-recognized gestures.
+ */
+
+#define TSG_NONE 0x00
+#define TSG_NORTH 0x10
+#define TSG_NORTHEAST 0x12
+#define TSG_EAST 0x14
+#define TSG_SOUTHEAST 0x16
+#define TSG_SOUTH 0x18
+#define TSG_SOUTHWEST 0x1A
+#define TSG_WEST 0x1C
+#define TSG_NORTHWEST 0x1E
+#define TSG_ROTATE_CW 0x28 /* Clockwise */
+#define TSG_ROTATE_CCW 0x29 /* Counter Clockwise */
+#define TSG_CLICK 0x20
+#define TSG_DCLICK 0x22 /* Double Click */
+#define TSG2_NORTH 0x30
+#define TSG2_NORTHEAST 0x32
+#define TSG2_EAST 0x34
+#define TSG2_SOUTHEAST 0x36
+#define TSG2_SOUTH 0x38
+#define TSG2_SOUTHWEST 0x3A
+#define TSG2_WEST 0x3C
+#define TSG2_NORTHWEST 0x3E
+#define TSG2_CLICK 0x40
+#define TSG2_ZOOM_IN 0x48
+#define TSG2_ZOOM_OUT 0x49
+
+/*
* Driver setup routines from the bus attachment/teardown.
*/
int terasic_mtl_attach(struct terasic_mtl_softc *sc);
@@ -172,6 +219,8 @@ int terasic_mtl_syscons_attach(struct te
void terasic_mtl_syscons_detach(struct terasic_mtl_softc *sc);
int terasic_mtl_text_attach(struct terasic_mtl_softc *sc);
void terasic_mtl_text_detach(struct terasic_mtl_softc *sc);
+int terasic_mtl_touch_attach(struct terasic_mtl_softc *sc);
+void terasic_mtl_touch_detach(struct terasic_mtl_softc *sc);
/*
* Control register I/O routines.
Added: user/jceel/soc2014_evdev/head/sys/dev/terasic/mtl/terasic_mtl_touch.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ user/jceel/soc2014_evdev/head/sys/dev/terasic/mtl/terasic_mtl_touch.c Wed Jul 16 16:30:30 2014 (r268768)
@@ -0,0 +1,251 @@
+
+/*-
+ * Copyright (c) 2014 Jakub Wojciech Klama <jceel at FreeBSD.org>
+ * All rights reserved.
+ *
+ * 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$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/fbio.h> /* video_adapter_t */
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+
+#include <dev/evdev/evdev.h>
+#include <dev/evdev/input.h>
+
+#include <dev/terasic/mtl/terasic_mtl.h>
+
+static void terasic_mtl_touch_intr(void *);
+static evdev_open_t terasic_mtl_touch_open;
+static evdev_close_t terasic_mtl_touch_close;
+
+struct evdev_methods terasic_mtl_ev_methods = {
+ .ev_open = &terasic_mtl_touch_open,
+ .ev_close = &terasic_mtl_touch_close,
+};
+
+
+static uint16_t terasic_mtl_gestures[256] = {
+ /* Single finger gestures */
+ [TSG_NONE] = KEY_RESERVED,
+ [TSG_NORTH] = BTN_NORTH,
+ [TSG_EAST] = BTN_EAST,
+ [TSG_WEST] = BTN_WEST,
+ [TSG_SOUTH] = BTN_SOUTH,
+ [TSG_CLICK] = BTN_TOUCH,
+ [TSG_DCLICK] = BTN_TOUCH,
+ [TSG_ROTATE_CW] = BTN_1,
+ [TSG_ROTATE_CCW] = BTN_2,
+ /* Two finger gestures */
+ [TSG2_NORTH] = BTN_NORTH,
+ [TSG2_EAST] = BTN_EAST,
+ [TSG2_WEST] = BTN_WEST,
+ [TSG2_SOUTH] = BTN_SOUTH,
+ [TSG2_CLICK] = BTN_TOOL_DOUBLETAP,
+ [TSG2_ZOOM_IN] = KEY_ZOOMIN,
+ [TSG2_ZOOM_OUT] = KEY_ZOOMOUT,
+};
+
+int
+terasic_mtl_touch_attach(struct terasic_mtl_softc *sc)
+{
+ struct input_absinfo absinfo;
+ sc->mtl_evdev = evdev_alloc();
+ evdev_set_name(sc->mtl_evdev, device_get_desc(sc->mtl_dev));
+ evdev_set_softc(sc->mtl_evdev, sc);
+ evdev_set_methods(sc->mtl_evdev, &terasic_mtl_ev_methods);
+ evdev_support_event(sc->mtl_evdev, EV_SYN);
+ evdev_support_event(sc->mtl_evdev, EV_KEY);
+ evdev_support_event(sc->mtl_evdev, EV_ABS);
+ evdev_support_abs(sc->mtl_evdev, ABS_MT_POSITION_X);
+ evdev_support_abs(sc->mtl_evdev, ABS_MT_POSITION_Y);
+
+ /* Support gestures as a keys */
+ evdev_support_key(sc->mtl_evdev, BTN_TOUCH);
+ evdev_support_key(sc->mtl_evdev, BTN_TOOL_DOUBLETAP);
+ evdev_support_key(sc->mtl_evdev, BTN_NORTH);
+ evdev_support_key(sc->mtl_evdev, BTN_SOUTH);
+ evdev_support_key(sc->mtl_evdev, BTN_WEST);
+ evdev_support_key(sc->mtl_evdev, BTN_EAST);
+ evdev_support_key(sc->mtl_evdev, BTN_1);
+ evdev_support_key(sc->mtl_evdev, BTN_2);
+ evdev_support_key(sc->mtl_evdev, KEY_ZOOMIN);
+ evdev_support_key(sc->mtl_evdev, KEY_ZOOMOUT);
+
+ bzero(&absinfo, sizeof(struct input_absinfo));
+
+ /* Set X axis bounds */
+ absinfo.minimum = 0;
+ absinfo.maximum = 1024;
+ evdev_set_absinfo(sc->mtl_evdev, ABS_MT_POSITION_X, &absinfo);
+
+ /* Set Y axis bounds */
+ absinfo.minimum = 0;
+ absinfo.maximum = 512;
+ evdev_set_absinfo(sc->mtl_evdev, ABS_MT_POSITION_Y, &absinfo);
+
+ evdev_register(sc->mtl_dev, sc->mtl_evdev);
+
+ callout_init(&sc->mtl_evdev_callout, 1);
+ return (0);
+}
+
+void
+terasic_mtl_touch_detach(struct terasic_mtl_softc *sc)
+{
+
+ evdev_unregister(sc->mtl_dev, sc->mtl_evdev);
+}
+
+static int
+terasic_mtl_touch_open(struct evdev_dev *evdev, void *softc)
+{
+ struct terasic_mtl_softc *sc = (struct terasic_mtl_softc *)softc;
+
+ /* Start polling */
+ callout_reset(&sc->mtl_evdev_callout, hz / 10,
+ terasic_mtl_touch_intr, sc);
+
+ sc->mtl_evdev_opened = true;
+ return (0);
+}
+
+static void
+terasic_mtl_touch_close(struct evdev_dev *evdev, void *softc)
+{
+ struct terasic_mtl_softc *sc = (struct terasic_mtl_softc *)softc;
+
+ /* Stop polling */
+ callout_stop(&sc->mtl_evdev_callout);
+
+ sc->mtl_evdev_opened = false;
+}
+
+static void
+terasic_mtl_touch_intr(void *arg)
+{
+ struct terasic_mtl_softc *sc = (struct terasic_mtl_softc *)arg;
+ struct terasic_mtl_touch_state *state = &sc->mtl_evdev_state;
+ int32_t x1, y1, x2, y2;
+ bool sync = false;
+
+ int tsg = le32toh(bus_read_4(sc->mtl_reg_res,
+ TERASIC_MTL_OFF_TOUCHGESTURE));
+ int touchpoints = tsg >> 8;
+ int gesture = tsg & 0xff;
+
+ if (touchpoints == 0 || touchpoints == 0xffffff) {
+ /*
+ * Check if it's a release and if so, push empty
+ * MT_SYNC event
+ */
+ if (state->touchpoints != 0) {
+ evdev_mt_sync(sc->mtl_evdev);
+ evdev_sync(sc->mtl_evdev);
+ }
+
+ state->touchpoints = 0;
+
+ callout_reset(&sc->mtl_evdev_callout, hz / 10,
+ terasic_mtl_touch_intr, sc);
+ return;
+ }
+
+ if (gesture != 0 && gesture != 0xff) {
+ uint16_t code = terasic_mtl_gestures[gesture];
+ if (code != KEY_RESERVED) {
+ evdev_push_event(sc->mtl_evdev, EV_KEY, code, 1);
+ sync = true;
+ state->gesture = code;
+ }
+ } else {
+ if (state->gesture != 0) {
+ /* Push a release event */
+ evdev_push_event(sc->mtl_evdev, EV_KEY, state->gesture, 0);
+ sync = true;
+ state->gesture = 0;
+ }
+ }
+
+ if (touchpoints > 0) {
+ x1 = le32toh(bus_read_4(sc->mtl_reg_res,
+ TERASIC_MTL_OFF_TOUCHPOINT_X1));
+ y1 = le32toh(bus_read_4(sc->mtl_reg_res,
+ TERASIC_MTL_OFF_TOUCHPOINT_Y1));
+
+ if (x1 != -1 && y1 != -1 && (x1 != state->x1) &&
+ (y1 != state->y1)) {
+ evdev_push_event(sc->mtl_evdev, EV_ABS,
+ ABS_MT_POSITION_X, x1);
+ evdev_push_event(sc->mtl_evdev, EV_ABS,
+ ABS_MT_POSITION_Y, y1);
+ evdev_mt_sync(sc->mtl_evdev);
+
+ state->x1 = x1;
+ state->y1 = y1;
+ sync = true;
+ }
+ }
+
+ if (touchpoints > 1) {
+ x2 = le32toh(bus_read_4(sc->mtl_reg_res,
+ TERASIC_MTL_OFF_TOUCHPOINT_X2));
+ y2 = le32toh(bus_read_4(sc->mtl_reg_res,
+ TERASIC_MTL_OFF_TOUCHPOINT_Y2));
+
+ if (x2 != -1 && y2 != -1 && (x2 != state->x2) &&
+ (y2 != state->y2)) {
+ evdev_push_event(sc->mtl_evdev, EV_ABS,
+ ABS_MT_POSITION_X, x2);
+ evdev_push_event(sc->mtl_evdev, EV_ABS,
+ ABS_MT_POSITION_Y, y2);
+ evdev_mt_sync(sc->mtl_evdev);
+
+ state->x2 = x2;
+ state->y2 = y2;
+ sync = true;
+ }
+ }
+
+ state->touchpoints = touchpoints;
+
+ if (sync)
+ evdev_sync(sc->mtl_evdev);
+
+ callout_reset(&sc->mtl_evdev_callout, hz / 10,
+ terasic_mtl_touch_intr, sc);
+}
More information about the svn-src-user
mailing list