📄 usbkeyboardlib.c
字号:
/* Try to allocate space for a new keyboard struct */
if ((pSioChan = OSS_CALLOC (sizeof (*pSioChan))) == NULL)
return NULL;
if ((pSioChan->pBootReport = OSS_CALLOC (sizeof (*pSioChan->pBootReport)))
== NULL)
{
OSS_FREE (pSioChan);
return NULL;
}
pSioChan->sioChan.pDrvFuncs = &usbKeyboardSioDrvFuncs;
pSioChan->nodeId = nodeId;
pSioChan->connected = TRUE;
pSioChan->mode = SIO_MODE_POLL;
pSioChan->scanMode = SIO_KYBD_MODE_ASCII;
pSioChan->configuration = configuration;
pSioChan->interface = interface;
for (i = 0; i < BOOT_RPT_KEYCOUNT; i++)
pSioChan->activeScanCodes [i] = NOTKEY;
/* Try to configure the keyboard. */
if (!configureSioChan (pSioChan))
{
destroySioChan (pSioChan);
return NULL;
}
/* Link the newly created structure. */
usbListLinkProt (&sioList, pSioChan, &pSioChan->sioLink, LINK_TAIL,kbdMutex);
return pSioChan;
}
/***************************************************************************
*
* findSioChan - Searches for a USB_KBD_SIO_CHAN for indicated node ID
*
* Searches for a USB_KBD_SIO_CHAN for indicated <nodeId>.
*
* RETURNS: pointer to matching USB_KBD_SIO_CHAN or NULL if not found
*
* ERRNO: none
*
*\NOMANUAL
*/
LOCAL pUSB_KBD_SIO_CHAN findSioChan
(
USBD_NODE_ID nodeId
)
{
pUSB_KBD_SIO_CHAN pSioChan = usbListFirst (&sioList);
while (pSioChan != NULL)
{
if (pSioChan->nodeId == nodeId)
break;
pSioChan = usbListNext (&pSioChan->sioLink);
}
return pSioChan;
}
/***************************************************************************
*
* notifyAttach - Notifies registered callers of attachment/removal
*
* This function notifies of the device attachment or removal to the
* registered clients
*
* RETURNS: N/A
*
* ERRNO: none
*
*\NOMANUAL
*/
LOCAL VOID notifyAttach
(
pUSB_KBD_SIO_CHAN pSioChan,
UINT16 attachCode
)
{
pATTACH_REQUEST pRequest = usbListFirst (&reqList);
while (pRequest != NULL)
{
(*pRequest->callback) (pRequest->callbackArg,
(SIO_CHAN *) pSioChan,
attachCode);
pRequest = usbListNext (&pRequest->reqLink);
}
}
/***************************************************************************
*
* usbKeyboardAttachCallback - called by USBD when keyboard attached/removed
*
* The USBD will invoke this callback when a USB keyboard is attached to or
* removed from the system. <nodeId> is the USBD_NODE_ID of the node being
* attached or removed. <attachAction> is USBD_DYNA_ATTACH or USBD_DYNA_REMOVE.
* Keyboards generally report their class information at the interface level,
* so <configuration> and <interface> will indicate the configuration/interface
* that reports itself as a keyboard. Finally, <deviceClass>, <deviceSubClass>,
* and <deviceProtocol> will identify a HID/BOOT/KEYBOARD device.
*
* NOTE: The USBD will invoke this function once for each configuration/
* interface which reports itself as a keyboard. So, it is possible that
* a single device insertion/removal may trigger multiple callbacks. We
* ignore all callbacks except the first for a given device.
*
* RETURNS: N/A
*
* ERRNO: none
*
*\NOMANUAL
*/
LOCAL VOID usbKeyboardAttachCallback
(
USBD_NODE_ID nodeId,
UINT16 attachAction,
UINT16 configuration,
UINT16 interface,
UINT16 deviceClass,
UINT16 deviceSubClass,
UINT16 deviceProtocol
)
{
pUSB_KBD_SIO_CHAN pSioChan;
OSS_MUTEX_TAKE (kbdMutex, OSS_BLOCK);
/* Depending on the attach code, add a new keyboard or disabled one
* that's already been created.
*/
switch (attachAction)
{
case USBD_DYNA_ATTACH:
/* A new device is being attached. Check if we already
* have a structure for this device.
*/
if (findSioChan (nodeId) != NULL)
break;
/* Create a new structure to manage this device. If there's
* an error, there's nothing we can do about it, so skip the
* device and return immediately.
*/
if ((pSioChan = createSioChan (nodeId, configuration, interface)) == NULL)
break;
/* Notify registered callers that a new keyboard has been
* added and a new channel created.
*/
notifyAttach (pSioChan, USB_KBD_ATTACH);
break;
case USBD_DYNA_REMOVE:
/* A device is being detached. Check if we have any
* structures to manage this device.
*/
if ((pSioChan = findSioChan (nodeId)) == NULL)
break;
/* The device has been disconnected. */
pSioChan->connected = FALSE;
/* Notify registered callers that the keyboard has been
* removed and the channel disabled.
*
* NOTE: We temporarily increment the channel's lock count
* to prevent usbKeyboardSioChanUnlock() from destroying the
* structure while we're still using it.
*/
pSioChan->lockCount++;
notifyAttach (pSioChan, USB_KBD_REMOVE);
pSioChan->lockCount--;
/* If no callers have the channel structure locked, destroy
* it now. If it is locked, it will be destroyed later during
* a call to usbKeyboardUnlock().
*/
if (pSioChan->lockCount == 0)
destroySioChan (pSioChan);
break;
}
OSS_MUTEX_RELEASE (kbdMutex);
}
/***************************************************************************
*
* doShutdown - shuts down USB keyboard SIO driver
*
* <errCode> should be OK or S_usbKeyboardLib_xxxx. This value will be
* passed to ossStatus() and the return value from ossStatus() is the
* return value of this function.
*
* RETURNS: OK, or ERROR per value of <errCode> passed by caller
*
* ERRNO: appropiate error code
*
*\NOMANUAL
*/
LOCAL STATUS doShutdown
(
int errCode
)
{
pATTACH_REQUEST pRequest;
pUSB_KBD_SIO_CHAN pSioChan;
/* Kill typematic thread */
if (typematicThread != NULL)
{
killTypematic = TRUE;
while (!typematicExit)
OSS_THREAD_SLEEP (1);
OSS_THREAD_DESTROY (typematicHandle);
}
/* Dispose of any outstanding notification requests */
while ((pRequest = usbListFirst (&reqList)) != NULL)
destroyAttachRequest (pRequest);
/* Dispose of any open keyboard connections. */
while ((pSioChan = usbListFirst (&sioList)) != NULL)
destroySioChan (pSioChan);
/* Release our connection to the USBD. The USBD automatically
* releases any outstanding dynamic attach requests when a client
* unregisters.
*/
if (usbdHandle != NULL)
{
usbdClientUnregister (usbdHandle);
usbdHandle = NULL;
}
/* Release resources. */
if (kbdMutex != NULL)
{
OSS_MUTEX_DESTROY (kbdMutex);
kbdMutex = NULL;
}
return ossStatus (errCode);
}
/***************************************************************************
*
* usbKeyboardDevInit - initialize USB keyboard SIO driver
*
* Initializes the USB keyboard SIO driver. The USB keyboard SIO driver
* maintains an initialization count, so calls to this function may be
* nested.
*
* RETURNS: OK, or ERROR if unable to initialize.
*
* ERRNO:
* \is
* \i S_usbKeyboardLib_OUT_OF_RESOURCES
* Sufficient resources are not available to create mutex
*
* \i S_usbKeyboardLib_USBD_FAULT
* Fault in the USBD Layer
* \ie
*/
STATUS usbKeyboardDevInit (void)
{
/* If not already initialized, then initialize internal structures
* and connection to USBD.
*/
if (initCount == 0)
{
/* Initialize lists, structures, resources. */
memset (&sioList, 0, sizeof (sioList));
memset (&reqList, 0, sizeof (reqList));
kbdMutex = NULL;
usbdHandle = NULL;
typematicHandle = NULL;
killTypematic = FALSE;
typematicExit = FALSE;
if (OSS_MUTEX_CREATE (&kbdMutex) != OK)
return doShutdown (S_usbKeyboardLib_OUT_OF_RESOURCES);
/* Initialize typematic repeat thread */
if (OSS_THREAD_CREATE (typematicThread,
NULL,
OSS_PRIORITY_LOW,
TYPEMATIC_NAME,
&typematicHandle)
!= OK)
return doShutdown (S_usbKeyboardLib_OUT_OF_RESOURCES);
/* Establish connection to USBD
* The usbdDynamicAttachRegister requires a flag as the fourth parameter
* to indicate whether the device registered with this driver will be a
* vendor specific device (flag = TRUE) or class specific device (flag =
* FALSE
*/
if (usbdClientRegister (KBD_CLIENT_NAME, &usbdHandle) != OK ||
usbdDynamicAttachRegister (usbdHandle,
USB_CLASS_HID,
USB_SUBCLASS_HID_BOOT,
USB_PROTOCOL_HID_BOOT_KEYBOARD,FALSE,
usbKeyboardAttachCallback)
!= OK)
{
return doShutdown (S_usbKeyboardLib_USBD_FAULT);
}
}
initCount++;
return OK;
}
/***************************************************************************
*
* usbKeyboardDevShutdown - shuts down keyboard SIO driver
*
* This function shuts down the keyboard driver. The driver is shutdown only
* if <initCount> after decrementing. If it is more the 0, it is decremented.
*
* RETURNS: OK, or ERROR if unable to shutdown.
*
* ERRNO:
* \is
* \i S_usbKeyboardLib_NOT_INITIALIZED
* Keyboard Driver not initialized
* \ie
*/
STATUS usbKeyboardDevShutdown (void)
{
/* Shut down the USB keyboard SIO driver if the initCount goes to 0. */
if (initCount == 0)
return ossStatus (S_usbKeyboardLib_NOT_INITIALIZED);
if (--initCount == 0)
return doShutdown (OK);
return OK;
}
/***************************************************************************
*
* usbKeyboardDynamicAttachRegister - Register keyboard attach callback
*
* <callback> is a caller-supplied function of the form:
*
* \cs
* typedef (*USB_KBD_ATTACH_CALLBACK)
* (
* pVOID arg,
* SIO_CHAN *pSioChan,
* UINT16 attachCode
* );
* \ce
*
* usbKeyboardLib will invoke <callback> each time a USB keyboard
* is attached to or removed from the system. <arg> is a caller-defined
* parameter which will be passed to the <callback> each time it is
* invoked. The <callback> will also be passed a pointer to the
* SIO_CHAN structure for the channel being created/destroyed and
* an attach code of USB_KBD_ATTACH or USB_KBD_REMOVE.
*
* RETURNS: OK, or ERROR if unable to register callback
*
* ERRNO:
* \is
* \i S_usbKeyboardLib_BAD_PARAM
* Bad Parameter are passed
*
* \i S_usbKeyboardLib_OUT_OF_MEMORY
* Not sufficient memory is available
* \ie
*/
STATUS usbKeyboardDynamicAttachRegister
(
USB_KBD_ATTACH_CALLBACK callback, /* new callback to be registered */
pVOID arg /* user-defined arg to callback */
)
{
pATTACH_REQUEST pRequest;
pUSB_KBD_SIO_CHAN pSioChan;
int status = OK;
/* Validate parameters */
if (callback == NULL)
return ossStatus (S_usbKeyboardLib_BAD_PARAM);
OSS_MUTEX_TAKE (kbdMutex, OSS_BLOCK);
/* Create a new
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -