📄 usbkeyboardlib.c
字号:
{ updateTypematic (pSioChan); pSioChan = usbListNext (&pSioChan->sioLink); } OSS_MUTEX_RELEASE (kbdMutex); OSS_THREAD_SLEEP (TYPEMATIC_PERIOD); } typematicExit = TRUE; }/***************************************************************************** configureSioChan - configure USB keyboard for operation** Selects the configuration/interface specified in the <pSioChan>* structure. These values come from the USBD dynamic attach callback,* which in turn retrieved them from the configuration/interface* descriptors which reported the device to be a keyboard.** RETURNS: TRUE if successful, else FALSE if failed to configure channel** ERRNO: none**\NOMANUAL*/LOCAL BOOL configureSioChan ( pUSB_KBD_SIO_CHAN pSioChan ) { pUSB_CONFIG_DESCR pCfgDescr; pUSB_INTERFACE_DESCR pIfDescr; pUSB_ENDPOINT_DESCR pEpDescr; UINT8 * pBfr; UINT8 * pScratchBfr; UINT16 actLen; UINT16 ifNo; UINT16 maxPacketSize; if ((pBfr = OSS_MALLOC (USB_MAX_DESCR_LEN)) == NULL) return FALSE; /* Read the configuration descriptor to get the configuration selection * value and to determine the device's power requirements. */ if (usbdDescriptorGet (usbdHandle, pSioChan->nodeId, USB_RT_STANDARD | USB_RT_DEVICE, USB_DESCR_CONFIGURATION, 0, 0, USB_MAX_DESCR_LEN, pBfr, &actLen) != OK) { OSS_FREE (pBfr); return FALSE; } if ((pCfgDescr = usbDescrParse (pBfr, actLen, USB_DESCR_CONFIGURATION)) == NULL) { OSS_FREE (pBfr); return FALSE; } /* Look for the interface indicated in the pSioChan structure. */ ifNo = 0; /* * usbDescrParseSkip() modifies the value of the pointer it recieves * so we pass it a copy of our buffer pointer */ pScratchBfr = pBfr; while ((pIfDescr = usbDescrParseSkip (&pScratchBfr, &actLen, USB_DESCR_INTERFACE)) != NULL) { if (ifNo == pSioChan->interface) break; ifNo++; } if (pIfDescr == NULL) { OSS_FREE (pBfr); return FALSE; } /* Retrieve the endpoint descriptor following the identified interface * descriptor. */ if ((pEpDescr = usbDescrParseSkip (&pScratchBfr, &actLen, USB_DESCR_ENDPOINT)) == NULL) { OSS_FREE (pBfr); return FALSE; } /* Select the configuration. */ if (usbdConfigurationSet (usbdHandle, pSioChan->nodeId, pCfgDescr->configurationValue, pCfgDescr->maxPower * USB_POWER_MA_PER_UNIT) != OK) { OSS_FREE (pBfr); return FALSE; } /* Select interface * * NOTE: Some devices may reject this command, and this does not represent * a fatal error. Therefore, we ignore the return status. */ usbdInterfaceSet (usbdHandle, pSioChan->nodeId, pSioChan->interface, pIfDescr->alternateSetting); /* Select the keyboard boot protocol. */ if (usbHidProtocolSet (usbdHandle, pSioChan->nodeId, pSioChan->interface, USB_HID_PROTOCOL_BOOT) != OK) { OSS_FREE (pBfr); return FALSE; } /* Set the keyboard idle time to infinite. */ if (usbHidIdleSet (usbdHandle, pSioChan->nodeId, pSioChan->interface, 0 /* no report ID */, 0 /* infinite */) != OK) { OSS_FREE (pBfr); return FALSE; } /* Turn off LEDs. */ setLedReport (pSioChan, 0); /* Create a pipe to monitor input reports from the keyboard. */ maxPacketSize = *((pUINT8) &pEpDescr->maxPacketSize) | (*(((pUINT8) &pEpDescr->maxPacketSize) + 1) << 8); if (usbdPipeCreate (usbdHandle, pSioChan->nodeId, pEpDescr->endpointAddress, pCfgDescr->configurationValue, pSioChan->interface, USB_XFRTYPE_INTERRUPT, USB_DIR_IN, maxPacketSize, sizeof (HID_KBD_BOOT_REPORT), pEpDescr->interval, &pSioChan->pipeHandle) != OK) { OSS_FREE (pBfr); return FALSE; } /* Initiate IRP to listen for input on interrupt pipe */ if (!initKbdIrp (pSioChan)) { OSS_FREE (pBfr); return FALSE; } OSS_FREE (pBfr); return TRUE; }/***************************************************************************** destroyAttachRequest - disposes of an ATTACH_REQUEST structure** This function disposes of an ATTACH_REQUEST structure.** RETURNS: N/A** ERRNO: none**\NOMANUAL*/LOCAL VOID destroyAttachRequest ( pATTACH_REQUEST pRequest ) { /* Unlink request */ usbListUnlinkProt (&pRequest->reqLink,kbdMutex); /* Dispose of structure */ OSS_FREE (pRequest); }/***************************************************************************** destroySioChan - disposes of a USB_KBD_SIO_CHAN structure** Unlinks the indicated USB_KBD_SIO_CHAN structure and de-allocates* resources associated with the channel.** RETURNS: N/A** ERRNO: none**\NOMANUAL*/LOCAL VOID destroySioChan ( pUSB_KBD_SIO_CHAN pSioChan ) { /* Unlink the structure. */ usbListUnlinkProt (&pSioChan->sioLink,kbdMutex); /* Release pipe if one has been allocated. Wait for the IRP to be * cancelled if necessary. */ if (pSioChan->pipeHandle != NULL) usbdPipeDestroy (usbdHandle, pSioChan->pipeHandle); /* The following block is commented out to address the nonblocking * issue of destroySioChan when the keyboard is removed and a read is * in progress SPR #98731 */ /* OSS_MUTEX_RELEASE (kbdMutex); while (pSioChan->irpInUse) OSS_THREAD_SLEEP (1); OSS_MUTEX_TAKE (kbdMutex, OSS_BLOCK); */ /* Release structure. */ if (!pSioChan->irpInUse) { if (pSioChan->pBootReport != NULL) OSS_FREE (pSioChan->pBootReport); OSS_FREE (pSioChan); } }/***************************************************************************** createSioChan - creates a new USB_KBD_SIO_CHAN structure** Creates a new USB_KBD_SIO_CHAN structure for the indicated <nodeId>.* If successful, the new structure is linked into the sioList upon * return.** <configuration> and <interface> identify the configuration/interface* that first reported itself as a keyboard for this device.** RETURNS: pointer to newly created structure, or NULL if failure** ERRNO: none**\NOMANUAL*/LOCAL pUSB_KBD_SIO_CHAN createSioChan ( USBD_NODE_ID nodeId, UINT16 configuration, UINT16 interface ) { pUSB_KBD_SIO_CHAN pSioChan; UINT16 i; /* 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 configuratin/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. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -