xref: /netbsd-src/sys/arch/dreamcast/dev/maple/mms.c (revision c7fb772b85b2b5d4cfb282f868f454b4701534fd)
1*c7fb772bSthorpej /*	$NetBSD: mms.c,v 1.19 2021/08/07 16:18:48 thorpej Exp $	*/
2b4255677Sthorpej 
3b4255677Sthorpej /*-
4b4255677Sthorpej  * Copyright (c) 2001 The NetBSD Foundation, Inc.
5b4255677Sthorpej  * All rights reserved.
6b4255677Sthorpej  *
7b4255677Sthorpej  * This code is derived from software contributed to The NetBSD Foundation
8b4255677Sthorpej  * by Jason R. Thorpe.
9b4255677Sthorpej  *
10b4255677Sthorpej  * Redistribution and use in source and binary forms, with or without
11b4255677Sthorpej  * modification, are permitted provided that the following conditions
12b4255677Sthorpej  * are met:
13b4255677Sthorpej  * 1. Redistributions of source code must retain the above copyright
14b4255677Sthorpej  *    notice, this list of conditions and the following disclaimer.
15b4255677Sthorpej  * 2. Redistributions in binary form must reproduce the above copyright
16b4255677Sthorpej  *    notice, this list of conditions and the following disclaimer in the
17b4255677Sthorpej  *    documentation and/or other materials provided with the distribution.
18b4255677Sthorpej  *
19b4255677Sthorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20b4255677Sthorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21b4255677Sthorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22b4255677Sthorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23b4255677Sthorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24b4255677Sthorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25b4255677Sthorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26b4255677Sthorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27b4255677Sthorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28b4255677Sthorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29b4255677Sthorpej  * POSSIBILITY OF SUCH DAMAGE.
30b4255677Sthorpej  */
31b4255677Sthorpej 
3214172728Slukem #include <sys/cdefs.h>
33*c7fb772bSthorpej __KERNEL_RCSID(0, "$NetBSD: mms.c,v 1.19 2021/08/07 16:18:48 thorpej Exp $");
3414172728Slukem 
35b4255677Sthorpej #include <sys/param.h>
36b4255677Sthorpej #include <sys/device.h>
37b4255677Sthorpej #include <sys/proc.h>
38b4255677Sthorpej #include <sys/systm.h>
39b4255677Sthorpej 
40b4255677Sthorpej #include "wsmouse.h"
41b4255677Sthorpej 
42b4255677Sthorpej #include <dev/wscons/wsconsio.h>
43b4255677Sthorpej #include <dev/wscons/wsmousevar.h>
44b4255677Sthorpej 
45b4255677Sthorpej #include <dreamcast/dev/maple/maple.h>
46b4255677Sthorpej #include <dreamcast/dev/maple/mapleconf.h>
47b4255677Sthorpej 
48b4255677Sthorpej struct mms_condition {
49154b121fSitohy 	uint32_t func_code;	/* function code (big endian) */
50b4255677Sthorpej 	uint32_t buttons;
51b4255677Sthorpej 	uint16_t axis1;		/* X */
52b4255677Sthorpej 	uint16_t axis2;		/* Y */
53b4255677Sthorpej 	uint16_t axis3;		/* wheel */
54b4255677Sthorpej 	uint16_t axis4;
55b4255677Sthorpej 	uint16_t axis5;
56b4255677Sthorpej 	uint16_t axis6;
57b4255677Sthorpej 	uint16_t axis7;
58b4255677Sthorpej 	uint16_t axis8;
59b4255677Sthorpej };
60b4255677Sthorpej 
61b4255677Sthorpej #define	MMS_BUTTON_C		0x01	/* middle */
62b4255677Sthorpej #define	MMS_BUTTON_B		0x02	/* right */
63b4255677Sthorpej #define	MMS_BUTTON_A		0x04	/* left */
64b4255677Sthorpej #define	MMS_BUTTON_START	0x08	/* thumb */
65b4255677Sthorpej #define	MMS_BUTTON_MASK		0x0f
66b4255677Sthorpej 
67b4255677Sthorpej #define	MMS_MOVEMENT_BASE	0x200
68b4255677Sthorpej #define	MMS_MOVEMENT_MAX	0x3ff
69b4255677Sthorpej 
70b4255677Sthorpej #define	MMS_FUNCDATA_AXIS1	0x001
71b4255677Sthorpej #define	MMS_FUNCDATA_AXIS2	0x002
72b4255677Sthorpej #define	MMS_FUNCDATA_AXIS3	0x004
73b4255677Sthorpej #define	MMS_FUNCDATA_AXIS4	0x008
74b4255677Sthorpej #define	MMS_FUNCDATA_AXIS5	0x010
75b4255677Sthorpej #define	MMS_FUNCDATA_AXIS6	0x020
76b4255677Sthorpej #define	MMS_FUNCDATA_AXIS7	0x040
77b4255677Sthorpej #define	MMS_FUNCDATA_AXIS8	0x080
78b4255677Sthorpej #define	MMS_FUNCDATA_C		0x100
79b4255677Sthorpej #define	MMS_FUNCDATA_B		0x200
80b4255677Sthorpej #define	MMS_FUNCDATA_A		0x400
81b4255677Sthorpej #define	MMS_FUNCDATA_START	0x800
82b4255677Sthorpej 
83b4255677Sthorpej struct mms_softc {
8407d8ce49Stsutsui 	device_t sc_dev;
85b4255677Sthorpej 
8607d8ce49Stsutsui 	device_t sc_parent;
87154b121fSitohy 	struct maple_unit *sc_unit;
88b4255677Sthorpej 
89b4255677Sthorpej 	uint32_t sc_oldbuttons;
90b4255677Sthorpej 
91cbab9cadSchs 	device_t sc_wsmousedev;
92b4255677Sthorpej };
93b4255677Sthorpej 
9483c0ebaeStsutsui static int	mms_match(device_t, cfdata_t, void *);
9583c0ebaeStsutsui static void	mms_attach(device_t, device_t, void *);
9683c0ebaeStsutsui static int	mms_detach(device_t, int);
97b4255677Sthorpej 
9807d8ce49Stsutsui CFATTACH_DECL_NEW(mms, sizeof(struct mms_softc),
99154b121fSitohy     mms_match, mms_attach, mms_detach, NULL);
100b4255677Sthorpej 
10183c0ebaeStsutsui static int	mms_enable(void *);
10283c0ebaeStsutsui static int	mms_ioctl(void *, u_long, void *, int, struct lwp *);
10383c0ebaeStsutsui static void	mms_disable(void *);
104b4255677Sthorpej 
105b4255677Sthorpej const struct wsmouse_accessops mms_accessops = {
106b4255677Sthorpej 	mms_enable,
107b4255677Sthorpej 	mms_ioctl,
108b4255677Sthorpej 	mms_disable,
109b4255677Sthorpej };
110b4255677Sthorpej 
11183c0ebaeStsutsui static void	mms_intr(void *, struct maple_response *, int, int);
112b4255677Sthorpej 
11383c0ebaeStsutsui static int
mms_match(device_t parent,cfdata_t cf,void * aux)11407d8ce49Stsutsui mms_match(device_t parent, cfdata_t cf, void *aux)
115b4255677Sthorpej {
116b4255677Sthorpej 	struct maple_attach_args *ma = aux;
117b4255677Sthorpej 
118cb6453dbStsutsui 	return ma->ma_function == MAPLE_FN_MOUSE ? MAPLE_MATCH_FUNC : 0;
119b4255677Sthorpej }
120b4255677Sthorpej 
12183c0ebaeStsutsui static void
mms_attach(device_t parent,device_t self,void * aux)12207d8ce49Stsutsui mms_attach(device_t parent, device_t self, void *aux)
123b4255677Sthorpej {
12407d8ce49Stsutsui 	struct mms_softc *sc = device_private(self);
125b4255677Sthorpej 	struct maple_attach_args *ma = aux;
126b4255677Sthorpej 	struct wsmousedev_attach_args a;
127b4255677Sthorpej 	uint32_t data;
128b4255677Sthorpej 
129b4255677Sthorpej 	printf(": SEGA Dreamcast Mouse\n");
130b4255677Sthorpej 
13107d8ce49Stsutsui 	sc->sc_dev = self;
1326e91aedcSitohy 	sc->sc_parent = parent;
133154b121fSitohy 	sc->sc_unit = ma->ma_unit;
134b4255677Sthorpej 
135b4255677Sthorpej 	data = maple_get_function_data(ma->ma_devinfo,
136154b121fSitohy 	    MAPLE_FN_MOUSE);
137b4255677Sthorpej 
13807d8ce49Stsutsui 	printf("%s: buttons:", device_xname(self));
139b4255677Sthorpej 	if (data & MMS_FUNCDATA_A)
140b4255677Sthorpej 		printf(" left");
141b4255677Sthorpej 	if (data & MMS_FUNCDATA_C)
142b4255677Sthorpej 		printf(" middle");
143b4255677Sthorpej 	if (data & MMS_FUNCDATA_B)
144b4255677Sthorpej 		printf(" right");
145b4255677Sthorpej 	if (data & MMS_FUNCDATA_START)
146b4255677Sthorpej 		printf(" thumb");
147b4255677Sthorpej 	printf("\n");
148b4255677Sthorpej 
149b4255677Sthorpej 	sc->sc_oldbuttons = 0;
150b4255677Sthorpej 
151b4255677Sthorpej 	a.accessops = &mms_accessops;
152b4255677Sthorpej 	a.accesscookie = sc;
153b4255677Sthorpej 
154b4255677Sthorpej 	/*
155b4255677Sthorpej 	 * Attach the mouse, saving a handle to it.
156b4255677Sthorpej 	 */
157*c7fb772bSthorpej 	sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint, CFARGS_NONE);
158b4255677Sthorpej 	if (sc->sc_wsmousedev == NULL) {
159b4255677Sthorpej 		/* Nothing more to do here. */
160b4255677Sthorpej 		return;
161b4255677Sthorpej 	}
162b4255677Sthorpej 
163154b121fSitohy 	maple_set_callback(parent, sc->sc_unit, MAPLE_FN_MOUSE, mms_intr, sc);
164154b121fSitohy }
165154b121fSitohy 
16683c0ebaeStsutsui static int
mms_detach(device_t self,int flags)16707d8ce49Stsutsui mms_detach(device_t self, int flags)
168154b121fSitohy {
16907d8ce49Stsutsui 	struct mms_softc *sc = device_private(self);
170154b121fSitohy 	int rv = 0;
171154b121fSitohy 
172154b121fSitohy 	if (sc->sc_wsmousedev != NULL)
173154b121fSitohy 		rv = config_detach(sc->sc_wsmousedev, flags);
174154b121fSitohy 
175154b121fSitohy 	return rv;
176b4255677Sthorpej }
177b4255677Sthorpej 
17883c0ebaeStsutsui static int
mms_enable(void * v)179b4255677Sthorpej mms_enable(void *v)
180b4255677Sthorpej {
1816e91aedcSitohy 	struct mms_softc *sc = v;
182b4255677Sthorpej 
1836e91aedcSitohy 	maple_enable_periodic(sc->sc_parent, sc->sc_unit, MAPLE_FN_MOUSE, 1);
184cb6453dbStsutsui 	return 0;
185b4255677Sthorpej }
186b4255677Sthorpej 
18783c0ebaeStsutsui static void
mms_disable(void * v)188b4255677Sthorpej mms_disable(void *v)
189b4255677Sthorpej {
1906e91aedcSitohy 	struct mms_softc *sc = v;
191b4255677Sthorpej 
1926e91aedcSitohy 	maple_enable_periodic(sc->sc_parent, sc->sc_unit, MAPLE_FN_MOUSE, 0);
193b4255677Sthorpej }
194b4255677Sthorpej 
19583c0ebaeStsutsui static int
mms_ioctl(void * v,u_long cmd,void * data,int flag,struct lwp * l)19653524e44Schristos mms_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
197b4255677Sthorpej {
198b4255677Sthorpej 
199b4255677Sthorpej 	switch (cmd) {
200b4255677Sthorpej 	case WSMOUSEIO_GTYPE:
2016e91aedcSitohy 		*(u_int *) data = WSMOUSE_TYPE_MAPLE;
202b4255677Sthorpej 		break;
203b4255677Sthorpej 
204b4255677Sthorpej 	case WSMOUSEIO_SRES:
205b4255677Sthorpej 		/* XXX */
206cb6453dbStsutsui 		return EOPNOTSUPP;
207b4255677Sthorpej 
208b4255677Sthorpej 	default:
209cb6453dbStsutsui 		return EPASSTHROUGH;
210b4255677Sthorpej 	}
211b4255677Sthorpej 
212cb6453dbStsutsui 	return 0;
213b4255677Sthorpej }
214b4255677Sthorpej 
21583c0ebaeStsutsui static void
mms_intr(void * arg,struct maple_response * response,int size,int flags)216154b121fSitohy mms_intr(void *arg, struct maple_response *response, int size, int flags)
217b4255677Sthorpej {
218b4255677Sthorpej 	struct mms_softc *sc = arg;
219154b121fSitohy 	struct mms_condition *data = (void *) response->data;
220b4255677Sthorpej 	int dx = 0, dy = 0, dz = 0, buttons = 0;
221b4255677Sthorpej 	uint32_t buttonchg;
222b4255677Sthorpej 
223154b121fSitohy 	if ((flags & MAPLE_FLAG_PERIODIC) == 0 ||
224154b121fSitohy 	    size < sizeof(*data))
225b4255677Sthorpej 		return;
226b4255677Sthorpej 
227b4255677Sthorpej 	data->buttons &= MMS_BUTTON_MASK;
228b4255677Sthorpej 	buttonchg = sc->sc_oldbuttons ^ data->buttons;
229b4255677Sthorpej 	sc->sc_oldbuttons = data->buttons;
230b4255677Sthorpej 
231b4255677Sthorpej 	dx = (data->axis1 & MMS_MOVEMENT_MAX) - MMS_MOVEMENT_BASE;
232b4255677Sthorpej 	dy = (data->axis2 & MMS_MOVEMENT_MAX) - MMS_MOVEMENT_BASE;
233b4255677Sthorpej 	dz = (data->axis3 & MMS_MOVEMENT_MAX) - MMS_MOVEMENT_BASE;
234b4255677Sthorpej 
235b4255677Sthorpej 	if (dx || dy || dz || buttonchg) {
236b4255677Sthorpej 		if ((data->buttons & MMS_BUTTON_A) == 0)
237b4255677Sthorpej 			buttons |= 0x01;
238b4255677Sthorpej 		if ((data->buttons & MMS_BUTTON_C) == 0)
239b4255677Sthorpej 			buttons |= 0x02;
240b4255677Sthorpej 		if ((data->buttons & MMS_BUTTON_B) == 0)
241b4255677Sthorpej 			buttons |= 0x04;
242b4255677Sthorpej 		if ((data->buttons & MMS_BUTTON_START) == 0)
243b4255677Sthorpej 			buttons |= 0x08;
244b4255677Sthorpej 
24557c0199dSplunky 		wsmouse_input(sc->sc_wsmousedev,
24657c0199dSplunky 				buttons,
24757c0199dSplunky 				dx, -dy, dz, 0,
24857c0199dSplunky 				WSMOUSE_INPUT_DELTA);
249b4255677Sthorpej 	}
250b4255677Sthorpej }
251