kbd.c revision 42421
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 * 2642421Syokota * $Id: $ 2742421Syokota */ 2842421Syokota 2942421Syokota#include "kbd.h" 3042421Syokota#include "opt_kbd.h" 3142421Syokota 3242421Syokota#include <sys/param.h> 3342421Syokota#include <sys/systm.h> 3442421Syokota#include <sys/kernel.h> 3542421Syokota#include <sys/malloc.h> 3642421Syokota#include <sys/conf.h> 3742421Syokota#include <sys/proc.h> 3842421Syokota#include <sys/tty.h> 3942421Syokota#include <sys/poll.h> 4042421Syokota#include <sys/vnode.h> 4142421Syokota#include <sys/uio.h> 4242421Syokota 4342421Syokota#include <machine/console.h> 4442421Syokota 4542421Syokota#include <dev/kbd/kbdreg.h> 4642421Syokota 4742421Syokota/* local arrays */ 4842421Syokota 4942421Syokota/* 5042421Syokota * We need at least one entry each in order to initialize a keyboard 5142421Syokota * for the kernel console. The arrays will be increased dynamically 5242421Syokota * when necessary. 5342421Syokota */ 5442421Syokotastatic keyboard_t *kbd_ini; 5542421Syokotastatic keyboard_switch_t *kbdsw_ini; 5642421Syokotastatic struct cdevsw *kbdcdevsw_ini; 5742421Syokota 5842421Syokotastatic keyboard_t **keyboard = &kbd_ini; 5942421Syokotastatic int keyboards = 1; 6042421Syokota keyboard_switch_t **kbdsw = &kbdsw_ini; 6142421Syokotastatic struct cdevsw **kbdcdevsw = &kbdcdevsw_ini; 6242421Syokota 6342421Syokota#define ARRAY_DELTA 4 6442421Syokota 6542421Syokotastatic void 6642421Syokotakbd_realloc_array(void) 6742421Syokota{ 6842421Syokota keyboard_t **new_kbd; 6942421Syokota keyboard_switch_t **new_kbdsw; 7042421Syokota struct cdevsw **new_cdevsw; 7142421Syokota int newsize; 7242421Syokota int s; 7342421Syokota 7442421Syokota s = spltty(); 7542421Syokota newsize = ((keyboards + ARRAY_DELTA)/ARRAY_DELTA)*ARRAY_DELTA; 7642421Syokota new_kbd = malloc(sizeof(*new_kbd)*newsize, M_DEVBUF, M_NOWAIT); 7742421Syokota new_kbdsw = malloc(sizeof(*new_kbdsw)*newsize, M_DEVBUF, M_NOWAIT); 7842421Syokota new_cdevsw = malloc(sizeof(*new_cdevsw)*newsize, M_DEVBUF, M_NOWAIT); 7942421Syokota bzero(new_kbd, sizeof(*new_kbd)*newsize); 8042421Syokota bzero(new_kbdsw, sizeof(*new_kbdsw)*newsize); 8142421Syokota bzero(new_cdevsw, sizeof(*new_cdevsw)*newsize); 8242421Syokota bcopy(keyboard, new_kbd, sizeof(*keyboard)*keyboards); 8342421Syokota bcopy(kbdsw, new_kbdsw, sizeof(*kbdsw)*keyboards); 8442421Syokota bcopy(kbdcdevsw, new_cdevsw, sizeof(*kbdcdevsw)*keyboards); 8542421Syokota if (keyboards > 1) { 8642421Syokota free(keyboard, M_DEVBUF); 8742421Syokota free(kbdsw, M_DEVBUF); 8842421Syokota free(kbdcdevsw, M_DEVBUF); 8942421Syokota } 9042421Syokota keyboard = new_kbd; 9142421Syokota kbdsw = new_kbdsw; 9242421Syokota kbdcdevsw = new_cdevsw; 9342421Syokota keyboards = newsize; 9442421Syokota splx(s); 9542421Syokota 9642421Syokota if (bootverbose) 9742421Syokota printf("kbd: new array size %d\n", keyboards); 9842421Syokota} 9942421Syokota 10042421Syokota/* 10142421Syokota * Low-level keyboard driver functions 10242421Syokota * Keyboard subdrivers, such as the AT keyboard driver and the USB keyboard 10342421Syokota * driver, call these functions to initialize the keyboard_t structure 10442421Syokota * and register it to the virtual keyboard driver `kbd'. 10542421Syokota */ 10642421Syokota 10742421Syokota/* initialize the keyboard_t structure */ 10842421Syokotavoid 10942421Syokotakbd_init_struct(keyboard_t *kbd, char *name, int type, int unit, int config, 11042421Syokota int port, int port_size) 11142421Syokota{ 11242421Syokota kbd->kb_flags = KB_NO_DEVICE; /* device has not been found */ 11342421Syokota kbd->kb_name = name; 11442421Syokota kbd->kb_type = type; 11542421Syokota kbd->kb_unit = unit; 11642421Syokota kbd->kb_config = config; 11742421Syokota kbd->kb_led = 0; /* unknown */ 11842421Syokota kbd->kb_io_base = port; 11942421Syokota kbd->kb_io_size = port_size; 12042421Syokota kbd->kb_data = NULL; 12142421Syokota kbd->kb_keymap = NULL; 12242421Syokota kbd->kb_accentmap = NULL; 12342421Syokota kbd->kb_fkeytab = NULL; 12442421Syokota kbd->kb_fkeytab_size = 0; 12542421Syokota} 12642421Syokota 12742421Syokotavoid 12842421Syokotakbd_set_maps(keyboard_t *kbd, keymap_t *keymap, accentmap_t *accmap, 12942421Syokota fkeytab_t *fkeymap, int fkeymap_size) 13042421Syokota{ 13142421Syokota kbd->kb_keymap = keymap; 13242421Syokota kbd->kb_accentmap = accmap; 13342421Syokota kbd->kb_fkeytab = fkeymap; 13442421Syokota kbd->kb_fkeytab_size = fkeymap_size; 13542421Syokota} 13642421Syokota 13742421Syokota/* register a keyboard and associate it with a function table */ 13842421Syokotaint 13942421Syokotakbd_register(keyboard_t *kbd) 14042421Syokota{ 14142421Syokota keyboard_driver_t **list; 14242421Syokota keyboard_driver_t *p; 14342421Syokota int index; 14442421Syokota 14542421Syokota for (index = 0; index < keyboards; ++index) { 14642421Syokota if (keyboard[index] == NULL) 14742421Syokota break; 14842421Syokota } 14942421Syokota if (index >= keyboards) 15042421Syokota return -1; 15142421Syokota 15242421Syokota kbd->kb_index = index; 15342421Syokota KBD_UNBUSY(kbd); 15442421Syokota KBD_VALID(kbd); 15542421Syokota kbd->kb_active = 0; /* disabled until someone calls kbd_enable() */ 15642421Syokota kbd->kb_token = NULL; 15742421Syokota kbd->kb_callback.kc_func = NULL; 15842421Syokota kbd->kb_callback.kc_arg = NULL; 15942421Syokota 16042421Syokota list = (keyboard_driver_t **)kbddriver_set.ls_items; 16142421Syokota while ((p = *list++) != NULL) { 16242421Syokota if (strcmp(p->name, kbd->kb_name) == 0) { 16342421Syokota keyboard[index] = kbd; 16442421Syokota kbdsw[index] = p->kbdsw; 16542421Syokota return index; 16642421Syokota } 16742421Syokota } 16842421Syokota 16942421Syokota return -1; 17042421Syokota} 17142421Syokota 17242421Syokotaint 17342421Syokotakbd_unregister(keyboard_t *kbd) 17442421Syokota{ 17542421Syokota int error; 17642421Syokota int s; 17742421Syokota 17842421Syokota if ((kbd->kb_index < 0) || (kbd->kb_index >= keyboards)) 17942421Syokota return ENOENT; 18042421Syokota if (keyboard[kbd->kb_index] != kbd) 18142421Syokota return ENOENT; 18242421Syokota 18342421Syokota s = spltty(); 18442421Syokota if (KBD_IS_BUSY(kbd)) { 18542421Syokota error = (*kbd->kb_callback.kc_func)(kbd, KBDIO_UNLOADING, 18642421Syokota kbd->kb_callback.kc_arg); 18742421Syokota if (error) { 18842421Syokota splx(s); 18942421Syokota return error; 19042421Syokota } 19142421Syokota if (KBD_IS_BUSY(kbd)) { 19242421Syokota splx(s); 19342421Syokota return EBUSY; 19442421Syokota } 19542421Syokota } 19642421Syokota KBD_INVALID(kbd); 19742421Syokota keyboard[kbd->kb_index] = NULL; 19842421Syokota kbdsw[kbd->kb_index] = NULL; 19942421Syokota 20042421Syokota splx(s); 20142421Syokota return 0; 20242421Syokota} 20342421Syokota 20442421Syokota/* find a funciton table by the driver name */ 20542421Syokotakeyboard_switch_t 20642421Syokota*kbd_get_switch(char *driver) 20742421Syokota{ 20842421Syokota keyboard_driver_t **list; 20942421Syokota keyboard_driver_t *p; 21042421Syokota 21142421Syokota list = (keyboard_driver_t **)kbddriver_set.ls_items; 21242421Syokota while ((p = *list++) != NULL) { 21342421Syokota if (strcmp(p->name, driver) == 0) 21442421Syokota return p->kbdsw; 21542421Syokota } 21642421Syokota 21742421Syokota return NULL; 21842421Syokota} 21942421Syokota 22042421Syokota/* 22142421Syokota * Keyboard client functions 22242421Syokota * Keyboard clients, such as the console driver `syscons' and the keyboard 22342421Syokota * cdev driver, use these functions to claim and release a keyboard for 22442421Syokota * exclusive use. 22542421Syokota */ 22642421Syokota 22742421Syokota/* find the keyboard specified by a driver name and a unit number */ 22842421Syokotaint 22942421Syokotakbd_find_keyboard(char *driver, int unit) 23042421Syokota{ 23142421Syokota int i; 23242421Syokota 23342421Syokota for (i = 0; i < keyboards; ++i) { 23442421Syokota if (keyboard[i] == NULL) 23542421Syokota continue; 23642421Syokota if (!KBD_IS_VALID(keyboard[i])) 23742421Syokota continue; 23842421Syokota if (strcmp("*", driver) && strcmp(keyboard[i]->kb_name, driver)) 23942421Syokota continue; 24042421Syokota if ((unit != -1) && (keyboard[i]->kb_unit != unit)) 24142421Syokota continue; 24242421Syokota return i; 24342421Syokota } 24442421Syokota return -1; 24542421Syokota} 24642421Syokota 24742421Syokota/* allocate a keyboard */ 24842421Syokotaint 24942421Syokotakbd_allocate(char *driver, int unit, void *id, kbd_callback_func_t *func, 25042421Syokota void *arg) 25142421Syokota{ 25242421Syokota int index; 25342421Syokota int s; 25442421Syokota 25542421Syokota if (func == NULL) 25642421Syokota return -1; 25742421Syokota 25842421Syokota s = spltty(); 25942421Syokota index = kbd_find_keyboard(driver, unit); 26042421Syokota if (index >= 0) { 26142421Syokota if (KBD_IS_BUSY(keyboard[index])) { 26242421Syokota splx(s); 26342421Syokota return -1; 26442421Syokota } 26542421Syokota keyboard[index]->kb_token = id; 26642421Syokota KBD_BUSY(keyboard[index]); 26742421Syokota keyboard[index]->kb_callback.kc_func = func; 26842421Syokota keyboard[index]->kb_callback.kc_arg = arg; 26942421Syokota (*kbdsw[index]->clear_state)(keyboard[index]); 27042421Syokota } 27142421Syokota splx(s); 27242421Syokota return index; 27342421Syokota} 27442421Syokota 27542421Syokotaint 27642421Syokotakbd_release(keyboard_t *kbd, void *id) 27742421Syokota{ 27842421Syokota int error; 27942421Syokota int s; 28042421Syokota 28142421Syokota s = spltty(); 28242421Syokota if (!KBD_IS_VALID(kbd) || !KBD_IS_BUSY(kbd)) { 28342421Syokota error = EINVAL; 28442421Syokota } else if (kbd->kb_token != id) { 28542421Syokota error = EPERM; 28642421Syokota } else { 28742421Syokota kbd->kb_token = NULL; 28842421Syokota KBD_UNBUSY(kbd); 28942421Syokota kbd->kb_callback.kc_func = NULL; 29042421Syokota kbd->kb_callback.kc_arg = NULL; 29142421Syokota (*kbdsw[kbd->kb_index]->clear_state)(kbd); 29242421Syokota error = 0; 29342421Syokota } 29442421Syokota splx(s); 29542421Syokota return error; 29642421Syokota} 29742421Syokota 29842421Syokotaint 29942421Syokotakbd_change_callback(keyboard_t *kbd, void *id, kbd_callback_func_t *func, 30042421Syokota void *arg) 30142421Syokota{ 30242421Syokota int error; 30342421Syokota int s; 30442421Syokota 30542421Syokota s = spltty(); 30642421Syokota if (!KBD_IS_VALID(kbd) || !KBD_IS_BUSY(kbd)) { 30742421Syokota error = EINVAL; 30842421Syokota } else if (kbd->kb_token != id) { 30942421Syokota error = EPERM; 31042421Syokota } else if (func == NULL) { 31142421Syokota error = EINVAL; 31242421Syokota } else { 31342421Syokota kbd->kb_callback.kc_func = func; 31442421Syokota kbd->kb_callback.kc_arg = arg; 31542421Syokota error = 0; 31642421Syokota } 31742421Syokota splx(s); 31842421Syokota return error; 31942421Syokota} 32042421Syokota 32142421Syokota/* get a keyboard structure */ 32242421Syokotakeyboard_t 32342421Syokota*kbd_get_keyboard(int index) 32442421Syokota{ 32542421Syokota if ((index < 0) || (index >= keyboards)) 32642421Syokota return NULL; 32742421Syokota if (!KBD_IS_VALID(keyboard[index])) 32842421Syokota return NULL; 32942421Syokota return keyboard[index]; 33042421Syokota} 33142421Syokota 33242421Syokota/* 33342421Syokota * The back door for the console driver; configure keyboards 33442421Syokota * This function is for the kernel console to initialize keyboards 33542421Syokota * at very early stage. 33642421Syokota */ 33742421Syokota 33842421Syokotaint 33942421Syokotakbd_configure(int flags) 34042421Syokota{ 34142421Syokota keyboard_driver_t **list; 34242421Syokota keyboard_driver_t *p; 34342421Syokota 34442421Syokota list = (keyboard_driver_t **)kbddriver_set.ls_items; 34542421Syokota while ((p = *list++) != NULL) { 34642421Syokota if (p->configure != NULL) 34742421Syokota (*p->configure)(flags); 34842421Syokota } 34942421Syokota 35042421Syokota return 0; 35142421Syokota} 35242421Syokota 35342421Syokota#ifdef KBD_INSTALL_CDEV 35442421Syokota 35542421Syokota/* 35642421Syokota * Virtual keyboard cdev driver functions 35742421Syokota * The virtual keyboard driver dispatches driver functions to 35842421Syokota * appropriate subdrivers. 35942421Syokota */ 36042421Syokota 36142421Syokota#define KBD_UNIT(dev) minor(dev) 36242421Syokota 36342421Syokotastatic d_open_t kbdopen; 36442421Syokotastatic d_close_t kbdclose; 36542421Syokotastatic d_read_t kbdread; 36642421Syokotastatic d_write_t kbdwrite; 36742421Syokotastatic d_ioctl_t kbdioctl; 36842421Syokotastatic d_reset_t kbdreset; 36942421Syokotastatic d_devtotty_t kbddevtotty; 37042421Syokotastatic d_poll_t kbdpoll; 37142421Syokotastatic d_mmap_t kbdmmap; 37242421Syokota 37342421Syokota#define CDEV_MAJOR 112 37442421Syokota 37542421Syokotastatic struct cdevsw kbd_cdevsw = { 37642421Syokota kbdopen, kbdclose, kbdread, kbdwrite, /* ??? */ 37742421Syokota kbdioctl, nullstop, kbdreset, kbddevtotty, 37842421Syokota kbdpoll, kbdmmap, nostrategy, "kbd", 37942421Syokota NULL, -1, nodump, nopsize, 38042421Syokota}; 38142421Syokota 38242421Syokotastatic void 38342421Syokotavkbdattach(void *arg) 38442421Syokota{ 38542421Syokota static int kbd_devsw_installed = FALSE; 38642421Syokota dev_t dev; 38742421Syokota 38842421Syokota if (!kbd_devsw_installed) { 38942421Syokota dev = makedev(CDEV_MAJOR, 0); 39042421Syokota cdevsw_add(&dev, &kbd_cdevsw, NULL); 39142421Syokota kbd_devsw_installed = TRUE; 39242421Syokota } 39342421Syokota} 39442421Syokota 39542421SyokotaPSEUDO_SET(vkbdattach, kbd); 39642421Syokota 39742421Syokotaint 39842421Syokotakbd_attach(dev_t dev, keyboard_t *kbd, struct cdevsw *cdevsw) 39942421Syokota{ 40042421Syokota int s; 40142421Syokota 40242421Syokota if (kbd->kb_index >= keyboards) 40342421Syokota return EINVAL; 40442421Syokota if (keyboard[kbd->kb_index] != kbd) 40542421Syokota return EINVAL; 40642421Syokota 40742421Syokota s = spltty(); 40842421Syokota kbd->kb_minor = minor(dev); 40942421Syokota kbdcdevsw[kbd->kb_index] = cdevsw; 41042421Syokota splx(s); 41142421Syokota 41242421Syokota /* XXX: DEVFS? */ 41342421Syokota 41442421Syokota if (kbd->kb_index + 1 >= keyboards) 41542421Syokota kbd_realloc_array(); 41642421Syokota 41742421Syokota printf("kbd%d at %s%d\n", kbd->kb_index, kbd->kb_name, kbd->kb_unit); 41842421Syokota return 0; 41942421Syokota} 42042421Syokota 42142421Syokotaint 42242421Syokotakbd_detach(dev_t dev, keyboard_t *kbd, struct cdevsw *cdevsw) 42342421Syokota{ 42442421Syokota int s; 42542421Syokota 42642421Syokota if (kbd->kb_index >= keyboards) 42742421Syokota return EINVAL; 42842421Syokota if (keyboard[kbd->kb_index] != kbd) 42942421Syokota return EINVAL; 43042421Syokota if (kbdcdevsw[kbd->kb_index] != cdevsw) 43142421Syokota return EINVAL; 43242421Syokota 43342421Syokota s = spltty(); 43442421Syokota (*kbdsw[kbd->kb_index]->term)(kbd); 43542421Syokota kbdcdevsw[kbd->kb_index] = NULL; 43642421Syokota splx(s); 43742421Syokota return 0; 43842421Syokota} 43942421Syokota 44042421Syokotastatic int 44142421Syokotakbdopen(dev_t dev, int flag, int mode, struct proc *p) 44242421Syokota{ 44342421Syokota int unit; 44442421Syokota 44542421Syokota unit = KBD_UNIT(dev); 44642421Syokota if (unit >= keyboards) 44742421Syokota return ENXIO; 44842421Syokota if (kbdcdevsw[unit] == NULL) 44942421Syokota return ENXIO; 45042421Syokota if (KBD_IS_BUSY(keyboard[unit])) 45142421Syokota return EBUSY; 45242421Syokota return (*kbdcdevsw[unit]->d_open)(makedev(0, keyboard[unit]->kb_minor), 45342421Syokota flag, mode, p); 45442421Syokota} 45542421Syokota 45642421Syokotastatic int 45742421Syokotakbdclose(dev_t dev, int flag, int mode, struct proc *p) 45842421Syokota{ 45942421Syokota int unit; 46042421Syokota 46142421Syokota unit = KBD_UNIT(dev); 46242421Syokota if (kbdcdevsw[unit] == NULL) 46342421Syokota return ENXIO; 46442421Syokota return (*kbdcdevsw[unit]->d_close)(makedev(0, keyboard[unit]->kb_minor), 46542421Syokota flag, mode, p); 46642421Syokota} 46742421Syokota 46842421Syokotastatic int 46942421Syokotakbdread(dev_t dev, struct uio *uio, int flag) 47042421Syokota{ 47142421Syokota int unit; 47242421Syokota 47342421Syokota unit = KBD_UNIT(dev); 47442421Syokota if (kbdcdevsw[unit] == NULL) 47542421Syokota return ENXIO; 47642421Syokota return (*kbdcdevsw[unit]->d_read)(makedev(0, keyboard[unit]->kb_minor), 47742421Syokota uio, flag); 47842421Syokota} 47942421Syokota 48042421Syokotastatic int 48142421Syokotakbdwrite(dev_t dev, struct uio *uio, int flag) 48242421Syokota{ 48342421Syokota int unit; 48442421Syokota 48542421Syokota unit = KBD_UNIT(dev); 48642421Syokota if (kbdcdevsw[unit] == NULL) 48742421Syokota return ENXIO; 48842421Syokota return (*kbdcdevsw[unit]->d_write)(makedev(0, keyboard[unit]->kb_minor), 48942421Syokota uio, flag); 49042421Syokota} 49142421Syokota 49242421Syokotastatic int 49342421Syokotakbdioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p) 49442421Syokota{ 49542421Syokota int unit; 49642421Syokota 49742421Syokota unit = KBD_UNIT(dev); 49842421Syokota if (kbdcdevsw[unit] == NULL) 49942421Syokota return ENXIO; 50042421Syokota return (*kbdcdevsw[unit]->d_ioctl)(makedev(0, keyboard[unit]->kb_minor), 50142421Syokota cmd, arg, flag, p); 50242421Syokota} 50342421Syokota 50442421Syokotastatic int 50542421Syokotakbdreset(dev_t dev) 50642421Syokota{ 50742421Syokota int unit; 50842421Syokota 50942421Syokota unit = KBD_UNIT(dev); 51042421Syokota if (kbdcdevsw[unit] == NULL) 51142421Syokota return ENXIO; 51242421Syokota return (*kbdcdevsw[unit]->d_reset)(makedev(0, keyboard[unit]->kb_minor)); 51342421Syokota} 51442421Syokota 51542421Syokotastatic struct tty 51642421Syokota*kbddevtotty(dev_t dev) 51742421Syokota{ 51842421Syokota int unit; 51942421Syokota 52042421Syokota unit = KBD_UNIT(dev); 52142421Syokota if (kbdcdevsw[unit] == NULL) 52242421Syokota return NULL; 52342421Syokota return (*kbdcdevsw[unit]->d_devtotty)(makedev(0, keyboard[unit]->kb_minor)); 52442421Syokota} 52542421Syokota 52642421Syokotastatic int 52742421Syokotakbdpoll(dev_t dev, int event, struct proc *p) 52842421Syokota{ 52942421Syokota int unit; 53042421Syokota 53142421Syokota unit = KBD_UNIT(dev); 53242421Syokota if (kbdcdevsw[unit] == NULL) 53342421Syokota return ENXIO; 53442421Syokota return (*kbdcdevsw[unit]->d_poll)(makedev(0, keyboard[unit]->kb_minor), 53542421Syokota event, p); 53642421Syokota} 53742421Syokota 53842421Syokotastatic int 53942421Syokotakbdmmap(dev_t dev, vm_offset_t offset, int nprot) 54042421Syokota{ 54142421Syokota int unit; 54242421Syokota 54342421Syokota unit = KBD_UNIT(dev); 54442421Syokota if (kbdcdevsw[unit] == NULL) 54542421Syokota return ENXIO; 54642421Syokota return (*kbdcdevsw[unit]->d_mmap)(makedev(0, keyboard[unit]->kb_minor), 54742421Syokota offset, nprot); 54842421Syokota} 54942421Syokota 55042421Syokota/* 55142421Syokota * Generic keyboard cdev driver functions 55242421Syokota * Keyboard subdrivers may call these functions to implement common 55342421Syokota * driver functions. 55442421Syokota */ 55542421Syokota 55642421Syokota#define KB_QSIZE 512 55742421Syokota#define KB_BUFSIZE 64 55842421Syokota 55942421Syokotastatic kbd_callback_func_t genkbd_event; 56042421Syokota 56142421Syokotaint 56242421Syokotagenkbdopen(genkbd_softc_t *sc, keyboard_t *kbd, int mode, int flag, 56342421Syokota struct proc *p) 56442421Syokota{ 56542421Syokota int s; 56642421Syokota int i; 56742421Syokota 56842421Syokota s = spltty(); 56942421Syokota if (!KBD_IS_VALID(kbd)) { 57042421Syokota splx(s); 57142421Syokota return ENXIO; 57242421Syokota } 57342421Syokota i = kbd_allocate(kbd->kb_name, kbd->kb_unit, sc, 57442421Syokota genkbd_event, (void *)sc); 57542421Syokota if (i < 0) { 57642421Syokota splx(s); 57742421Syokota return EBUSY; 57842421Syokota } 57942421Syokota /* assert(i == kbd->kb_index) */ 58042421Syokota /* assert(kbd == kbd_get_keyboard(i)) */ 58142421Syokota 58242421Syokota /* 58342421Syokota * NOTE: even when we have successfully claimed a keyboard, 58442421Syokota * the device may still be missing (!KBD_HAS_DEVICE(kbd)). 58542421Syokota */ 58642421Syokota 58742421Syokota#if 0 58842421Syokota bzero(&sc->gkb_q, sizeof(sc->gkb_q)); 58942421Syokota#endif 59042421Syokota clist_alloc_cblocks(&sc->gkb_q, KB_QSIZE, KB_QSIZE/2); /* XXX */ 59142421Syokota sc->gkb_rsel.si_flags = 0; 59242421Syokota sc->gkb_rsel.si_pid = 0; 59342421Syokota splx(s); 59442421Syokota 59542421Syokota return 0; 59642421Syokota} 59742421Syokota 59842421Syokotaint 59942421Syokotagenkbdclose(genkbd_softc_t *sc, keyboard_t *kbd, int mode, int flag, 60042421Syokota struct proc *p) 60142421Syokota{ 60242421Syokota int s; 60342421Syokota 60442421Syokota /* 60542421Syokota * NOTE: the device may have already become invalid. 60642421Syokota * !KBD_IS_VALID(kbd) 60742421Syokota */ 60842421Syokota s = spltty(); 60942421Syokota kbd_release(kbd, (void *)sc); 61042421Syokota#if 0 61142421Syokota clist_free_cblocks(&sc->gkb_q); 61242421Syokota#endif 61342421Syokota splx(s); 61442421Syokota 61542421Syokota return 0; 61642421Syokota} 61742421Syokota 61842421Syokotaint 61942421Syokotagenkbdread(genkbd_softc_t *sc, keyboard_t *kbd, struct uio *uio, int flag) 62042421Syokota{ 62142421Syokota u_char buffer[KB_BUFSIZE]; 62242421Syokota int len; 62342421Syokota int error; 62442421Syokota int s; 62542421Syokota 62642421Syokota /* wait for input */ 62742421Syokota s = spltty(); 62842421Syokota while (sc->gkb_q.c_cc == 0) { 62942421Syokota if (!KBD_IS_VALID(kbd)) { 63042421Syokota splx(s); 63142421Syokota return EIO; 63242421Syokota } 63342421Syokota if (flag & IO_NDELAY) { 63442421Syokota splx(s); 63542421Syokota return EWOULDBLOCK; 63642421Syokota } 63742421Syokota sc->gkb_flags |= KB_ASLEEP; 63842421Syokota error = tsleep((caddr_t)sc, PZERO | PCATCH, "kbdrea", 0); 63942421Syokota if (error) { 64042421Syokota sc->gkb_flags &= ~KB_ASLEEP; 64142421Syokota splx(s); 64242421Syokota return error; 64342421Syokota } 64442421Syokota } 64542421Syokota splx(s); 64642421Syokota 64742421Syokota /* copy as much input as possible */ 64842421Syokota error = 0; 64942421Syokota while (uio->uio_resid > 0) { 65042421Syokota len = imin(uio->uio_resid, sizeof(buffer)); 65142421Syokota len = q_to_b(&sc->gkb_q, buffer, len); 65242421Syokota if (len <= 0) 65342421Syokota break; 65442421Syokota error = uiomove(buffer, len, uio); 65542421Syokota if (error) 65642421Syokota break; 65742421Syokota } 65842421Syokota 65942421Syokota return error; 66042421Syokota} 66142421Syokota 66242421Syokotaint 66342421Syokotagenkbdwrite(genkbd_softc_t *sc, keyboard_t *kbd, struct uio *uio, int flag) 66442421Syokota{ 66542421Syokota if (!KBD_IS_VALID(kbd)) 66642421Syokota return ENXIO; 66742421Syokota return ENODEV; 66842421Syokota} 66942421Syokota 67042421Syokotaint 67142421Syokotagenkbdioctl(genkbd_softc_t *sc, keyboard_t *kbd, u_long cmd, caddr_t arg, 67242421Syokota int flag, struct proc *p) 67342421Syokota{ 67442421Syokota int error; 67542421Syokota 67642421Syokota if (kbd == NULL) /* XXX */ 67742421Syokota return ENXIO; 67842421Syokota if (!KBD_IS_VALID(kbd)) 67942421Syokota return ENXIO; 68042421Syokota error = (*kbdsw[kbd->kb_index]->ioctl)(kbd, cmd, arg); 68142421Syokota if (error == ENOIOCTL) 68242421Syokota error = ENODEV; 68342421Syokota return error; 68442421Syokota} 68542421Syokota 68642421Syokotaint 68742421Syokotagenkbdpoll(genkbd_softc_t *sc, keyboard_t *kbd, int events, struct proc *p) 68842421Syokota{ 68942421Syokota int revents; 69042421Syokota int s; 69142421Syokota 69242421Syokota revents = 0; 69342421Syokota s = spltty(); 69442421Syokota if (events & (POLLIN | POLLRDNORM)) { 69542421Syokota if ((sc->gkb_q.c_cc > 0) || !KBD_IS_VALID(kbd)) 69642421Syokota revents |= (POLLIN | POLLRDNORM); 69742421Syokota else 69842421Syokota selrecord(p, &sc->gkb_rsel); 69942421Syokota } 70042421Syokota splx(s); 70142421Syokota return revents; 70242421Syokota} 70342421Syokota 70442421Syokotastatic int 70542421Syokotagenkbd_event(keyboard_t *kbd, int event, void *arg) 70642421Syokota{ 70742421Syokota genkbd_softc_t *sc; 70842421Syokota size_t len; 70942421Syokota u_char *cp; 71042421Syokota int mode; 71142421Syokota int c; 71242421Syokota 71342421Syokota /* assert(KBD_IS_VALID(kbd)) */ 71442421Syokota sc = (genkbd_softc_t *)arg; 71542421Syokota 71642421Syokota switch (event) { 71742421Syokota case KBDIO_KEYINPUT: 71842421Syokota break; 71942421Syokota case KBDIO_UNLOADING: 72042421Syokota /* the keyboard is going... */ 72142421Syokota kbd_release(kbd, (void *)sc); 72242421Syokota return 0; 72342421Syokota default: 72442421Syokota return EINVAL; 72542421Syokota } 72642421Syokota 72742421Syokota /* obtain the current key input mode */ 72842421Syokota if ((*kbdsw[kbd->kb_index]->ioctl)(kbd, KDGKBMODE, (caddr_t)&mode)) 72942421Syokota mode = K_XLATE; 73042421Syokota 73142421Syokota /* read all pending input */ 73242421Syokota while ((*kbdsw[kbd->kb_index]->check_char)(kbd)) { 73342421Syokota c = (*kbdsw[kbd->kb_index]->read_char)(kbd, FALSE); 73442421Syokota if (c == NOKEY) 73542421Syokota continue; 73642421Syokota if (c == ERRKEY) /* XXX: ring bell? */ 73742421Syokota continue; 73842421Syokota if (!KBD_IS_BUSY(kbd)) 73942421Syokota /* the device is not open, discard the input */ 74042421Syokota continue; 74142421Syokota 74242421Syokota /* store the byte as is for K_RAW and K_CODE modes */ 74342421Syokota if (mode != K_XLATE) { 74442421Syokota putc(KEYCHAR(c), &sc->gkb_q); 74542421Syokota continue; 74642421Syokota } 74742421Syokota 74842421Syokota /* K_XLATE */ 74942421Syokota if (c & RELKEY) /* key release is ignored */ 75042421Syokota continue; 75142421Syokota 75242421Syokota /* process special keys; most of them are just ignored... */ 75342421Syokota if (c & SPCLKEY) { 75442421Syokota switch (KEYCHAR(c)) { 75542421Syokota /* locking keys */ 75642421Syokota case NLK: case CLK: case SLK: case ALK: 75742421Syokota /* shift keys */ 75842421Syokota case LSH: case RSH: case LCTR: case RCTR: 75942421Syokota case LALT: case RALT: case ASH: case META: 76042421Syokota /* other special keys */ 76142421Syokota case NOP: case SPSC: case RBT: case SUSP: 76242421Syokota case STBY: case DBG: case NEXT: 76342421Syokota /* ignore them... */ 76442421Syokota continue; 76542421Syokota case BTAB: /* a backtab: ESC [ Z */ 76642421Syokota putc(0x1b, &sc->gkb_q); 76742421Syokota putc('[', &sc->gkb_q); 76842421Syokota putc('Z', &sc->gkb_q); 76942421Syokota continue; 77042421Syokota } 77142421Syokota } 77242421Syokota 77342421Syokota /* normal chars, normal chars with the META, function keys */ 77442421Syokota switch (KEYFLAGS(c)) { 77542421Syokota case 0: /* a normal char */ 77642421Syokota putc(KEYCHAR(c), &sc->gkb_q); 77742421Syokota break; 77842421Syokota case MKEY: /* the META flag: prepend ESC */ 77942421Syokota putc(0x1b, &sc->gkb_q); 78042421Syokota putc(KEYCHAR(c), &sc->gkb_q); 78142421Syokota break; 78242421Syokota case FKEY | SPCLKEY: /* a function key, return string */ 78342421Syokota cp = (*kbdsw[kbd->kb_index]->get_fkeystr)(kbd, 78442421Syokota KEYCHAR(c), &len); 78542421Syokota if (cp != NULL) { 78642421Syokota while (len-- > 0) 78742421Syokota putc(*cp++, &sc->gkb_q); 78842421Syokota } 78942421Syokota break; 79042421Syokota } 79142421Syokota } 79242421Syokota 79342421Syokota /* wake up sleeping/polling processes */ 79442421Syokota if (sc->gkb_q.c_cc > 0) { 79542421Syokota if (sc->gkb_flags & KB_ASLEEP) { 79642421Syokota sc->gkb_flags &= ~KB_ASLEEP; 79742421Syokota wakeup((caddr_t)sc); 79842421Syokota } 79942421Syokota selwakeup(&sc->gkb_rsel); 80042421Syokota } 80142421Syokota 80242421Syokota return 0; 80342421Syokota} 80442421Syokota 80542421Syokota#endif /* KBD_INSTALL_CDEV */ 80642421Syokota 80742421Syokota/* 80842421Syokota * Generic low-level keyboard functions 80942421Syokota * The low-level functions in the keyboard subdriver may use these 81042421Syokota * functions. 81142421Syokota */ 81242421Syokota 81342421Syokotaint 81442421Syokotagenkbd_commonioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) 81542421Syokota{ 81642421Syokota keyarg_t *keyp; 81742421Syokota fkeyarg_t *fkeyp; 81842421Syokota int s; 81942421Syokota int i; 82042421Syokota 82142421Syokota s = spltty(); 82242421Syokota switch (cmd) { 82342421Syokota 82442421Syokota case KDGKBINFO: /* get keyboard information */ 82542421Syokota ((keyboard_info_t *)arg)->kb_index = kbd->kb_index; 82642421Syokota i = imin(strlen(kbd->kb_name) + 1, 82742421Syokota sizeof(((keyboard_info_t *)arg)->kb_name)); 82842421Syokota bcopy(kbd->kb_name, ((keyboard_info_t *)arg)->kb_name, i); 82942421Syokota ((keyboard_info_t *)arg)->kb_unit = kbd->kb_unit; 83042421Syokota ((keyboard_info_t *)arg)->kb_type = kbd->kb_type; 83142421Syokota ((keyboard_info_t *)arg)->kb_config = kbd->kb_config; 83242421Syokota ((keyboard_info_t *)arg)->kb_flags = kbd->kb_flags; 83342421Syokota break; 83442421Syokota 83542421Syokota case KDGKBTYPE: /* get keyboard type */ 83642421Syokota *(int *)arg = kbd->kb_type; 83742421Syokota break; 83842421Syokota 83942421Syokota case GIO_KEYMAP: /* get keyboard translation table */ 84042421Syokota bcopy(kbd->kb_keymap, arg, sizeof(*kbd->kb_keymap)); 84142421Syokota break; 84242421Syokota case PIO_KEYMAP: /* set keyboard translation table */ 84342421Syokota bzero(kbd->kb_accentmap, sizeof(*kbd->kb_accentmap)); 84442421Syokota bcopy(arg, kbd->kb_keymap, sizeof(*kbd->kb_keymap)); 84542421Syokota break; 84642421Syokota 84742421Syokota case GIO_KEYMAPENT: /* get keyboard translation table entry */ 84842421Syokota keyp = (keyarg_t *)arg; 84942421Syokota if (keyp->keynum >= sizeof(kbd->kb_keymap->key) 85042421Syokota /sizeof(kbd->kb_keymap->key[0])) { 85142421Syokota splx(s); 85242421Syokota return EINVAL; 85342421Syokota } 85442421Syokota bcopy(&kbd->kb_keymap[keyp->keynum], &keyp->key, 85542421Syokota sizeof(keyp->key)); 85642421Syokota break; 85742421Syokota case PIO_KEYMAPENT: /* set keyboard translation table entry */ 85842421Syokota keyp = (keyarg_t *)arg; 85942421Syokota if (keyp->keynum >= sizeof(kbd->kb_keymap->key) 86042421Syokota /sizeof(kbd->kb_keymap->key[0])) { 86142421Syokota splx(s); 86242421Syokota return EINVAL; 86342421Syokota } 86442421Syokota bcopy(&keyp->key, &kbd->kb_keymap[keyp->keynum], 86542421Syokota sizeof(keyp->key)); 86642421Syokota break; 86742421Syokota 86842421Syokota case GIO_DEADKEYMAP: /* get accent key translation table */ 86942421Syokota bcopy(kbd->kb_accentmap, arg, sizeof(*kbd->kb_accentmap)); 87042421Syokota break; 87142421Syokota case PIO_DEADKEYMAP: /* set accent key translation table */ 87242421Syokota bcopy(arg, kbd->kb_accentmap, sizeof(*kbd->kb_accentmap)); 87342421Syokota break; 87442421Syokota 87542421Syokota case GETFKEY: /* get functionkey string */ 87642421Syokota fkeyp = (fkeyarg_t *)arg; 87742421Syokota if (fkeyp->keynum >= kbd->kb_fkeytab_size) { 87842421Syokota splx(s); 87942421Syokota return EINVAL; 88042421Syokota } 88142421Syokota bcopy(kbd->kb_fkeytab[fkeyp->keynum].str, fkeyp->keydef, 88242421Syokota kbd->kb_fkeytab[fkeyp->keynum].len); 88342421Syokota fkeyp->flen = kbd->kb_fkeytab[fkeyp->keynum].len; 88442421Syokota break; 88542421Syokota case SETFKEY: /* set functionkey string */ 88642421Syokota fkeyp = (fkeyarg_t *)arg; 88742421Syokota if (fkeyp->keynum >= kbd->kb_fkeytab_size) { 88842421Syokota splx(s); 88942421Syokota return EINVAL; 89042421Syokota } 89142421Syokota kbd->kb_fkeytab[fkeyp->keynum].len = imin(fkeyp->flen, MAXFK); 89242421Syokota bcopy(fkeyp->keydef, kbd->kb_fkeytab[fkeyp->keynum].str, 89342421Syokota kbd->kb_fkeytab[fkeyp->keynum].len); 89442421Syokota break; 89542421Syokota 89642421Syokota default: 89742421Syokota splx(s); 89842421Syokota return ENOIOCTL; 89942421Syokota } 90042421Syokota 90142421Syokota splx(s); 90242421Syokota return 0; 90342421Syokota} 90442421Syokota 90542421Syokota/* get a pointer to the string associated with the given function key */ 90642421Syokotau_char 90742421Syokota*genkbd_get_fkeystr(keyboard_t *kbd, int fkey, size_t *len) 90842421Syokota{ 90942421Syokota if (kbd == NULL) 91042421Syokota return NULL; 91142421Syokota fkey -= F_FN; 91242421Syokota if (fkey > kbd->kb_fkeytab_size) 91342421Syokota return NULL; 91442421Syokota *len = kbd->kb_fkeytab[fkey].len; 91542421Syokota return kbd->kb_fkeytab[fkey].str; 91642421Syokota} 91742421Syokota 91842421Syokota/* diagnostic dump */ 91942421Syokotastatic char 92042421Syokota*get_kbd_type_name(int type) 92142421Syokota{ 92242421Syokota static struct { 92342421Syokota int type; 92442421Syokota char *name; 92542421Syokota } name_table[] = { 92642421Syokota { KB_84, "AT 84" }, 92742421Syokota { KB_101, "AT 101/102" }, 92842421Syokota { KB_OTHER, "generic" }, 92942421Syokota }; 93042421Syokota int i; 93142421Syokota 93242421Syokota for (i = 0; i < sizeof(name_table)/sizeof(name_table[0]); ++i) { 93342421Syokota if (type == name_table[i].type) 93442421Syokota return name_table[i].name; 93542421Syokota } 93642421Syokota return "unknown"; 93742421Syokota} 93842421Syokota 93942421Syokotavoid 94042421Syokotagenkbd_diag(keyboard_t *kbd, int level) 94142421Syokota{ 94242421Syokota if (level > 0) { 94342421Syokota printf("kbd%d: %s%d, %s (%d), config:0x%x, flags:0x%x", 94442421Syokota kbd->kb_index, kbd->kb_name, kbd->kb_unit, 94542421Syokota get_kbd_type_name(kbd->kb_type), kbd->kb_type, 94642421Syokota kbd->kb_config, kbd->kb_flags); 94742421Syokota if (kbd->kb_io_base > 0) 94842421Syokota printf(", port:0x%x-0x%x", kbd->kb_io_base, 94942421Syokota kbd->kb_io_base + kbd->kb_io_size - 1); 95042421Syokota printf("\n"); 95142421Syokota } 95242421Syokota} 95342421Syokota 95442421Syokota#define set_lockkey_state(k, s, l) \ 95542421Syokota if (!((s) & l ## DOWN)) { \ 95642421Syokota int i; \ 95742421Syokota (s) |= l ## DOWN; \ 95842421Syokota (s) ^= l ## ED; \ 95942421Syokota i = (s) & LOCK_MASK; \ 96042421Syokota (*kbdsw[(k)->kb_index]->ioctl)((k), KDSETLED, (caddr_t)&i); \ 96142421Syokota } 96242421Syokota 96342421Syokotastatic u_int 96442421Syokotasave_accent_key(keyboard_t *kbd, u_int key, int *accents) 96542421Syokota{ 96642421Syokota int i; 96742421Syokota 96842421Syokota /* make an index into the accent map */ 96942421Syokota i = key - F_ACC + 1; 97042421Syokota if ((i > kbd->kb_accentmap->n_accs) 97142421Syokota || (kbd->kb_accentmap->acc[i - 1].accchar == 0)) { 97242421Syokota /* the index is out of range or pointing to an empty entry */ 97342421Syokota *accents = 0; 97442421Syokota return ERRKEY; 97542421Syokota } 97642421Syokota 97742421Syokota /* 97842421Syokota * If the same accent key has been hit twice, produce the accent char 97942421Syokota * itself. 98042421Syokota */ 98142421Syokota if (i == *accents) { 98242421Syokota key = kbd->kb_accentmap->acc[i - 1].accchar; 98342421Syokota *accents = 0; 98442421Syokota return key; 98542421Syokota } 98642421Syokota 98742421Syokota /* remember the index and wait for the next key */ 98842421Syokota *accents = i; 98942421Syokota return NOKEY; 99042421Syokota} 99142421Syokota 99242421Syokotastatic u_int 99342421Syokotamake_accent_char(keyboard_t *kbd, u_int ch, int *accents) 99442421Syokota{ 99542421Syokota struct acc_t *acc; 99642421Syokota int i; 99742421Syokota 99842421Syokota acc = &kbd->kb_accentmap->acc[*accents - 1]; 99942421Syokota *accents = 0; 100042421Syokota 100142421Syokota /* 100242421Syokota * If the accent key is followed by the space key, 100342421Syokota * produce the accent char itself. 100442421Syokota */ 100542421Syokota if (ch == ' ') 100642421Syokota return acc->accchar; 100742421Syokota 100842421Syokota /* scan the accent map */ 100942421Syokota for (i = 0; i < NUM_ACCENTCHARS; ++i) { 101042421Syokota if (acc->map[i][0] == 0) /* end of table */ 101142421Syokota break; 101242421Syokota if (acc->map[i][0] == ch) 101342421Syokota return acc->map[i][1]; 101442421Syokota } 101542421Syokota /* this char cannot be accented... */ 101642421Syokota return ERRKEY; 101742421Syokota} 101842421Syokota 101942421Syokotaint 102042421Syokotagenkbd_keyaction(keyboard_t *kbd, int keycode, int up, int *shiftstate, 102142421Syokota int *accents) 102242421Syokota{ 102342421Syokota struct keyent_t *key; 102442421Syokota int state = *shiftstate; 102542421Syokota int action; 102642421Syokota int f; 102742421Syokota int i; 102842421Syokota 102942421Syokota f = state & (AGRS | ALKED); 103042421Syokota if ((f == AGRS1) || (f == AGRS2) || (f == ALKED)) 103142421Syokota keycode += ALTGR_OFFSET; 103242421Syokota key = &kbd->kb_keymap->key[keycode]; 103342421Syokota i = ((state & SHIFTS) ? 1 : 0) 103442421Syokota | ((state & CTLS) ? 2 : 0) 103542421Syokota | ((state & ALTS) ? 4 : 0); 103642421Syokota if (((key->flgs & FLAG_LOCK_C) && (state & CLKED)) 103742421Syokota || ((key->flgs & FLAG_LOCK_N) && (state & NLKED)) ) 103842421Syokota i ^= 1; 103942421Syokota 104042421Syokota action = key->map[i]; 104142421Syokota if (up) { /* break: key released */ 104242421Syokota if (key->spcl & (0x80 >> i)) { 104342421Syokota /* special keys */ 104442421Syokota switch (action) { 104542421Syokota case LSH: 104642421Syokota state &= ~SHIFTS1; 104742421Syokota break; 104842421Syokota case RSH: 104942421Syokota state &= ~SHIFTS2; 105042421Syokota break; 105142421Syokota case LCTR: 105242421Syokota state &= ~CTLS1; 105342421Syokota break; 105442421Syokota case RCTR: 105542421Syokota state &= ~CTLS2; 105642421Syokota break; 105742421Syokota case LALT: 105842421Syokota state &= ~ALTS1; 105942421Syokota break; 106042421Syokota case RALT: 106142421Syokota state &= ~ALTS2; 106242421Syokota break; 106342421Syokota case ASH: 106442421Syokota state &= ~AGRS1; 106542421Syokota break; 106642421Syokota case META: 106742421Syokota state &= ~METAS1; 106842421Syokota break; 106942421Syokota case NLK: 107042421Syokota state &= ~NLKDOWN; 107142421Syokota break; 107242421Syokota case CLK: 107342421Syokota#ifndef PC98 107442421Syokota state &= ~CLKDOWN; 107542421Syokota#else 107642421Syokota state &= ~CLKED; 107742421Syokota i = state & LOCK_MASK; 107842421Syokota (*kbdsw[kbd->kb_index]->ioctl)(kbd, KDSETLED, 107942421Syokota (caddr_t)&i); 108042421Syokota#endif 108142421Syokota break; 108242421Syokota case SLK: 108342421Syokota state &= ~SLKDOWN; 108442421Syokota break; 108542421Syokota case ALK: 108642421Syokota state &= ~ALKDOWN; 108742421Syokota break; 108842421Syokota } 108942421Syokota *shiftstate = state; 109042421Syokota return (SPCLKEY | RELKEY | action); 109142421Syokota } 109242421Syokota /* release events of regular keys are not reported */ 109342421Syokota return NOKEY; 109442421Syokota } else { /* make: key pressed */ 109542421Syokota if (key->spcl & (0x80 >> i)) { 109642421Syokota /* special keys */ 109742421Syokota switch (action) { 109842421Syokota /* LOCKING KEYS */ 109942421Syokota case NLK: 110042421Syokota set_lockkey_state(kbd, state, NLK); 110142421Syokota break; 110242421Syokota case CLK: 110342421Syokota#ifndef PC98 110442421Syokota set_lockkey_state(kbd, state, CLK); 110542421Syokota#else 110642421Syokota state |= CLKED; 110742421Syokota i = state & LOCK_MASK; 110842421Syokota (*kbdsw[kbd->kb_index]->ioctl)(kbd, KDSETLED, 110942421Syokota (caddr_t)&i); 111042421Syokota#endif 111142421Syokota break; 111242421Syokota case SLK: 111342421Syokota set_lockkey_state(kbd, state, SLK); 111442421Syokota break; 111542421Syokota case ALK: 111642421Syokota set_lockkey_state(kbd, state, ALK); 111742421Syokota break; 111842421Syokota /* NON-LOCKING KEYS */ 111942421Syokota case SPSC: case RBT: case SUSP: case STBY: 112042421Syokota case DBG: case NEXT: 112142421Syokota *accents = 0; 112242421Syokota break; 112342421Syokota case BTAB: 112442421Syokota *accents = 0; 112542421Syokota action |= BKEY; 112642421Syokota break; 112742421Syokota case LSH: 112842421Syokota state |= SHIFTS1; 112942421Syokota break; 113042421Syokota case RSH: 113142421Syokota state |= SHIFTS2; 113242421Syokota break; 113342421Syokota case LCTR: 113442421Syokota state |= CTLS1; 113542421Syokota break; 113642421Syokota case RCTR: 113742421Syokota state |= CTLS2; 113842421Syokota break; 113942421Syokota case LALT: 114042421Syokota state |= ALTS1; 114142421Syokota break; 114242421Syokota case RALT: 114342421Syokota state |= ALTS2; 114442421Syokota break; 114542421Syokota case ASH: 114642421Syokota state |= AGRS1; 114742421Syokota break; 114842421Syokota case META: 114942421Syokota state |= METAS1; 115042421Syokota break; 115142421Syokota default: 115242421Syokota /* is this an accent (dead) key? */ 115342421Syokota if (action >= F_ACC && action <= L_ACC) { 115442421Syokota action = save_accent_key(kbd, action, 115542421Syokota accents); 115642421Syokota switch (action) { 115742421Syokota case NOKEY: 115842421Syokota case ERRKEY: 115942421Syokota return action; 116042421Syokota default: 116142421Syokota if (state & METAS) 116242421Syokota return (action | MKEY); 116342421Syokota else 116442421Syokota return action; 116542421Syokota } 116642421Syokota /* NOT REACHED */ 116742421Syokota } 116842421Syokota /* other special keys */ 116942421Syokota if (*accents > 0) { 117042421Syokota *accents = 0; 117142421Syokota return ERRKEY; 117242421Syokota } 117342421Syokota if (action >= F_FN && action <= L_FN) 117442421Syokota action |= FKEY; 117542421Syokota /* XXX: return fkey string for the FKEY? */ 117642421Syokota } 117742421Syokota *shiftstate = state; 117842421Syokota return (SPCLKEY | action); 117942421Syokota } else { 118042421Syokota /* regular keys */ 118142421Syokota if (*accents > 0) { 118242421Syokota /* make an accented char */ 118342421Syokota action = make_accent_char(kbd, action, accents); 118442421Syokota if (action == ERRKEY) 118542421Syokota return action; 118642421Syokota } 118742421Syokota if (state & METAS) 118842421Syokota action |= MKEY; 118942421Syokota return action; 119042421Syokota } 119142421Syokota } 119242421Syokota /* NOT REACHED */ 119342421Syokota} 1194