kbd.c revision 78161
142421Syokota/*- 242421Syokota * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 342421Syokota * All rights reserved. 442421Syokota * 542421Syokota * Redistribution and use in source and binary forms, with or without 642421Syokota * modification, are permitted provided that the following conditions 742421Syokota * are met: 842421Syokota * 1. Redistributions of source code must retain the above copyright 942421Syokota * notice, this list of conditions and the following disclaimer as 1042421Syokota * the first lines of this file unmodified. 1142421Syokota * 2. Redistributions in binary form must reproduce the above copyright 1242421Syokota * notice, this list of conditions and the following disclaimer in the 1342421Syokota * documentation and/or other materials provided with the distribution. 1442421Syokota * 1542421Syokota * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 1642421Syokota * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1742421Syokota * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1842421Syokota * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 1942421Syokota * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2042421Syokota * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2142421Syokota * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2242421Syokota * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2342421Syokota * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2442421Syokota * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2542421Syokota * 2650477Speter * $FreeBSD: head/sys/dev/kbd/kbd.c 78161 2001-06-13 10:58:39Z peter $ 2742421Syokota */ 2842421Syokota 2942421Syokota#include "opt_kbd.h" 3042421Syokota 3142421Syokota#include <sys/param.h> 3242421Syokota#include <sys/systm.h> 3342421Syokota#include <sys/kernel.h> 3442421Syokota#include <sys/malloc.h> 3542421Syokota#include <sys/conf.h> 3642421Syokota#include <sys/tty.h> 3742421Syokota#include <sys/poll.h> 3842421Syokota#include <sys/vnode.h> 3942421Syokota#include <sys/uio.h> 4042421Syokota 4166834Sphk#include <sys/kbio.h> 4242421Syokota 4342421Syokota#include <dev/kbd/kbdreg.h> 4442421Syokota 4550154Syokota#define KBD_INDEX(dev) minor(dev) 4650154Syokota 4750154Syokotatypedef struct genkbd_softc { 4850154Syokota int gkb_flags; /* flag/status bits */ 4950154Syokota#define KB_ASLEEP (1 << 0) 5050154Syokota struct clist gkb_q; /* input queue */ 5150154Syokota struct selinfo gkb_rsel; 5250154Syokota} genkbd_softc_t; 5350154Syokota 5460938Sjakestatic SLIST_HEAD(, keyboard_driver) keyboard_drivers = 5554545Syokota SLIST_HEAD_INITIALIZER(keyboard_drivers); 5654545Syokota 5778161SpeterSET_DECLARE(kbddriver_set, const keyboard_driver_t); 5878161Speter 5942421Syokota/* local arrays */ 6042421Syokota 6142421Syokota/* 6242421Syokota * We need at least one entry each in order to initialize a keyboard 6342421Syokota * for the kernel console. The arrays will be increased dynamically 6442421Syokota * when necessary. 6542421Syokota */ 6642564Syokota 6742564Syokotastatic int keyboards = 1; 6842421Syokotastatic keyboard_t *kbd_ini; 6942564Syokotastatic keyboard_t **keyboard = &kbd_ini; 7042421Syokotastatic keyboard_switch_t *kbdsw_ini; 7142421Syokota keyboard_switch_t **kbdsw = &kbdsw_ini; 7242421Syokota 7342421Syokota#define ARRAY_DELTA 4 7442421Syokota 7544628Syokotastatic int 7642421Syokotakbd_realloc_array(void) 7742421Syokota{ 7842421Syokota keyboard_t **new_kbd; 7942421Syokota keyboard_switch_t **new_kbdsw; 8042421Syokota int newsize; 8142421Syokota int s; 8242421Syokota 8342421Syokota s = spltty(); 8442421Syokota newsize = ((keyboards + ARRAY_DELTA)/ARRAY_DELTA)*ARRAY_DELTA; 8569781Sdwmalone new_kbd = malloc(sizeof(*new_kbd)*newsize, M_DEVBUF, M_NOWAIT|M_ZERO); 8644628Syokota if (new_kbd == NULL) { 8744628Syokota splx(s); 8844628Syokota return ENOMEM; 8944628Syokota } 9069781Sdwmalone new_kbdsw = malloc(sizeof(*new_kbdsw)*newsize, M_DEVBUF, 9169781Sdwmalone M_NOWAIT|M_ZERO); 9244628Syokota if (new_kbdsw == NULL) { 9344628Syokota free(new_kbd, M_DEVBUF); 9444628Syokota splx(s); 9544628Syokota return ENOMEM; 9644628Syokota } 9742421Syokota bcopy(keyboard, new_kbd, sizeof(*keyboard)*keyboards); 9842421Syokota bcopy(kbdsw, new_kbdsw, sizeof(*kbdsw)*keyboards); 9942421Syokota if (keyboards > 1) { 10042421Syokota free(keyboard, M_DEVBUF); 10142421Syokota free(kbdsw, M_DEVBUF); 10242421Syokota } 10342421Syokota keyboard = new_kbd; 10442421Syokota kbdsw = new_kbdsw; 10542421Syokota keyboards = newsize; 10642421Syokota splx(s); 10742421Syokota 10842421Syokota if (bootverbose) 10942421Syokota printf("kbd: new array size %d\n", keyboards); 11044628Syokota 11144628Syokota return 0; 11242421Syokota} 11342421Syokota 11442421Syokota/* 11542421Syokota * Low-level keyboard driver functions 11642421Syokota * Keyboard subdrivers, such as the AT keyboard driver and the USB keyboard 11742421Syokota * driver, call these functions to initialize the keyboard_t structure 11842421Syokota * and register it to the virtual keyboard driver `kbd'. 11942421Syokota */ 12042421Syokota 12142421Syokota/* initialize the keyboard_t structure */ 12242421Syokotavoid 12342421Syokotakbd_init_struct(keyboard_t *kbd, char *name, int type, int unit, int config, 12442421Syokota int port, int port_size) 12542421Syokota{ 12642421Syokota kbd->kb_flags = KB_NO_DEVICE; /* device has not been found */ 12742421Syokota kbd->kb_name = name; 12842421Syokota kbd->kb_type = type; 12942421Syokota kbd->kb_unit = unit; 13044628Syokota kbd->kb_config = config & ~KB_CONF_PROBE_ONLY; 13142421Syokota kbd->kb_led = 0; /* unknown */ 13242421Syokota kbd->kb_io_base = port; 13342421Syokota kbd->kb_io_size = port_size; 13442421Syokota kbd->kb_data = NULL; 13542421Syokota kbd->kb_keymap = NULL; 13642421Syokota kbd->kb_accentmap = NULL; 13742421Syokota kbd->kb_fkeytab = NULL; 13842421Syokota kbd->kb_fkeytab_size = 0; 13944628Syokota kbd->kb_delay1 = KB_DELAY1; /* these values are advisory only */ 14044628Syokota kbd->kb_delay2 = KB_DELAY2; 14154382Syokota kbd->kb_count = 0L; 14242421Syokota} 14342421Syokota 14442421Syokotavoid 14542421Syokotakbd_set_maps(keyboard_t *kbd, keymap_t *keymap, accentmap_t *accmap, 14642421Syokota fkeytab_t *fkeymap, int fkeymap_size) 14742421Syokota{ 14842421Syokota kbd->kb_keymap = keymap; 14942421Syokota kbd->kb_accentmap = accmap; 15042421Syokota kbd->kb_fkeytab = fkeymap; 15142421Syokota kbd->kb_fkeytab_size = fkeymap_size; 15242421Syokota} 15342421Syokota 15454545Syokota/* declare a new keyboard driver */ 15554545Syokotaint 15654545Syokotakbd_add_driver(keyboard_driver_t *driver) 15754545Syokota{ 15854545Syokota if (SLIST_NEXT(driver, link)) 15954545Syokota return EINVAL; 16054545Syokota SLIST_INSERT_HEAD(&keyboard_drivers, driver, link); 16154545Syokota return 0; 16254545Syokota} 16354545Syokota 16454545Syokotaint 16554545Syokotakbd_delete_driver(keyboard_driver_t *driver) 16654545Syokota{ 16760938Sjake SLIST_REMOVE(&keyboard_drivers, driver, keyboard_driver, link); 16854545Syokota SLIST_NEXT(driver, link) = NULL; 16954545Syokota return 0; 17054545Syokota} 17154545Syokota 17242421Syokota/* register a keyboard and associate it with a function table */ 17342421Syokotaint 17442421Syokotakbd_register(keyboard_t *kbd) 17542421Syokota{ 17647295Syokota const keyboard_driver_t **list; 17747295Syokota const keyboard_driver_t *p; 17842421Syokota int index; 17942421Syokota 18042421Syokota for (index = 0; index < keyboards; ++index) { 18142421Syokota if (keyboard[index] == NULL) 18242421Syokota break; 18342421Syokota } 18444628Syokota if (index >= keyboards) { 18544628Syokota if (kbd_realloc_array()) 18644628Syokota return -1; 18744628Syokota } 18842421Syokota 18942421Syokota kbd->kb_index = index; 19042421Syokota KBD_UNBUSY(kbd); 19142421Syokota KBD_VALID(kbd); 19242421Syokota kbd->kb_active = 0; /* disabled until someone calls kbd_enable() */ 19342421Syokota kbd->kb_token = NULL; 19442421Syokota kbd->kb_callback.kc_func = NULL; 19542421Syokota kbd->kb_callback.kc_arg = NULL; 19642421Syokota 19754545Syokota SLIST_FOREACH(p, &keyboard_drivers, link) { 19854545Syokota if (strcmp(p->name, kbd->kb_name) == 0) { 19954545Syokota keyboard[index] = kbd; 20054545Syokota kbdsw[index] = p->kbdsw; 20154545Syokota return index; 20254545Syokota } 20354545Syokota } 20478161Speter SET_FOREACH(list, kbddriver_set) { 20578161Speter p = *list; 20642421Syokota if (strcmp(p->name, kbd->kb_name) == 0) { 20742421Syokota keyboard[index] = kbd; 20842421Syokota kbdsw[index] = p->kbdsw; 20942421Syokota return index; 21042421Syokota } 21142421Syokota } 21242421Syokota 21342421Syokota return -1; 21442421Syokota} 21542421Syokota 21642421Syokotaint 21742421Syokotakbd_unregister(keyboard_t *kbd) 21842421Syokota{ 21942421Syokota int error; 22042421Syokota int s; 22142421Syokota 22242421Syokota if ((kbd->kb_index < 0) || (kbd->kb_index >= keyboards)) 22342421Syokota return ENOENT; 22442421Syokota if (keyboard[kbd->kb_index] != kbd) 22542421Syokota return ENOENT; 22642421Syokota 22742421Syokota s = spltty(); 22842421Syokota if (KBD_IS_BUSY(kbd)) { 22942421Syokota error = (*kbd->kb_callback.kc_func)(kbd, KBDIO_UNLOADING, 23042421Syokota kbd->kb_callback.kc_arg); 23142421Syokota if (error) { 23242421Syokota splx(s); 23342421Syokota return error; 23442421Syokota } 23542421Syokota if (KBD_IS_BUSY(kbd)) { 23642421Syokota splx(s); 23742421Syokota return EBUSY; 23842421Syokota } 23942421Syokota } 24042421Syokota KBD_INVALID(kbd); 24142421Syokota keyboard[kbd->kb_index] = NULL; 24242421Syokota kbdsw[kbd->kb_index] = NULL; 24342421Syokota 24442421Syokota splx(s); 24542421Syokota return 0; 24642421Syokota} 24742421Syokota 24842421Syokota/* find a funciton table by the driver name */ 24942421Syokotakeyboard_switch_t 25042421Syokota*kbd_get_switch(char *driver) 25142421Syokota{ 25247295Syokota const keyboard_driver_t **list; 25347295Syokota const keyboard_driver_t *p; 25442421Syokota 25554545Syokota SLIST_FOREACH(p, &keyboard_drivers, link) { 25654545Syokota if (strcmp(p->name, driver) == 0) 25754545Syokota return p->kbdsw; 25854545Syokota } 25978161Speter SET_FOREACH(list, kbddriver_set) { 26078161Speter p = *list; 26142421Syokota if (strcmp(p->name, driver) == 0) 26242421Syokota return p->kbdsw; 26342421Syokota } 26442421Syokota 26542421Syokota return NULL; 26642421Syokota} 26742421Syokota 26842421Syokota/* 26942421Syokota * Keyboard client functions 27042421Syokota * Keyboard clients, such as the console driver `syscons' and the keyboard 27142421Syokota * cdev driver, use these functions to claim and release a keyboard for 27242421Syokota * exclusive use. 27342421Syokota */ 27442421Syokota 27542421Syokota/* find the keyboard specified by a driver name and a unit number */ 27642421Syokotaint 27742421Syokotakbd_find_keyboard(char *driver, int unit) 27842421Syokota{ 27942421Syokota int i; 28042421Syokota 28142421Syokota for (i = 0; i < keyboards; ++i) { 28242421Syokota if (keyboard[i] == NULL) 28342421Syokota continue; 28442421Syokota if (!KBD_IS_VALID(keyboard[i])) 28542421Syokota continue; 28642421Syokota if (strcmp("*", driver) && strcmp(keyboard[i]->kb_name, driver)) 28742421Syokota continue; 28842421Syokota if ((unit != -1) && (keyboard[i]->kb_unit != unit)) 28942421Syokota continue; 29042421Syokota return i; 29142421Syokota } 29242421Syokota return -1; 29342421Syokota} 29442421Syokota 29542421Syokota/* allocate a keyboard */ 29642421Syokotaint 29742421Syokotakbd_allocate(char *driver, int unit, void *id, kbd_callback_func_t *func, 29842421Syokota void *arg) 29942421Syokota{ 30042421Syokota int index; 30142421Syokota int s; 30242421Syokota 30342421Syokota if (func == NULL) 30442421Syokota return -1; 30542421Syokota 30642421Syokota s = spltty(); 30742421Syokota index = kbd_find_keyboard(driver, unit); 30842421Syokota if (index >= 0) { 30942421Syokota if (KBD_IS_BUSY(keyboard[index])) { 31042421Syokota splx(s); 31142421Syokota return -1; 31242421Syokota } 31342421Syokota keyboard[index]->kb_token = id; 31442421Syokota KBD_BUSY(keyboard[index]); 31542421Syokota keyboard[index]->kb_callback.kc_func = func; 31642421Syokota keyboard[index]->kb_callback.kc_arg = arg; 31742421Syokota (*kbdsw[index]->clear_state)(keyboard[index]); 31842421Syokota } 31942421Syokota splx(s); 32042421Syokota return index; 32142421Syokota} 32242421Syokota 32342421Syokotaint 32442421Syokotakbd_release(keyboard_t *kbd, void *id) 32542421Syokota{ 32642421Syokota int error; 32742421Syokota int s; 32842421Syokota 32942421Syokota s = spltty(); 33042421Syokota if (!KBD_IS_VALID(kbd) || !KBD_IS_BUSY(kbd)) { 33142421Syokota error = EINVAL; 33242421Syokota } else if (kbd->kb_token != id) { 33342421Syokota error = EPERM; 33442421Syokota } else { 33542421Syokota kbd->kb_token = NULL; 33642421Syokota KBD_UNBUSY(kbd); 33742421Syokota kbd->kb_callback.kc_func = NULL; 33842421Syokota kbd->kb_callback.kc_arg = NULL; 33942421Syokota (*kbdsw[kbd->kb_index]->clear_state)(kbd); 34042421Syokota error = 0; 34142421Syokota } 34242421Syokota splx(s); 34342421Syokota return error; 34442421Syokota} 34542421Syokota 34642421Syokotaint 34742421Syokotakbd_change_callback(keyboard_t *kbd, void *id, kbd_callback_func_t *func, 34842421Syokota void *arg) 34942421Syokota{ 35042421Syokota int error; 35142421Syokota int s; 35242421Syokota 35342421Syokota s = spltty(); 35442421Syokota if (!KBD_IS_VALID(kbd) || !KBD_IS_BUSY(kbd)) { 35542421Syokota error = EINVAL; 35642421Syokota } else if (kbd->kb_token != id) { 35742421Syokota error = EPERM; 35842421Syokota } else if (func == NULL) { 35942421Syokota error = EINVAL; 36042421Syokota } else { 36142421Syokota kbd->kb_callback.kc_func = func; 36242421Syokota kbd->kb_callback.kc_arg = arg; 36342421Syokota error = 0; 36442421Syokota } 36542421Syokota splx(s); 36642421Syokota return error; 36742421Syokota} 36842421Syokota 36942421Syokota/* get a keyboard structure */ 37042421Syokotakeyboard_t 37142421Syokota*kbd_get_keyboard(int index) 37242421Syokota{ 37342421Syokota if ((index < 0) || (index >= keyboards)) 37442421Syokota return NULL; 37550154Syokota if (keyboard[index] == NULL) 37650154Syokota return NULL; 37742421Syokota if (!KBD_IS_VALID(keyboard[index])) 37842421Syokota return NULL; 37942421Syokota return keyboard[index]; 38042421Syokota} 38142421Syokota 38242421Syokota/* 38342421Syokota * The back door for the console driver; configure keyboards 38442421Syokota * This function is for the kernel console to initialize keyboards 38542421Syokota * at very early stage. 38642421Syokota */ 38742421Syokota 38842421Syokotaint 38942421Syokotakbd_configure(int flags) 39042421Syokota{ 39147295Syokota const keyboard_driver_t **list; 39247295Syokota const keyboard_driver_t *p; 39342421Syokota 39454545Syokota SLIST_FOREACH(p, &keyboard_drivers, link) { 39554545Syokota if (p->configure != NULL) 39654545Syokota (*p->configure)(flags); 39754545Syokota } 39878161Speter SET_FOREACH(list, kbddriver_set) { 39978161Speter p = *list; 40042421Syokota if (p->configure != NULL) 40142421Syokota (*p->configure)(flags); 40242421Syokota } 40342421Syokota 40442421Syokota return 0; 40542421Syokota} 40642421Syokota 40742421Syokota#ifdef KBD_INSTALL_CDEV 40842421Syokota 40942421Syokota/* 41042421Syokota * Virtual keyboard cdev driver functions 41142421Syokota * The virtual keyboard driver dispatches driver functions to 41242421Syokota * appropriate subdrivers. 41342421Syokota */ 41442421Syokota 41542421Syokota#define KBD_UNIT(dev) minor(dev) 41642421Syokota 41750154Syokotastatic d_open_t genkbdopen; 41850154Syokotastatic d_close_t genkbdclose; 41950154Syokotastatic d_read_t genkbdread; 42050154Syokotastatic d_write_t genkbdwrite; 42150154Syokotastatic d_ioctl_t genkbdioctl; 42250154Syokotastatic d_poll_t genkbdpoll; 42342421Syokota 42442421Syokota#define CDEV_MAJOR 112 42542421Syokota 42642421Syokotastatic struct cdevsw kbd_cdevsw = { 42750154Syokota /* open */ genkbdopen, 42850154Syokota /* close */ genkbdclose, 42950154Syokota /* read */ genkbdread, 43050154Syokota /* write */ genkbdwrite, 43150154Syokota /* ioctl */ genkbdioctl, 43250154Syokota /* poll */ genkbdpoll, 43350154Syokota /* mmap */ nommap, 43447625Sphk /* strategy */ nostrategy, 43547625Sphk /* name */ "kbd", 43647625Sphk /* maj */ CDEV_MAJOR, 43747625Sphk /* dump */ nodump, 43847625Sphk /* psize */ nopsize, 43947625Sphk /* flags */ 0, 44042421Syokota}; 44142421Syokota 44242421Syokotaint 44350154Syokotakbd_attach(keyboard_t *kbd) 44442421Syokota{ 44550154Syokota dev_t dev; 44642421Syokota 44742421Syokota if (kbd->kb_index >= keyboards) 44842421Syokota return EINVAL; 44942421Syokota if (keyboard[kbd->kb_index] != kbd) 45042421Syokota return EINVAL; 45142421Syokota 45250154Syokota dev = make_dev(&kbd_cdevsw, kbd->kb_index, UID_ROOT, GID_WHEEL, 0600, 45350154Syokota "kbd%r", kbd->kb_index); 45450154Syokota if (dev->si_drv1 == NULL) 45550154Syokota dev->si_drv1 = malloc(sizeof(genkbd_softc_t), M_DEVBUF, 45650154Syokota M_WAITOK); 45750154Syokota bzero(dev->si_drv1, sizeof(genkbd_softc_t)); 45842421Syokota 45942421Syokota printf("kbd%d at %s%d\n", kbd->kb_index, kbd->kb_name, kbd->kb_unit); 46042421Syokota return 0; 46142421Syokota} 46242421Syokota 46342421Syokotaint 46450154Syokotakbd_detach(keyboard_t *kbd) 46542421Syokota{ 46654545Syokota dev_t dev; 46754545Syokota 46842421Syokota if (kbd->kb_index >= keyboards) 46942421Syokota return EINVAL; 47042421Syokota if (keyboard[kbd->kb_index] != kbd) 47142421Syokota return EINVAL; 47242421Syokota 47354545Syokota dev = makedev(kbd_cdevsw.d_maj, kbd->kb_index); 47454545Syokota if (dev->si_drv1) 47554545Syokota free(dev->si_drv1, M_DEVBUF); 47654545Syokota destroy_dev(dev); 47754545Syokota 47842421Syokota return 0; 47942421Syokota} 48042421Syokota 48142421Syokota/* 48242421Syokota * Generic keyboard cdev driver functions 48342421Syokota * Keyboard subdrivers may call these functions to implement common 48442421Syokota * driver functions. 48542421Syokota */ 48642421Syokota 48742421Syokota#define KB_QSIZE 512 48842421Syokota#define KB_BUFSIZE 64 48942421Syokota 49042421Syokotastatic kbd_callback_func_t genkbd_event; 49142421Syokota 49250154Syokotastatic int 49350154Syokotagenkbdopen(dev_t dev, int mode, int flag, struct proc *p) 49442421Syokota{ 49550154Syokota keyboard_t *kbd; 49650154Syokota genkbd_softc_t *sc; 49742421Syokota int s; 49842421Syokota int i; 49942421Syokota 50042421Syokota s = spltty(); 50150154Syokota sc = dev->si_drv1; 50250154Syokota kbd = kbd_get_keyboard(KBD_INDEX(dev)); 50350154Syokota if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) { 50442421Syokota splx(s); 50542421Syokota return ENXIO; 50642421Syokota } 50742421Syokota i = kbd_allocate(kbd->kb_name, kbd->kb_unit, sc, 50842421Syokota genkbd_event, (void *)sc); 50942421Syokota if (i < 0) { 51042421Syokota splx(s); 51142421Syokota return EBUSY; 51242421Syokota } 51342421Syokota /* assert(i == kbd->kb_index) */ 51442421Syokota /* assert(kbd == kbd_get_keyboard(i)) */ 51542421Syokota 51642421Syokota /* 51742421Syokota * NOTE: even when we have successfully claimed a keyboard, 51842421Syokota * the device may still be missing (!KBD_HAS_DEVICE(kbd)). 51942421Syokota */ 52042421Syokota 52142421Syokota#if 0 52242421Syokota bzero(&sc->gkb_q, sizeof(sc->gkb_q)); 52342421Syokota#endif 52442421Syokota clist_alloc_cblocks(&sc->gkb_q, KB_QSIZE, KB_QSIZE/2); /* XXX */ 52542421Syokota sc->gkb_rsel.si_flags = 0; 52642421Syokota sc->gkb_rsel.si_pid = 0; 52742421Syokota splx(s); 52842421Syokota 52942421Syokota return 0; 53042421Syokota} 53142421Syokota 53250154Syokotastatic int 53350154Syokotagenkbdclose(dev_t dev, int mode, int flag, struct proc *p) 53442421Syokota{ 53550154Syokota keyboard_t *kbd; 53650154Syokota genkbd_softc_t *sc; 53742421Syokota int s; 53842421Syokota 53942421Syokota /* 54042421Syokota * NOTE: the device may have already become invalid. 54150154Syokota * kbd == NULL || !KBD_IS_VALID(kbd) 54242421Syokota */ 54342421Syokota s = spltty(); 54450154Syokota sc = dev->si_drv1; 54550154Syokota kbd = kbd_get_keyboard(KBD_INDEX(dev)); 54650154Syokota if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) { 54750154Syokota /* XXX: we shall be forgiving and don't report error... */ 54850154Syokota } else { 54950154Syokota kbd_release(kbd, (void *)sc); 55042421Syokota#if 0 55150154Syokota clist_free_cblocks(&sc->gkb_q); 55242421Syokota#endif 55350154Syokota } 55442421Syokota splx(s); 55542421Syokota return 0; 55642421Syokota} 55742421Syokota 55850154Syokotastatic int 55950154Syokotagenkbdread(dev_t dev, struct uio *uio, int flag) 56042421Syokota{ 56150154Syokota keyboard_t *kbd; 56250154Syokota genkbd_softc_t *sc; 56342421Syokota u_char buffer[KB_BUFSIZE]; 56442421Syokota int len; 56542421Syokota int error; 56642421Syokota int s; 56742421Syokota 56842421Syokota /* wait for input */ 56942421Syokota s = spltty(); 57050154Syokota sc = dev->si_drv1; 57150154Syokota kbd = kbd_get_keyboard(KBD_INDEX(dev)); 57250154Syokota if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) { 57350154Syokota splx(s); 57450154Syokota return ENXIO; 57550154Syokota } 57642421Syokota while (sc->gkb_q.c_cc == 0) { 57742421Syokota if (flag & IO_NDELAY) { 57842421Syokota splx(s); 57942421Syokota return EWOULDBLOCK; 58042421Syokota } 58142421Syokota sc->gkb_flags |= KB_ASLEEP; 58242421Syokota error = tsleep((caddr_t)sc, PZERO | PCATCH, "kbdrea", 0); 58350154Syokota kbd = kbd_get_keyboard(KBD_INDEX(dev)); 58450154Syokota if ((kbd == NULL) || !KBD_IS_VALID(kbd)) { 58550154Syokota splx(s); 58650154Syokota return ENXIO; /* our keyboard has gone... */ 58750154Syokota } 58842421Syokota if (error) { 58942421Syokota sc->gkb_flags &= ~KB_ASLEEP; 59042421Syokota splx(s); 59142421Syokota return error; 59242421Syokota } 59342421Syokota } 59442421Syokota splx(s); 59542421Syokota 59642421Syokota /* copy as much input as possible */ 59742421Syokota error = 0; 59842421Syokota while (uio->uio_resid > 0) { 59942421Syokota len = imin(uio->uio_resid, sizeof(buffer)); 60042421Syokota len = q_to_b(&sc->gkb_q, buffer, len); 60142421Syokota if (len <= 0) 60242421Syokota break; 60342421Syokota error = uiomove(buffer, len, uio); 60442421Syokota if (error) 60542421Syokota break; 60642421Syokota } 60742421Syokota 60842421Syokota return error; 60942421Syokota} 61042421Syokota 61150154Syokotastatic int 61250154Syokotagenkbdwrite(dev_t dev, struct uio *uio, int flag) 61342421Syokota{ 61450154Syokota keyboard_t *kbd; 61550154Syokota 61650154Syokota kbd = kbd_get_keyboard(KBD_INDEX(dev)); 61750154Syokota if ((kbd == NULL) || !KBD_IS_VALID(kbd)) 61842421Syokota return ENXIO; 61942421Syokota return ENODEV; 62042421Syokota} 62142421Syokota 62250154Syokotastatic int 62350154Syokotagenkbdioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p) 62442421Syokota{ 62550154Syokota keyboard_t *kbd; 62642421Syokota int error; 62742421Syokota 62850154Syokota kbd = kbd_get_keyboard(KBD_INDEX(dev)); 62950154Syokota if ((kbd == NULL) || !KBD_IS_VALID(kbd)) 63042421Syokota return ENXIO; 63142421Syokota error = (*kbdsw[kbd->kb_index]->ioctl)(kbd, cmd, arg); 63242421Syokota if (error == ENOIOCTL) 63342421Syokota error = ENODEV; 63442421Syokota return error; 63542421Syokota} 63642421Syokota 63750154Syokotastatic int 63850154Syokotagenkbdpoll(dev_t dev, int events, struct proc *p) 63942421Syokota{ 64050154Syokota keyboard_t *kbd; 64150154Syokota genkbd_softc_t *sc; 64242421Syokota int revents; 64342421Syokota int s; 64442421Syokota 64542421Syokota revents = 0; 64642421Syokota s = spltty(); 64750154Syokota sc = dev->si_drv1; 64850154Syokota kbd = kbd_get_keyboard(KBD_INDEX(dev)); 64950154Syokota if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) { 65050154Syokota revents = POLLHUP; /* the keyboard has gone */ 65150154Syokota } else if (events & (POLLIN | POLLRDNORM)) { 65250154Syokota if (sc->gkb_q.c_cc > 0) 65350154Syokota revents = events & (POLLIN | POLLRDNORM); 65442421Syokota else 65542421Syokota selrecord(p, &sc->gkb_rsel); 65642421Syokota } 65742421Syokota splx(s); 65842421Syokota return revents; 65942421Syokota} 66042421Syokota 66142421Syokotastatic int 66242421Syokotagenkbd_event(keyboard_t *kbd, int event, void *arg) 66342421Syokota{ 66442421Syokota genkbd_softc_t *sc; 66542421Syokota size_t len; 66642421Syokota u_char *cp; 66742421Syokota int mode; 66842421Syokota int c; 66942421Syokota 67042421Syokota /* assert(KBD_IS_VALID(kbd)) */ 67142421Syokota sc = (genkbd_softc_t *)arg; 67242421Syokota 67342421Syokota switch (event) { 67442421Syokota case KBDIO_KEYINPUT: 67542421Syokota break; 67642421Syokota case KBDIO_UNLOADING: 67742421Syokota /* the keyboard is going... */ 67842421Syokota kbd_release(kbd, (void *)sc); 67950154Syokota if (sc->gkb_flags & KB_ASLEEP) { 68050154Syokota sc->gkb_flags &= ~KB_ASLEEP; 68150154Syokota wakeup((caddr_t)sc); 68250154Syokota } 68350154Syokota selwakeup(&sc->gkb_rsel); 68442421Syokota return 0; 68542421Syokota default: 68642421Syokota return EINVAL; 68742421Syokota } 68842421Syokota 68942421Syokota /* obtain the current key input mode */ 69042421Syokota if ((*kbdsw[kbd->kb_index]->ioctl)(kbd, KDGKBMODE, (caddr_t)&mode)) 69142421Syokota mode = K_XLATE; 69242421Syokota 69342421Syokota /* read all pending input */ 69442421Syokota while ((*kbdsw[kbd->kb_index]->check_char)(kbd)) { 69542421Syokota c = (*kbdsw[kbd->kb_index]->read_char)(kbd, FALSE); 69642421Syokota if (c == NOKEY) 69742421Syokota continue; 69842421Syokota if (c == ERRKEY) /* XXX: ring bell? */ 69942421Syokota continue; 70042421Syokota if (!KBD_IS_BUSY(kbd)) 70142421Syokota /* the device is not open, discard the input */ 70242421Syokota continue; 70342421Syokota 70442421Syokota /* store the byte as is for K_RAW and K_CODE modes */ 70542421Syokota if (mode != K_XLATE) { 70642421Syokota putc(KEYCHAR(c), &sc->gkb_q); 70742421Syokota continue; 70842421Syokota } 70942421Syokota 71042421Syokota /* K_XLATE */ 71142421Syokota if (c & RELKEY) /* key release is ignored */ 71242421Syokota continue; 71342421Syokota 71442421Syokota /* process special keys; most of them are just ignored... */ 71542421Syokota if (c & SPCLKEY) { 71642421Syokota switch (KEYCHAR(c)) { 71754382Syokota default: 71842421Syokota /* ignore them... */ 71942421Syokota continue; 72042421Syokota case BTAB: /* a backtab: ESC [ Z */ 72142421Syokota putc(0x1b, &sc->gkb_q); 72242421Syokota putc('[', &sc->gkb_q); 72342421Syokota putc('Z', &sc->gkb_q); 72442421Syokota continue; 72542421Syokota } 72642421Syokota } 72742421Syokota 72842421Syokota /* normal chars, normal chars with the META, function keys */ 72942421Syokota switch (KEYFLAGS(c)) { 73042421Syokota case 0: /* a normal char */ 73142421Syokota putc(KEYCHAR(c), &sc->gkb_q); 73242421Syokota break; 73342421Syokota case MKEY: /* the META flag: prepend ESC */ 73442421Syokota putc(0x1b, &sc->gkb_q); 73542421Syokota putc(KEYCHAR(c), &sc->gkb_q); 73642421Syokota break; 73742421Syokota case FKEY | SPCLKEY: /* a function key, return string */ 73842421Syokota cp = (*kbdsw[kbd->kb_index]->get_fkeystr)(kbd, 73942421Syokota KEYCHAR(c), &len); 74042421Syokota if (cp != NULL) { 74142421Syokota while (len-- > 0) 74242421Syokota putc(*cp++, &sc->gkb_q); 74342421Syokota } 74442421Syokota break; 74542421Syokota } 74642421Syokota } 74742421Syokota 74842421Syokota /* wake up sleeping/polling processes */ 74942421Syokota if (sc->gkb_q.c_cc > 0) { 75042421Syokota if (sc->gkb_flags & KB_ASLEEP) { 75142421Syokota sc->gkb_flags &= ~KB_ASLEEP; 75242421Syokota wakeup((caddr_t)sc); 75342421Syokota } 75442421Syokota selwakeup(&sc->gkb_rsel); 75542421Syokota } 75642421Syokota 75742421Syokota return 0; 75842421Syokota} 75942421Syokota 76042421Syokota#endif /* KBD_INSTALL_CDEV */ 76142421Syokota 76242421Syokota/* 76342421Syokota * Generic low-level keyboard functions 76442421Syokota * The low-level functions in the keyboard subdriver may use these 76542421Syokota * functions. 76642421Syokota */ 76742421Syokota 76842421Syokotaint 76942421Syokotagenkbd_commonioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) 77042421Syokota{ 77142421Syokota keyarg_t *keyp; 77242421Syokota fkeyarg_t *fkeyp; 77342421Syokota int s; 77442421Syokota int i; 77542421Syokota 77642421Syokota s = spltty(); 77742421Syokota switch (cmd) { 77842421Syokota 77942421Syokota case KDGKBINFO: /* get keyboard information */ 78042421Syokota ((keyboard_info_t *)arg)->kb_index = kbd->kb_index; 78142421Syokota i = imin(strlen(kbd->kb_name) + 1, 78242421Syokota sizeof(((keyboard_info_t *)arg)->kb_name)); 78342421Syokota bcopy(kbd->kb_name, ((keyboard_info_t *)arg)->kb_name, i); 78442421Syokota ((keyboard_info_t *)arg)->kb_unit = kbd->kb_unit; 78542421Syokota ((keyboard_info_t *)arg)->kb_type = kbd->kb_type; 78642421Syokota ((keyboard_info_t *)arg)->kb_config = kbd->kb_config; 78742421Syokota ((keyboard_info_t *)arg)->kb_flags = kbd->kb_flags; 78842421Syokota break; 78942421Syokota 79042421Syokota case KDGKBTYPE: /* get keyboard type */ 79142421Syokota *(int *)arg = kbd->kb_type; 79242421Syokota break; 79342421Syokota 79454543Syokota case KDGETREPEAT: /* get keyboard repeat rate */ 79554543Syokota ((int *)arg)[0] = kbd->kb_delay1; 79654543Syokota ((int *)arg)[1] = kbd->kb_delay2; 79754543Syokota break; 79854543Syokota 79942421Syokota case GIO_KEYMAP: /* get keyboard translation table */ 80042421Syokota bcopy(kbd->kb_keymap, arg, sizeof(*kbd->kb_keymap)); 80142421Syokota break; 80242421Syokota case PIO_KEYMAP: /* set keyboard translation table */ 80344628Syokota#ifndef KBD_DISABLE_KEYMAP_LOAD 80442421Syokota bzero(kbd->kb_accentmap, sizeof(*kbd->kb_accentmap)); 80542421Syokota bcopy(arg, kbd->kb_keymap, sizeof(*kbd->kb_keymap)); 80642421Syokota break; 80744628Syokota#else 80844628Syokota splx(s); 80944628Syokota return ENODEV; 81044628Syokota#endif 81142421Syokota 81242421Syokota case GIO_KEYMAPENT: /* get keyboard translation table entry */ 81342421Syokota keyp = (keyarg_t *)arg; 81442421Syokota if (keyp->keynum >= sizeof(kbd->kb_keymap->key) 81542421Syokota /sizeof(kbd->kb_keymap->key[0])) { 81642421Syokota splx(s); 81742421Syokota return EINVAL; 81842421Syokota } 81942573Syokota bcopy(&kbd->kb_keymap->key[keyp->keynum], &keyp->key, 82042421Syokota sizeof(keyp->key)); 82142421Syokota break; 82242421Syokota case PIO_KEYMAPENT: /* set keyboard translation table entry */ 82344628Syokota#ifndef KBD_DISABLE_KEYMAP_LOAD 82442421Syokota keyp = (keyarg_t *)arg; 82542421Syokota if (keyp->keynum >= sizeof(kbd->kb_keymap->key) 82642421Syokota /sizeof(kbd->kb_keymap->key[0])) { 82742421Syokota splx(s); 82842421Syokota return EINVAL; 82942421Syokota } 83042573Syokota bcopy(&keyp->key, &kbd->kb_keymap->key[keyp->keynum], 83142421Syokota sizeof(keyp->key)); 83242421Syokota break; 83344628Syokota#else 83444628Syokota splx(s); 83544628Syokota return ENODEV; 83644628Syokota#endif 83742421Syokota 83842421Syokota case GIO_DEADKEYMAP: /* get accent key translation table */ 83942421Syokota bcopy(kbd->kb_accentmap, arg, sizeof(*kbd->kb_accentmap)); 84042421Syokota break; 84142421Syokota case PIO_DEADKEYMAP: /* set accent key translation table */ 84244628Syokota#ifndef KBD_DISABLE_KEYMAP_LOAD 84342421Syokota bcopy(arg, kbd->kb_accentmap, sizeof(*kbd->kb_accentmap)); 84442421Syokota break; 84544628Syokota#else 84644628Syokota splx(s); 84744628Syokota return ENODEV; 84844628Syokota#endif 84942421Syokota 85042421Syokota case GETFKEY: /* get functionkey string */ 85142421Syokota fkeyp = (fkeyarg_t *)arg; 85242421Syokota if (fkeyp->keynum >= kbd->kb_fkeytab_size) { 85342421Syokota splx(s); 85442421Syokota return EINVAL; 85542421Syokota } 85642421Syokota bcopy(kbd->kb_fkeytab[fkeyp->keynum].str, fkeyp->keydef, 85742421Syokota kbd->kb_fkeytab[fkeyp->keynum].len); 85842421Syokota fkeyp->flen = kbd->kb_fkeytab[fkeyp->keynum].len; 85942421Syokota break; 86042421Syokota case SETFKEY: /* set functionkey string */ 86144628Syokota#ifndef KBD_DISABLE_KEYMAP_LOAD 86242421Syokota fkeyp = (fkeyarg_t *)arg; 86342421Syokota if (fkeyp->keynum >= kbd->kb_fkeytab_size) { 86442421Syokota splx(s); 86542421Syokota return EINVAL; 86642421Syokota } 86742421Syokota kbd->kb_fkeytab[fkeyp->keynum].len = imin(fkeyp->flen, MAXFK); 86842421Syokota bcopy(fkeyp->keydef, kbd->kb_fkeytab[fkeyp->keynum].str, 86942421Syokota kbd->kb_fkeytab[fkeyp->keynum].len); 87042421Syokota break; 87144628Syokota#else 87244628Syokota splx(s); 87344628Syokota return ENODEV; 87444628Syokota#endif 87542421Syokota 87642421Syokota default: 87742421Syokota splx(s); 87842421Syokota return ENOIOCTL; 87942421Syokota } 88042421Syokota 88142421Syokota splx(s); 88242421Syokota return 0; 88342421Syokota} 88442421Syokota 88542421Syokota/* get a pointer to the string associated with the given function key */ 88642421Syokotau_char 88742421Syokota*genkbd_get_fkeystr(keyboard_t *kbd, int fkey, size_t *len) 88842421Syokota{ 88942421Syokota if (kbd == NULL) 89042421Syokota return NULL; 89142421Syokota fkey -= F_FN; 89242421Syokota if (fkey > kbd->kb_fkeytab_size) 89342421Syokota return NULL; 89442421Syokota *len = kbd->kb_fkeytab[fkey].len; 89542421Syokota return kbd->kb_fkeytab[fkey].str; 89642421Syokota} 89742421Syokota 89842421Syokota/* diagnostic dump */ 89942421Syokotastatic char 90042421Syokota*get_kbd_type_name(int type) 90142421Syokota{ 90242421Syokota static struct { 90342421Syokota int type; 90442421Syokota char *name; 90542421Syokota } name_table[] = { 90642421Syokota { KB_84, "AT 84" }, 90742421Syokota { KB_101, "AT 101/102" }, 90842421Syokota { KB_OTHER, "generic" }, 90942421Syokota }; 91042421Syokota int i; 91142421Syokota 91242421Syokota for (i = 0; i < sizeof(name_table)/sizeof(name_table[0]); ++i) { 91342421Syokota if (type == name_table[i].type) 91442421Syokota return name_table[i].name; 91542421Syokota } 91642421Syokota return "unknown"; 91742421Syokota} 91842421Syokota 91942421Syokotavoid 92042421Syokotagenkbd_diag(keyboard_t *kbd, int level) 92142421Syokota{ 92242421Syokota if (level > 0) { 92342421Syokota printf("kbd%d: %s%d, %s (%d), config:0x%x, flags:0x%x", 92442421Syokota kbd->kb_index, kbd->kb_name, kbd->kb_unit, 92542421Syokota get_kbd_type_name(kbd->kb_type), kbd->kb_type, 92642421Syokota kbd->kb_config, kbd->kb_flags); 92742421Syokota if (kbd->kb_io_base > 0) 92842421Syokota printf(", port:0x%x-0x%x", kbd->kb_io_base, 92942421Syokota kbd->kb_io_base + kbd->kb_io_size - 1); 93042421Syokota printf("\n"); 93142421Syokota } 93242421Syokota} 93342421Syokota 93442421Syokota#define set_lockkey_state(k, s, l) \ 93542421Syokota if (!((s) & l ## DOWN)) { \ 93642421Syokota int i; \ 93742421Syokota (s) |= l ## DOWN; \ 93842421Syokota (s) ^= l ## ED; \ 93942421Syokota i = (s) & LOCK_MASK; \ 94042421Syokota (*kbdsw[(k)->kb_index]->ioctl)((k), KDSETLED, (caddr_t)&i); \ 94142421Syokota } 94242421Syokota 94342421Syokotastatic u_int 94442421Syokotasave_accent_key(keyboard_t *kbd, u_int key, int *accents) 94542421Syokota{ 94642421Syokota int i; 94742421Syokota 94842421Syokota /* make an index into the accent map */ 94942421Syokota i = key - F_ACC + 1; 95042421Syokota if ((i > kbd->kb_accentmap->n_accs) 95142421Syokota || (kbd->kb_accentmap->acc[i - 1].accchar == 0)) { 95242421Syokota /* the index is out of range or pointing to an empty entry */ 95342421Syokota *accents = 0; 95442421Syokota return ERRKEY; 95542421Syokota } 95642421Syokota 95742421Syokota /* 95842421Syokota * If the same accent key has been hit twice, produce the accent char 95942421Syokota * itself. 96042421Syokota */ 96142421Syokota if (i == *accents) { 96242421Syokota key = kbd->kb_accentmap->acc[i - 1].accchar; 96342421Syokota *accents = 0; 96442421Syokota return key; 96542421Syokota } 96642421Syokota 96742421Syokota /* remember the index and wait for the next key */ 96842421Syokota *accents = i; 96942421Syokota return NOKEY; 97042421Syokota} 97142421Syokota 97242421Syokotastatic u_int 97342421Syokotamake_accent_char(keyboard_t *kbd, u_int ch, int *accents) 97442421Syokota{ 97542421Syokota struct acc_t *acc; 97642421Syokota int i; 97742421Syokota 97842421Syokota acc = &kbd->kb_accentmap->acc[*accents - 1]; 97942421Syokota *accents = 0; 98042421Syokota 98142421Syokota /* 98242421Syokota * If the accent key is followed by the space key, 98342421Syokota * produce the accent char itself. 98442421Syokota */ 98542421Syokota if (ch == ' ') 98642421Syokota return acc->accchar; 98742421Syokota 98842421Syokota /* scan the accent map */ 98942421Syokota for (i = 0; i < NUM_ACCENTCHARS; ++i) { 99042421Syokota if (acc->map[i][0] == 0) /* end of table */ 99142421Syokota break; 99242421Syokota if (acc->map[i][0] == ch) 99342421Syokota return acc->map[i][1]; 99442421Syokota } 99542421Syokota /* this char cannot be accented... */ 99642421Syokota return ERRKEY; 99742421Syokota} 99842421Syokota 99942421Syokotaint 100042421Syokotagenkbd_keyaction(keyboard_t *kbd, int keycode, int up, int *shiftstate, 100142421Syokota int *accents) 100242421Syokota{ 100342421Syokota struct keyent_t *key; 100442421Syokota int state = *shiftstate; 100542421Syokota int action; 100642421Syokota int f; 100742421Syokota int i; 100842421Syokota 100954382Syokota i = keycode; 101042421Syokota f = state & (AGRS | ALKED); 101142421Syokota if ((f == AGRS1) || (f == AGRS2) || (f == ALKED)) 101254382Syokota i += ALTGR_OFFSET; 101354382Syokota key = &kbd->kb_keymap->key[i]; 101442421Syokota i = ((state & SHIFTS) ? 1 : 0) 101542421Syokota | ((state & CTLS) ? 2 : 0) 101642421Syokota | ((state & ALTS) ? 4 : 0); 101742421Syokota if (((key->flgs & FLAG_LOCK_C) && (state & CLKED)) 101842421Syokota || ((key->flgs & FLAG_LOCK_N) && (state & NLKED)) ) 101942421Syokota i ^= 1; 102042421Syokota 102142421Syokota action = key->map[i]; 102242421Syokota if (up) { /* break: key released */ 102342421Syokota if (key->spcl & (0x80 >> i)) { 102442421Syokota /* special keys */ 102542421Syokota switch (action) { 102654382Syokota case LSHA: 102755820Syokota if (state & SHIFTAON) { 102854382Syokota set_lockkey_state(kbd, state, ALK); 102954382Syokota state &= ~ALKDOWN; 103054382Syokota } 103154382Syokota action = LSH; 103254382Syokota /* FALL THROUGH */ 103342421Syokota case LSH: 103442421Syokota state &= ~SHIFTS1; 103542421Syokota break; 103654382Syokota case RSHA: 103755820Syokota if (state & SHIFTAON) { 103854382Syokota set_lockkey_state(kbd, state, ALK); 103954382Syokota state &= ~ALKDOWN; 104054382Syokota } 104154382Syokota action = RSH; 104254382Syokota /* FALL THROUGH */ 104342421Syokota case RSH: 104442421Syokota state &= ~SHIFTS2; 104542421Syokota break; 104654382Syokota case LCTRA: 104755820Syokota if (state & SHIFTAON) { 104854382Syokota set_lockkey_state(kbd, state, ALK); 104954382Syokota state &= ~ALKDOWN; 105054382Syokota } 105154382Syokota action = LCTR; 105254382Syokota /* FALL THROUGH */ 105342421Syokota case LCTR: 105442421Syokota state &= ~CTLS1; 105542421Syokota break; 105654382Syokota case RCTRA: 105755820Syokota if (state & SHIFTAON) { 105854382Syokota set_lockkey_state(kbd, state, ALK); 105954382Syokota state &= ~ALKDOWN; 106054382Syokota } 106154382Syokota action = RCTR; 106254382Syokota /* FALL THROUGH */ 106342421Syokota case RCTR: 106442421Syokota state &= ~CTLS2; 106542421Syokota break; 106654382Syokota case LALTA: 106755820Syokota if (state & SHIFTAON) { 106854382Syokota set_lockkey_state(kbd, state, ALK); 106954382Syokota state &= ~ALKDOWN; 107054382Syokota } 107154382Syokota action = LALT; 107254382Syokota /* FALL THROUGH */ 107342421Syokota case LALT: 107442421Syokota state &= ~ALTS1; 107542421Syokota break; 107654382Syokota case RALTA: 107755820Syokota if (state & SHIFTAON) { 107854382Syokota set_lockkey_state(kbd, state, ALK); 107954382Syokota state &= ~ALKDOWN; 108054382Syokota } 108154382Syokota action = RALT; 108254382Syokota /* FALL THROUGH */ 108342421Syokota case RALT: 108442421Syokota state &= ~ALTS2; 108542421Syokota break; 108642421Syokota case ASH: 108742421Syokota state &= ~AGRS1; 108842421Syokota break; 108942421Syokota case META: 109042421Syokota state &= ~METAS1; 109142421Syokota break; 109242421Syokota case NLK: 109342421Syokota state &= ~NLKDOWN; 109442421Syokota break; 109542421Syokota case CLK: 109642421Syokota#ifndef PC98 109742421Syokota state &= ~CLKDOWN; 109842421Syokota#else 109942421Syokota state &= ~CLKED; 110042421Syokota i = state & LOCK_MASK; 110142421Syokota (*kbdsw[kbd->kb_index]->ioctl)(kbd, KDSETLED, 110242421Syokota (caddr_t)&i); 110342421Syokota#endif 110442421Syokota break; 110542421Syokota case SLK: 110642421Syokota state &= ~SLKDOWN; 110742421Syokota break; 110842421Syokota case ALK: 110942421Syokota state &= ~ALKDOWN; 111042421Syokota break; 111142421Syokota } 111255820Syokota *shiftstate = state & ~SHIFTAON; 111342421Syokota return (SPCLKEY | RELKEY | action); 111442421Syokota } 111542421Syokota /* release events of regular keys are not reported */ 111655820Syokota *shiftstate &= ~SHIFTAON; 111742421Syokota return NOKEY; 111842421Syokota } else { /* make: key pressed */ 111955820Syokota state &= ~SHIFTAON; 112042421Syokota if (key->spcl & (0x80 >> i)) { 112142421Syokota /* special keys */ 112242421Syokota switch (action) { 112342421Syokota /* LOCKING KEYS */ 112442421Syokota case NLK: 112542421Syokota set_lockkey_state(kbd, state, NLK); 112642421Syokota break; 112742421Syokota case CLK: 112842421Syokota#ifndef PC98 112942421Syokota set_lockkey_state(kbd, state, CLK); 113042421Syokota#else 113142421Syokota state |= CLKED; 113242421Syokota i = state & LOCK_MASK; 113342421Syokota (*kbdsw[kbd->kb_index]->ioctl)(kbd, KDSETLED, 113442421Syokota (caddr_t)&i); 113542421Syokota#endif 113642421Syokota break; 113742421Syokota case SLK: 113842421Syokota set_lockkey_state(kbd, state, SLK); 113942421Syokota break; 114042421Syokota case ALK: 114142421Syokota set_lockkey_state(kbd, state, ALK); 114242421Syokota break; 114342421Syokota /* NON-LOCKING KEYS */ 114442421Syokota case SPSC: case RBT: case SUSP: case STBY: 114554382Syokota case DBG: case NEXT: case PREV: case PNC: 114665759Sdwmalone case HALT: case PDWN: 114742421Syokota *accents = 0; 114842421Syokota break; 114942421Syokota case BTAB: 115042421Syokota *accents = 0; 115142421Syokota action |= BKEY; 115242421Syokota break; 115354382Syokota case LSHA: 115455820Syokota state |= SHIFTAON; 115554382Syokota action = LSH; 115654382Syokota /* FALL THROUGH */ 115742421Syokota case LSH: 115842421Syokota state |= SHIFTS1; 115942421Syokota break; 116054382Syokota case RSHA: 116155820Syokota state |= SHIFTAON; 116254382Syokota action = RSH; 116354382Syokota /* FALL THROUGH */ 116442421Syokota case RSH: 116542421Syokota state |= SHIFTS2; 116642421Syokota break; 116754382Syokota case LCTRA: 116855820Syokota state |= SHIFTAON; 116954382Syokota action = LCTR; 117054382Syokota /* FALL THROUGH */ 117142421Syokota case LCTR: 117242421Syokota state |= CTLS1; 117342421Syokota break; 117454382Syokota case RCTRA: 117555820Syokota state |= SHIFTAON; 117654382Syokota action = RCTR; 117754382Syokota /* FALL THROUGH */ 117842421Syokota case RCTR: 117942421Syokota state |= CTLS2; 118042421Syokota break; 118154382Syokota case LALTA: 118255820Syokota state |= SHIFTAON; 118354382Syokota action = LALT; 118454382Syokota /* FALL THROUGH */ 118542421Syokota case LALT: 118642421Syokota state |= ALTS1; 118742421Syokota break; 118854382Syokota case RALTA: 118955820Syokota state |= SHIFTAON; 119054382Syokota action = RALT; 119154382Syokota /* FALL THROUGH */ 119242421Syokota case RALT: 119342421Syokota state |= ALTS2; 119442421Syokota break; 119542421Syokota case ASH: 119642421Syokota state |= AGRS1; 119742421Syokota break; 119842421Syokota case META: 119942421Syokota state |= METAS1; 120042421Syokota break; 120142421Syokota default: 120242421Syokota /* is this an accent (dead) key? */ 120355820Syokota *shiftstate = state; 120442421Syokota if (action >= F_ACC && action <= L_ACC) { 120542421Syokota action = save_accent_key(kbd, action, 120642421Syokota accents); 120742421Syokota switch (action) { 120842421Syokota case NOKEY: 120942421Syokota case ERRKEY: 121042421Syokota return action; 121142421Syokota default: 121242421Syokota if (state & METAS) 121342421Syokota return (action | MKEY); 121442421Syokota else 121542421Syokota return action; 121642421Syokota } 121742421Syokota /* NOT REACHED */ 121842421Syokota } 121942421Syokota /* other special keys */ 122042421Syokota if (*accents > 0) { 122142421Syokota *accents = 0; 122242421Syokota return ERRKEY; 122342421Syokota } 122442421Syokota if (action >= F_FN && action <= L_FN) 122542421Syokota action |= FKEY; 122642421Syokota /* XXX: return fkey string for the FKEY? */ 122755820Syokota return (SPCLKEY | action); 122842421Syokota } 122942421Syokota *shiftstate = state; 123042421Syokota return (SPCLKEY | action); 123142421Syokota } else { 123242421Syokota /* regular keys */ 123355820Syokota *shiftstate = state; 123442421Syokota if (*accents > 0) { 123542421Syokota /* make an accented char */ 123642421Syokota action = make_accent_char(kbd, action, accents); 123742421Syokota if (action == ERRKEY) 123842421Syokota return action; 123942421Syokota } 124042421Syokota if (state & METAS) 124142421Syokota action |= MKEY; 124242421Syokota return action; 124342421Syokota } 124442421Syokota } 124542421Syokota /* NOT REACHED */ 124642421Syokota} 1247