1 /* $NetBSD: mkbd.c,v 1.26 2008/10/19 14:57:22 marcus Exp $ */
4 * Copyright (c) 2001 Marcus Comstedt
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Marcus Comstedt.
18 * 4. Neither the name of The NetBSD Foundation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: mkbd.c,v 1.26 2008/10/19 14:57:22 marcus Exp $");
38 #include <sys/param.h>
39 #include <sys/device.h>
40 #include <sys/fcntl.h>
42 #include <sys/select.h>
44 #include <sys/signalvar.h>
45 #include <sys/systm.h>
49 #include <dev/wscons/wsconsio.h>
50 #include <dev/wscons/wskbdvar.h>
51 #include <dev/wscons/wsksymdef.h>
52 #include <dev/wscons/wsksymvar.h>
54 #include <machine/cpu.h>
55 #include <machine/bus.h>
57 #include <dreamcast/dev/maple/maple.h>
58 #include <dreamcast/dev/maple/mapleconf.h>
59 #include <dreamcast/dev/maple/mkbdvar.h>
60 #include <dreamcast/dev/maple/mkbdmap.h>
63 * Function declarations.
65 static int mkbdmatch(struct device
*, struct cfdata
*, void *);
66 static void mkbdattach(struct device
*, struct device
*, void *);
67 static int mkbddetach(struct device
*, int);
69 int mkbd_enable(void *, int);
70 void mkbd_set_leds(void *, int);
71 int mkbd_ioctl(void *, u_long
, void *, int, struct lwp
*);
73 struct wskbd_accessops mkbd_accessops
= {
79 static void mkbd_intr(void *, struct maple_response
*, int, int);
81 void mkbd_cngetc(void *, u_int
*, int *);
82 void mkbd_cnpollc(void *, int);
83 int mkbd_cnattach(void);
85 struct wskbd_consops mkbd_consops
= {
90 struct wskbd_mapdata mkbd_keymapdata
= {
95 static struct mkbd_softc
*mkbd_console_softc
;
97 static int mkbd_is_console
;
98 static int mkbd_console_initted
;
100 CFATTACH_DECL(mkbd
, sizeof(struct mkbd_softc
),
101 mkbdmatch
, mkbdattach
, mkbddetach
, NULL
);
104 mkbdmatch(struct device
*parent
, struct cfdata
*cf
, void *aux
)
106 struct maple_attach_args
*ma
= aux
;
108 return ma
->ma_function
== MAPLE_FN_KEYBOARD
? MAPLE_MATCH_FUNC
: 0;
112 mkbdattach(struct device
*parent
, struct device
*self
, void *aux
)
114 struct mkbd_softc
*sc
= (struct mkbd_softc
*) self
;
115 struct maple_attach_args
*ma
= aux
;
117 struct wskbddev_attach_args a
;
121 sc
->sc_parent
= parent
;
122 sc
->sc_unit
= ma
->ma_unit
;
124 kbdtype
= maple_get_function_data(ma
->ma_devinfo
,
125 MAPLE_FN_KEYBOARD
) >> 24;
128 printf(": Japanese keyboard");
129 mkbd_keymapdata
.layout
= KB_JP
;
132 printf(": US keyboard");
133 mkbd_keymapdata
.layout
= KB_US
;
136 printf(": European keyboard");
137 mkbd_keymapdata
.layout
= KB_UK
;
140 printf(": Unknown keyboard %d", kbdtype
);
144 /* allow user to override the default keymap */
145 mkbd_keymapdata
.layout
= MKBD_LAYOUT
;
147 #ifdef MKBD_SWAPCTRLCAPS
148 /* allow user to specify swapctrlcaps with the default keymap */
149 mkbd_keymapdata
.layout
|= KB_SWAPCTRLCAPS
;
153 if ((a
.console
= mkbd_is_console
) != 0) {
155 if (!mkbd_console_initted
)
156 wskbd_cnattach(&mkbd_consops
, NULL
, &mkbd_keymapdata
);
157 mkbd_console_softc
= sc
;
159 a
.keymap
= &mkbd_keymapdata
;
160 a
.accessops
= &mkbd_accessops
;
162 sc
->sc_wskbddev
= config_found(self
, &a
, wskbddevprint
);
165 maple_set_callback(parent
, sc
->sc_unit
, MAPLE_FN_KEYBOARD
,
167 maple_enable_periodic(parent
, sc
->sc_unit
, MAPLE_FN_KEYBOARD
, 1);
171 mkbddetach(struct device
*self
, int flags
)
173 struct mkbd_softc
*sc
= (struct mkbd_softc
*) self
;
176 if (sc
== mkbd_console_softc
) {
178 * Hack to allow another Maple keyboard to be new console.
179 * XXX Should some other type device can be console.
181 printf("%s: was console keyboard\n", sc
->sc_dev
.dv_xname
);
183 mkbd_console_softc
= NULL
;
184 mkbd_console_initted
= 0;
188 rv
= config_detach(sc
->sc_wskbddev
, flags
);
194 mkbd_enable(void *v
, int on
)
201 mkbd_set_leds(void *v
, int on
)
206 mkbd_ioctl(void *v
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
211 *(int *) data
= WSKBD_TYPE_MAPLE
;
213 case WSKBDIO_SETLEDS
:
215 case WSKBDIO_GETLEDS
:
219 case WSKBDIO_COMPLEXBELL
:
230 wskbd_cnattach(&mkbd_consops
, NULL
, &mkbd_keymapdata
);
231 mkbd_console_initted
= 1;
237 static int polledkey
;
238 extern int maple_polling
;
240 #define SHIFT_KEYCODE_BASE 0xe0
241 #define UP_KEYCODE_FLAG 0x1000
243 #define KEY_UP(n) do { \
245 polledkey = (n)|UP_KEYCODE_FLAG; \
247 wskbd_input(sc->sc_wskbddev, WSCONS_EVENT_KEY_UP, (n)); \
248 } while (/*CONSTCOND*/0)
250 #define KEY_DOWN(n) do { \
254 wskbd_input(sc->sc_wskbddev, WSCONS_EVENT_KEY_DOWN, (n)); \
255 } while (/*CONSTCOND*/0)
257 #define SHIFT_UP(n) KEY_UP((n) | SHIFT_KEYCODE_BASE)
258 #define SHIFT_DOWN(n) KEY_DOWN((n) | SHIFT_KEYCODE_BASE)
261 mkbd_intr(void *arg
, struct maple_response
*response
, int sz
, int flags
)
263 struct mkbd_softc
*sc
= arg
;
264 struct mkbd_condition
*kbddata
= (void *) response
->data
;
266 if ((flags
& MAPLE_FLAG_PERIODIC
) &&
267 sz
>= sizeof(struct mkbd_condition
)) {
270 v
= sc
->sc_condition
.shift
& ~kbddata
->shift
;
272 for (i
= 0; i
< 8; i
++)
276 v
= kbddata
->shift
& ~sc
->sc_condition
.shift
;
278 for (i
= 0; i
< 8; i
++)
282 for (i
= 0, j
= 0; i
< 6; i
++)
283 if (sc
->sc_condition
.key
[i
] < 4)
285 else if (sc
->sc_condition
.key
[i
] == kbddata
->key
[j
])
288 KEY_UP(sc
->sc_condition
.key
[i
]);
291 if (kbddata
->key
[j
] < 4)
294 KEY_DOWN(kbddata
->key
[j
]);
296 memcpy(&sc
->sc_condition
, kbddata
,
297 sizeof(struct mkbd_condition
));
302 mkbd_cngetc(void *v
, u_int
*type
, int *data
)
308 while (polledkey
== -1) {
309 if (mkbd_console_softc
!= NULL
&&
310 mkbd_console_softc
->sc_parent
!= NULL
) {
312 maple_run_polling(mkbd_console_softc
->sc_parent
);
318 *data
= key
& ~UP_KEYCODE_FLAG
;
319 *type
= (key
& UP_KEYCODE_FLAG
) ?
320 WSCONS_EVENT_KEY_UP
: WSCONS_EVENT_KEY_DOWN
;
324 mkbd_cnpollc(void *v
, int on
)