⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbkeyboardlib.c

📁 cpc-1631的BSP包for VxWorks操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
/* usbKeyboardLib.c - USB keyboard class drive with vxWorks SIO interface */

/* Copyright 2000-2006 Wind River Systems, Inc. */

/*
modification history
--------------------
01n,20jan06,ami  Support for auto repeat added in Raw Mode (SPR #88022)
01m,19jan06,ami  Check for Error Scan codes incorporated in Ascii Mode
01l,10jan06,ami  Support for vendor specific class driver added (SPR #113619)
01k,26aug05,ami  Prototype declaration of function pointer in the structure
                 usb_kbd_sio_chan changed
01j,04oct04,mdo  Documentation fixes for apigen
01j,19jan05,ami  commented peice of code cleaned
01i,15oct04,ami  Apigen Changes
01h,18dec03,cfc  Fix compiler warning
01g,08may02,wef  Add ioctl to set keyboard mode to return raw scan codes - 
		 SPR #70988. 
01f,29oct01,wef  Remove automatic buffer creations and repalce with OSS_MALLOC.
01e,18sep01,wef  merge from wrs.tor2_0.usb1_1-f for veloce
01d,03jul01,jsv	 Re-wrote key tracking logic to fix issue with extra chars
                 when shift is released before the desired shifted key.
                 Made typematic setting globals so they can be modified.
                 Fixed typematic task, not calling callback after queueing
                 chars.
                 Added support of extended keycodes.
                 Fixed shifted key operation when CAPSLOCK is on.
01c,22jan01,wef  fix tab stops.
01b,20mar00,rcb  Re-write code to fetch maxPacketSize from endpoint descriptor
	 	 on machines which don't support non-aligned word access.
	 	 Allocate "report" structure separately from SIO_CHAN in order
 		 to avoid cache problems on MIPS platform.
01a,27jul99,rcb  written.
*/

/*
DESCRIPTION

This module implements the USB keyboard class driver for the vxWorks operating
system.  This module presents an interface which is a superset of the vxWorks
SIO (serial IO) driver model.  That is, this driver presents the external APIs
which would be expected of a standard "multi-mode serial (SIO) driver" and
adds certain extensions which are needed to address adequately the requirements
of the hot-plugging USB environment.

USB keyboards are described as part of the USB "human interface device" class
specification and related documents.  This driver concerns itself only with USB
devices which claim to be keyboards as set forth in the USB HID specification
and ignores other types of human interface devices (i.e., mouse).  USB
keyboards can operate according to either a "boot protocol" or to a "report
protocol".  This driver enables keyboards for operation using the boot
protocol.

As the SIO driver model presents a fairly limited, byte-stream oriented view of
a serial device, this driver maps USB keyboard scan codes into appropriate
ASCII codes.  Scan codes and combinations of scan codes which do not map to the
ASCII character set are suppressed.

Unlike most SIO drivers, the number of channels supported by this driver is not
fixed.	Rather, USB keyboards may be added or removed from the system at any
time.  This creates a situation in which the number of channels is dynamic, and
clients of usbKeyboardLib.c need to be made aware of the appearance and 
disappearance of channels.  Therefore, this driver adds an additional set of
functions which allows clients to register for notification upon the insertion
and removal of USB keyboards, and hence the creation and deletion of channels.

This module itself is a client of the Universal Serial Bus Driver (USBD).  All
interaction with the USB buses and devices is handled through the USBD.


INITIALIZATION

As with standard SIO drivers, this driver must be initialized by calling
usbKeyboardDevInit().  usbKeyboardDevInit() in turn initializes its 
connection to the USBD and other internal resources needed for operation.  
Unlike some SIO drivers, there are no usbKeyboardLib.c data structures which need 
to be initialized prior to calling usbKeyboardDevInit().

Prior to calling usbKeyboardDevInit(), the caller must ensure that the USBD
has been properly initialized by calling - at a minimum - usbdInitialize().
It is also the caller's responsibility to ensure that at least one USB HCD
(USB Host Controller Driver) is attached to the USBD - using the USBD function
usbdHcdAttach() - before keyboard operation can begin.	However, it is not 
necessary for usbdHcdAttach() to be called prior to initializating usbKeyboardLib.c.
usbKeyboardLib.c uses the USBD dynamic attach services and is capable of 
recognizing USB keyboard attachment and removal on the fly.  Therefore, it is 
possible for USB HCDs to be attached to or detached from the USBD at run time
- as may be required, for example, in systems supporting hot swapping of
hardware.

usbKeyboardLib.c does not export entry points for transmit, receive, and error
interrupt entry points like traditional SIO drivers.  All "interrupt" driven
behavior is managed by the underlying USBD and USB HCD(s), so there is no
need for a caller (or BSP) to connect interrupts on behalf of usbKeyboardLib.c.
For the same reason, there is no post-interrupt-connect initialization code
and usbKeboardLib.c therefore also omits the "devInit2" entry point.


OTHER FUNCTIONS

usbKeyboardLib.c also supports the SIO ioctl interface.  However, attempts to
set parameters like baud rates and start/stop bits have no meaning in the USB
environment and will be treated as no-ops.  


DATA FLOW

For each USB keyboard connected to the system, usbKeyboardLib.c sets up a
USB pipe to monitor input from the keyboard.  Input, in the form of scan codes,
is translated to ASCII codes and placed in an input queue.  If SIO callbacks
have been installed and usbKeyboardLib.c has been placed in the SIO "interrupt" 
mode of operation, then usbKeyboardLib.c will invoke the "character received"
callback for each character in the queue.  When usbKeyboardLib.c has been placed
in the "polled" mode of operation, callbacks will not be invoked and the 
caller will be responsible for fetching keyboard input using the driver's
pollInput() function.

usbKeyboardLib.c does not support output to the keyboard.  Therefore, calls to
the txStartup() and pollOutput() functions will fail.  The only "output" 
supported is the control of the keyboard LEDs, and this is handled internally
by usbKeyboardLib.c.

The caller needs to be aware that usbKeyboardLib.c is not capable of operating
in a true "polled mode" as the underlying USBD and USB HCD always operate in
an interrupt mode.  


TYPEMATIC REPEAT

USB keyboards do not implement typematic repeat, and it is the responsibility
of the host software to implement this feature.  For this purpose, this module
creates a task called typematicThread() which monitors all open channels and
injects repeated characters into input queues as appropriate.


INCLUDE FILES: sioLib.h, usbKeyboardLib.h
*/


/* includes */

#include "vxWorks.h"
#include "string.h"
#include "sioLib.h"
#include "errno.h"
#include "ctype.h"

#include "usb/usbPlatform.h"
#include "usb/ossLib.h" 	/* operations system srvcs */
#include "usb/usb.h"		/* general USB definitions */
#include "usb/usbListLib.h"	/* linked list functions */
#include "usb/usbdLib.h"	/* USBD interface */
#include "usb/usbLib.h" 	/* USB utility functions */
#include "usb/usbHid.h" 	/* USB HID definitions */
#include "drv/usb/usbKeyboardLib.h" /* our API */


/* defines */

#define KBD_CLIENT_NAME "usbKeyboardLib"    /* our USBD client name */

#define KBD_Q_DEPTH 8	    /* Max characters in keyboard queue */

#define ISEXTENDEDKEYCODE(keyCode)          (keyCode & 0xFF00)
#define ISALPHASCANCODE(scanCode)           ( (scanCode >= 0x04) && (scanCode <= 0x1D) )
#define ISNUMERICSCANCODE(scanCode)         ( (scanCode >= 0x1E) && (scanCode <= 0x27) )
#define ISKEYPADSCANCODE(scanCode)          ( (scanCode >= 0x53) && (scanCode <= 0x63) )
#define ISKEYPADEXTSCANCODE(scanCode)       ( (scanCode >= 0x59) && (scanCode <= 0x63) )
#define ISFUNCTIONSCANCODE(scanCode)        ( (scanCode >= 0x3A) && (scanCode <= 0x45) )
#define ISOTHEREXTENDEDSCANCODE(scanCode)   ( (scanCode >= 0x49) && (scanCode <= 0x52) )
#define ISEXTENDEDSCANCODE(scanCode, modifiers)                                 \
                ( (modifiers & MOD_KEY_ALT) && ISALPHASCANCODE(scanCode) )      \
                || ISFUNCTIONSCANCODE(scanCode)                                 \
                || ISOTHEREXTENDEDSCANCODE(scanCode)

/* If your hardware platform has problems sharing cache lines, then define
 * CACHE_LINE_SIZE below so that critical buffers can be allocated within
 * their own cache lines.
 */

#define CACHE_LINE_SIZE     16


/* typematic definitions */

#define TYPEMATIC_NAME	    "tUsbKbd"


/* typedefs */

/*
 * ATTACH_REQUEST
 */

typedef struct attach_request
    {
    LINK reqLink;	    /* linked list of requests */
    USB_KBD_ATTACH_CALLBACK callback;	/* client callback routine */
    pVOID callbackArg;		/* client callback argument */
    } ATTACH_REQUEST, *pATTACH_REQUEST;


/* USB_KBD_SIO_CHAN is the internal data structure we use to track each USB
 * keyboard.
 */

typedef struct usb_kbd_sio_chan
    {
    SIO_CHAN sioChan;		/* must be first field */

    LINK sioLink;	        /* linked list of keyboard structs */

    UINT16 lockCount;		/* Count of times structure locked */

    USBD_NODE_ID nodeId;	/* keyboard node Id */
    UINT16 configuration;	/* configuration/interface reported as */
    UINT16 interface;		/* a keyboard by this device */

    BOOL connected;	        /* TRUE if keyboard currently connected */

    USBD_PIPE_HANDLE pipeHandle;/* USBD pipe handle for interrupt pipe */
    USB_IRP irp;	        /* IRP to monitor interrupt pipe */
    BOOL irpInUse;	        /* TRUE while IRP is outstanding */
    pHID_KBD_BOOT_REPORT pBootReport;/* Keyboard boot report fetched thru pipe */

    char inQueue [KBD_Q_DEPTH]; /* Circular queue for keyboard input */
    UINT16 inQueueCount;	/* count of characters in input queue */
    UINT16 inQueueIn;		/* next location in queue */
    UINT16 inQueueOut;		/* next character to fetch */

    UINT32 typematicTime;	/* time current typematic period started */
    UINT32 typematicCount;	/* count of keys injected */
    UINT16 typematicChar; 	/* current character to repeat */

    int mode;		        /* SIO_MODE_INT or SIO_MODE_POLL */

    STATUS (*getTxCharCallback) (void *, ...); /* tx callback */
    void *getTxCharArg; 	/* tx callback argument */

    STATUS (*putRxCharCallback) (void *, ...); /* rx callback */
    void *putRxCharArg; 	/* rx callback argument */

    /* Following variables used to emulate certain ioctl functions. */

    int baudRate;	        /* has no meaning in USB */

    /* Following variables maintain keyboard state */

    BOOL capsLock;	        /* TRUE if CAPLOCK in effect */
    BOOL scrLock;	        /* TRUE if SCRLOCK in effect */
    BOOL numLock;	        /* TRUE if NUMLOCK in effect */

    UINT16 activeScanCodes [BOOT_RPT_KEYCOUNT];

    int scanMode;		/* raw or ascii */

    } USB_KBD_SIO_CHAN, *pUSB_KBD_SIO_CHAN;


/* forward static declarations */

LOCAL int usbKeyboardTxStartup (SIO_CHAN * pSioChan);
LOCAL int usbKeyboardCallbackInstall (SIO_CHAN *pSioChan, int callbackType,
    STATUS (*callback)(void *, ...), void *callbackArg);
LOCAL int usbKeyboardPollOutput (SIO_CHAN *pSioChan, char   outChar);
LOCAL int usbKeyboardPollInput (SIO_CHAN *pSioChan, char *thisChar);
LOCAL int usbKeyboardIoctl (SIO_CHAN *pSioChan, int request, void *arg);

LOCAL VOID usbKeyboardIrpCallback (pVOID p);


/* locals */

LOCAL UINT16 initCount = 0;	/* Count of init nesting */

LOCAL MUTEX_HANDLE kbdMutex;    /* mutex used to protect internal structs */

LOCAL LIST_HEAD sioList;	/* linked list of USB_KBD_SIO_CHAN */
LOCAL LIST_HEAD reqList;	/* Attach callback request list */

LOCAL USBD_CLIENT_HANDLE usbdHandle; /* our USBD client handle */

LOCAL THREAD_HANDLE typematicHandle;/* task used to generate typematic repeat */
LOCAL BOOL killTypematic;	/* TRUE when typematic thread should exit */
LOCAL BOOL typematicExit;	/* TRUE when typematic thread exits */


/* Channel function table. */

LOCAL SIO_DRV_FUNCS usbKeyboardSioDrvFuncs =
    {
    usbKeyboardIoctl,
    usbKeyboardTxStartup,
    usbKeyboardCallbackInstall,
    usbKeyboardPollInput,
    usbKeyboardPollOutput
    };


/* ASCI definitions */

#define SHIFT_CASE_OFFSET   ('a' - 'A')
#define CTRL_CASE_OFFSET    64		/* diff between 'A' and CTRL-A */

#define BS	    8		/* backspace, CTRL-H */
#define DEL	    BS		/* delete key */
#define TAB	    9		/* tab, CTRL-I */
#define CR	    0xa/*13*/		/* carriage return, CTRL-M */
#define ESC	    27		/* escape */


/* Scan code lookup table and related constants. */

#define ASCII_MIN	        0x0000
#define ASCII_MAX	        0x007f

#define CAPLOCK 	        0x39
#define CAPLOCK_LOCKING     	0x82
#define NUMLOCK 	        0x53
#define NUMLOCK_LOCKING 	0x83
#define SCRLOCK 	        0x47
#define SCRLOCK_LOCKING 	0x84

#define NOTKEY		        0

#define isAscii(a)  ((a) <= ASCII_MAX)

/*
 * according to specification the scancodes 0x01, 0x02 and 0x03 are
 * for keyboard status and keyboard error
 */
#define KBD_ERROR_ROLLOVER          0x01    /* keyboard roll over error */
#define KBD_POST_FAIL               0x02    /* keyboard post failed */
#define KBD_ERROR_UNDEFINED         0x03    /* keyboard error undefined */


/* NOTE: The following scan code tables are populated only so far as is useful
 * in order to map the ASCI character set.  Also, the following two tables must
 * remain exactly the same length.
 */

LOCAL UINT16 scanCodes [] =
    {
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, 'a',    'b',    'c',    'd',    /* 0 - 7 */
    'e',    'f',    'g',    'h',    'i',    'j',    'k',    'l',    /* 8 - 15 */
    'm',    'n',    'o',    'p',    'q',    'r',    's',    't',    /* 16 - 23 */
    'u',    'v',    'w',    'x',    'y',    'z',    '1',    '2',    /* 24 - 31 */
    '3',    '4',    '5',    '6',    '7',    '8',    '9',    '0',    /* 32 - 39 */
    CR,     ESC,    DEL,    TAB,    ' ',    '-',    '=',    '[',    /* 40 - 47 */
    ']',    '\\',   '#',    ';',    '\'',   '`',    ',',    '.',    /* 48 - 55 */
    '/',    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 56 - 63 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 64 - 71 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, DEL,    NOTKEY, NOTKEY, NOTKEY, /* 72 - 79 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, '/',    '*',    '-',    '+',    /* 80 - 87 */
    CR,     '1',    '2',    '3',    '4',    '5',    '6',    '7',    /* 88 - 95 */
    '8',    '9',    '0',    '.',    '|',    NOTKEY, NOTKEY, '=',    /* 96 - 103 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 104 - 111 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 112 - 119 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 120 - 127 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, ',',    '=', 	NOTKEY, /* 128 - 135 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 136 - 143 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 144 - 151 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 152 - 159 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 160 - 167 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 168 - 175 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 176 - 183 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 184 - 191 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 192 - 199 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 200 - 207 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 208 - 215 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 216 - 223 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 224 - 231 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 232 - 239 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 240 - 247 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY  /* 248 - 255 */
    };


