📄 usbkeyboardlib.c
字号:
{
pHID_KBD_BOOT_REPORT pReport = pSioChan->pBootReport;
UINT16 keyCode;
UINT16 newTypematicChar = 0;
UINT16 activeCount = 0;
UINT16 i = 0;
BOOL validScanCode = FALSE;
/*
* interpret each key position in a keyboard boot report
* (handles CAPS/SCROLL/NUM lock).
*/
for (i = 0; i < BOOT_RPT_KEYCOUNT; i++)
interpScanCode (pSioChan, pReport->scanCodes [i], pReport->modifiers);
/* Raw mode has been set, handle accordingly */
if (pSioChan->scanMode == SIO_KYBD_MODE_RAW)
{
/* The first byte is any modifier keys, CTRL, SHIFT, ALT, GUI */
putInChar (pSioChan, pReport->modifiers);
/* determine if the scan codes are valid */
for (i = 0; i < BOOT_RPT_KEYCOUNT; i++)
{
if (pReport->scanCodes [i] != 0)
validScanCode = TRUE;
}
if (validScanCode)
{
for (i = 0; i < BOOT_RPT_KEYCOUNT; i++)
{
if (pReport->scanCodes [i] > KBD_ERROR_UNDEFINED)
{
/* determine if this key is present in the active scancode */
if (!isKeyPresent (pSioChan->activeScanCodes,
pReport->scanCodes [i]))
/* put the data into scancode into the queue */
putInChar (pSioChan, pReport->scanCodes [i]);
/*
* update the newTypematicChar for auto repeat. The first byte
* will be modifier byte and the second byte is for scan code
*/
newTypematicChar = (pReport->modifiers << 0x8) |
(pReport->scanCodes [i]);
activeCount++;
}
}
}
/* trailing byte */
putInChar (pSioChan, 0xff);
}
/* then pSioChan->scanMode must = SIO_KYBD_MODE_ASCII */
else
{
/* insert newly activated keys into the input queue for the keyboard */
for (i = 0; i < BOOT_RPT_KEYCOUNT; i++)
{
/*
* According to the specification, scan code 0x00 is reserved
* scan code 0x01, 0x02, 0x03 specify the keyboard status and error
* conditions. Therefore interpret the scan code only when it is
* greater than 0x03
*/
if(pReport->scanCodes[i] > KBD_ERROR_UNDEFINED)
{
keyCode = cvtScanCodeToKeyCode (pSioChan,
pReport->scanCodes [i],
pReport->modifiers);
if (!isKeyPresent (pSioChan->activeScanCodes,
pReport->scanCodes [i]))
{
/* If there is room in the input queue, enqueue the key,
* else discard it.
* For extended keyCodes, make sure there is room for two
* chars - the 0 and the ext key.
*/
if( ISEXTENDEDKEYCODE(keyCode) )
{
if(pSioChan->inQueueCount < KBD_Q_DEPTH-1)
{
putInChar (pSioChan, (char) 0);
putInChar (pSioChan, (char) keyCode & 0xFF);
}
}
else
{
if(keyCode)
putInChar (pSioChan, (char) keyCode & 0xFF);
}
}
newTypematicChar = keyCode;
activeCount++;
}
}
}
/*
* If newTypematicChar is 0, then no keys were received in
* this report - so no keys are being held down. If
* newTypematicChar matches the previous typematic char,
* then allow the typematic timer to continue. If
* newTypematicChar is different (but non-zero), then start
* a new timer. In all cases, only one key may be active
* for typematic repeat to be enabled.
*/
if (activeCount == 0)
newTypematicChar = 0;
if (newTypematicChar != pSioChan->typematicChar)
{
pSioChan->typematicChar = newTypematicChar;
if (newTypematicChar != 0)
{
pSioChan->typematicTime = OSS_TIME ();
pSioChan->typematicCount = 0;
}
}
/* call the typematic function */
updateTypematic (pSioChan);
/* invoke receive callback */
while (pSioChan->inQueueCount > 0 &&
pSioChan->putRxCharCallback != NULL &&
pSioChan->mode == SIO_MODE_INT)
{
(*pSioChan->putRxCharCallback) (pSioChan->putRxCharArg,
nextInChar (pSioChan));
}
/*
* the active scan codes array is only to be updated when no error condition
* is encountered. According to specification the scan codes 0x01, 0x02 and
* 0x03 report the condition of the keyboard. Hence return if any of the scan
* codes received matches these scan codes.
*/
for (i = 0; i < BOOT_RPT_KEYCOUNT; i++)
{
if ( pReport->scanCodes[i] == KBD_ERROR_ROLLOVER ||
pReport->scanCodes[i] == KBD_POST_FAIL ||
pReport->scanCodes[i] == KBD_ERROR_UNDEFINED )
{
/*
* error occured at keyboard end
* do not change the active scan codes
*/
return;
}
}
for (i = 0; i < BOOT_RPT_KEYCOUNT; i++)
pSioChan->activeScanCodes [i] = pReport->scanCodes [i];
return;
}
/***************************************************************************
*
* usbKeyboardIoctl - special device control
*
* This routine is largely a no-op for the usbKeyboardLib. The only ioctls
* which are used by this module are the SIO_AVAIL_MODES_GET and SIO_MODE_SET.
*
* RETURNS: OK on success, ENOSYS on unsupported request, EIO on failed request
*
* ERRNO: none
*
*\NOMANUAL
*/
LOCAL int usbKeyboardIoctl
(
SIO_CHAN *pChan, /* device to control */
int request, /* request code */
void *someArg /* some argument */
)
{
pUSB_KBD_SIO_CHAN pSioChan = (pUSB_KBD_SIO_CHAN) pChan;
int arg = (int) someArg;
switch (request)
{
case SIO_BAUD_SET:
/* baud rate has no meaning for USB. We store the desired
* baud rate value and return OK.
*/
pSioChan->baudRate = arg;
return OK;
case SIO_BAUD_GET:
/* Return baud rate to caller */
*((int *) arg) = pSioChan->baudRate;
return OK;
case SIO_MODE_SET:
/* Set driver operating mode: interrupt or polled */
if (arg != SIO_MODE_POLL && arg != SIO_MODE_INT)
return EIO;
pSioChan->mode = arg;
return OK;
case SIO_MODE_GET:
/* Return current driver operating mode for channel */
*((int *) arg) = pSioChan->mode;
return OK;
case SIO_AVAIL_MODES_GET:
/* Return modes supported by driver. */
*((int *) arg) = SIO_MODE_INT | SIO_MODE_POLL;
return OK;
case SIO_OPEN:
/* Channel is always open. */
return OK;
case SIO_KYBD_MODE_SET:
switch (arg)
{
case SIO_KYBD_MODE_RAW:
case SIO_KYBD_MODE_ASCII:
break;
case SIO_KYBD_MODE_UNICODE:
return ENOSYS; /* usb doesn't support unicode */
}
pSioChan->scanMode = arg;
return OK;
case SIO_KYBD_MODE_GET:
*(int *)someArg = pSioChan->scanMode;
return OK;
case SIO_KYBD_LED_SET:
{
UINT8 ledReport;
/* update the channel's information about the LED state */
pSioChan->numLock = (arg & SIO_KYBD_LED_NUM) ? SIO_KYBD_LED_NUM : 0;
pSioChan->capsLock = (arg & SIO_KYBD_LED_CAP) ?
SIO_KYBD_LED_CAP : 0;
pSioChan->scrLock = (arg & SIO_KYBD_LED_SCR) ?
SIO_KYBD_LED_SCR : 0;
/*
* We are relying on the SIO_KYBD_LED_X macros matching the USB
* LED equivalent.
*/
ledReport = arg;
/* set the LED's */
setLedReport (pSioChan, ledReport);
return OK;
}
case SIO_KYBD_LED_GET:
{
int tempArg;
tempArg = (pSioChan->capsLock) ? SIO_KYBD_LED_CAP : 0;
tempArg |= (pSioChan->scrLock) ? SIO_KYBD_LED_SCR : 0;
tempArg |= (pSioChan->numLock) ? SIO_KYBD_LED_NUM : 0;
*(int *) someArg = tempArg;
return OK;
}
case SIO_HW_OPTS_SET: /* optional, not supported */
case SIO_HW_OPTS_GET: /* optional, not supported */
case SIO_HUP: /* hang up is not supported */
default: /* unknown/unsupported command. */
return ENOSYS;
}
}
/***************************************************************************
*
* usbKeyboardTxStartup - start the interrupt transmitter
*
* The USB keyboard SIO driver does not support output to the keyboard.
*
* RETURNS: EIO
*
* ERRNO: none
*
*\NOMANUAL
*/
LOCAL int usbKeyboardTxStartup
(
SIO_CHAN *pChan /* channel to start */
)
{
return EIO;
}
/***************************************************************************
*
* usbKeyboardCallbackInstall - install ISR callbacks to get/put chars
*
* This driver allows interrupt callbacks for transmitting characters
* and receiving characters.
*
* RETURNS: OK on success, or ENOSYS for an unsupported callback type
*
* ERRNO: none
*
*\NOMANUAL
*/
LOCAL int usbKeyboardCallbackInstall
(
SIO_CHAN *pChan, /* channel */
int callbackType, /* type of callback */
STATUS (*callback) (void *tmp, ...), /* callback */
void *callbackArg /* parameter to callback */
)
{
pUSB_KBD_SIO_CHAN pSioChan = (pUSB_KBD_SIO_CHAN) pChan;
switch (callbackType)
{
case SIO_CALLBACK_GET_TX_CHAR:
pSioChan->getTxCharCallback = (callback);
pSioChan->getTxCharArg = callbackArg;
return OK;
case SIO_CALLBACK_PUT_RCV_CHAR:
pSioChan->putRxCharCallback = (callback);
pSioChan->putRxCharArg = callbackArg;
return OK;
default:
return ENOSYS;
}
}
/***************************************************************************
*
* usbKeyboardPollOutput - output a character in polled mode
*
* The USB keyboard SIO driver does not support output to the keyboard.
*
* RETURNS: EIO
*
* ERRNO: none
*
*\NOMANUAL
*/
LOCAL int usbKeyboardPollOutput
(
SIO_CHAN *pChan,
char outChar
)
{
return EIO;
}
/***************************************************************************
*
* usbKeyboardPollInput - poll the device for input
*
* This function polls the keyboard device for input.
*
* RETURNS: OK if a character arrived, EIO on device error, EAGAIN
* if the input buffer if empty, ENOSYS if the device is interrupt-only.
*
* ERRNO: none
*
*\NOMANUAL
*/
LOCAL int usbKeyboardPollInput
(
SIO_CHAN *pChan,
char *thisChar
)
{
pUSB_KBD_SIO_CHAN pSioChan = (pUSB_KBD_SIO_CHAN) pChan;
int status = OK;
/* validate parameters */
if (thisChar == NULL)
return EIO;
OSS_MUTEX_TAKE (kbdMutex, OSS_BLOCK);
/* Check if the input queue is empty. */
if (pSioChan->inQueueCount == 0)
status = EAGAIN;
else
{
/* Return a character from the input queue. */
*thisChar = nextInChar (pSioChan);
}
OSS_MUTEX_RELEASE (kbdMutex);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -