1 1.49 riastrad /* $NetBSD: akbd.c,v 1.49 2025/01/13 16:17:36 riastradh Exp $ */ 2 1.1 tsubai 3 1.1 tsubai /* 4 1.1 tsubai * Copyright (C) 1998 Colin Wood 5 1.1 tsubai * All rights reserved. 6 1.1 tsubai * 7 1.1 tsubai * Redistribution and use in source and binary forms, with or without 8 1.1 tsubai * modification, are permitted provided that the following conditions 9 1.1 tsubai * are met: 10 1.1 tsubai * 1. Redistributions of source code must retain the above copyright 11 1.1 tsubai * notice, this list of conditions and the following disclaimer. 12 1.1 tsubai * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 tsubai * notice, this list of conditions and the following disclaimer in the 14 1.1 tsubai * documentation and/or other materials provided with the distribution. 15 1.1 tsubai * 3. All advertising materials mentioning features or use of this software 16 1.1 tsubai * must display the following acknowledgement: 17 1.1 tsubai * This product includes software developed by Colin Wood. 18 1.1 tsubai * 4. The name of the author may not be used to endorse or promote products 19 1.1 tsubai * derived from this software without specific prior written permission. 20 1.1 tsubai * 21 1.1 tsubai * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 1.1 tsubai * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 1.1 tsubai * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 1.1 tsubai * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 1.1 tsubai * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 1.1 tsubai * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 1.1 tsubai * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 1.1 tsubai * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 1.1 tsubai * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 1.1 tsubai * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 1.1 tsubai */ 32 1.30 lukem 33 1.30 lukem #include <sys/cdefs.h> 34 1.49 riastrad __KERNEL_RCSID(0, "$NetBSD: akbd.c,v 1.49 2025/01/13 16:17:36 riastradh Exp $"); 35 1.1 tsubai 36 1.1 tsubai #include <sys/param.h> 37 1.1 tsubai #include <sys/device.h> 38 1.1 tsubai #include <sys/fcntl.h> 39 1.1 tsubai #include <sys/poll.h> 40 1.1 tsubai #include <sys/select.h> 41 1.1 tsubai #include <sys/proc.h> 42 1.1 tsubai #include <sys/signalvar.h> 43 1.1 tsubai #include <sys/systm.h> 44 1.1 tsubai 45 1.2 tsubai #include <dev/wscons/wsconsio.h> 46 1.2 tsubai #include <dev/wscons/wskbdvar.h> 47 1.2 tsubai #include <dev/wscons/wsksymdef.h> 48 1.2 tsubai #include <dev/wscons/wsksymvar.h> 49 1.16 tsubai #include <dev/ofw/openfirm.h> 50 1.2 tsubai 51 1.37 macallan #include <dev/adb/adb_keymap.h> 52 1.37 macallan 53 1.1 tsubai #include <machine/autoconf.h> 54 1.2 tsubai #define KEYBOARD_ARRAY 55 1.2 tsubai #include <machine/keyboard.h> 56 1.1 tsubai 57 1.1 tsubai #include <macppc/dev/adbvar.h> 58 1.1 tsubai #include <macppc/dev/aedvar.h> 59 1.1 tsubai #include <macppc/dev/akbdvar.h> 60 1.16 tsubai #include <macppc/dev/pm_direct.h> 61 1.1 tsubai 62 1.3 tsubai #include "aed.h" 63 1.3 tsubai 64 1.1 tsubai /* 65 1.1 tsubai * Function declarations. 66 1.1 tsubai */ 67 1.44 matt static int akbdmatch(device_t, cfdata_t, void *); 68 1.44 matt static void akbdattach(device_t, device_t, void *); 69 1.40 dsl static void kbd_processevent(adb_event_t *event, struct akbd_softc *); 70 1.1 tsubai #ifdef notyet 71 1.40 dsl static u_char getleds(int); 72 1.40 dsl static int setleds(struct akbd_softc *, u_char); 73 1.40 dsl static void blinkleds(struct akbd_softc *); 74 1.1 tsubai #endif 75 1.1 tsubai 76 1.1 tsubai /* Driver definition. */ 77 1.45 chs CFATTACH_DECL_NEW(akbd, sizeof(struct akbd_softc), 78 1.29 thorpej akbdmatch, akbdattach, NULL, NULL); 79 1.2 tsubai 80 1.2 tsubai extern struct cfdriver akbd_cd; 81 1.2 tsubai 82 1.40 dsl int akbd_enable(void *, int); 83 1.40 dsl void akbd_set_leds(void *, int); 84 1.40 dsl int akbd_ioctl(void *, u_long, void *, int, struct lwp *); 85 1.2 tsubai 86 1.2 tsubai struct wskbd_accessops akbd_accessops = { 87 1.2 tsubai akbd_enable, 88 1.2 tsubai akbd_set_leds, 89 1.2 tsubai akbd_ioctl, 90 1.2 tsubai }; 91 1.2 tsubai 92 1.40 dsl void akbd_cngetc(void *, u_int *, int *); 93 1.40 dsl void akbd_cnpollc(void *, int); 94 1.2 tsubai 95 1.2 tsubai struct wskbd_consops akbd_consops = { 96 1.2 tsubai akbd_cngetc, 97 1.2 tsubai akbd_cnpollc, 98 1.2 tsubai }; 99 1.2 tsubai 100 1.2 tsubai struct wskbd_mapdata akbd_keymapdata = { 101 1.2 tsubai akbd_keydesctab, 102 1.10 tsubai #ifdef AKBD_LAYOUT 103 1.10 tsubai AKBD_LAYOUT, 104 1.10 tsubai #else 105 1.2 tsubai KB_US, 106 1.10 tsubai #endif 107 1.1 tsubai }; 108 1.1 tsubai 109 1.7 thorpej static int akbd_is_console; 110 1.22 wrstuden static int akbd_console_attached; 111 1.16 tsubai static int pcmcia_soft_eject; 112 1.1 tsubai 113 1.1 tsubai static int 114 1.44 matt akbdmatch(device_t parent, cfdata_t cf, void *aux) 115 1.1 tsubai { 116 1.12 tsubai struct adb_attach_args *aa_args = aux; 117 1.1 tsubai 118 1.1 tsubai if (aa_args->origaddr == ADBADDR_KBD) 119 1.1 tsubai return 1; 120 1.1 tsubai else 121 1.1 tsubai return 0; 122 1.1 tsubai } 123 1.1 tsubai 124 1.1 tsubai static void 125 1.44 matt akbdattach(device_t parent, device_t self, void *aux) 126 1.1 tsubai { 127 1.1 tsubai ADBSetInfoBlock adbinfo; 128 1.44 matt struct akbd_softc *sc = device_private(self); 129 1.12 tsubai struct adb_attach_args *aa_args = aux; 130 1.11 tsubai int error, kbd_done; 131 1.1 tsubai short cmd; 132 1.1 tsubai u_char buffer[9]; 133 1.2 tsubai struct wskbddev_attach_args a; 134 1.1 tsubai 135 1.16 tsubai /* ohare based models have soft ejectable card slot. */ 136 1.16 tsubai if (OF_finddevice("/bandit/ohare") != -1) 137 1.16 tsubai pcmcia_soft_eject = 1; 138 1.16 tsubai 139 1.1 tsubai sc->origaddr = aa_args->origaddr; 140 1.1 tsubai sc->adbaddr = aa_args->adbaddr; 141 1.1 tsubai sc->handler_id = aa_args->handler_id; 142 1.1 tsubai 143 1.1 tsubai sc->sc_leds = (u_int8_t)0x00; /* initially off */ 144 1.1 tsubai 145 1.1 tsubai adbinfo.siServiceRtPtr = (Ptr)kbd_adbcomplete; 146 1.35 christos adbinfo.siDataAreaAddr = (void *)sc; 147 1.1 tsubai 148 1.1 tsubai switch (sc->handler_id) { 149 1.1 tsubai case ADB_STDKBD: 150 1.1 tsubai printf("standard keyboard\n"); 151 1.1 tsubai break; 152 1.1 tsubai case ADB_ISOKBD: 153 1.1 tsubai printf("standard keyboard (ISO layout)\n"); 154 1.1 tsubai break; 155 1.1 tsubai case ADB_EXTKBD: 156 1.11 tsubai cmd = ADBTALK(sc->adbaddr, 1); 157 1.11 tsubai kbd_done = 158 1.33 nathanw (adb_op_sync((Ptr)buffer, NULL, (Ptr)0, cmd) == 0); 159 1.1 tsubai 160 1.1 tsubai /* Ignore Logitech MouseMan/Trackman pseudo keyboard */ 161 1.1 tsubai if (kbd_done && buffer[1] == 0x9a && buffer[2] == 0x20) { 162 1.1 tsubai printf("Mouseman (non-EMP) pseudo keyboard\n"); 163 1.1 tsubai adbinfo.siServiceRtPtr = (Ptr)0; 164 1.1 tsubai adbinfo.siDataAreaAddr = (Ptr)0; 165 1.1 tsubai } else if (kbd_done && buffer[1] == 0x9a && buffer[2] == 0x21) { 166 1.1 tsubai printf("Trackman (non-EMP) pseudo keyboard\n"); 167 1.1 tsubai adbinfo.siServiceRtPtr = (Ptr)0; 168 1.1 tsubai adbinfo.siDataAreaAddr = (Ptr)0; 169 1.1 tsubai } else { 170 1.1 tsubai printf("extended keyboard\n"); 171 1.8 tsubai #ifdef notyet 172 1.1 tsubai blinkleds(sc); 173 1.1 tsubai #endif 174 1.1 tsubai } 175 1.1 tsubai break; 176 1.1 tsubai case ADB_EXTISOKBD: 177 1.1 tsubai printf("extended keyboard (ISO layout)\n"); 178 1.1 tsubai #ifdef notyet 179 1.1 tsubai blinkleds(sc); 180 1.1 tsubai #endif 181 1.1 tsubai break; 182 1.1 tsubai case ADB_KBDII: 183 1.1 tsubai printf("keyboard II\n"); 184 1.1 tsubai break; 185 1.1 tsubai case ADB_ISOKBDII: 186 1.1 tsubai printf("keyboard II (ISO layout)\n"); 187 1.1 tsubai break; 188 1.1 tsubai case ADB_PBKBD: 189 1.1 tsubai printf("PowerBook keyboard\n"); 190 1.1 tsubai break; 191 1.1 tsubai case ADB_PBISOKBD: 192 1.1 tsubai printf("PowerBook keyboard (ISO layout)\n"); 193 1.1 tsubai break; 194 1.1 tsubai case ADB_ADJKPD: 195 1.1 tsubai printf("adjustable keypad\n"); 196 1.1 tsubai break; 197 1.1 tsubai case ADB_ADJKBD: 198 1.1 tsubai printf("adjustable keyboard\n"); 199 1.1 tsubai break; 200 1.1 tsubai case ADB_ADJISOKBD: 201 1.1 tsubai printf("adjustable keyboard (ISO layout)\n"); 202 1.1 tsubai break; 203 1.1 tsubai case ADB_ADJJAPKBD: 204 1.1 tsubai printf("adjustable keyboard (Japanese layout)\n"); 205 1.1 tsubai break; 206 1.1 tsubai case ADB_PBEXTISOKBD: 207 1.1 tsubai printf("PowerBook extended keyboard (ISO layout)\n"); 208 1.1 tsubai break; 209 1.1 tsubai case ADB_PBEXTJAPKBD: 210 1.1 tsubai printf("PowerBook extended keyboard (Japanese layout)\n"); 211 1.1 tsubai break; 212 1.4 tsubai case ADB_JPKBDII: 213 1.1 tsubai printf("keyboard II (Japanese layout)\n"); 214 1.1 tsubai break; 215 1.1 tsubai case ADB_PBEXTKBD: 216 1.1 tsubai printf("PowerBook extended keyboard\n"); 217 1.1 tsubai break; 218 1.1 tsubai case ADB_DESIGNKBD: 219 1.1 tsubai printf("extended keyboard\n"); 220 1.1 tsubai #ifdef notyet 221 1.1 tsubai blinkleds(sc); 222 1.1 tsubai #endif 223 1.1 tsubai break; 224 1.4 tsubai case ADB_PBJPKBD: 225 1.4 tsubai printf("PowerBook keyboard (Japanese layout)\n"); 226 1.15 nathanw break; 227 1.17 tsubai case ADB_PBG3KBD: 228 1.17 tsubai printf("PowerBook G3 keyboard\n"); 229 1.8 tsubai break; 230 1.8 tsubai case ADB_PBG3JPKBD: 231 1.8 tsubai printf("PowerBook G3 keyboard (Japanese layout)\n"); 232 1.4 tsubai break; 233 1.1 tsubai default: 234 1.1 tsubai printf("mapped device (%d)\n", sc->handler_id); 235 1.1 tsubai break; 236 1.1 tsubai } 237 1.1 tsubai error = SetADBInfo(&adbinfo, sc->adbaddr); 238 1.1 tsubai #ifdef ADB_DEBUG 239 1.1 tsubai if (adb_debug) 240 1.11 tsubai printf("akbd: returned %d from SetADBInfo\n", error); 241 1.1 tsubai #endif 242 1.2 tsubai 243 1.22 wrstuden if (akbd_is_console && !akbd_console_attached) { 244 1.21 dbj wskbd_cnattach(&akbd_consops, sc, &akbd_keymapdata); 245 1.22 wrstuden akbd_console_attached = 1; 246 1.19 dbj } 247 1.19 dbj 248 1.7 thorpej a.console = akbd_is_console; 249 1.2 tsubai a.keymap = &akbd_keymapdata; 250 1.2 tsubai a.accessops = &akbd_accessops; 251 1.2 tsubai a.accesscookie = sc; 252 1.2 tsubai 253 1.47 thorpej sc->sc_wskbddev = config_found(self, &a, wskbddevprint, CFARGS_NONE); 254 1.1 tsubai } 255 1.1 tsubai 256 1.1 tsubai /* 257 1.1 tsubai * Handle putting the keyboard data received from the ADB into 258 1.1 tsubai * an ADB event record. 259 1.1 tsubai */ 260 1.49 riastrad void 261 1.41 dsl kbd_adbcomplete(uint8_t *buffer, uint8_t *data_area, int adb_command) 262 1.1 tsubai { 263 1.1 tsubai adb_event_t event; 264 1.2 tsubai struct akbd_softc *ksc; 265 1.1 tsubai int adbaddr; 266 1.1 tsubai #ifdef ADB_DEBUG 267 1.1 tsubai int i; 268 1.1 tsubai 269 1.1 tsubai if (adb_debug) 270 1.1 tsubai printf("adb: transaction completion\n"); 271 1.1 tsubai #endif 272 1.1 tsubai 273 1.11 tsubai adbaddr = ADB_CMDADDR(adb_command); 274 1.2 tsubai ksc = (struct akbd_softc *)data_area; 275 1.1 tsubai 276 1.1 tsubai event.addr = adbaddr; 277 1.1 tsubai event.hand_id = ksc->handler_id; 278 1.1 tsubai event.def_addr = ksc->origaddr; 279 1.1 tsubai event.byte_count = buffer[0]; 280 1.1 tsubai memcpy(event.bytes, buffer + 1, event.byte_count); 281 1.1 tsubai 282 1.1 tsubai #ifdef ADB_DEBUG 283 1.1 tsubai if (adb_debug) { 284 1.11 tsubai printf("akbd: from %d at %d (org %d) %d:", event.addr, 285 1.1 tsubai event.hand_id, event.def_addr, buffer[0]); 286 1.1 tsubai for (i = 1; i <= buffer[0]; i++) 287 1.1 tsubai printf(" %x", buffer[i]); 288 1.1 tsubai printf("\n"); 289 1.1 tsubai } 290 1.1 tsubai #endif 291 1.1 tsubai 292 1.1 tsubai microtime(&event.timestamp); 293 1.1 tsubai 294 1.1 tsubai kbd_processevent(&event, ksc); 295 1.1 tsubai } 296 1.1 tsubai 297 1.1 tsubai /* 298 1.49 riastrad * Given a keyboard ADB event, record the keycodes and call the key 299 1.1 tsubai * repeat handler, optionally passing the event through the mouse 300 1.1 tsubai * button emulation handler first. 301 1.1 tsubai */ 302 1.1 tsubai static void 303 1.41 dsl kbd_processevent(adb_event_t *event, struct akbd_softc *ksc) 304 1.1 tsubai { 305 1.1 tsubai adb_event_t new_event; 306 1.1 tsubai 307 1.1 tsubai new_event = *event; 308 1.1 tsubai new_event.u.k.key = event->bytes[0]; 309 1.1 tsubai new_event.bytes[1] = 0xff; 310 1.48 nat #if NAED > 0 311 1.48 nat int result; 312 1.48 nat 313 1.48 nat if ((result = aed_input(&new_event)) != 0) 314 1.48 nat return; 315 1.48 nat #endif 316 1.3 tsubai kbd_intr(&new_event); 317 1.3 tsubai #if NAED > 0 318 1.1 tsubai aed_input(&new_event); 319 1.3 tsubai #endif 320 1.1 tsubai if (event->bytes[1] != 0xff) { 321 1.1 tsubai new_event.u.k.key = event->bytes[1]; 322 1.1 tsubai new_event.bytes[0] = event->bytes[1]; 323 1.1 tsubai new_event.bytes[1] = 0xff; 324 1.3 tsubai kbd_intr(&new_event); 325 1.3 tsubai #if NAED > 0 326 1.1 tsubai aed_input(&new_event); 327 1.3 tsubai #endif 328 1.1 tsubai } 329 1.1 tsubai 330 1.1 tsubai } 331 1.1 tsubai 332 1.1 tsubai #ifdef notyet 333 1.1 tsubai /* 334 1.1 tsubai * Get the actual hardware LED state and convert it to softc format. 335 1.1 tsubai */ 336 1.1 tsubai static u_char 337 1.41 dsl getleds(int addr) 338 1.1 tsubai { 339 1.1 tsubai short cmd; 340 1.1 tsubai u_char buffer[9], leds; 341 1.1 tsubai 342 1.1 tsubai leds = 0x00; /* all off */ 343 1.1 tsubai buffer[0] = 0; 344 1.1 tsubai 345 1.1 tsubai /* talk R2 */ 346 1.11 tsubai cmd = ADBTALK(addr, 2); 347 1.11 tsubai if (adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd) == 0 && 348 1.11 tsubai buffer[0] > 0) 349 1.1 tsubai leds = ~(buffer[2]) & 0x07; 350 1.1 tsubai 351 1.1 tsubai return (leds); 352 1.1 tsubai } 353 1.1 tsubai 354 1.1 tsubai /* 355 1.1 tsubai * Set the keyboard LED's. 356 1.49 riastrad * 357 1.1 tsubai * Automatically translates from ioctl/softc format to the 358 1.1 tsubai * actual keyboard register format 359 1.1 tsubai */ 360 1.49 riastrad static int 361 1.41 dsl setleds(struct akbd_softc *ksc, u_char leds) 362 1.1 tsubai { 363 1.1 tsubai int addr; 364 1.1 tsubai short cmd; 365 1.1 tsubai u_char buffer[9]; 366 1.1 tsubai 367 1.1 tsubai if ((leds & 0x07) == (ksc->sc_leds & 0x07)) 368 1.1 tsubai return (0); 369 1.1 tsubai 370 1.6 tsubai addr = ksc->adbaddr; 371 1.1 tsubai buffer[0] = 0; 372 1.1 tsubai 373 1.11 tsubai cmd = ADBTALK(addr, 2); 374 1.11 tsubai if (adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd) || buffer[0] == 0) 375 1.1 tsubai return (EIO); 376 1.1 tsubai 377 1.1 tsubai leds = ~leds & 0x07; 378 1.1 tsubai buffer[2] &= 0xf8; 379 1.1 tsubai buffer[2] |= leds; 380 1.1 tsubai 381 1.11 tsubai cmd = ADBLISTEN(addr, 2); 382 1.11 tsubai adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd); 383 1.1 tsubai 384 1.11 tsubai cmd = ADBTALK(addr, 2); 385 1.11 tsubai if (adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd) || buffer[0] == 0) 386 1.1 tsubai return (EIO); 387 1.1 tsubai 388 1.1 tsubai ksc->sc_leds = ~((u_int8_t)buffer[2]) & 0x07; 389 1.1 tsubai 390 1.1 tsubai if ((buffer[2] & 0xf8) != leds) 391 1.1 tsubai return (EIO); 392 1.1 tsubai else 393 1.49 riastrad return (0); 394 1.1 tsubai } 395 1.1 tsubai 396 1.1 tsubai /* 397 1.1 tsubai * Toggle all of the LED's on and off, just for show. 398 1.1 tsubai */ 399 1.49 riastrad static void 400 1.41 dsl blinkleds(struct akbd_softc *ksc) 401 1.1 tsubai { 402 1.1 tsubai int addr, i; 403 1.1 tsubai u_char blinkleds, origleds; 404 1.1 tsubai 405 1.6 tsubai addr = ksc->adbaddr; 406 1.1 tsubai origleds = getleds(addr); 407 1.1 tsubai blinkleds = LED_NUMLOCK | LED_CAPSLOCK | LED_SCROLL_LOCK; 408 1.1 tsubai 409 1.1 tsubai (void)setleds(ksc, blinkleds); 410 1.1 tsubai 411 1.1 tsubai for (i = 0; i < 10000; i++) 412 1.1 tsubai delay(50); 413 1.1 tsubai 414 1.1 tsubai /* make sure that we restore the LED settings */ 415 1.1 tsubai i = 10; 416 1.1 tsubai do { 417 1.1 tsubai (void)setleds(ksc, (u_char)0x00); 418 1.49 riastrad } while (setleds(ksc, (u_char)0x00) && (i-- > 0)); 419 1.1 tsubai 420 1.1 tsubai return; 421 1.1 tsubai } 422 1.1 tsubai #endif 423 1.1 tsubai 424 1.1 tsubai int 425 1.41 dsl akbd_enable(void *v, int on) 426 1.2 tsubai { 427 1.2 tsubai return 0; 428 1.2 tsubai } 429 1.2 tsubai 430 1.2 tsubai void 431 1.41 dsl akbd_set_leds(void *v, int on) 432 1.2 tsubai { 433 1.2 tsubai } 434 1.2 tsubai 435 1.2 tsubai int 436 1.41 dsl akbd_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l) 437 1.1 tsubai { 438 1.26 aymeric #ifdef WSDISPLAY_COMPAT_RAWKBD 439 1.26 aymeric struct akbd_softc *sc = (struct akbd_softc *) v; 440 1.26 aymeric #endif 441 1.26 aymeric 442 1.2 tsubai switch (cmd) { 443 1.2 tsubai 444 1.2 tsubai case WSKBDIO_GTYPE: 445 1.18 mycroft *(int *)data = WSKBD_TYPE_ADB; 446 1.2 tsubai return 0; 447 1.2 tsubai case WSKBDIO_SETLEDS: 448 1.2 tsubai return 0; 449 1.2 tsubai case WSKBDIO_GETLEDS: 450 1.2 tsubai *(int *)data = 0; 451 1.2 tsubai return 0; 452 1.26 aymeric #ifdef WSDISPLAY_COMPAT_RAWKBD 453 1.26 aymeric case WSKBDIO_SETMODE: 454 1.26 aymeric sc->sc_rawkbd = *(int *)data == WSKBD_RAW; 455 1.26 aymeric return 0; 456 1.26 aymeric #endif 457 1.2 tsubai } 458 1.2 tsubai /* kbdioctl(...); */ 459 1.2 tsubai 460 1.23 atatat return EPASSTHROUGH; 461 1.2 tsubai } 462 1.2 tsubai 463 1.2 tsubai extern int adb_polling; 464 1.2 tsubai 465 1.21 dbj void 466 1.41 dsl kbd_passup(struct akbd_softc *sc,int key) 467 1.21 dbj { 468 1.21 dbj if (sc->sc_polling) { 469 1.21 dbj if (sc->sc_npolledkeys < 470 1.21 dbj (sizeof(sc->sc_polledkeys)/sizeof(unsigned char))) { 471 1.21 dbj sc->sc_polledkeys[sc->sc_npolledkeys++] = key; 472 1.21 dbj } 473 1.21 dbj #ifdef ADB_DEBUG 474 1.21 dbj else { 475 1.21 dbj printf("akbd: dumping polled key 0x%02x\n",key); 476 1.21 dbj } 477 1.26 aymeric #endif 478 1.26 aymeric #ifdef WSDISPLAY_COMPAT_RAWKBD 479 1.26 aymeric } else if (sc->sc_rawkbd) { 480 1.27 aymeric char cbuf[2]; 481 1.26 aymeric int s; 482 1.26 aymeric int j = 0; 483 1.26 aymeric int c = keyboard[ADBK_KEYVAL(key)][3]; 484 1.26 aymeric 485 1.26 aymeric if (c == 0) /* XXX */ 486 1.26 aymeric return; 487 1.26 aymeric 488 1.26 aymeric if (c & 0x80) 489 1.26 aymeric cbuf[j++] = 0xe0; 490 1.26 aymeric 491 1.27 aymeric cbuf[j++] = (c & 0x7f) | (ADBK_PRESS(key)? 0 : 0x80); 492 1.26 aymeric 493 1.26 aymeric s = spltty(); 494 1.26 aymeric wskbd_rawinput(sc->sc_wskbddev, cbuf, j); 495 1.26 aymeric splx(s); 496 1.21 dbj #endif 497 1.21 dbj } else { 498 1.21 dbj int press, val; 499 1.21 dbj int type; 500 1.49 riastrad 501 1.21 dbj press = ADBK_PRESS(key); 502 1.21 dbj val = ADBK_KEYVAL(key); 503 1.49 riastrad 504 1.21 dbj type = press ? WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP; 505 1.21 dbj 506 1.21 dbj wskbd_input(sc->sc_wskbddev, type, val); 507 1.21 dbj } 508 1.21 dbj } 509 1.21 dbj 510 1.2 tsubai int 511 1.39 cegger kbd_intr(void *arg) 512 1.2 tsubai { 513 1.14 matt adb_event_t *event = arg; 514 1.21 dbj int key; 515 1.24 itojun #ifdef CAPS_IS_CONTROL 516 1.24 itojun static int shift; 517 1.24 itojun #endif 518 1.2 tsubai 519 1.39 cegger struct akbd_softc *sc = device_lookup_private(&akbd_cd, 0); 520 1.1 tsubai 521 1.2 tsubai key = event->u.k.key; 522 1.25 itojun 523 1.24 itojun #ifdef CAPS_IS_CONTROL 524 1.24 itojun /* 525 1.24 itojun * Caps lock is weird. The key sequence generated is: 526 1.24 itojun * press: down(57) [57] (LED turns on) 527 1.24 itojun * release: up(127) [255] 528 1.24 itojun * press: up(127) [255] 529 1.24 itojun * release: up(57) [185] (LED turns off) 530 1.24 itojun */ 531 1.24 itojun if ((key == 57) || (key == 185)) 532 1.24 itojun shift = 0; 533 1.49 riastrad 534 1.24 itojun if (key == 255) { 535 1.24 itojun if (shift == 0) { 536 1.24 itojun key = 185; 537 1.24 itojun shift = 1; 538 1.24 itojun } else { 539 1.24 itojun key = 57; 540 1.24 itojun shift = 0; 541 1.24 itojun } 542 1.24 itojun } 543 1.24 itojun #endif 544 1.2 tsubai 545 1.9 tsubai switch (key) { 546 1.24 itojun #ifndef CAPS_IS_CONTROL 547 1.13 tsubai case 57: /* Caps Lock pressed */ 548 1.9 tsubai case 185: /* Caps Lock released */ 549 1.21 dbj key = ADBK_KEYDOWN(ADBK_KEYVAL(key)); 550 1.21 dbj kbd_passup(sc,key); 551 1.21 dbj key = ADBK_KEYUP(ADBK_KEYVAL(key)); 552 1.9 tsubai break; 553 1.24 itojun #endif 554 1.9 tsubai case 245: 555 1.16 tsubai if (pcmcia_soft_eject) 556 1.16 tsubai pm_eject_pcmcia(0); 557 1.9 tsubai break; 558 1.9 tsubai case 244: 559 1.16 tsubai if (pcmcia_soft_eject) 560 1.16 tsubai pm_eject_pcmcia(1); 561 1.9 tsubai break; 562 1.2 tsubai } 563 1.2 tsubai 564 1.21 dbj kbd_passup(sc,key); 565 1.2 tsubai 566 1.2 tsubai return 0; 567 1.2 tsubai } 568 1.2 tsubai 569 1.2 tsubai int 570 1.43 cegger akbd_cnattach(void) 571 1.2 tsubai { 572 1.5 tsubai 573 1.7 thorpej akbd_is_console = 1; 574 1.2 tsubai return 0; 575 1.2 tsubai } 576 1.2 tsubai 577 1.2 tsubai void 578 1.41 dsl akbd_cngetc(void *v, u_int *type, int *data) 579 1.2 tsubai { 580 1.2 tsubai int key, press, val; 581 1.2 tsubai int s; 582 1.21 dbj struct akbd_softc *sc = v; 583 1.2 tsubai 584 1.2 tsubai s = splhigh(); 585 1.2 tsubai 586 1.21 dbj KASSERT(sc->sc_polling); 587 1.20 dbj KASSERT(adb_polling); 588 1.2 tsubai 589 1.21 dbj while (sc->sc_npolledkeys == 0) { 590 1.32 briggs adb_intr(NULL); 591 1.2 tsubai DELAY(10000); /* XXX */ 592 1.1 tsubai } 593 1.2 tsubai 594 1.2 tsubai splx(s); 595 1.2 tsubai 596 1.21 dbj key = sc->sc_polledkeys[0]; 597 1.21 dbj sc->sc_npolledkeys--; 598 1.21 dbj memmove(sc->sc_polledkeys,sc->sc_polledkeys+1, 599 1.21 dbj sc->sc_npolledkeys * sizeof(unsigned char)); 600 1.21 dbj 601 1.2 tsubai press = ADBK_PRESS(key); 602 1.2 tsubai val = ADBK_KEYVAL(key); 603 1.2 tsubai 604 1.2 tsubai *data = val; 605 1.2 tsubai *type = press ? WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP; 606 1.2 tsubai } 607 1.2 tsubai 608 1.2 tsubai void 609 1.41 dsl akbd_cnpollc(void *v, int on) 610 1.2 tsubai { 611 1.21 dbj struct akbd_softc *sc = v; 612 1.21 dbj sc->sc_polling = on; 613 1.21 dbj if (!on) { 614 1.21 dbj int i; 615 1.21 dbj for(i=0;i<sc->sc_npolledkeys;i++) { 616 1.21 dbj kbd_passup(sc,sc->sc_polledkeys[i]); 617 1.21 dbj } 618 1.21 dbj sc->sc_npolledkeys = 0; 619 1.21 dbj } 620 1.20 dbj adb_polling = on; 621 1.1 tsubai } 622