ukbd.c
来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 1,538 行 · 第 1/3 页
C
1,538 行
/* $NetBSD: ukbd.c,v 1.22 1999/01/09 12:10:36 drochner Exp $ *//* $FreeBSD: src/sys/dev/usb/ukbd.c,v 1.8.2.1 1999/05/09 11:02:23 yokota Exp $ *//* * Copyright (c) 1998 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Lennart Augustsson (augustss@carlstedt.se) at * Carlstedt Research & Technology. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the NetBSD * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. *//* * HID spec: http://www.usb.org/developers/data/usbhid10.pdf */#include "ukbd.h"#include "opt_kbd.h"#include <sys/param.h>#include <sys/systm.h>#include <sys/kernel.h>#include <sys/ioccom.h>#include <sys/module.h>#include <sys/bus.h>#include <machine/clock.h>#include <sys/tty.h>#include <sys/file.h>#include <sys/select.h>#include <sys/proc.h>#include <sys/vnode.h>#include <sys/poll.h>#include <dev/usb/usb.h>#include <dev/usb/usbhid.h>#include <dev/usb/usbdi.h>#include <dev/usb/usbdi_util.h>#include <dev/usb/usbdevs.h>#include <dev/usb/usb_quirks.h>#include <dev/usb/hid.h>#include <sys/conf.h>#include <dev/kbd/kbdreg.h>#define UKBD_EMULATE_ATSCANCODE 1#define DRIVER_NAME "ukbd"#define delay(d) DELAY(d)#ifdef UKBD_DEBUG#define DPRINTF(x) if (ukbddebug) logprintf x#define DPRINTFN(n,x) if (ukbddebug>(n)) logprintf xint ukbddebug = 1;#else#define DPRINTF(x)#define DPRINTFN(n,x)#endif#define UPROTO_BOOT_KEYBOARD 1#define NKEYCODE 6struct ukbd_data { u_int8_t modifiers;#define MOD_CONTROL_L 0x01#define MOD_CONTROL_R 0x10#define MOD_SHIFT_L 0x02#define MOD_SHIFT_R 0x20#define MOD_ALT_L 0x04#define MOD_ALT_R 0x40#define MOD_WIN_L 0x08#define MOD_WIN_R 0x80 u_int8_t reserved; u_int8_t keycode[NKEYCODE];};#define MAXKEYS (NMOD+2*NKEYCODE)typedef struct ukbd_softc { bdevice sc_dev; /* base device */ usbd_interface_handle sc_iface; /* interface */ short sc_flags;#define UKBD_ATTACHED (1 << 0) keyboard_t *sc_kbd;#ifdef KBD_INSTALL_CDEV genkbd_softc_t sc_gensc;#endif} ukbd_softc_t;#define UKBDUNIT(dev) (minor(dev))#define UKBD_CHUNK 128 /* chunk size for read */#define UKBD_BSIZE 1020 /* buffer size */typedef void usbd_intr_t(usbd_request_handle, usbd_private_handle, usbd_status);typedef void usbd_disco_t(void *);static usbd_intr_t ukbd_intr;static usbd_disco_t ukbd_disconnect;static int ukbd_remove_kbd(struct ukbd_softc *sc);#ifdef KBD_INSTALL_CDEVstatic d_open_t ukbdopen;static d_close_t ukbdclose;static d_read_t ukbdread;static d_ioctl_t ukbdioctl;static d_poll_t ukbdpoll;static struct cdevsw ukbd_cdevsw = { ukbdopen, ukbdclose, ukbdread, nowrite, ukbdioctl, nostop, nullreset, nodevtotty, ukbdpoll, nommap, NULL, DRIVER_NAME, NULL, -1,};#endif /* KBD_INSTALL_CDEV */USB_DECLARE_DRIVER(ukbd);USB_MATCH(ukbd){ USB_MATCH_START(ukbd, uaa); keyboard_switch_t *sw; void *arg[4]; int unit = device_get_unit(device); sw = kbd_get_switch(DRIVER_NAME); if (sw == NULL) return (UMATCH_NONE); arg[0] = (void *)uaa; arg[1] = (void *)ukbd_intr; arg[2] = (void *)ukbd_disconnect; arg[3] = (void *)device; if ((*sw->probe)(unit, (void *)arg, 0)) return (UMATCH_NONE); return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO);}USB_ATTACH(ukbd){ USB_ATTACH_START(ukbd, sc, uaa); usbd_interface_handle iface = uaa->iface; usb_interface_descriptor_t *id; char devinfo[1024]; keyboard_switch_t *sw; void *arg[4]; int unit = device_get_unit(self); sw = kbd_get_switch(DRIVER_NAME); if (sw == NULL) USB_ATTACH_ERROR_RETURN; sc->sc_iface = iface; id = usbd_get_interface_descriptor(iface); usbd_devinfo(uaa->device, 0, devinfo); USB_ATTACH_SETUP; printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev), devinfo, id->bInterfaceClass, id->bInterfaceSubClass); arg[0] = (void *)uaa; arg[1] = (void *)ukbd_intr; arg[2] = (void *)ukbd_disconnect; arg[3] = (void *)self; sc->sc_kbd = NULL; if ((*sw->probe)(unit, (void *)arg, 0)) USB_ATTACH_ERROR_RETURN; if ((*sw->init)(unit, &sc->sc_kbd, (void *)arg, 0)) USB_ATTACH_ERROR_RETURN; (*sw->enable)(sc->sc_kbd);#ifdef KBD_INSTALL_CDEV if (kbd_attach(makedev(0, unit), sc->sc_kbd, &ukbd_cdevsw)) USB_ATTACH_ERROR_RETURN;#endif if (bootverbose) (*sw->diag)(sc->sc_kbd, bootverbose); sc->sc_flags |= UKBD_ATTACHED; USB_ATTACH_SUCCESS_RETURN;}intukbd_detach(device_t self){ struct ukbd_softc *sc = device_get_softc(self); const char *devinfo = device_get_desc(self); int error; error = ukbd_remove_kbd(sc); if (error) return error; sc->sc_flags &= ~UKBD_ATTACHED; DPRINTF(("%s: disconnected\n", USBDEVNAME(self))); if (devinfo) { device_set_desc(self, NULL); free((void *)devinfo, M_USB); } return (0);}static voidukbd_disconnect(void *p){ device_t self = (device_t)p; struct ukbd_softc *sc = device_get_softc(self); DPRINTF(("ukbd_disconnect: sc:%p\n", sc)); (*kbdsw[sc->sc_kbd->kb_index]->disable)(sc->sc_kbd);}static intukbd_remove_kbd(struct ukbd_softc *sc){ int error;#ifdef KBD_INSTALL_CDEV error = kbd_detach(makedev(0, sc->sc_kbd->kb_unit), sc->sc_kbd, &ukbd_cdevsw); if (error) return error;#endif error = (*kbdsw[sc->sc_kbd->kb_index]->term)(sc->sc_kbd); if (error) return error; sc->sc_kbd = NULL; return 0;}/* cdev driver functions */#ifdef KBD_INSTALL_CDEVstatic intukbdopen(dev_t dev, int flag, int mode, struct proc *p){ USB_GET_SC_OPEN(ukbd, UKBDUNIT(dev), sc); /* FIXME: set the initial input mode (K_XLATE?) and lock state? */ return genkbdopen(&sc->sc_gensc, sc->sc_kbd, flag, mode, p);}static intukbdclose(dev_t dev, int flag, int mode, struct proc *p){ USB_GET_SC(ukbd, UKBDUNIT(dev),sc); return genkbdclose(&sc->sc_gensc, sc->sc_kbd, flag, mode, p);}static intukbdread(dev_t dev, struct uio *uio, int flag){ USB_GET_SC(ukbd, UKBDUNIT(dev),sc); return genkbdread(&sc->sc_gensc, sc->sc_kbd, uio, flag);}static intukbdioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p){ USB_GET_SC(ukbd, UKBDUNIT(dev),sc); return genkbdioctl(&sc->sc_gensc, sc->sc_kbd, cmd, arg, flag, p);}static intukbdpoll(dev_t dev, int event, struct proc *p){ USB_GET_SC(ukbd, UKBDUNIT(dev),sc); return genkbdpoll(&sc->sc_gensc, sc->sc_kbd, event, p);}#endif /* KBD_INSTALL_CDEV */voidukbd_intr(usbd_request_handle reqh, usbd_private_handle addr, usbd_status status){ keyboard_t *kbd = (keyboard_t *)addr; (*kbdsw[kbd->kb_index]->intr)(kbd, (void *)status);}DRIVER_MODULE(ukbd, uhub, ukbd_driver, ukbd_devclass, usbd_driver_load, 0);#include <machine/limits.h>#include <machine/console.h>#include <machine/clock.h>#define UKBD_DEFAULT 0#define KEY_ERROR 0x01#define KEY_PRESS 0#define KEY_RELEASE 0x400#define KEY_INDEX(c) ((c) & ~KEY_RELEASE)#define SCAN_PRESS 0#define SCAN_RELEASE 0x80#define SCAN_PREFIX_E0 0x100#define SCAN_PREFIX_E1 0x200#define SCAN_PREFIX_CTL 0x400#define SCAN_PREFIX_SHIFT 0x800#define SCAN_PREFIX (SCAN_PREFIX_E0 | SCAN_PREFIX_E1 | SCAN_PREFIX_CTL \ | SCAN_PREFIX_SHIFT)#define SCAN_CHAR(c) ((c) & 0x7f)#define NMOD 8static struct { int mask, key;} ukbd_mods[NMOD] = { { MOD_CONTROL_L, 0xe0 }, { MOD_CONTROL_R, 0xe4 }, { MOD_SHIFT_L, 0xe1 }, { MOD_SHIFT_R, 0xe5 }, { MOD_ALT_L, 0xe2 }, { MOD_ALT_R, 0xe6 }, { MOD_WIN_L, 0xe3 }, { MOD_WIN_R, 0xe7 },};#define NN 0 /* no translation *//* * Translate USB keycodes to AT keyboard scancodes. *//* * FIXME: Mac USB keyboard generates: * 0x53: keypad NumLock/Clear * 0x66: Power * 0x67: keypad = * 0x68: F13 * 0x69: F14 * 0x6a: F15 */static u_int8_t ukbd_trtab[256] = { 0, 0, 0, 0, 30, 48, 46, 32, /* 00 - 07 */ 18, 33, 34, 35, 23, 36, 37, 38, /* 08 - 0F */ 50, 49, 24, 25, 16, 19, 31, 20, /* 10 - 17 */ 22, 47, 17, 45, 21, 44, 2, 3, /* 18 - 1F */ 4, 5, 6, 7, 8, 9, 10, 11, /* 20 - 27 */ 28, 1, 14, 15, 57, 12, 13, 26, /* 28 - 2F */ 27, 43, 43, 39, 40, 41, 51, 52, /* 30 - 37 */ 53, 58, 59, 60, 61, 62, 63, 64, /* 38 - 3F */ 65, 66, 67, 68, 87, 88, 92, 70, /* 40 - 47 */ 104, 102, 94, 96, 103, 99, 101, 98, /* 48 - 4F */ 97, 100, 95, 69, 91, 55, 74, 78, /* 50 - 57 */ 89, 79, 80, 81, 75, 76, 77, 71, /* 58 - 5F */ 72, 73, 82, 83, 86, 107, NN, NN, /* 60 - 67 */ NN, NN, NN, NN, NN, NN, NN, NN, /* 68 - 6F */ NN, NN, NN, NN, NN, NN, NN, NN, /* 70 - 77 */ NN, NN, NN, NN, NN, NN, NN, NN, /* 78 - 7F */ NN, NN, NN, NN, NN, NN, NN, 115, /* 80 - 87 */ 112, 125, 121, 123, NN, NN, NN, NN, /* 88 - 8F */ NN, NN, NN, NN, NN, NN, NN, NN, /* 90 - 97 */ NN, NN, NN, NN, NN, NN, NN, NN, /* 98 - 9F */ NN, NN, NN, NN, NN, NN, NN, NN, /* A0 - A7 */ NN, NN, NN, NN, NN, NN, NN, NN, /* A8 - AF */ NN, NN, NN, NN, NN, NN, NN, NN, /* B0 - B7 */ NN, NN, NN, NN, NN, NN, NN, NN, /* B8 - BF */ NN, NN, NN, NN, NN, NN, NN, NN, /* C0 - C7 */ NN, NN, NN, NN, NN, NN, NN, NN, /* C8 - CF */ NN, NN, NN, NN, NN, NN, NN, NN, /* D0 - D7 */ NN, NN, NN, NN, NN, NN, NN, NN, /* D8 - DF */ 29, 42, 56, 105, 90, 54, 93, 106, /* E0 - E7 */ NN, NN, NN, NN, NN, NN, NN, NN, /* E8 - EF */ NN, NN, NN, NN, NN, NN, NN, NN, /* F0 - F7 */ NN, NN, NN, NN, NN, NN, NN, NN, /* F8 - FF */};typedef struct ukbd_state { usbd_interface_handle ks_iface; /* interface */ usbd_pipe_handle ks_intrpipe; /* interrupt pipe */ struct usb_attach_arg *ks_uaa; int ks_ep_addr; struct ukbd_data ks_ndata; struct ukbd_data ks_odata; u_long ks_ntime[NKEYCODE]; u_long ks_otime[NKEYCODE];#define INPUTBUFSIZE (NMOD + 2*NKEYCODE) u_int ks_input[INPUTBUFSIZE]; /* input buffer */ int ks_inputs; int ks_inputhead; int ks_inputtail; int ks_ifstate;#define INTRENABLED (1 << 0)#define DISCONNECTED (1 << 1) struct callout_handle ks_timeout_handle; int ks_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */ int ks_flags; /* flags */#define COMPOSE (1 << 0) int ks_polling; int ks_state; /* shift/lock key state */ int ks_accents; /* accent key index (> 0) */ u_int ks_composed_char; /* composed char code (> 0) */#ifdef UKBD_EMULATE_ATSCANCODE u_int ks_buffered_char[2];#endif} ukbd_state_t;/* keyboard driver declaration */static int ukbd_configure(int flags);static kbd_probe_t ukbd_probe;static kbd_init_t ukbd_init;static kbd_term_t ukbd_term;static kbd_intr_t ukbd_interrupt;static kbd_test_if_t ukbd_test_if;static kbd_enable_t ukbd_enable;static kbd_disable_t ukbd_disable;static kbd_read_t ukbd_read;static kbd_check_t ukbd_check;static kbd_read_char_t ukbd_read_char;static kbd_check_char_t ukbd_check_char;static kbd_ioctl_t ukbd_ioctl;static kbd_lock_t ukbd_lock;static kbd_clear_state_t ukbd_clear_state;static kbd_get_state_t ukbd_get_state;static kbd_set_state_t ukbd_set_state;static kbd_poll_mode_t ukbd_poll;keyboard_switch_t ukbdsw = { ukbd_probe, ukbd_init, ukbd_term, ukbd_interrupt, ukbd_test_if, ukbd_enable, ukbd_disable, ukbd_read, ukbd_check, ukbd_read_char, ukbd_check_char, ukbd_ioctl, ukbd_lock, ukbd_clear_state, ukbd_get_state, ukbd_set_state, genkbd_get_fkeystr, ukbd_poll, genkbd_diag,};KEYBOARD_DRIVER(ukbd, ukbdsw, ukbd_configure);/* local functions */static int ukbd_enable_intr(keyboard_t *kbd, int on, usbd_intr_t *func);static timeout_t ukbd_timeout;static int ukbd_getc(ukbd_state_t *state);static int probe_keyboard(struct usb_attach_arg *uaa, int flags);static int init_keyboard(ukbd_state_t *state, int *type, int flags);static void set_leds(ukbd_state_t *state, int leds);static int set_typematic(keyboard_t *kbd, int code);#ifdef UKBD_EMULATE_ATSCANCODEstatic int keycode2scancode(int keycode, int shift, int up);#endif/* local variables *//* the initial key map, accent map and fkey strings */#ifdef UKBD_DFLT_KEYMAP#define KBD_DFLT_KEYMAP#include "ukbdmap.h"#endif#include <dev/kbd/kbdtables.h>/* structures for the default keyboard */static keyboard_t default_kbd;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?