📄 usbkeyboardlib.c
字号:
};
LOCAL UINT16 extendedAltFunctionKeyCodes [] =
{
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x8b, 0x8c
};
LOCAL UINT16 extendedKeypadKeyCodes [] =
{
0x4F, 0x50, 0x51, 0x4B, 0x00, 0x4D, 0x47, 0x48,
0x49, 0x52, 0x53
};
/* globals */
unsigned int TYPEMATIC_DELAY = 500; /* 500 msec delay */
unsigned int TYPEMATIC_PERIOD = 66; /* 66 msec = approx 15 char/sec */
/***************************************************************************
*
* cvtScanCodeToKeyCode - converts scan code to key code if possible
*
* <scanCode> is the scan code to be interpreted and <modifiers> is the
* current state of the keyboard modifies (e.g., SHIFT).
*
* RETURNS: ASCII code if mapping exists, CAPLOCK, SCRLOCK, NUMLOCK, or
* NOTKEY if no mapping.
*
* ERRNO: None
*
*\NOMANUAL
*/
LOCAL UINT16 cvtScanCodeToKeyCode
(
pUSB_KBD_SIO_CHAN pSioChan,
UINT16 scanCode,
UINT16 modifiers
)
{
/* Translate keypad keys. */
if( ISKEYPADSCANCODE(scanCode) )
{
if( !!(modifiers & MOD_KEY_SHIFT) ^ !!(pSioChan->numLock) )
return( scanCodes [scanCode] );
if( ISKEYPADEXTSCANCODE(scanCode) )
{
/* If the table contains 0 (like entry for keypad '5')
* return NOTKEY.
*/
if(extendedKeypadKeyCodes[scanCode-0x59] == 0)
return(NOTKEY);
return(0xFF00 | extendedKeypadKeyCodes[scanCode-0x59]);
}
return( scanCodes [scanCode] );
}
/* Translate extended keys. */
if( ISALPHASCANCODE(scanCode) && (modifiers & MOD_KEY_ALT) )
return(0xFF00 | extendedAlphaKeyCodes[scanCode-0x04]);
if( ISOTHEREXTENDEDSCANCODE(scanCode) )
return(0xFF00 | extendedOtherKeyCodes[scanCode-0x49]);
if( ISFUNCTIONSCANCODE(scanCode) && (modifiers & MOD_KEY_ALT) )
return(0xFF00 | extendedAltFunctionKeyCodes[scanCode-0x3A]);
if( ISFUNCTIONSCANCODE(scanCode))
return(0xFF00 | extendedFunctionKeyCodes[scanCode-0x3A]);
/* Translate the scan code into a preliminary ASCII code */
if (scanCode < SCAN_CODE_TBL_LEN)
{
/* Translate alpha keys */
if( ISALPHASCANCODE(scanCode) )
{
if( modifiers & MOD_KEY_CTRL )
return( scanCodesShift [scanCode] - CTRL_CASE_OFFSET);
if( !!(modifiers & MOD_KEY_SHIFT) ^ !!(pSioChan->capsLock) )
return( scanCodesShift [scanCode] );
else
return( scanCodes [scanCode] );
}
/* Translate non-alpha keys */
if ((modifiers & (MOD_KEY_SHIFT | MOD_KEY_CTRL)) != 0)
return( scanCodesShift [scanCode] );
else
return( scanCodes [scanCode] );
}
return(NOTKEY);
}
/***************************************************************************
*
* isKeyPresent - determines if a key is present in an array of keys
*
* This function determines whether the <key> is present in the array <pKeyArray>
*
* RETURNS: TRUE if <key> is present in the <keyArray>, else returns FALSE
*
* ERRNO: none
*
*\NOMANUAL
*/
LOCAL BOOL isKeyPresent
(
pUINT16 pKeyArray,
UINT16 key
)
{
UINT16 i;
for (i = 0; i < BOOT_RPT_KEYCOUNT; i++)
if (key == pKeyArray [i])
return TRUE;
return FALSE;
}
/***************************************************************************
*
* setLedReport - Issues a SET_REPORT to change a keyboard's LEDs
*
* This function isses a <SET_REPORT> request to change keyboards LED
*
* RETURNS: N/A
*
* ERRNO: none
*
*\NOMANUAL
*/
LOCAL VOID setLedReport
(
pUSB_KBD_SIO_CHAN pSioChan,
UINT8 ledReport
)
{
UINT8 * pLedReport = OSS_CALLOC (sizeof (UINT8));
if (pLedReport == NULL)
return;
*pLedReport = ledReport;
usbHidReportSet (usbdHandle,
pSioChan->nodeId,
pSioChan->interface,
USB_HID_RPT_TYPE_OUTPUT,
0,
pLedReport,
sizeof (ledReport));
OSS_FREE (pLedReport);
}
/***************************************************************************
*
* changeKeyState - changes keyboard state
*
* <key> is CAPLOCK, SCRLOCK, or NUMLOCK. If <key> is not already
* active, then, toggle the current keyboard state for the corresponding item.
*
* RETURNS: N/A
*
* ERRNO: none
*
*\NOMANUAL
*/
LOCAL VOID changeKbdState
(
pUSB_KBD_SIO_CHAN pSioChan,
UINT16 scanCode, /* not used */
pBOOL pKeyState
)
{
UINT8 ledReport;
/* The scancode is newly active, toggle the corresponding keyboard state. */
*pKeyState = !(*pKeyState);
/* Update the keyboard LEDs */
ledReport = (pSioChan->capsLock) ? RPT_LED_CAPS_LOCK : 0;
ledReport |= (pSioChan->scrLock) ? RPT_LED_SCROLL_LOCK : 0;
ledReport |= (pSioChan->numLock) ? RPT_LED_NUM_LOCK : 0;
setLedReport (pSioChan, ledReport);
}
/***************************************************************************
*
* interpScanCode - interprets keyboard scan code
*
* Interprets the <scanCode> according to the <modifiers>. This function
* handles any special requirements, such as turning an LED ON or OFF in
* response to a keypress.
*
* RETURNS: N/A.
*
* ERRNO: none
*
*\NOMANUAL
*/
LOCAL void interpScanCode
(
pUSB_KBD_SIO_CHAN pSioChan,
UINT16 scanCode,
UINT16 modifiers
)
{
/* If the key is already active, ignore it. */
if (isKeyPresent (pSioChan->activeScanCodes, scanCode))
return;
/* Determine if special handling is required for the key */
switch (scanCode)
{
case CAPLOCK: /* key is CAPLOCK */
case CAPLOCK_LOCKING: /* key is CAPLOCK */
changeKbdState (pSioChan, scanCode, &pSioChan->capsLock);
break;
case SCRLOCK: /* key is SCRLOCK */
case SCRLOCK_LOCKING: /* key is SCRLOCK */
changeKbdState (pSioChan, scanCode, &pSioChan->scrLock);
break;
case NUMLOCK: /* key is NUMLOCK */
case NUMLOCK_LOCKING: /* key is NUMLOCK */
changeKbdState (pSioChan, scanCode, &pSioChan->numLock);
break;
case NOTKEY: /* no valid scan code mapping */
default: /* an ASCII character */
break;
}
}
/***************************************************************************
*
* putInChar - puts a character into channel's input queue
*
* This function puts character <putChar> in the queue
*
* RETURNS: N/A
*
* ERRNO: none
*
*\NOMANUAL
*/
LOCAL VOID putInChar
(
pUSB_KBD_SIO_CHAN pSioChan,
char putChar
)
{
if (pSioChan->inQueueCount < KBD_Q_DEPTH)
{
pSioChan->inQueue [pSioChan->inQueueIn] = putChar;
if (++pSioChan->inQueueIn == KBD_Q_DEPTH)
pSioChan->inQueueIn = 0;
pSioChan->inQueueCount++;
}
}
/***************************************************************************
*
* nextInChar - returns next character from input queue
*
* Returns the next character from the channel's input queue and updates
* the queue pointers. The caller must ensure that at least one character
* is in the queue prior to calling this function.
*
* RETURNS: next char in queue
*
* ERRNO: none
*
*\NOMANUAL
*/
LOCAL char nextInChar
(
pUSB_KBD_SIO_CHAN pSioChan
)
{
char inChar = pSioChan->inQueue [pSioChan->inQueueOut];
if (++pSioChan->inQueueOut == KBD_Q_DEPTH)
pSioChan->inQueueOut = 0;
pSioChan->inQueueCount--;
return inChar;
}
/***************************************************************************
*
* updateTypematic - generates typematic characters for channel if appropriate
*
* This function generates typematic characters for channel if appropriate
*
* RETURNS: N/A
*
* ERRNO: none
*
*\NOMANUAL
*/
LOCAL VOID updateTypematic
(
pUSB_KBD_SIO_CHAN pSioChan
)
{
UINT32 diffTime;
UINT32 repeatCount;
/* If the given channel is active and a typematic character is
* indicated, then update the typematic state.
*/
if (pSioChan->connected && pSioChan->typematicChar != 0)
{
diffTime = OSS_TIME () - pSioChan->typematicTime;
/* If the typematic delay has passed, then it is time to start
* injecting characters into the queue.
*/
if (diffTime >= TYPEMATIC_DELAY)
{
diffTime -= TYPEMATIC_DELAY;
repeatCount = diffTime / TYPEMATIC_PERIOD + 1;
/* Inject characters into the queue. If the queue is
* full, putInChar() dumps the character, but we increment
* the typematicCount anyway. This keeps the queue from
* getting too far ahead of the user.
*/
while (repeatCount > pSioChan->typematicCount)
{
/* determine the mode in which the driver is operating */
if (pSioChan->scanMode == SIO_KYBD_MODE_ASCII)
{
if (ISEXTENDEDKEYCODE(pSioChan->typematicChar))
{
if(pSioChan->inQueueCount < KBD_Q_DEPTH-1)
{
putInChar (pSioChan, (char) 0);
putInChar (pSioChan,
(char) pSioChan->typematicChar & 0xFF);
}
}
else
{
putInChar (pSioChan, pSioChan->typematicChar);
}
}
else
{
/*
* in RAW Mode put the modifier, scancode and trailing byte
* into the queue
* in the typematicChar variable the 1st byte is for the
* modifier and the second byte is for scan code
*/
putInChar (pSioChan, (pSioChan->typematicChar) >> 0x8);
putInChar (pSioChan, (pSioChan->typematicChar & 0xFF));
putInChar (pSioChan, 0xFF);
}
pSioChan->typematicCount++;
}
/* invoke receive callback */
while (pSioChan->inQueueCount > 0 &&
pSioChan->putRxCharCallback != NULL &&
pSioChan->mode == SIO_MODE_INT)
{
(*pSioChan->putRxCharCallback) (pSioChan->putRxCharArg,
nextInChar (pSioChan));
}
}
}
}
/***************************************************************************
*
* interpKbdReport - interprets USB keyboard BOOT report
*
* Interprets a keyboard boot report and updates channel state as
* appropriate. Operates in one of two modes: ASCII or RAW. In ASCII mode
* it inserts the ascii character into the character buffer and implements
* typematic repeat. In RAW mode it always inserts the modifier byte
* regardless of change, it inserts any keypresses that are currently active
* and it inserts a terminating byte of 0xff into the character buffer.
*
* RETURNS: N/A
*
* ERRNO: none
*
*\NOMANUAL
*/
LOCAL VOID interpKbdReport
(
pUSB_KBD_SIO_CHAN pSioChan
)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -