--- sys.orig/arch/dreamcast/conf/files.dreamcast	2005-12-11 21:17:06.000000000 +0900
+++ sys/arch/dreamcast/conf/files.dreamcast	2006-08-28 21:30:21.000000000 +0900
@@ -69,6 +69,10 @@
 attach	mms at maple
 file	arch/dreamcast/dev/maple/mms.c			mms	needs-flag
 
+device	maracas: wsmousedev
+attach	maracas at maple
+file	arch/dreamcast/dev/maple/maracas.c		maracas	needs-flag
+
 device	mmem: disk
 attach	mmem at maple
 file	arch/dreamcast/dev/maple/mmemcard.c		mmem	needs-flag

--- sys.orig/arch/dreamcast/dev/maple/maracas.c	1970-01-01 09:00:00.000000000 +0900
+++ sys/arch/dreamcast/dev/maple/maracas.c	2006-09-05 22:22:54.000000000 +0900
@@ -0,0 +1,395 @@
+/* $NetBSD$ */
+/*
+ * This code is based on mms.c.
+ *     made by Y.Oshima, 2006
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+
+#include "wsmouse.h"
+
+#include <dev/wscons/wsconsio.h> 
+#include <dev/wscons/wsmousevar.h>
+
+#include <dreamcast/dev/maple/maple.h>
+#include <dreamcast/dev/maple/mapleconf.h>
+
+/*
+ * XXX: Original IOCTL.
+ *
+ * MARACAS_MODE_MOUSE is delta-pinter emulation mode.
+ *    Left button + Left move : Pointer move
+ *    Right button + Right height : Button
+ * MARACAS_MODE_RAW is absolute twin-pointer mode.
+ *    Left X-Y point : X-Y value (0 to 255)
+ *    Right X-Y point : Z-W value (0 to 255)
+ *    Buttons :
+ *          bit 7 |  6 |  5 |  4 |  3 |  2 |  1 |  0 |
+ *             ---+----+----+----+----+----+----+----+
+ *              0 |  0 | RA | RS | RB | LA | LS | LB |
+ *      LB: Left Button   LS: Left Shake   LA: Left Area Out
+ *      RB: Right Button  RS: Right Shake  RA: Right Area Out
+ */
+
+#define WSMOUSEIO_SMARACAS     _IOW('W', 63, u_int)
+#define MARACAS_MODE_MOUSE	0
+#define MARACAS_MODE_RAW	1
+
+/*
+ * for Pointer mode,
+ *  Change click button by hight of right maracas
+ *
+ *   HIGHT         MAX(255)----------------
+ *                           ( button 3 )
+ *   MARACAS_POINTER_UPPER ----------------
+ *                           ( button 1 )
+ *   MARACAS_POINTER_LOWER ----------------
+ *                           ( button 2 )
+ *                 MIN  (0)----------------
+ *   
+ */
+#define MARACAS_POINTER_LOWER		85
+#define MARACAS_POINTER_UPPER		150
+
+struct maracas_condition {
+	uint32_t func_code;     /* function code (big endian) */
+	uint16_t buttons;
+	uint8_t  ltrigger;	/* Not Use */
+	uint8_t  rtrigger;	/* Not Use */
+	uint8_t  joyx;		/* left X */
+	uint8_t  joyy;		/* left Y */
+	uint8_t  joyx2;		/* right X */
+	uint8_t  joyy2;		/* right Y */
+};
+
+
+#define MARACAS_BUTTON_C           0x0001 /* Left Button */
+#define MARACAS_BUTTON_B           0x0002 /* Left Shake */
+#define MARACAS_BUTTON_A           0x0004 /* Right Shake */
+#define MARACAS_BUTTON_START       0x0008 /* Right Button */
+#define MARACAS_BUTTON_UP          0x0010 /* NONE */
+#define MARACAS_BUTTON_DOWN        0x0020 /* NONE */
+#define MARACAS_BUTTON_LEFT        0x0040 /* NONE */
+#define MARACAS_BUTTON_RIGHT       0x0080 /* NONE */
+#define MARACAS_BUTTON_Z           0x0100 /* Left Area Check? */
+#define MARACAS_BUTTON_Y           0x0200 /* NONE */
+#define MARACAS_BUTTON_X           0x0400 /* NONE */
+#define MARACAS_BUTTON_D           0x0800 /* Right Area Check? */
+#define MARACAS_BUTTON_UP2         0x1000 /* NONE */
+#define MARACAS_BUTTON_DOWN2       0x2000 /* NONE */
+#define MARACAS_BUTTON_LEFT2       0x4000 /* NONE */
+#define MARACAS_BUTTON_RIGHT2      0x8000 /* NONE */
+
+#define MARACAS_BUTTON_MASK        0xFFFF
+
+
+#define	MARACAS_MOVEMENT_BASE	0x80
+#define	MARACAS_MOVEMENT_MAX	0xFF
+
+#define MARACAS_FUNCDATA_BUTTON_C          0x0001
+#define MARACAS_FUNCDATA_BUTTON_B          0x0002
+#define MARACAS_FUNCDATA_BUTTON_A          0x0004
+#define MARACAS_FUNCDATA_BUTTON_START      0x0008
+#define MARACAS_FUNCDATA_BUTTON_UP         0x0010
+#define MARACAS_FUNCDATA_BUTTON_DOWN       0x0020
+#define MARACAS_FUNCDATA_BUTTON_LEFT       0x0040
+#define MARACAS_FUNCDATA_BUTTON_RIGHT      0x0080
+#define MARACAS_FUNCDATA_BUTTON_Z          0x0100
+#define MARACAS_FUNCDATA_BUTTON_Y          0x0200
+#define MARACAS_FUNCDATA_BUTTON_X          0x0400
+#define MARACAS_FUNCDATA_BUTTON_D          0x0800
+#define MARACAS_FUNCDATA_BUTTON_UP2        0x1000
+#define MARACAS_FUNCDATA_BUTTON_DOWN2      0x2000
+#define MARACAS_FUNCDATA_BUTTON_LEFT2      0x4000
+#define MARACAS_FUNCDATA_BUTTON_RIGHT2     0x8000
+#define MARACAS_FUNCDATA_ANALOG_R          0x10000
+#define MARACAS_FUNCDATA_ANALOG_L          0x20000
+#define MARACAS_FUNCDATA_ANALOG_H          0x40000
+#define MARACAS_FUNCDATA_ANALOG_V          0x80000
+#define MARACAS_FUNCDATA_ANALOG_H2         0x100000
+#define MARACAS_FUNCDATA_ANALOG_V2         0x200000
+
+
+struct maracas_softc {
+	struct device sc_dev;
+
+	struct device *sc_parent;
+	struct maple_unit *sc_unit;
+	int maracas_mode;
+	uint16_t sc_oldbuttons;
+	int sc_oldx;
+	int sc_oldy;
+	uint8_t sc_don;
+	uint8_t sc_analog_2nd;
+
+	struct device *sc_wsmousedev;
+};
+
+int	maracas_match(struct device *, struct cfdata *, void *);
+void	maracas_attach(struct device *, struct device *, void *);
+int	maracas_detach(struct device *, int);
+
+CFATTACH_DECL(maracas, sizeof(struct maracas_softc),
+    maracas_match, maracas_attach, maracas_detach, NULL);
+
+int	maracas_enable(void *);
+int	maracas_ioctl(void *, u_long, caddr_t, int, struct proc *);
+void	maracas_disable(void *);
+
+const struct wsmouse_accessops maracas_accessops = {
+	maracas_enable,
+	maracas_ioctl,
+	maracas_disable,
+};
+
+void	maracas_intr(void *, struct maple_response *, int, int);
+
+int
+maracas_match(struct device *parent, struct cfdata *cf, void *aux)
+{
+	struct maple_attach_args *ma = aux;
+	char *prod = ma->ma_devinfo->di_product_name;
+	const char maracas_id[] = "Maracas Controller";
+
+	if (ma->ma_function == MAPLE_FN_CONTROLLER)
+	{
+		return (memcmp(maracas_id, prod, 18)? 0 : MAPLE_MATCH_FUNC);
+	}
+	return 0;
+}
+
+void
+maracas_attach(struct device *parent, struct device *self, void *aux)
+{
+	struct maracas_softc *sc = (void *) self;
+	struct maple_attach_args *ma = aux;
+	struct wsmousedev_attach_args a;
+	uint32_t data;
+
+	printf(": SEGA Dreamcast Maracas Controller (Mouse input)\n");
+
+	sc->sc_parent = parent;
+	sc->sc_unit = ma->ma_unit;
+
+	data = maple_get_function_data(ma->ma_devinfo,
+	    MAPLE_FN_CONTROLLER);
+
+	printf("%s: Coltroller function: %x\n", sc->sc_dev.dv_xname,data);
+
+	sc->sc_analog_2nd = 0;
+	if ( data & MARACAS_FUNCDATA_ANALOG_H2 ) {
+		printf("%s: Enable Analog controll Horizontal 2\n", sc->sc_dev.dv_xname);
+		sc->sc_analog_2nd |= 1;
+	}
+	if ( data & MARACAS_FUNCDATA_ANALOG_V2 ) {
+		printf("%s: Enable Analog controll Vertical 2\n", sc->sc_dev.dv_xname);
+		sc->sc_analog_2nd |= 2;
+	}
+
+	sc->sc_oldbuttons = 0;
+
+	a.accessops = &maracas_accessops;
+	a.accesscookie = sc;
+
+	/*
+	 * Attach the mouse, saving a handle to it.
+	 */
+	sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
+	if (sc->sc_wsmousedev == NULL) {
+		/* Nothing more to do here. */
+		return;
+	}
+
+	maple_set_callback(parent, sc->sc_unit, MAPLE_FN_CONTROLLER, maracas_intr, sc);
+}
+
+int
+maracas_detach(struct device *self, int flags)
+{
+	struct maracas_softc *sc = (void *) self;
+	int rv = 0;
+
+	if (sc->sc_wsmousedev != NULL)
+		rv = config_detach(sc->sc_wsmousedev, flags);
+
+	return rv;
+}
+
+int
+maracas_enable(void *v)
+{
+	struct maracas_softc *sc = v;
+
+	maple_enable_periodic(sc->sc_parent, sc->sc_unit, MAPLE_FN_CONTROLLER, 1);
+	sc->maracas_mode = MARACAS_MODE_MOUSE;
+	return (0);
+}
+
+void
+maracas_disable(void *v)
+{
+	struct maracas_softc *sc = v;
+
+	maple_enable_periodic(sc->sc_parent, sc->sc_unit, MAPLE_FN_CONTROLLER, 0);
+}
+
+int
+maracas_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
+{
+	struct maracas_softc *sc = v;
+
+	switch (cmd) {
+	case WSMOUSEIO_GTYPE:
+		*(u_int *) data = WSMOUSE_TYPE_MAPLE;
+		break;
+
+	case WSMOUSEIO_SRES:
+		/* XXX */
+		return (EOPNOTSUPP);
+
+	case WSMOUSEIO_SMARACAS:
+		/*
+		 * XXX: Change mode
+		 */
+		switch(*(u_int *)data) {
+		case MARACAS_MODE_MOUSE:
+			sc->maracas_mode = MARACAS_MODE_MOUSE;
+			sc->sc_oldbuttons = 0;
+			sc->sc_oldx = 0;
+			sc->sc_oldy = 0;
+			sc->sc_don = 0;
+			break;
+		case MARACAS_MODE_RAW:
+			sc->maracas_mode = MARACAS_MODE_RAW;
+			sc->sc_oldbuttons = 0;
+			break;
+		default:
+			return (EOPNOTSUPP);
+		}
+		break;
+		
+	default:
+		return (EPASSTHROUGH);
+	}
+
+	return (0);
+}
+
+void
+maracas_intr(void *arg, struct maple_response *response, int size, int flags)
+{
+	struct maracas_softc *sc = arg;
+	struct maracas_condition *data = (void *) response->data;
+	int dx = 0, dy = 0, dz = 0, dw = 0, buttons = 0;
+	uint16_t buttonchg;
+
+	if ((flags & MAPLE_FLAG_PERIODIC) == 0 ||
+	    size < sizeof(*data))
+		return;
+
+	data->buttons &= MARACAS_BUTTON_MASK;
+	buttonchg = sc->sc_oldbuttons ^ data->buttons;
+	sc->sc_oldbuttons = data->buttons;
+
+	if ( sc->maracas_mode == MARACAS_MODE_MOUSE ) {
+		/*
+		 * MOUSE Pointer delta-emulation mode
+		 */
+		if (sc->sc_don) {
+			/*
+			 * Left button still ON
+			 *   drag pointer
+			 */
+			dx = (data->joyx & MARACAS_MOVEMENT_MAX) - sc->sc_oldx;
+				/* calculate X delta */
+			dy = (data->joyy & MARACAS_MOVEMENT_MAX) - sc->sc_oldy;
+				/* calculate Y delta */
+			sc->sc_oldx = data->joyx & MARACAS_MOVEMENT_MAX;
+			sc->sc_oldy = data->joyy & MARACAS_MOVEMENT_MAX;
+		}
+
+		if (dx || dy || buttonchg) {
+			if ((data->buttons & MARACAS_BUTTON_C) == 0){
+				/*
+				 * Left button OFF -> ON
+				 *   get start point for drag
+				 */
+				sc->sc_don = 0xff;
+				sc->sc_oldx = data->joyx & MARACAS_MOVEMENT_MAX;
+				sc->sc_oldy = data->joyy & MARACAS_MOVEMENT_MAX;
+			} else {
+				/*
+				 * Released Left button
+				 */
+				sc->sc_don = 0;
+			}
+			if ((data->buttons & MARACAS_BUTTON_START) == 0) {
+				/*
+				 * get Button status from height of joyy2
+				 */
+				if ( data->joyy2 < MARACAS_POINTER_LOWER ) {
+					buttons |= 0x2;
+				} else if ( data->joyy2 > MARACAS_POINTER_UPPER) {
+					buttons |= 0x4;
+				} else {
+					buttons |= 0x1;
+				}
+			}
+			wsmouse_input(sc->sc_wsmousedev, buttons,
+			    dx, -dy, 0, WSMOUSE_INPUT_DELTA);
+		}
+	} else if (sc->maracas_mode == MARACAS_MODE_RAW ) {
+		/*
+		 * Native mode.
+		 */
+
+		/*
+		 * Left Maracas point to dx and dy.
+		 */
+		dx = (data->joyx & MARACAS_MOVEMENT_MAX);
+		dy = (data->joyy & MARACAS_MOVEMENT_MAX);
+		/*
+		 * Right Maracas point to dx and dy.
+		 */
+		dz = (data->joyx2 & MARACAS_MOVEMENT_MAX);
+		dw = (data->joyy2 & MARACAS_MOVEMENT_MAX);
+		if ( (data->buttons & MARACAS_BUTTON_C)==0 ) {
+			/* Left Button */
+			buttons |= 0x1;
+		}
+		if ( (data->buttons & MARACAS_BUTTON_B)==0 ) {
+			/* Left Shake */
+			buttons |= 0x2;
+		}
+		if ( (data->buttons & MARACAS_BUTTON_Z)==0 ) {
+			/* Left Area Check */
+			buttons |= 0x4;
+		}
+		if ( (data->buttons & MARACAS_BUTTON_START)==0 ) {
+			/* Right Button */
+			buttons |= 0x8;
+		}
+		if ( (data->buttons & MARACAS_BUTTON_A)==0 ) {
+			/* Right Shake */
+			buttons |= 0x10;
+		}
+		if ( (data->buttons & MARACAS_BUTTON_D)==0 ) {
+			/* Right Area Check */
+			buttons |= 0x20;
+		}
+		/*
+		 * value input to wsmouse as absolute
+		 */
+		wsmouse_input_xyzw(sc->sc_wsmousedev, buttons,
+		    dx, dy, dz, dw,
+		    WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y
+		    | WSMOUSE_INPUT_ABSOLUTE_Z | WSMOUSE_INPUT_ABSOLUTE_W );
+
+	}
+}
