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 + -
显示快捷键?