1 /* $NetBSD: mkbd.c,v 1.11 2001/12/04 15:27:36 atatat Exp $ */ 2 3 /*- 4 * Copyright (c) 2001 Marcus Comstedt 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 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. 21 * 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. 33 */ 34 35 #include <sys/param.h> 36 #include <sys/device.h> 37 #include <sys/fcntl.h> 38 #include <sys/poll.h> 39 #include <sys/select.h> 40 #include <sys/proc.h> 41 #include <sys/signalvar.h> 42 #include <sys/systm.h> 43 44 #include "wskbd.h" 45 46 #include <dev/wscons/wsconsio.h> 47 #include <dev/wscons/wskbdvar.h> 48 #include <dev/wscons/wsksymdef.h> 49 #include <dev/wscons/wsksymvar.h> 50 51 #include <machine/cpu.h> 52 #include <machine/bus.h> 53 54 #include <dreamcast/dev/maple/maple.h> 55 #include <dreamcast/dev/maple/mapleconf.h> 56 #include <dreamcast/dev/maple/mkbdvar.h> 57 #include <dreamcast/dev/maple/mkbdmap.h> 58 59 60 /* 61 * Function declarations. 62 */ 63 static int mkbdmatch __P((struct device *, struct cfdata *, void *)); 64 static void mkbdattach __P((struct device *, struct device *, void *)); 65 66 int mkbd_enable __P((void *, int)); 67 void mkbd_set_leds __P((void *, int)); 68 int mkbd_ioctl __P((void *, u_long, caddr_t, int, struct proc *)); 69 70 struct wskbd_accessops mkbd_accessops = { 71 mkbd_enable, 72 mkbd_set_leds, 73 mkbd_ioctl, 74 }; 75 76 static void mkbd_intr __P((struct mkbd_softc *, struct mkbd_condition *, int)); 77 78 void mkbd_cngetc __P((void *, u_int *, int *)); 79 void mkbd_cnpollc __P((void *, int)); 80 int mkbd_cnattach __P((void)); 81 82 struct wskbd_consops mkbd_consops = { 83 mkbd_cngetc, 84 mkbd_cnpollc, 85 }; 86 87 struct wskbd_mapdata mkbd_keymapdata = { 88 mkbd_keydesctab, 89 KB_JP, 90 }; 91 92 static struct mkbd_softc *mkbd_console_softc = NULL; 93 94 static int mkbd_console_initted = 0; 95 96 /* Driver definition. */ 97 struct cfattach mkbd_ca = { 98 sizeof(struct mkbd_softc), mkbdmatch, mkbdattach 99 }; 100 101 static int 102 mkbdmatch(parent, cf, aux) 103 struct device *parent; 104 struct cfdata *cf; 105 void *aux; 106 { 107 struct maple_attach_args *ma = aux; 108 109 return (ma->ma_function & MAPLE_FUNC_KEYBOARD) != 0; 110 } 111 112 static void 113 mkbdattach(parent, self, aux) 114 struct device *parent, *self; 115 void *aux; 116 { 117 struct mkbd_softc *sc = (struct mkbd_softc *) self; 118 struct maple_attach_args *ma = aux; 119 #if NWSKBD > 0 120 struct wskbddev_attach_args a; 121 #endif 122 u_int32_t kbdtype; 123 124 sc->sc_parent = parent; 125 sc->sc_port = ma->ma_port; 126 sc->sc_subunit = ma->ma_subunit; 127 128 kbdtype = maple_get_function_data(ma->ma_devinfo, 129 MAPLE_FUNC_KEYBOARD) >> 24; 130 switch (kbdtype) { 131 case 1: 132 printf(": Japanese keyboard"); 133 mkbd_keymapdata.layout = KB_JP; 134 break; 135 case 2: 136 printf(": US keyboard"); 137 mkbd_keymapdata.layout = KB_US; 138 break; 139 case 3: 140 printf(": European keyboard"); 141 mkbd_keymapdata.layout = KB_UK; 142 break; 143 default: 144 printf(": Unknown keyboard %d", kbdtype); 145 } 146 printf("\n"); 147 148 #if NWSKBD > 0 149 a.console = ((sc->sc_dev.dv_unit == 0) && (mkbd_console_initted == 1)) 150 ? 1 : 0; 151 a.keymap = &mkbd_keymapdata; 152 a.accessops = &mkbd_accessops; 153 a.accesscookie = sc; 154 if (a.console) 155 mkbd_console_softc = sc; 156 sc->sc_wskbddev = config_found(self, &a, wskbddevprint); 157 #endif 158 159 maple_set_condition_callback(parent, sc->sc_port, sc->sc_subunit, 160 MAPLE_FUNC_KEYBOARD, 161 (void (*) (void *, void *, int)) mkbd_intr, 162 sc); 163 } 164 165 166 167 int 168 mkbd_enable(v, on) 169 void *v; 170 int on; 171 { 172 173 return 0; 174 } 175 176 void 177 mkbd_set_leds(v, on) 178 void *v; 179 int on; 180 { 181 } 182 183 int 184 mkbd_ioctl(v, cmd, data, flag, p) 185 void *v; 186 u_long cmd; 187 caddr_t data; 188 int flag; 189 struct proc *p; 190 { 191 192 switch (cmd) { 193 case WSKBDIO_GTYPE: 194 *(int *) data = WSKBD_TYPE_USB; /* XXX */ 195 return 0; 196 case WSKBDIO_SETLEDS: 197 return 0; 198 case WSKBDIO_GETLEDS: 199 *(int *) data = 0; 200 return 0; 201 case WSKBDIO_BELL: 202 case WSKBDIO_COMPLEXBELL: 203 return 0; 204 } 205 206 return -1; 207 } 208 209 210 int 211 mkbd_cnattach() 212 { 213 214 wskbd_cnattach(&mkbd_consops, NULL, &mkbd_keymapdata); 215 mkbd_console_initted = 1; 216 217 return 0; 218 } 219 220 static int polledkey; 221 extern int maple_polling; 222 223 #define SHIFT_KEYCODE_BASE 0xe0 224 #define UP_KEYCODE_FLAG 0x1000 225 226 #define KEY_UP(n) do { \ 227 if (maple_polling) \ 228 polledkey = (n)|UP_KEYCODE_FLAG; \ 229 else \ 230 wskbd_input(sc->sc_wskbddev, WSCONS_EVENT_KEY_UP, (n)); \ 231 } while (0) 232 233 #define KEY_DOWN(n) do { \ 234 if (maple_polling) \ 235 polledkey = (n); \ 236 else \ 237 wskbd_input(sc->sc_wskbddev, WSCONS_EVENT_KEY_DOWN, (n)); \ 238 } while (0) 239 240 #define SHIFT_UP(n) KEY_UP((n)|SHIFT_KEYCODE_BASE) 241 #define SHIFT_DOWN(n) KEY_DOWN((n)|SHIFT_KEYCODE_BASE) 242 243 static void 244 mkbd_intr(sc, kbddata, sz) 245 struct mkbd_softc *sc; 246 struct mkbd_condition *kbddata; 247 int sz; 248 { 249 250 if (sz >= sizeof(struct mkbd_condition)) { 251 int i, j, v; 252 253 v = sc->sc_condition.shift & ~kbddata->shift; 254 if (v) 255 for (i = 0; i < 8; i++) 256 if (v & (1 << i)) 257 SHIFT_UP(i); 258 259 v = kbddata->shift & ~sc->sc_condition.shift; 260 if (v) 261 for (i = 0; i < 8; i++) 262 if (v & (1 << i)) 263 SHIFT_DOWN(i); 264 265 for (i = 0, j = 0; i < 6; i++) 266 if (sc->sc_condition.key[i] < 4) 267 break; 268 else if (sc->sc_condition.key[i] == kbddata->key[j]) 269 j++; 270 else 271 KEY_UP(sc->sc_condition.key[i]); 272 273 for (; j < 6; j++) 274 if (kbddata->key[j] < 4) 275 break; 276 else 277 KEY_DOWN(kbddata->key[j]); 278 279 memcpy(&sc->sc_condition, kbddata, 280 sizeof(struct mkbd_condition)); 281 } 282 } 283 284 void 285 mkbd_cngetc(v, type, data) 286 void *v; 287 u_int *type; 288 int *data; 289 { 290 int key; 291 292 polledkey = -1; 293 maple_polling = 1; 294 while (polledkey == -1) { 295 if (mkbd_console_softc != NULL || 296 mkbd_console_softc->sc_parent != NULL) { 297 int t; 298 for (t = 0; t < 1000000; t++); 299 maple_run_polling(mkbd_console_softc->sc_parent); 300 } 301 } 302 maple_polling = 0; 303 key = polledkey; 304 305 *data = key & ~UP_KEYCODE_FLAG; 306 *type = (key & UP_KEYCODE_FLAG) ? 307 WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN; 308 } 309 310 void 311 mkbd_cnpollc(v, on) 312 void *v; 313 int on; 314 { 315 } 316