📄 usbmouselib.c
字号:
pIrp->userCallback = usbMouseIrpCallback; pIrp->timeout = USB_TIMEOUT_NONE; pIrp->transferLen = sizeof (HID_MSE_BOOT_REPORT); pIrp->bfrCount = 1; pIrp->bfrList [0].pid = USB_PID_IN; pIrp->bfrList [0].pBfr = pSioChan->pIrpBfr; pIrp->bfrList [0].bfrLen = min (pSioChan->intMaxPacketSize, HID_BOOT_REPORT_MAX_LEN); /* Submit IRP */ if (usbdTransfer (usbdHandle, pSioChan->pipeHandle, pIrp) != OK) return FALSE; pSioChan->irpInUse = TRUE; return TRUE; }/***************************************************************************** usbMouseIrpCallback - Invoked upon IRP completion/cancellation** Examines the cause of the IRP completion. If completion was successful,* interprets the USB mouse's boot report and re-submits the IRP.** RETURNS: N/A*/LOCAL VOID usbMouseIrpCallback ( pVOID p /* completed IRP */ ) { pUSB_IRP pIrp = (pUSB_IRP) p; pUSB_MSE_SIO_CHAN pSioChan = pIrp->userPtr; OSS_MUTEX_TAKE (mseMutex, OSS_BLOCK); /* Was the IRP successful? */ if (pIrp->result == OK) { /* Interpret the mouse report */ interpMseReport (pSioChan); } /* Re-submit the IRP unless it was canceled - which would happen only * during pipe shutdown (e.g., the disappearance of the device). */ pSioChan->irpInUse = FALSE; if (pIrp->result != S_usbHcdLib_IRP_CANCELED) initMseIrp (pSioChan); OSS_MUTEX_RELEASE (mseMutex); }/***************************************************************************** configureSioChan - configure USB mouse 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 mouse.** RETURNS: TRUE if successful, else FALSE if failed to configure channel*/LOCAL BOOL configureSioChan ( pUSB_MSE_SIO_CHAN pSioChan ) { pUSB_CONFIG_DESCR pCfgDescr; pUSB_INTERFACE_DESCR pIfDescr; pUSB_ENDPOINT_DESCR pEpDescr; UINT8 * pBfr; UINT8 * pScratchBfr; UINT16 actLen; UINT16 ifNo; 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 mouse boot protocol. */ if (usbHidProtocolSet (usbdHandle, pSioChan->nodeId, pSioChan->interface, USB_HID_PROTOCOL_BOOT) != OK) { OSS_FREE (pBfr); return FALSE; } /* Set the mouse idle time to infinite. */ if (usbHidIdleSet (usbdHandle, pSioChan->nodeId, pSioChan->interface, 0 /* no report ID */, 0 /* infinite */) != OK) { OSS_FREE (pBfr); return FALSE; } /* Create a pipe to monitor input reports from the mouse. */ pSioChan->intMaxPacketSize = *((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, pSioChan->intMaxPacketSize, sizeof (HID_MSE_BOOT_REPORT), pEpDescr->interval, &pSioChan->pipeHandle) != OK) { OSS_FREE (pBfr); return FALSE; } /* Initiate IRP to listen for input on interrupt pipe */ if (!initMseIrp (pSioChan)) { OSS_FREE (pBfr); return FALSE; } OSS_FREE (pBfr); return TRUE; }/***************************************************************************** destroyAttachRequest - disposes of an ATTACH_REQUEST structure** RETURNS: N/A*/LOCAL VOID destroyAttachRequest ( pATTACH_REQUEST pRequest ) { /* Unlink request */ usbListUnlink (&pRequest->reqLink); /* Dispose of structure */ OSS_FREE (pRequest); }/***************************************************************************** destroySioChan - disposes of a USB_MSE_SIO_CHAN structure** Unlinks the indicated USB_MSE_SIO_CHAN structure and de-allocates* resources associated with the channel.** RETURNS: N/A*/LOCAL VOID destroySioChan ( pUSB_MSE_SIO_CHAN pSioChan ) { /* Unlink the structure. */ usbListUnlink (&pSioChan->sioLink); /* Release pipe if one has been allocated. Wait for the IRP to be * cancelled if necessary. */ if (pSioChan->pipeHandle != NULL) usbdPipeDestroy (usbdHandle, pSioChan->pipeHandle); while (pSioChan->irpInUse) OSS_THREAD_SLEEP (1); /* Release structure. */ if (pSioChan->pIrpBfr != NULL) OSS_FREE (pSioChan->pIrpBfr); OSS_FREE (pSioChan); }/***************************************************************************** createSioChan - creates a new USB_MSE_SIO_CHAN structure** Creates a new USB_MSE_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 mouse for this device.** RETURNS: pointer to newly created structure, or NULL if failure*/LOCAL pUSB_MSE_SIO_CHAN createSioChan ( USBD_NODE_ID nodeId, UINT16 configuration, UINT16 interface ) { pUSB_MSE_SIO_CHAN pSioChan; /* Try to allocate space for a new mouse struct */ if ((pSioChan = OSS_CALLOC (sizeof (*pSioChan))) == NULL) return NULL; if ((pSioChan->pIrpBfr = OSS_MALLOC (HID_BOOT_REPORT_MAX_LEN)) == NULL) { OSS_FREE (pSioChan); return NULL; } pSioChan->sioChan.pDrvFuncs = &usbMouseSioDrvFuncs; pSioChan->nodeId = nodeId; pSioChan->connected = TRUE; pSioChan->mode = SIO_MODE_INT; pSioChan->configuration = configuration; pSioChan->interface = interface; pSioChan->pReport = (pHID_MSE_BOOT_REPORT) pSioChan->pIrpBfr; /* Try to configure the mouse. */ if (!configureSioChan (pSioChan)) { destroySioChan (pSioChan); return NULL; } /* Link the newly created structure. */ usbListLink (&sioList, pSioChan, &pSioChan->sioLink, LINK_TAIL); return pSioChan; }/***************************************************************************** findSioChan - Searches for a USB_MSE_SIO_CHAN for indicated node ID** RETURNS: pointer to matching USB_MSE_SIO_CHAN or NULL if not found*/LOCAL pUSB_MSE_SIO_CHAN findSioChan ( USBD_NODE_ID nodeId ) { pUSB_MSE_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** RETURNS: N/A*/LOCAL VOID notifyAttach ( pUSB_MSE_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); } }/***************************************************************************** usbMouseAttachCallback - called by USBD when mouse attached/removed** The USBD will invoke this callback when a USB mouse is attached to or* removed from the system. <nodeId> is the USBD_NODE_ID of the node being
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -