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