LOCAL UINT16 scanCodesShift [] =
    {
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, 'A',    'B',    'C',    'D',    /* 0 - 7 */
    'E',    'F',    'G',    'H',    'I',    'J',    'K',    'L',    /* 8 - 15 */
    'M',    'N',    'O',    'P',    'Q',    'R',    'S',    'T',    /* 16 - 23 */
    'U',    'V',    'W',    'X',    'Y',    'Z',    '!',    '@',    /* 24 - 31 */
    '#',    '$',    '%',    '^',    '&',    '*',    '(',    ')',    /* 32 - 39 */
    CR,     ESC,    DEL,    TAB,    ' ',    '_',    '+',    '{',    /* 40 - 47 */
    '}',    '|',    '~',    ':',    '"',    '~',    '<',    '>',    /* 48 - 55 */
    '?',    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 56 - 63 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 64 - 71 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, DEL,    NOTKEY, NOTKEY, NOTKEY, /* 72 - 79 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, '/',    '*',    '-',    '+',    /* 80 - 87 */
    CR,     '1',    '2',    '3',    '4',    '5',    '6',    '7',    /* 88 - 95 */
    '8',    '9',    '0',    '.',    '|',    NOTKEY, NOTKEY, '=',    /* 96 - 103 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 104 - 111 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 112 - 119 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 120 - 127 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, ',',    '=', 	NOTKEY, /* 128 - 135 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 136 - 143 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 144 - 151 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 152 - 159 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 160 - 167 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 168 - 175 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 176 - 183 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 184 - 191 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 192 - 199 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 200 - 207 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 208 - 215 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 216 - 223 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 224 - 231 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 232 - 239 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, /* 240 - 247 */
    NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY, NOTKEY  /* 248 - 255 */
    };


#define SCAN_CODE_TBL_LEN   (sizeof (scanCodes) / sizeof (UINT16))

/*  IBM Extended keycodes.
    Char.     Hex Pair       Char.    Hex Pair
    ALT-A     (0x00,0x1e)    ALT-B    (0x00,0x30)
    ALT-C     (0x00,0x2e)    ALT-D    (0x00,0x20)
    ALT-E     (0x00,0x12)    ALT-F    (0x00,0x21)
    ALT-G     (0x00,0x22)    ALT-H    (0x00,0x23)
    ALT-I     (0x00,0x17)    ALT-J    (0x00,0x24)
    ALT-K     (0x00,0x25)    ALT-L    (0x00,0x26)
    ALT-M     (0x00,0x32)    ALT-N    (0x00,0x31)
    ALT-O     (0x00,0x18)    ALT-P    (0x00,0x19)
    ALT-Q     (0x00,0x10)    ALT-R    (0x00,0x13)
    ALT-S     (0x00,0x1a)    ALT-T    (0x00,0x14)
    ALT-U     (0x00,0x16)    ALT-V    (0x00,0x2f)
    ALT-W     (0x00,0x11)    ALT-X    (0x00,0x2d)
    ALT-Y     (0x00,0x15)    ALT-Z    (0x00,0x2c)
    PgUp      (0x00,0x49)    PgDn     (0x00,0x51)
    Home      (0x00,0x47)    End      (0x00,0x4f)
    UpArrw    (0x00,0x48)    DnArrw   (0x00,0x50)
    LftArrw   (0x00,0x4b)    RtArrw   (0x00,0x4d)
    F1        (0x00,0x3b)    F2       (0x00,0x3c)
    F3        (0x00,0x3d)    F4       (0x00,0x3e)
    F5        (0x00,0x3f)    F6       (0x00,0x40)
    F7        (0x00,0x41)    F8       (0x00,0x42)
    F9        (0x00,0x43)    F10      (0x00,0x44)
    F11       (0x00,0x85)    F12      (0x00,0x86)
    ALT-F1    (0x00,0x68)    ALT-F2   (0x00,0x69)
    ALT-F3    (0x00,0x6a)    ALT-F4   (0x00,0x6b)
    ALT-F5    (0x00,0x6c)    ALT-F6   (0x00,0x6d)
    ALT-F7    (0x00,0x6e)    ALT-F8   (0x00,0x6f)
    ALT-F9    (0x00,0x70)    ALT-F10  (0x00,0x71)
    ALT-F11   (0x00,0x8b)    ALT-F12  (0x00,0x8c)
*/

LOCAL UINT16 extendedAlphaKeyCodes [] =
    {
        0x1e, 0x30, 0x2e, 0x20, 0x12, 0x21, 0x22, 0x23,
        0x17, 0x24, 0x25, 0x26, 0x32, 0x31, 0x18, 0x19,
        0x10, 0x13, 0x1a, 0x14, 0x16, 0x2f, 0x11, 0x2d,
        0x15, 0x2c
    };

LOCAL UINT16 extendedOtherKeyCodes [] =
    {
        0x52, 0x47, 0x49, 0x53, 0x4f, 0x51, 0x4d ,0x4b, 0x50,
        0x48,
    };

LOCAL UINT16 extendedFunctionKeyCodes [] =
    {
        0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42,
        0x43, 0x44, 0x85, 0x86

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -