On Wednesday 08 June 2011 00:57:43 you wrote:
> I'm not sure if this is operationally equivalent to what you have, but
> it might be of some interest.

Hello,
I've read the code and it has some differences:
-what I export to userland has no prepreprocessing (I see that you filter out 
only full, proper synaptics packets)
-I have also added support for writing (which is directly translated into ps 
commands)

I think that (correct me if I'm wrong) your solution cannot be used for X11 
driver, because there would be 2 sources of ps commands - one from the X 
driver and one from the kernel synaptics driver.

Can I ask you, what are you using this driver for?

Anyway, I'll send a query to tech-x11, maybe they have some better ideas how 
to make use of the userspace X11 synaptics driver.

I attach the patch to be more specific

Regards

-- 
Marek Dopiera
ma...@dopiera.pl
diff --git a/sys/arch/amd64/conf/majors.amd64 b/sys/arch/amd64/conf/majors.amd64
index f8f3a9a..719d4c3 100644
--- a/sys/arch/amd64/conf/majors.amd64
+++ b/sys/arch/amd64/conf/majors.amd64
@@ -90,6 +90,7 @@ device-major	kttcp		char 92			kttcp
 device-major	dpt		char 96			dpt
 device-major	twe		char 97			twe
 device-major	nsmb		char 98			nsmb		
+device-major	psaux	char 99			psaux
 
 #
 # Device majors for Xen. These are assigned here so that:
diff --git a/sys/dev/pckbport/files.pckbport b/sys/dev/pckbport/files.pckbport
index b047ce5..7da8626 100644
--- a/sys/dev/pckbport/files.pckbport
+++ b/sys/dev/pckbport/files.pckbport
@@ -20,4 +20,7 @@ device	pms: wsmousedev
 attach	pms at pckbport
 file	dev/pckbport/pms.c		pms
 file	dev/pckbport/synaptics.c	pms & pms_synaptics_touchpad
+device	psaux
+attach	psaux at pckbport
+file	dev/pckbport/psaux.c psaux
 file	dev/pckbport/elantech.c		pms & pms_elantech_touchpad
diff --git a/sys/dev/pckbport/psaux.c b/sys/dev/pckbport/psaux.c
new file mode 100644
index 0000000..95fa2e4
--- /dev/null
+++ b/sys/dev/pckbport/psaux.c
@@ -0,0 +1,412 @@
+/* $NetBSD: psaux.c,v 1.26 2008/03/15 18:59:07 cube Exp $ */
+
+/*-
+ * Copyright (c) 2010 Marek Dopiera
+ * Copyright (c) 2004 Kentaro Kurahone.
+ * Copyright (c) 2004 Ales Krenek.
+ * Copyright (c) 1994 Charles M. Hannum.
+ * Copyright (c) 1992, 1993 Erik Forsberg.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ``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 I 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>
+__KERNEL_RCSID(0, "$NetBSD: psaux.c,v 1.26 2008/03/15 18:59:07 cube Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/select.h>
+#include <sys/device.h>
+#include <sys/ioctl.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/conf.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/poll.h>
+#include <sys/vnode.h>
+
+#include <sys/bus.h>
+
+#include <dev/pckbport/pmsreg.h>
+#include <dev/pckbport/pckbportvar.h>
+//#define PSAUXDEBUG
+#ifdef PSAUXDEBUG
+static int const psaux_debug = 1;
+#else
+static int const psaux_debug = 0;
+#endif
+#define DPRINTF(...)    do { if (psaux_debug) printf(__VA_ARGS__); } while (0)
+
+#define RING_BUF_SIZE 64
+
+#define min(a,b) (((a) < (b)) ? (a):(b))
+
+struct ring_buffer {
+	unsigned char rb_buf[RING_BUF_SIZE];
+	size_t rb_start;
+	size_t rb_length;
+};
+
+struct psaux_softc {
+	device_t sc_dev;
+	pckbport_tag_t sc_kbctag;
+	int sc_kbcslot;
+	int sc_enabled;		/* input enabled? */
+	struct ring_buffer sc_rbuf;
+	struct selinfo sc_sel;
+	kmutex_t sc_lock;
+	kcondvar_t sc_cond;
+	int sc_closing;
+};
+
+static dev_type_open(psaux_open);
+static dev_type_close(psaux_close);
+static dev_type_read(psaux_read);
+static dev_type_write(psaux_write);
+static dev_type_poll(psaux_poll);
+static void rbuf_init(struct ring_buffer *);
+static size_t rbuf_drain(struct ring_buffer *, unsigned char *, size_t);
+static void rbuf_add(struct ring_buffer *, unsigned char);
+static __inline bool rbuf_empty(struct ring_buffer *);
+static int psaux_match(device_t, cfdata_t, void *);
+static void psaux_attach(device_t, device_t, void *);
+static void	do_enable(struct psaux_softc *);
+static void	do_disable(struct psaux_softc *);
+static int psaux_enable(void *);
+static void psaux_disable(void *);
+static bool	psaux_suspend(device_t PMF_FN_PROTO);
+static bool	psaux_resume(device_t PMF_FN_PROTO);
+static void psaux_input(void *, int);
+
+CFATTACH_DECL_NEW(psaux, sizeof (struct psaux_softc),
+    psaux_match, psaux_attach, NULL, NULL);
+extern struct cfdriver psaux_cd;
+
+const struct cdevsw psaux_cdevsw = {
+	psaux_open, psaux_close, psaux_read, psaux_write, noioctl,
+	nostop, notty, psaux_poll, nommap, nokqfilter, D_OTHER
+};
+
+static void
+rbuf_init(struct ring_buffer * rbuf)
+{
+	rbuf->rb_start = 0;
+	rbuf->rb_length = 0;
+}
+
+static size_t
+rbuf_drain(struct ring_buffer * rbuf, unsigned char * out_buf, size_t out_size)
+{
+	size_t to_copy, to_copy1;
+	to_copy = min(out_size, rbuf->rb_length);
+	to_copy1 = min(to_copy, RING_BUF_SIZE - rbuf->rb_start);
+	memcpy(out_buf, rbuf->rb_buf + rbuf->rb_start, to_copy1);
+	if (to_copy1 < to_copy)
+		memcpy(out_buf + to_copy1, rbuf->rb_buf, to_copy - to_copy1);
+	rbuf->rb_start = (rbuf->rb_start + to_copy) % RING_BUF_SIZE;
+	rbuf->rb_length -= to_copy;
+	return to_copy;
+}
+
+static void
+rbuf_add(struct ring_buffer * rbuf, unsigned char data)
+{
+	size_t pos = (rbuf->rb_start + rbuf->rb_length) % RING_BUF_SIZE;
+	if (rbuf->rb_length == RING_BUF_SIZE) {
+		DPRINTF(
+			"psaux: Ring buffer overflow, discarding oldest data (%02X)\n",
+			(int)rbuf->rb_buf[pos]
+			);
+		rbuf->rb_start = (rbuf->rb_start + 1) % RING_BUF_SIZE;
+	} else
+		++rbuf->rb_length;
+	rbuf->rb_buf[pos] = data;
+}
+
+static __inline bool
+rbuf_empty(struct ring_buffer * rbuf)
+{
+	return rbuf->rb_length == 0;
+}
+
+static int
+psaux_match(device_t parent, cfdata_t match, void *aux)
+{
+	struct pckbport_attach_args *pa = aux;
+	u_char cmd[1], resp[2];
+	int res;
+
+	if (pa->pa_slot != PCKBPORT_AUX_SLOT)
+		return 0;
+	pckbport_flush(pa->pa_tag, pa->pa_slot);
+
+	/*reset*/
+	cmd[0] = PMS_RESET;
+	res = pckbport_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 1);
+	if (res)
+		return 0;
+	if (resp[0] != PMS_RSTDONE)
+		return 0;
+	if (resp[1] != 0) /*not mouse*/
+		return 0;
+	printf("psaux: attached\n");
+	return 10;
+}
+
+static int
+psaux_open(dev_t dev, int flags, int mode, struct lwp *l)
+{
+	struct psaux_softc *sc = device_lookup_private(&psaux_cd, minor(dev));
+	psaux_enable(sc);
+	return (0);
+}
+
+static int
+psaux_close(dev_t dev, int flags, int mode,
+    struct lwp *l)
+{
+	struct psaux_softc *sc = device_lookup_private(&psaux_cd, minor(dev));
+	psaux_disable(sc);
+	return (0);
+}
+
+static int
+psaux_read(dev_t dev, struct uio *uio, int flags)
+{
+	struct psaux_softc *sc = device_lookup_private(&psaux_cd, minor(dev));
+	int err, ret = -1;
+	size_t copied;
+	unsigned char res_buf[RING_BUF_SIZE];
+	mutex_enter(&sc->sc_lock);
+	if (sc->sc_closing) {
+		ret = ENXIO;
+		goto out_unlock;
+	}
+	while (rbuf_empty(&sc->sc_rbuf)) {
+		if (flags & IO_NDELAY) {
+			ret = EWOULDBLOCK;
+			goto out_unlock;
+		}
+		err = cv_wait_sig(&sc->sc_cond, &sc->sc_lock);
+		if (err) {
+			ret = err;
+			goto out_unlock;
+		}
+	}
+	if (sc->sc_closing) {
+		ret = ENXIO;
+		goto out_unlock;
+	}
+	copied = rbuf_drain(
+		&sc->sc_rbuf,
+		res_buf,
+		min(uio->uio_resid, RING_BUF_SIZE)
+		);
+	ret = 0;
+out_unlock:
+	mutex_exit(&sc->sc_lock);
+	if (ret == 0) {
+		ret = uiomove(res_buf, copied, uio);
+		if (ret)
+			DPRINTF("pasuax: uiomove error: %d\n", err);
+	}
+	return ret;
+}
+
+static int
+psaux_write(dev_t dev, struct uio *uio, int flags)
+{
+	int ret;
+	struct psaux_softc *sc = device_lookup_private(&psaux_cd, minor(dev));
+	while (uio->uio_resid) {
+		u_char c;
+		if (uiomove(&c, 1, uio))
+			return EFAULT;
+		mutex_enter(&sc->sc_lock);
+		//quite ugly, but we have to omit the automatic ACK handling
+		ret = sc->sc_kbctag->t_ops->t_send_devcmd(
+			sc->sc_kbctag->t_cookie,
+			sc->sc_kbcslot,
+			c
+			);
+		mutex_exit(&sc->sc_lock);
+		if (!ret) {
+			DPRINTF("psaux: write error: %d\n", ret);
+			return EIO;
+		}
+		
+	}
+	return 0;
+}
+
+
+static int
+psaux_poll(dev_t dev, int events, struct lwp *l)
+{
+	struct psaux_softc *sc = device_lookup_private(&psaux_cd, minor(dev));
+	int revents = events & (POLLOUT | POLLWRNORM);
+	mutex_enter(&sc->sc_lock);
+	if (!rbuf_empty(&sc->sc_rbuf))
+		revents |= events & (POLLIN | POLLRDNORM);
+	else
+		selrecord(curlwp, &sc->sc_sel);
+	mutex_exit(&sc->sc_lock);
+	return revents;
+}
+
+static void
+psaux_attach(device_t parent, device_t self, void *aux)
+{
+	struct psaux_softc *sc = device_private(self);
+	struct pckbport_attach_args *pa = aux;
+	u_char cmd[2], resp[2];
+	int res;
+
+	sc->sc_dev = self;
+	sc->sc_kbctag = pa->pa_tag;
+	sc->sc_kbcslot = pa->pa_slot;
+	sc->sc_closing = 0;
+	rbuf_init(&sc->sc_rbuf);
+	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_TTY);
+	cv_init(&sc->sc_cond, "psaux");
+	selinit(&sc->sc_sel);
+
+	/* Flush any garbage. */
+	pckbport_flush(pa->pa_tag, pa->pa_slot);
+
+	/* reset the device */
+	cmd[0] = PMS_RESET;
+	res = pckbport_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 1);
+
+	/* Install generic handler. */
+	pckbport_set_inputhandler(sc->sc_kbctag, sc->sc_kbcslot,
+		psaux_input, sc, device_xname(sc->sc_dev));
+
+	/* no interrupts until enabled */
+	cmd[0] = PMS_DEV_DISABLE;
+	res = pckbport_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 0, 0, 0);
+	if (res)
+		aprint_error("psauxattach: disable error\n");
+	pckbport_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 0);
+	if (!pmf_device_register(self, psaux_suspend, psaux_resume))
+		aprint_error_dev(self, "couldn't establish power handler\n");
+}
+
+static void
+do_enable(struct psaux_softc *sc)
+{
+	u_char cmd[1];
+	int res;
+
+	pckbport_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 1);
+
+	cmd[0] = PMS_DEV_ENABLE;
+	res = pckbport_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd,
+	    1, 0, 1, 0);
+	if (res)
+		aprint_error("psaux_enable: command error %d\n", res);
+
+}
+
+static void
+do_disable(struct psaux_softc *sc)
+{
+	u_char cmd[1];
+	int res;
+
+	cmd[0] = PMS_DEV_DISABLE;
+	res = pckbport_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd,
+	    1, 0, 1, 0);
+	if (res)
+		aprint_error("psaux_disable: command error\n");
+
+	pckbport_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 0);
+}
+
+static int
+psaux_enable(void *v)
+{
+	struct psaux_softc *sc = v;
+
+	if (sc->sc_enabled)
+		return EBUSY;
+
+	do_enable(sc);
+
+	mutex_enter(&sc->sc_lock);
+	sc->sc_enabled = 1;
+	mutex_exit(&sc->sc_lock);
+
+	return 0;
+}
+
+static void
+psaux_disable(void *v)
+{
+	struct psaux_softc *sc = v;
+
+	do_disable(sc);
+
+	mutex_enter(&sc->sc_lock);
+	sc->sc_enabled = 0;
+	mutex_exit(&sc->sc_lock);
+}
+
+static bool
+psaux_suspend(device_t dv PMF_FN_ARGS)
+{
+	struct psaux_softc *sc = device_private(dv);
+
+	if (sc->sc_enabled)
+		do_disable(sc);
+
+	return true;
+}
+
+static bool
+psaux_resume(device_t dv PMF_FN_ARGS)
+{
+	struct psaux_softc *sc = device_private(dv);
+
+	if (sc->sc_enabled)
+		do_enable(sc); /* only if we were suspended */
+
+	return true;
+}
+
+static void
+psaux_input(void *vsc, int data)
+{
+	struct psaux_softc *sc = vsc;
+
+	if (!sc->sc_enabled)
+		/* Interrupts are not expected.	 Discard the byte. */
+		return;
+	if (data & (~0xff))
+		DPRINTF("psaux: got data bigger than one byte: %02X\n", data);
+	
+	/* now we can add it to the buffer */
+	mutex_enter(&sc->sc_lock);
+	rbuf_add(&sc->sc_rbuf, (unsigned char)data);
+	cv_signal(&sc->sc_cond);
+	selnotify(&sc->sc_sel, 0, 0);
+	mutex_exit(&sc->sc_lock);
+}
+

Reply via email to