1 /* $NetBSD: mkbd.c,v 1.9 2001/07/22 15:46:42 wiz 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 194 case WSKBDIO_GTYPE: 195 *(int *)data = WSKBD_TYPE_USB; /* XXX */ 196 return 0; 197 case WSKBDIO_SETLEDS: 198 return 0; 199 case WSKBDIO_GETLEDS: 200 *(int *)data = 0; 201 return 0; 202 case WSKBDIO_BELL: 203 case WSKBDIO_COMPLEXBELL: 204 return 0; 205 } 206 207 return -1; 208 } 209 210 211 int 212 mkbd_cnattach() 213 { 214 215 wskbd_cnattach(&mkbd_consops, NULL, &mkbd_keymapdata); 216 mkbd_console_initted = 1; 217 218 return 0; 219 } 220 221 static int polledkey; 222 extern int maple_polling; 223 224 #define SHIFT_KEYCODE_BASE 0xe0 225 #define UP_KEYCODE_FLAG 0x1000 226 227 #define KEY_UP(n) \ 228 if (maple_polling) \ 229 polledkey = (n)|UP_KEYCODE_FLAG; \ 230 else \ 231 wskbd_input(sc->sc_wskbddev, WSCONS_EVENT_KEY_UP, (n)) 232 233 #define KEY_DOWN(n) \ 234 if (maple_polling) \ 235 polledkey = (n); \ 236 else \ 237 wskbd_input(sc->sc_wskbddev, WSCONS_EVENT_KEY_DOWN, (n)) 238 239 #define SHIFT_UP(n) KEY_UP((n)|SHIFT_KEYCODE_BASE) 240 #define SHIFT_DOWN(n) KEY_DOWN((n)|SHIFT_KEYCODE_BASE) 241 242 static void 243 mkbd_intr(sc, kbddata, sz) 244 struct mkbd_softc *sc; 245 struct mkbd_condition *kbddata; 246 int sz; 247 { 248 249 if (sz >= sizeof(struct mkbd_condition)) { 250 int i, j, v; 251 252 v = sc->sc_condition.shift & ~kbddata->shift; 253 if (v) 254 for (i=0; i<8; i++) 255 if (v & (1<<i)) 256 SHIFT_UP(i); 257 258 v = kbddata->shift & ~sc->sc_condition.shift; 259 if (v) 260 for (i=0; i<8; i++) 261 if (v & (1<<i)) 262 SHIFT_DOWN(i); 263 264 for (i=0, j=0; i<6; i++) 265 if (sc->sc_condition.key[i] < 4) 266 break; 267 else if(sc->sc_condition.key[i] == kbddata->key[j]) 268 j++; 269 else 270 KEY_UP(sc->sc_condition.key[i]); 271 272 for (; j<6; j++) 273 if (kbddata->key[j] < 4) 274 break; 275 else 276 KEY_DOWN(kbddata->key[j]); 277 278 memcpy(&sc->sc_condition, kbddata, sizeof(struct mkbd_condition)); 279 } 280 } 281 282 void 283 mkbd_cngetc(v, type, data) 284 void *v; 285 u_int *type; 286 int *data; 287 { 288 int key; 289 290 polledkey = -1; 291 maple_polling = 1; 292 while (polledkey == -1) 293 if (mkbd_console_softc != NULL || 294 mkbd_console_softc->sc_parent != NULL) { 295 int t; 296 for(t=0; t<1000000; t++); 297 maple_run_polling(mkbd_console_softc->sc_parent); 298 } 299 maple_polling = 0; 300 key = polledkey; 301 302 *data = key & ~UP_KEYCODE_FLAG; 303 *type = (key & UP_KEYCODE_FLAG)? 304 WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN; 305 } 306 307 void 308 mkbd_cnpollc(v, on) 309 void *v; 310 int on; 311 { 312 } 313