kbd.c revision 83366
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 83366 2001-09-12 08:38:13Z julian $ 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; 14280040Syokota bzero(kbd->kb_lastact, sizeof(kbd->kb_lastact)); 14342421Syokota} 14442421Syokota 14542421Syokotavoid 14642421Syokotakbd_set_maps(keyboard_t *kbd, keymap_t *keymap, accentmap_t *accmap, 14742421Syokota fkeytab_t *fkeymap, int fkeymap_size) 14842421Syokota{ 14942421Syokota kbd->kb_keymap = keymap; 15042421Syokota kbd->kb_accentmap = accmap; 15142421Syokota kbd->kb_fkeytab = fkeymap; 15242421Syokota kbd->kb_fkeytab_size = fkeymap_size; 15342421Syokota} 15442421Syokota 15554545Syokota/* declare a new keyboard driver */ 15654545Syokotaint 15754545Syokotakbd_add_driver(keyboard_driver_t *driver) 15854545Syokota{ 15954545Syokota if (SLIST_NEXT(driver, link)) 16054545Syokota return EINVAL; 16154545Syokota SLIST_INSERT_HEAD(&keyboard_drivers, driver, link); 16254545Syokota return 0; 16354545Syokota} 16454545Syokota 16554545Syokotaint 16654545Syokotakbd_delete_driver(keyboard_driver_t *driver) 16754545Syokota{ 16860938Sjake SLIST_REMOVE(&keyboard_drivers, driver, keyboard_driver, link); 16954545Syokota SLIST_NEXT(driver, link) = NULL; 17054545Syokota return 0; 17154545Syokota} 17254545Syokota 17342421Syokota/* register a keyboard and associate it with a function table */ 17442421Syokotaint 17542421Syokotakbd_register(keyboard_t *kbd) 17642421Syokota{ 17747295Syokota const keyboard_driver_t **list; 17847295Syokota const keyboard_driver_t *p; 17942421Syokota int index; 18042421Syokota 18142421Syokota for (index = 0; index < keyboards; ++index) { 18242421Syokota if (keyboard[index] == NULL) 18342421Syokota break; 18442421Syokota } 18544628Syokota if (index >= keyboards) { 18644628Syokota if (kbd_realloc_array()) 18744628Syokota return -1; 18844628Syokota } 18942421Syokota 19042421Syokota kbd->kb_index = index; 19142421Syokota KBD_UNBUSY(kbd); 19242421Syokota KBD_VALID(kbd); 19342421Syokota kbd->kb_active = 0; /* disabled until someone calls kbd_enable() */ 19442421Syokota kbd->kb_token = NULL; 19542421Syokota kbd->kb_callback.kc_func = NULL; 19642421Syokota kbd->kb_callback.kc_arg = NULL; 19742421Syokota 19854545Syokota SLIST_FOREACH(p, &keyboard_drivers, link) { 19954545Syokota if (strcmp(p->name, kbd->kb_name) == 0) { 20054545Syokota keyboard[index] = kbd; 20154545Syokota kbdsw[index] = p->kbdsw; 20254545Syokota return index; 20354545Syokota } 20454545Syokota } 20578161Speter SET_FOREACH(list, kbddriver_set) { 20678161Speter p = *list; 20742421Syokota if (strcmp(p->name, kbd->kb_name) == 0) { 20842421Syokota keyboard[index] = kbd; 20942421Syokota kbdsw[index] = p->kbdsw; 21042421Syokota return index; 21142421Syokota } 21242421Syokota } 21342421Syokota 21442421Syokota return -1; 21542421Syokota} 21642421Syokota 21742421Syokotaint 21842421Syokotakbd_unregister(keyboard_t *kbd) 21942421Syokota{ 22042421Syokota int error; 22142421Syokota int s; 22242421Syokota 22342421Syokota if ((kbd->kb_index < 0) || (kbd->kb_index >= keyboards)) 22442421Syokota return ENOENT; 22542421Syokota if (keyboard[kbd->kb_index] != kbd) 22642421Syokota return ENOENT; 22742421Syokota 22842421Syokota s = spltty(); 22942421Syokota if (KBD_IS_BUSY(kbd)) { 23042421Syokota error = (*kbd->kb_callback.kc_func)(kbd, KBDIO_UNLOADING, 23142421Syokota kbd->kb_callback.kc_arg); 23242421Syokota if (error) { 23342421Syokota splx(s); 23442421Syokota return error; 23542421Syokota } 23642421Syokota if (KBD_IS_BUSY(kbd)) { 23742421Syokota splx(s); 23842421Syokota return EBUSY; 23942421Syokota } 24042421Syokota } 24142421Syokota KBD_INVALID(kbd); 24242421Syokota keyboard[kbd->kb_index] = NULL; 24342421Syokota kbdsw[kbd->kb_index] = NULL; 24442421Syokota 24542421Syokota splx(s); 24642421Syokota return 0; 24742421Syokota} 24842421Syokota 24942421Syokota/* find a funciton table by the driver name */ 25042421Syokotakeyboard_switch_t 25142421Syokota*kbd_get_switch(char *driver) 25242421Syokota{ 25347295Syokota const keyboard_driver_t **list; 25447295Syokota const keyboard_driver_t *p; 25542421Syokota 25654545Syokota SLIST_FOREACH(p, &keyboard_drivers, link) { 25754545Syokota if (strcmp(p->name, driver) == 0) 25854545Syokota return p->kbdsw; 25954545Syokota } 26078161Speter SET_FOREACH(list, kbddriver_set) { 26178161Speter p = *list; 26242421Syokota if (strcmp(p->name, driver) == 0) 26342421Syokota return p->kbdsw; 26442421Syokota } 26542421Syokota 26642421Syokota return NULL; 26742421Syokota} 26842421Syokota 26942421Syokota/* 27042421Syokota * Keyboard client functions 27142421Syokota * Keyboard clients, such as the console driver `syscons' and the keyboard 27242421Syokota * cdev driver, use these functions to claim and release a keyboard for 27342421Syokota * exclusive use. 27442421Syokota */ 27542421Syokota 27642421Syokota/* find the keyboard specified by a driver name and a unit number */ 27742421Syokotaint 27842421Syokotakbd_find_keyboard(char *driver, int unit) 27942421Syokota{ 28042421Syokota int i; 28142421Syokota 28242421Syokota for (i = 0; i < keyboards; ++i) { 28342421Syokota if (keyboard[i] == NULL) 28442421Syokota continue; 28542421Syokota if (!KBD_IS_VALID(keyboard[i])) 28642421Syokota continue; 28742421Syokota if (strcmp("*", driver) && strcmp(keyboard[i]->kb_name, driver)) 28842421Syokota continue; 28942421Syokota if ((unit != -1) && (keyboard[i]->kb_unit != unit)) 29042421Syokota continue; 29142421Syokota return i; 29242421Syokota } 29342421Syokota return -1; 29442421Syokota} 29542421Syokota 29642421Syokota/* allocate a keyboard */ 29742421Syokotaint 29842421Syokotakbd_allocate(char *driver, int unit, void *id, kbd_callback_func_t *func, 29942421Syokota void *arg) 30042421Syokota{ 30142421Syokota int index; 30242421Syokota int s; 30342421Syokota 30442421Syokota if (func == NULL) 30542421Syokota return -1; 30642421Syokota 30742421Syokota s = spltty(); 30842421Syokota index = kbd_find_keyboard(driver, unit); 30942421Syokota if (index >= 0) { 31042421Syokota if (KBD_IS_BUSY(keyboard[index])) { 31142421Syokota splx(s); 31242421Syokota return -1; 31342421Syokota } 31442421Syokota keyboard[index]->kb_token = id; 31542421Syokota KBD_BUSY(keyboard[index]); 31642421Syokota keyboard[index]->kb_callback.kc_func = func; 31742421Syokota keyboard[index]->kb_callback.kc_arg = arg; 31842421Syokota (*kbdsw[index]->clear_state)(keyboard[index]); 31942421Syokota } 32042421Syokota splx(s); 32142421Syokota return index; 32242421Syokota} 32342421Syokota 32442421Syokotaint 32542421Syokotakbd_release(keyboard_t *kbd, void *id) 32642421Syokota{ 32742421Syokota int error; 32842421Syokota int s; 32942421Syokota 33042421Syokota s = spltty(); 33142421Syokota if (!KBD_IS_VALID(kbd) || !KBD_IS_BUSY(kbd)) { 33242421Syokota error = EINVAL; 33342421Syokota } else if (kbd->kb_token != id) { 33442421Syokota error = EPERM; 33542421Syokota } else { 33642421Syokota kbd->kb_token = NULL; 33742421Syokota KBD_UNBUSY(kbd); 33842421Syokota kbd->kb_callback.kc_func = NULL; 33942421Syokota kbd->kb_callback.kc_arg = NULL; 34042421Syokota (*kbdsw[kbd->kb_index]->clear_state)(kbd); 34142421Syokota error = 0; 34242421Syokota } 34342421Syokota splx(s); 34442421Syokota return error; 34542421Syokota} 34642421Syokota 34742421Syokotaint 34842421Syokotakbd_change_callback(keyboard_t *kbd, void *id, kbd_callback_func_t *func, 34942421Syokota void *arg) 35042421Syokota{ 35142421Syokota int error; 35242421Syokota int s; 35342421Syokota 35442421Syokota s = spltty(); 35542421Syokota if (!KBD_IS_VALID(kbd) || !KBD_IS_BUSY(kbd)) { 35642421Syokota error = EINVAL; 35742421Syokota } else if (kbd->kb_token != id) { 35842421Syokota error = EPERM; 35942421Syokota } else if (func == NULL) { 36042421Syokota error = EINVAL; 36142421Syokota } else { 36242421Syokota kbd->kb_callback.kc_func = func; 36342421Syokota kbd->kb_callback.kc_arg = arg; 36442421Syokota error = 0; 36542421Syokota } 36642421Syokota splx(s); 36742421Syokota return error; 36842421Syokota} 36942421Syokota 37042421Syokota/* get a keyboard structure */ 37142421Syokotakeyboard_t 37242421Syokota*kbd_get_keyboard(int index) 37342421Syokota{ 37442421Syokota if ((index < 0) || (index >= keyboards)) 37542421Syokota return NULL; 37650154Syokota if (keyboard[index] == NULL) 37750154Syokota return NULL; 37842421Syokota if (!KBD_IS_VALID(keyboard[index])) 37942421Syokota return NULL; 38042421Syokota return keyboard[index]; 38142421Syokota} 38242421Syokota 38342421Syokota/* 38442421Syokota * The back door for the console driver; configure keyboards 38542421Syokota * This function is for the kernel console to initialize keyboards 38642421Syokota * at very early stage. 38742421Syokota */ 38842421Syokota 38942421Syokotaint 39042421Syokotakbd_configure(int flags) 39142421Syokota{ 39247295Syokota const keyboard_driver_t **list; 39347295Syokota const keyboard_driver_t *p; 39442421Syokota 39554545Syokota SLIST_FOREACH(p, &keyboard_drivers, link) { 39654545Syokota if (p->configure != NULL) 39754545Syokota (*p->configure)(flags); 39854545Syokota } 39978161Speter SET_FOREACH(list, kbddriver_set) { 40078161Speter p = *list; 40142421Syokota if (p->configure != NULL) 40242421Syokota (*p->configure)(flags); 40342421Syokota } 40442421Syokota 40542421Syokota return 0; 40642421Syokota} 40742421Syokota 40842421Syokota#ifdef KBD_INSTALL_CDEV 40942421Syokota 41042421Syokota/* 41142421Syokota * Virtual keyboard cdev driver functions 41242421Syokota * The virtual keyboard driver dispatches driver functions to 41342421Syokota * appropriate subdrivers. 41442421Syokota */ 41542421Syokota 41642421Syokota#define KBD_UNIT(dev) minor(dev) 41742421Syokota 41850154Syokotastatic d_open_t genkbdopen; 41950154Syokotastatic d_close_t genkbdclose; 42050154Syokotastatic d_read_t genkbdread; 42150154Syokotastatic d_write_t genkbdwrite; 42250154Syokotastatic d_ioctl_t genkbdioctl; 42350154Syokotastatic d_poll_t genkbdpoll; 42442421Syokota 42542421Syokota#define CDEV_MAJOR 112 42642421Syokota 42742421Syokotastatic struct cdevsw kbd_cdevsw = { 42850154Syokota /* open */ genkbdopen, 42950154Syokota /* close */ genkbdclose, 43050154Syokota /* read */ genkbdread, 43150154Syokota /* write */ genkbdwrite, 43250154Syokota /* ioctl */ genkbdioctl, 43350154Syokota /* poll */ genkbdpoll, 43450154Syokota /* mmap */ nommap, 43547625Sphk /* strategy */ nostrategy, 43647625Sphk /* name */ "kbd", 43747625Sphk /* maj */ CDEV_MAJOR, 43847625Sphk /* dump */ nodump, 43947625Sphk /* psize */ nopsize, 44047625Sphk /* flags */ 0, 44142421Syokota}; 44242421Syokota 44342421Syokotaint 44450154Syokotakbd_attach(keyboard_t *kbd) 44542421Syokota{ 44650154Syokota dev_t dev; 44742421Syokota 44842421Syokota if (kbd->kb_index >= keyboards) 44942421Syokota return EINVAL; 45042421Syokota if (keyboard[kbd->kb_index] != kbd) 45142421Syokota return EINVAL; 45242421Syokota 45350154Syokota dev = make_dev(&kbd_cdevsw, kbd->kb_index, UID_ROOT, GID_WHEEL, 0600, 45450154Syokota "kbd%r", kbd->kb_index); 45550154Syokota if (dev->si_drv1 == NULL) 45650154Syokota dev->si_drv1 = malloc(sizeof(genkbd_softc_t), M_DEVBUF, 45750154Syokota M_WAITOK); 45850154Syokota bzero(dev->si_drv1, sizeof(genkbd_softc_t)); 45942421Syokota 46042421Syokota printf("kbd%d at %s%d\n", kbd->kb_index, kbd->kb_name, kbd->kb_unit); 46142421Syokota return 0; 46242421Syokota} 46342421Syokota 46442421Syokotaint 46550154Syokotakbd_detach(keyboard_t *kbd) 46642421Syokota{ 46754545Syokota dev_t dev; 46854545Syokota 46942421Syokota if (kbd->kb_index >= keyboards) 47042421Syokota return EINVAL; 47142421Syokota if (keyboard[kbd->kb_index] != kbd) 47242421Syokota return EINVAL; 47342421Syokota 47454545Syokota dev = makedev(kbd_cdevsw.d_maj, kbd->kb_index); 47554545Syokota if (dev->si_drv1) 47654545Syokota free(dev->si_drv1, M_DEVBUF); 47754545Syokota destroy_dev(dev); 47854545Syokota 47942421Syokota return 0; 48042421Syokota} 48142421Syokota 48242421Syokota/* 48342421Syokota * Generic keyboard cdev driver functions 48442421Syokota * Keyboard subdrivers may call these functions to implement common 48542421Syokota * driver functions. 48642421Syokota */ 48742421Syokota 48842421Syokota#define KB_QSIZE 512 48942421Syokota#define KB_BUFSIZE 64 49042421Syokota 49142421Syokotastatic kbd_callback_func_t genkbd_event; 49242421Syokota 49350154Syokotastatic int 49483366Sjuliangenkbdopen(dev_t dev, int mode, int flag, struct thread *td) 49542421Syokota{ 49650154Syokota keyboard_t *kbd; 49750154Syokota genkbd_softc_t *sc; 49842421Syokota int s; 49942421Syokota int i; 50042421Syokota 50142421Syokota s = spltty(); 50250154Syokota sc = dev->si_drv1; 50350154Syokota kbd = kbd_get_keyboard(KBD_INDEX(dev)); 50450154Syokota if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) { 50542421Syokota splx(s); 50642421Syokota return ENXIO; 50742421Syokota } 50842421Syokota i = kbd_allocate(kbd->kb_name, kbd->kb_unit, sc, 50942421Syokota genkbd_event, (void *)sc); 51042421Syokota if (i < 0) { 51142421Syokota splx(s); 51242421Syokota return EBUSY; 51342421Syokota } 51442421Syokota /* assert(i == kbd->kb_index) */ 51542421Syokota /* assert(kbd == kbd_get_keyboard(i)) */ 51642421Syokota 51742421Syokota /* 51842421Syokota * NOTE: even when we have successfully claimed a keyboard, 51942421Syokota * the device may still be missing (!KBD_HAS_DEVICE(kbd)). 52042421Syokota */ 52142421Syokota 52242421Syokota#if 0 52342421Syokota bzero(&sc->gkb_q, sizeof(sc->gkb_q)); 52442421Syokota#endif 52542421Syokota clist_alloc_cblocks(&sc->gkb_q, KB_QSIZE, KB_QSIZE/2); /* XXX */ 52642421Syokota sc->gkb_rsel.si_flags = 0; 52742421Syokota sc->gkb_rsel.si_pid = 0; 52842421Syokota splx(s); 52942421Syokota 53042421Syokota return 0; 53142421Syokota} 53242421Syokota 53350154Syokotastatic int 53483366Sjuliangenkbdclose(dev_t dev, int mode, int flag, struct thread *td) 53542421Syokota{ 53650154Syokota keyboard_t *kbd; 53750154Syokota genkbd_softc_t *sc; 53842421Syokota int s; 53942421Syokota 54042421Syokota /* 54142421Syokota * NOTE: the device may have already become invalid. 54250154Syokota * kbd == NULL || !KBD_IS_VALID(kbd) 54342421Syokota */ 54442421Syokota s = spltty(); 54550154Syokota sc = dev->si_drv1; 54650154Syokota kbd = kbd_get_keyboard(KBD_INDEX(dev)); 54750154Syokota if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) { 54850154Syokota /* XXX: we shall be forgiving and don't report error... */ 54950154Syokota } else { 55050154Syokota kbd_release(kbd, (void *)sc); 55142421Syokota#if 0 55250154Syokota clist_free_cblocks(&sc->gkb_q); 55342421Syokota#endif 55450154Syokota } 55542421Syokota splx(s); 55642421Syokota return 0; 55742421Syokota} 55842421Syokota 55950154Syokotastatic int 56050154Syokotagenkbdread(dev_t dev, struct uio *uio, int flag) 56142421Syokota{ 56250154Syokota keyboard_t *kbd; 56350154Syokota genkbd_softc_t *sc; 56442421Syokota u_char buffer[KB_BUFSIZE]; 56542421Syokota int len; 56642421Syokota int error; 56742421Syokota int s; 56842421Syokota 56942421Syokota /* wait for input */ 57042421Syokota s = spltty(); 57150154Syokota sc = dev->si_drv1; 57250154Syokota kbd = kbd_get_keyboard(KBD_INDEX(dev)); 57350154Syokota if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) { 57450154Syokota splx(s); 57550154Syokota return ENXIO; 57650154Syokota } 57742421Syokota while (sc->gkb_q.c_cc == 0) { 57842421Syokota if (flag & IO_NDELAY) { 57942421Syokota splx(s); 58042421Syokota return EWOULDBLOCK; 58142421Syokota } 58242421Syokota sc->gkb_flags |= KB_ASLEEP; 58342421Syokota error = tsleep((caddr_t)sc, PZERO | PCATCH, "kbdrea", 0); 58450154Syokota kbd = kbd_get_keyboard(KBD_INDEX(dev)); 58550154Syokota if ((kbd == NULL) || !KBD_IS_VALID(kbd)) { 58650154Syokota splx(s); 58750154Syokota return ENXIO; /* our keyboard has gone... */ 58850154Syokota } 58942421Syokota if (error) { 59042421Syokota sc->gkb_flags &= ~KB_ASLEEP; 59142421Syokota splx(s); 59242421Syokota return error; 59342421Syokota } 59442421Syokota } 59542421Syokota splx(s); 59642421Syokota 59742421Syokota /* copy as much input as possible */ 59842421Syokota error = 0; 59942421Syokota while (uio->uio_resid > 0) { 60042421Syokota len = imin(uio->uio_resid, sizeof(buffer)); 60142421Syokota len = q_to_b(&sc->gkb_q, buffer, len); 60242421Syokota if (len <= 0) 60342421Syokota break; 60442421Syokota error = uiomove(buffer, len, uio); 60542421Syokota if (error) 60642421Syokota break; 60742421Syokota } 60842421Syokota 60942421Syokota return error; 61042421Syokota} 61142421Syokota 61250154Syokotastatic int 61350154Syokotagenkbdwrite(dev_t dev, struct uio *uio, int flag) 61442421Syokota{ 61550154Syokota keyboard_t *kbd; 61650154Syokota 61750154Syokota kbd = kbd_get_keyboard(KBD_INDEX(dev)); 61850154Syokota if ((kbd == NULL) || !KBD_IS_VALID(kbd)) 61942421Syokota return ENXIO; 62042421Syokota return ENODEV; 62142421Syokota} 62242421Syokota 62350154Syokotastatic int 62483366Sjuliangenkbdioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct thread *td) 62542421Syokota{ 62650154Syokota keyboard_t *kbd; 62742421Syokota int error; 62842421Syokota 62950154Syokota kbd = kbd_get_keyboard(KBD_INDEX(dev)); 63050154Syokota if ((kbd == NULL) || !KBD_IS_VALID(kbd)) 63142421Syokota return ENXIO; 63242421Syokota error = (*kbdsw[kbd->kb_index]->ioctl)(kbd, cmd, arg); 63342421Syokota if (error == ENOIOCTL) 63442421Syokota error = ENODEV; 63542421Syokota return error; 63642421Syokota} 63742421Syokota 63850154Syokotastatic int 63983366Sjuliangenkbdpoll(dev_t dev, int events, struct thread *td) 64042421Syokota{ 64150154Syokota keyboard_t *kbd; 64250154Syokota genkbd_softc_t *sc; 64342421Syokota int revents; 64442421Syokota int s; 64542421Syokota 64642421Syokota revents = 0; 64742421Syokota s = spltty(); 64850154Syokota sc = dev->si_drv1; 64950154Syokota kbd = kbd_get_keyboard(KBD_INDEX(dev)); 65050154Syokota if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) { 65150154Syokota revents = POLLHUP; /* the keyboard has gone */ 65250154Syokota } else if (events & (POLLIN | POLLRDNORM)) { 65350154Syokota if (sc->gkb_q.c_cc > 0) 65450154Syokota revents = events & (POLLIN | POLLRDNORM); 65542421Syokota else 65683366Sjulian selrecord(td, &sc->gkb_rsel); 65742421Syokota } 65842421Syokota splx(s); 65942421Syokota return revents; 66042421Syokota} 66142421Syokota 66242421Syokotastatic int 66342421Syokotagenkbd_event(keyboard_t *kbd, int event, void *arg) 66442421Syokota{ 66542421Syokota genkbd_softc_t *sc; 66642421Syokota size_t len; 66742421Syokota u_char *cp; 66842421Syokota int mode; 66942421Syokota int c; 67042421Syokota 67142421Syokota /* assert(KBD_IS_VALID(kbd)) */ 67242421Syokota sc = (genkbd_softc_t *)arg; 67342421Syokota 67442421Syokota switch (event) { 67542421Syokota case KBDIO_KEYINPUT: 67642421Syokota break; 67742421Syokota case KBDIO_UNLOADING: 67842421Syokota /* the keyboard is going... */ 67942421Syokota kbd_release(kbd, (void *)sc); 68050154Syokota if (sc->gkb_flags & KB_ASLEEP) { 68150154Syokota sc->gkb_flags &= ~KB_ASLEEP; 68250154Syokota wakeup((caddr_t)sc); 68350154Syokota } 68450154Syokota selwakeup(&sc->gkb_rsel); 68542421Syokota return 0; 68642421Syokota default: 68742421Syokota return EINVAL; 68842421Syokota } 68942421Syokota 69042421Syokota /* obtain the current key input mode */ 69142421Syokota if ((*kbdsw[kbd->kb_index]->ioctl)(kbd, KDGKBMODE, (caddr_t)&mode)) 69242421Syokota mode = K_XLATE; 69342421Syokota 69442421Syokota /* read all pending input */ 69542421Syokota while ((*kbdsw[kbd->kb_index]->check_char)(kbd)) { 69642421Syokota c = (*kbdsw[kbd->kb_index]->read_char)(kbd, FALSE); 69742421Syokota if (c == NOKEY) 69842421Syokota continue; 69942421Syokota if (c == ERRKEY) /* XXX: ring bell? */ 70042421Syokota continue; 70142421Syokota if (!KBD_IS_BUSY(kbd)) 70242421Syokota /* the device is not open, discard the input */ 70342421Syokota continue; 70442421Syokota 70542421Syokota /* store the byte as is for K_RAW and K_CODE modes */ 70642421Syokota if (mode != K_XLATE) { 70742421Syokota putc(KEYCHAR(c), &sc->gkb_q); 70842421Syokota continue; 70942421Syokota } 71042421Syokota 71142421Syokota /* K_XLATE */ 71242421Syokota if (c & RELKEY) /* key release is ignored */ 71342421Syokota continue; 71442421Syokota 71542421Syokota /* process special keys; most of them are just ignored... */ 71642421Syokota if (c & SPCLKEY) { 71742421Syokota switch (KEYCHAR(c)) { 71854382Syokota default: 71942421Syokota /* ignore them... */ 72042421Syokota continue; 72142421Syokota case BTAB: /* a backtab: ESC [ Z */ 72242421Syokota putc(0x1b, &sc->gkb_q); 72342421Syokota putc('[', &sc->gkb_q); 72442421Syokota putc('Z', &sc->gkb_q); 72542421Syokota continue; 72642421Syokota } 72742421Syokota } 72842421Syokota 72942421Syokota /* normal chars, normal chars with the META, function keys */ 73042421Syokota switch (KEYFLAGS(c)) { 73142421Syokota case 0: /* a normal char */ 73242421Syokota putc(KEYCHAR(c), &sc->gkb_q); 73342421Syokota break; 73442421Syokota case MKEY: /* the META flag: prepend ESC */ 73542421Syokota putc(0x1b, &sc->gkb_q); 73642421Syokota putc(KEYCHAR(c), &sc->gkb_q); 73742421Syokota break; 73842421Syokota case FKEY | SPCLKEY: /* a function key, return string */ 73942421Syokota cp = (*kbdsw[kbd->kb_index]->get_fkeystr)(kbd, 74042421Syokota KEYCHAR(c), &len); 74142421Syokota if (cp != NULL) { 74242421Syokota while (len-- > 0) 74342421Syokota putc(*cp++, &sc->gkb_q); 74442421Syokota } 74542421Syokota break; 74642421Syokota } 74742421Syokota } 74842421Syokota 74942421Syokota /* wake up sleeping/polling processes */ 75042421Syokota if (sc->gkb_q.c_cc > 0) { 75142421Syokota if (sc->gkb_flags & KB_ASLEEP) { 75242421Syokota sc->gkb_flags &= ~KB_ASLEEP; 75342421Syokota wakeup((caddr_t)sc); 75442421Syokota } 75542421Syokota selwakeup(&sc->gkb_rsel); 75642421Syokota } 75742421Syokota 75842421Syokota return 0; 75942421Syokota} 76042421Syokota 76142421Syokota#endif /* KBD_INSTALL_CDEV */ 76242421Syokota 76342421Syokota/* 76442421Syokota * Generic low-level keyboard functions 76542421Syokota * The low-level functions in the keyboard subdriver may use these 76642421Syokota * functions. 76742421Syokota */ 76842421Syokota 76942421Syokotaint 77042421Syokotagenkbd_commonioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) 77142421Syokota{ 77242421Syokota keyarg_t *keyp; 77342421Syokota fkeyarg_t *fkeyp; 77442421Syokota int s; 77542421Syokota int i; 77642421Syokota 77742421Syokota s = spltty(); 77842421Syokota switch (cmd) { 77942421Syokota 78042421Syokota case KDGKBINFO: /* get keyboard information */ 78142421Syokota ((keyboard_info_t *)arg)->kb_index = kbd->kb_index; 78242421Syokota i = imin(strlen(kbd->kb_name) + 1, 78342421Syokota sizeof(((keyboard_info_t *)arg)->kb_name)); 78442421Syokota bcopy(kbd->kb_name, ((keyboard_info_t *)arg)->kb_name, i); 78542421Syokota ((keyboard_info_t *)arg)->kb_unit = kbd->kb_unit; 78642421Syokota ((keyboard_info_t *)arg)->kb_type = kbd->kb_type; 78742421Syokota ((keyboard_info_t *)arg)->kb_config = kbd->kb_config; 78842421Syokota ((keyboard_info_t *)arg)->kb_flags = kbd->kb_flags; 78942421Syokota break; 79042421Syokota 79142421Syokota case KDGKBTYPE: /* get keyboard type */ 79242421Syokota *(int *)arg = kbd->kb_type; 79342421Syokota break; 79442421Syokota 79554543Syokota case KDGETREPEAT: /* get keyboard repeat rate */ 79654543Syokota ((int *)arg)[0] = kbd->kb_delay1; 79754543Syokota ((int *)arg)[1] = kbd->kb_delay2; 79854543Syokota break; 79954543Syokota 80042421Syokota case GIO_KEYMAP: /* get keyboard translation table */ 80142421Syokota bcopy(kbd->kb_keymap, arg, sizeof(*kbd->kb_keymap)); 80242421Syokota break; 80342421Syokota case PIO_KEYMAP: /* set keyboard translation table */ 80444628Syokota#ifndef KBD_DISABLE_KEYMAP_LOAD 80542421Syokota bzero(kbd->kb_accentmap, sizeof(*kbd->kb_accentmap)); 80642421Syokota bcopy(arg, kbd->kb_keymap, sizeof(*kbd->kb_keymap)); 80742421Syokota break; 80844628Syokota#else 80944628Syokota splx(s); 81044628Syokota return ENODEV; 81144628Syokota#endif 81242421Syokota 81342421Syokota case GIO_KEYMAPENT: /* get keyboard translation table entry */ 81442421Syokota keyp = (keyarg_t *)arg; 81542421Syokota if (keyp->keynum >= sizeof(kbd->kb_keymap->key) 81642421Syokota /sizeof(kbd->kb_keymap->key[0])) { 81742421Syokota splx(s); 81842421Syokota return EINVAL; 81942421Syokota } 82042573Syokota bcopy(&kbd->kb_keymap->key[keyp->keynum], &keyp->key, 82142421Syokota sizeof(keyp->key)); 82242421Syokota break; 82342421Syokota case PIO_KEYMAPENT: /* set keyboard translation table entry */ 82444628Syokota#ifndef KBD_DISABLE_KEYMAP_LOAD 82542421Syokota keyp = (keyarg_t *)arg; 82642421Syokota if (keyp->keynum >= sizeof(kbd->kb_keymap->key) 82742421Syokota /sizeof(kbd->kb_keymap->key[0])) { 82842421Syokota splx(s); 82942421Syokota return EINVAL; 83042421Syokota } 83142573Syokota bcopy(&keyp->key, &kbd->kb_keymap->key[keyp->keynum], 83242421Syokota sizeof(keyp->key)); 83342421Syokota break; 83444628Syokota#else 83544628Syokota splx(s); 83644628Syokota return ENODEV; 83744628Syokota#endif 83842421Syokota 83942421Syokota case GIO_DEADKEYMAP: /* get accent key translation table */ 84042421Syokota bcopy(kbd->kb_accentmap, arg, sizeof(*kbd->kb_accentmap)); 84142421Syokota break; 84242421Syokota case PIO_DEADKEYMAP: /* set accent key translation table */ 84344628Syokota#ifndef KBD_DISABLE_KEYMAP_LOAD 84442421Syokota bcopy(arg, kbd->kb_accentmap, sizeof(*kbd->kb_accentmap)); 84542421Syokota break; 84644628Syokota#else 84744628Syokota splx(s); 84844628Syokota return ENODEV; 84944628Syokota#endif 85042421Syokota 85142421Syokota case GETFKEY: /* get functionkey string */ 85242421Syokota fkeyp = (fkeyarg_t *)arg; 85342421Syokota if (fkeyp->keynum >= kbd->kb_fkeytab_size) { 85442421Syokota splx(s); 85542421Syokota return EINVAL; 85642421Syokota } 85742421Syokota bcopy(kbd->kb_fkeytab[fkeyp->keynum].str, fkeyp->keydef, 85842421Syokota kbd->kb_fkeytab[fkeyp->keynum].len); 85942421Syokota fkeyp->flen = kbd->kb_fkeytab[fkeyp->keynum].len; 86042421Syokota break; 86142421Syokota case SETFKEY: /* set functionkey string */ 86244628Syokota#ifndef KBD_DISABLE_KEYMAP_LOAD 86342421Syokota fkeyp = (fkeyarg_t *)arg; 86442421Syokota if (fkeyp->keynum >= kbd->kb_fkeytab_size) { 86542421Syokota splx(s); 86642421Syokota return EINVAL; 86742421Syokota } 86842421Syokota kbd->kb_fkeytab[fkeyp->keynum].len = imin(fkeyp->flen, MAXFK); 86942421Syokota bcopy(fkeyp->keydef, kbd->kb_fkeytab[fkeyp->keynum].str, 87042421Syokota kbd->kb_fkeytab[fkeyp->keynum].len); 87142421Syokota break; 87244628Syokota#else 87344628Syokota splx(s); 87444628Syokota return ENODEV; 87544628Syokota#endif 87642421Syokota 87742421Syokota default: 87842421Syokota splx(s); 87942421Syokota return ENOIOCTL; 88042421Syokota } 88142421Syokota 88242421Syokota splx(s); 88342421Syokota return 0; 88442421Syokota} 88542421Syokota 88642421Syokota/* get a pointer to the string associated with the given function key */ 88742421Syokotau_char 88842421Syokota*genkbd_get_fkeystr(keyboard_t *kbd, int fkey, size_t *len) 88942421Syokota{ 89042421Syokota if (kbd == NULL) 89142421Syokota return NULL; 89242421Syokota fkey -= F_FN; 89342421Syokota if (fkey > kbd->kb_fkeytab_size) 89442421Syokota return NULL; 89542421Syokota *len = kbd->kb_fkeytab[fkey].len; 89642421Syokota return kbd->kb_fkeytab[fkey].str; 89742421Syokota} 89842421Syokota 89942421Syokota/* diagnostic dump */ 90042421Syokotastatic char 90142421Syokota*get_kbd_type_name(int type) 90242421Syokota{ 90342421Syokota static struct { 90442421Syokota int type; 90542421Syokota char *name; 90642421Syokota } name_table[] = { 90742421Syokota { KB_84, "AT 84" }, 90842421Syokota { KB_101, "AT 101/102" }, 90942421Syokota { KB_OTHER, "generic" }, 91042421Syokota }; 91142421Syokota int i; 91242421Syokota 91342421Syokota for (i = 0; i < sizeof(name_table)/sizeof(name_table[0]); ++i) { 91442421Syokota if (type == name_table[i].type) 91542421Syokota return name_table[i].name; 91642421Syokota } 91742421Syokota return "unknown"; 91842421Syokota} 91942421Syokota 92042421Syokotavoid 92142421Syokotagenkbd_diag(keyboard_t *kbd, int level) 92242421Syokota{ 92342421Syokota if (level > 0) { 92442421Syokota printf("kbd%d: %s%d, %s (%d), config:0x%x, flags:0x%x", 92542421Syokota kbd->kb_index, kbd->kb_name, kbd->kb_unit, 92642421Syokota get_kbd_type_name(kbd->kb_type), kbd->kb_type, 92742421Syokota kbd->kb_config, kbd->kb_flags); 92842421Syokota if (kbd->kb_io_base > 0) 92942421Syokota printf(", port:0x%x-0x%x", kbd->kb_io_base, 93042421Syokota kbd->kb_io_base + kbd->kb_io_size - 1); 93142421Syokota printf("\n"); 93242421Syokota } 93342421Syokota} 93442421Syokota 93542421Syokota#define set_lockkey_state(k, s, l) \ 93642421Syokota if (!((s) & l ## DOWN)) { \ 93742421Syokota int i; \ 93842421Syokota (s) |= l ## DOWN; \ 93942421Syokota (s) ^= l ## ED; \ 94042421Syokota i = (s) & LOCK_MASK; \ 94142421Syokota (*kbdsw[(k)->kb_index]->ioctl)((k), KDSETLED, (caddr_t)&i); \ 94242421Syokota } 94342421Syokota 94442421Syokotastatic u_int 94542421Syokotasave_accent_key(keyboard_t *kbd, u_int key, int *accents) 94642421Syokota{ 94742421Syokota int i; 94842421Syokota 94942421Syokota /* make an index into the accent map */ 95042421Syokota i = key - F_ACC + 1; 95142421Syokota if ((i > kbd->kb_accentmap->n_accs) 95242421Syokota || (kbd->kb_accentmap->acc[i - 1].accchar == 0)) { 95342421Syokota /* the index is out of range or pointing to an empty entry */ 95442421Syokota *accents = 0; 95542421Syokota return ERRKEY; 95642421Syokota } 95742421Syokota 95842421Syokota /* 95942421Syokota * If the same accent key has been hit twice, produce the accent char 96042421Syokota * itself. 96142421Syokota */ 96242421Syokota if (i == *accents) { 96342421Syokota key = kbd->kb_accentmap->acc[i - 1].accchar; 96442421Syokota *accents = 0; 96542421Syokota return key; 96642421Syokota } 96742421Syokota 96842421Syokota /* remember the index and wait for the next key */ 96942421Syokota *accents = i; 97042421Syokota return NOKEY; 97142421Syokota} 97242421Syokota 97342421Syokotastatic u_int 97442421Syokotamake_accent_char(keyboard_t *kbd, u_int ch, int *accents) 97542421Syokota{ 97642421Syokota struct acc_t *acc; 97742421Syokota int i; 97842421Syokota 97942421Syokota acc = &kbd->kb_accentmap->acc[*accents - 1]; 98042421Syokota *accents = 0; 98142421Syokota 98242421Syokota /* 98342421Syokota * If the accent key is followed by the space key, 98442421Syokota * produce the accent char itself. 98542421Syokota */ 98642421Syokota if (ch == ' ') 98742421Syokota return acc->accchar; 98842421Syokota 98942421Syokota /* scan the accent map */ 99042421Syokota for (i = 0; i < NUM_ACCENTCHARS; ++i) { 99142421Syokota if (acc->map[i][0] == 0) /* end of table */ 99242421Syokota break; 99342421Syokota if (acc->map[i][0] == ch) 99442421Syokota return acc->map[i][1]; 99542421Syokota } 99642421Syokota /* this char cannot be accented... */ 99742421Syokota return ERRKEY; 99842421Syokota} 99942421Syokota 100042421Syokotaint 100142421Syokotagenkbd_keyaction(keyboard_t *kbd, int keycode, int up, int *shiftstate, 100242421Syokota int *accents) 100342421Syokota{ 100442421Syokota struct keyent_t *key; 100542421Syokota int state = *shiftstate; 100642421Syokota int action; 100742421Syokota int f; 100842421Syokota int i; 100942421Syokota 101054382Syokota i = keycode; 101142421Syokota f = state & (AGRS | ALKED); 101242421Syokota if ((f == AGRS1) || (f == AGRS2) || (f == ALKED)) 101354382Syokota i += ALTGR_OFFSET; 101454382Syokota key = &kbd->kb_keymap->key[i]; 101542421Syokota i = ((state & SHIFTS) ? 1 : 0) 101642421Syokota | ((state & CTLS) ? 2 : 0) 101742421Syokota | ((state & ALTS) ? 4 : 0); 101842421Syokota if (((key->flgs & FLAG_LOCK_C) && (state & CLKED)) 101942421Syokota || ((key->flgs & FLAG_LOCK_N) && (state & NLKED)) ) 102042421Syokota i ^= 1; 102142421Syokota 102242421Syokota if (up) { /* break: key released */ 102380040Syokota action = kbd->kb_lastact[keycode]; 102480040Syokota kbd->kb_lastact[keycode] = NOP; 102580040Syokota switch (action) { 102680040Syokota case LSHA: 102780040Syokota if (state & SHIFTAON) { 102880040Syokota set_lockkey_state(kbd, state, ALK); 102980040Syokota state &= ~ALKDOWN; 103080040Syokota } 103180040Syokota action = LSH; 103280040Syokota /* FALL THROUGH */ 103380040Syokota case LSH: 103480040Syokota state &= ~SHIFTS1; 103580040Syokota break; 103680040Syokota case RSHA: 103780040Syokota if (state & SHIFTAON) { 103880040Syokota set_lockkey_state(kbd, state, ALK); 103980040Syokota state &= ~ALKDOWN; 104080040Syokota } 104180040Syokota action = RSH; 104280040Syokota /* FALL THROUGH */ 104380040Syokota case RSH: 104480040Syokota state &= ~SHIFTS2; 104580040Syokota break; 104680040Syokota case LCTRA: 104780040Syokota if (state & SHIFTAON) { 104880040Syokota set_lockkey_state(kbd, state, ALK); 104980040Syokota state &= ~ALKDOWN; 105080040Syokota } 105180040Syokota action = LCTR; 105280040Syokota /* FALL THROUGH */ 105380040Syokota case LCTR: 105480040Syokota state &= ~CTLS1; 105580040Syokota break; 105680040Syokota case RCTRA: 105780040Syokota if (state & SHIFTAON) { 105880040Syokota set_lockkey_state(kbd, state, ALK); 105980040Syokota state &= ~ALKDOWN; 106080040Syokota } 106180040Syokota action = RCTR; 106280040Syokota /* FALL THROUGH */ 106380040Syokota case RCTR: 106480040Syokota state &= ~CTLS2; 106580040Syokota break; 106680040Syokota case LALTA: 106780040Syokota if (state & SHIFTAON) { 106880040Syokota set_lockkey_state(kbd, state, ALK); 106980040Syokota state &= ~ALKDOWN; 107080040Syokota } 107180040Syokota action = LALT; 107280040Syokota /* FALL THROUGH */ 107380040Syokota case LALT: 107480040Syokota state &= ~ALTS1; 107580040Syokota break; 107680040Syokota case RALTA: 107780040Syokota if (state & SHIFTAON) { 107880040Syokota set_lockkey_state(kbd, state, ALK); 107980040Syokota state &= ~ALKDOWN; 108080040Syokota } 108180040Syokota action = RALT; 108280040Syokota /* FALL THROUGH */ 108380040Syokota case RALT: 108480040Syokota state &= ~ALTS2; 108580040Syokota break; 108680040Syokota case ASH: 108780040Syokota state &= ~AGRS1; 108880040Syokota break; 108980040Syokota case META: 109080040Syokota state &= ~METAS1; 109180040Syokota break; 109280040Syokota case NLK: 109380040Syokota state &= ~NLKDOWN; 109480040Syokota break; 109580040Syokota case CLK: 109642421Syokota#ifndef PC98 109780040Syokota state &= ~CLKDOWN; 109842421Syokota#else 109980040Syokota state &= ~CLKED; 110080040Syokota i = state & LOCK_MASK; 110180040Syokota (*kbdsw[kbd->kb_index]->ioctl)(kbd, KDSETLED, 110280040Syokota (caddr_t)&i); 110342421Syokota#endif 110480040Syokota break; 110580040Syokota case SLK: 110680040Syokota state &= ~SLKDOWN; 110780040Syokota break; 110880040Syokota case ALK: 110980040Syokota state &= ~ALKDOWN; 111080040Syokota break; 111180040Syokota case NOP: 111280040Syokota /* release events of regular keys are not reported */ 111380040Syokota *shiftstate &= ~SHIFTAON; 111480040Syokota return NOKEY; 111542421Syokota } 111680040Syokota *shiftstate = state & ~SHIFTAON; 111780040Syokota return (SPCLKEY | RELKEY | action); 111842421Syokota } else { /* make: key pressed */ 111980040Syokota action = key->map[i]; 112055820Syokota state &= ~SHIFTAON; 112142421Syokota if (key->spcl & (0x80 >> i)) { 112242421Syokota /* special keys */ 112380040Syokota if (kbd->kb_lastact[keycode] == NOP) 112480040Syokota kbd->kb_lastact[keycode] = action; 112580040Syokota if (kbd->kb_lastact[keycode] != action) 112680040Syokota action = NOP; 112742421Syokota switch (action) { 112842421Syokota /* LOCKING KEYS */ 112942421Syokota case NLK: 113042421Syokota set_lockkey_state(kbd, state, NLK); 113142421Syokota break; 113242421Syokota case CLK: 113342421Syokota#ifndef PC98 113442421Syokota set_lockkey_state(kbd, state, CLK); 113542421Syokota#else 113642421Syokota state |= CLKED; 113742421Syokota i = state & LOCK_MASK; 113842421Syokota (*kbdsw[kbd->kb_index]->ioctl)(kbd, KDSETLED, 113942421Syokota (caddr_t)&i); 114042421Syokota#endif 114142421Syokota break; 114242421Syokota case SLK: 114342421Syokota set_lockkey_state(kbd, state, SLK); 114442421Syokota break; 114542421Syokota case ALK: 114642421Syokota set_lockkey_state(kbd, state, ALK); 114742421Syokota break; 114842421Syokota /* NON-LOCKING KEYS */ 114942421Syokota case SPSC: case RBT: case SUSP: case STBY: 115054382Syokota case DBG: case NEXT: case PREV: case PNC: 115165759Sdwmalone case HALT: case PDWN: 115242421Syokota *accents = 0; 115342421Syokota break; 115442421Syokota case BTAB: 115542421Syokota *accents = 0; 115642421Syokota action |= BKEY; 115742421Syokota break; 115854382Syokota case LSHA: 115955820Syokota state |= SHIFTAON; 116054382Syokota action = LSH; 116154382Syokota /* FALL THROUGH */ 116242421Syokota case LSH: 116342421Syokota state |= SHIFTS1; 116442421Syokota break; 116554382Syokota case RSHA: 116655820Syokota state |= SHIFTAON; 116754382Syokota action = RSH; 116854382Syokota /* FALL THROUGH */ 116942421Syokota case RSH: 117042421Syokota state |= SHIFTS2; 117142421Syokota break; 117254382Syokota case LCTRA: 117355820Syokota state |= SHIFTAON; 117454382Syokota action = LCTR; 117554382Syokota /* FALL THROUGH */ 117642421Syokota case LCTR: 117742421Syokota state |= CTLS1; 117842421Syokota break; 117954382Syokota case RCTRA: 118055820Syokota state |= SHIFTAON; 118154382Syokota action = RCTR; 118254382Syokota /* FALL THROUGH */ 118342421Syokota case RCTR: 118442421Syokota state |= CTLS2; 118542421Syokota break; 118654382Syokota case LALTA: 118755820Syokota state |= SHIFTAON; 118854382Syokota action = LALT; 118954382Syokota /* FALL THROUGH */ 119042421Syokota case LALT: 119142421Syokota state |= ALTS1; 119242421Syokota break; 119354382Syokota case RALTA: 119455820Syokota state |= SHIFTAON; 119554382Syokota action = RALT; 119654382Syokota /* FALL THROUGH */ 119742421Syokota case RALT: 119842421Syokota state |= ALTS2; 119942421Syokota break; 120042421Syokota case ASH: 120142421Syokota state |= AGRS1; 120242421Syokota break; 120342421Syokota case META: 120442421Syokota state |= METAS1; 120542421Syokota break; 120680040Syokota case NOP: 120780040Syokota *shiftstate = state; 120880040Syokota return NOKEY; 120942421Syokota default: 121042421Syokota /* is this an accent (dead) key? */ 121155820Syokota *shiftstate = state; 121242421Syokota if (action >= F_ACC && action <= L_ACC) { 121342421Syokota action = save_accent_key(kbd, action, 121442421Syokota accents); 121542421Syokota switch (action) { 121642421Syokota case NOKEY: 121742421Syokota case ERRKEY: 121842421Syokota return action; 121942421Syokota default: 122042421Syokota if (state & METAS) 122142421Syokota return (action | MKEY); 122242421Syokota else 122342421Syokota return action; 122442421Syokota } 122542421Syokota /* NOT REACHED */ 122642421Syokota } 122742421Syokota /* other special keys */ 122842421Syokota if (*accents > 0) { 122942421Syokota *accents = 0; 123042421Syokota return ERRKEY; 123142421Syokota } 123242421Syokota if (action >= F_FN && action <= L_FN) 123342421Syokota action |= FKEY; 123442421Syokota /* XXX: return fkey string for the FKEY? */ 123555820Syokota return (SPCLKEY | action); 123642421Syokota } 123742421Syokota *shiftstate = state; 123842421Syokota return (SPCLKEY | action); 123942421Syokota } else { 124042421Syokota /* regular keys */ 124180040Syokota kbd->kb_lastact[keycode] = NOP; 124255820Syokota *shiftstate = state; 124342421Syokota if (*accents > 0) { 124442421Syokota /* make an accented char */ 124542421Syokota action = make_accent_char(kbd, action, accents); 124642421Syokota if (action == ERRKEY) 124742421Syokota return action; 124842421Syokota } 124942421Syokota if (state & METAS) 125042421Syokota action |= MKEY; 125142421Syokota return action; 125242421Syokota } 125342421Syokota } 125442421Syokota /* NOT REACHED */ 125542421Syokota} 1256