📄 usbdcorelib.c
字号:
pNOTIFICATION pNotification; /* Execute messages from the callbackQueue until a CLIENT_FNC_TERMINATE message is received. */ do { if (usbQueueGet (pClient->callbackQueue, &msg, OSS_BLOCK) != OK) break; switch (msg.msg) { case CALLBACK_FNC_IRP_COMPLETE: /* invoke a client's IRP callback routine. The msg.lParam * is a pointer to the completed USB_IRP. */ pIrp = (pUSB_IRP) msg.lParam; if (pIrp->userCallback != NULL) (*pIrp->userCallback) (pIrp); break; case CALLBACK_FNC_NOTIFY_ATTACH: /* invoke a client's dynamic attach routine. The msg.lParam * is a pointer to a NOTIFICATION structure. * * NOTE: We dispose of the NOTIFICATION request after * consuming it. */ pNotification = (pNOTIFICATION) msg.lParam; (*pNotification->callback) (pNotification->nodeId, pNotification->attachCode, pNotification->configuration, pNotification->interface, pNotification->deviceClass, pNotification->deviceSubClass, pNotification->deviceProtocol); OSS_FREE (pNotification); break; case CALLBACK_FNC_MNGMT_EVENT: /* invoke a client's managment callback routine. The * msg.wParam is the management code and the msg.lParam is * the USBD_NODE_ID of the root for the affected bus. */ if (pClient->mngmtCallback != NULL) (*pClient->mngmtCallback) (pClient->mngmtCallbackParam, (USBD_NODE_ID) msg.lParam, msg.wParam); break; } } while (msg.msg != CALLBACK_FNC_TERMINATE); /* Mark the callback routine as having terminated. */ OSS_SEM_GIVE (pClient->callbackExit);}/***************************************************************************** doTransferAbort - Cancel an outstanding IRP** Directs the HCD to cancel the IRP and waits for the IRP callback to* be invoked signalling that the IRP has been unlinked successfully.** RETURNS: S_usbdLib_xxxx*/LOCAL int doTransferAbort (pUSBD_PIPE pPipe, /* Pipe owning transfer */ pUSB_IRP pIrp /* IRP to be cancelled */ ){ /* The callback which indicates that an IRP has been deleted is * asynchronous. However, when deleting an IRP (such as when * destroying a pipe) we generally need to know when the IRP * callback has actually been invoked - and hence the IRP unlinked * from the list of outstanding IRPs on the pipe. */ pPipe->irpBeingDeleted = pIrp; pPipe->irpDeleted = FALSE; /* Instruct the HCD to cancel the IRP */ if (usbHcdIrpCancel (&pPipe->pNode->pBus->pHcd->nexus, pIrp) != OK) return S_usbdLib_CANNOT_CANCEL; /* Wait for the IRP callback to be invoked. */ while (!pPipe->irpDeleted) OSS_THREAD_SLEEP (1); return OK;}/***************************************************************************** destroyNotify - de-allocates a USBD_NOTIFY_REQ** RETURNS: N/A*/LOCAL VOID destroyNotify (pUSBD_NOTIFY_REQ pNotify){ usbListUnlink (&pNotify->reqLink); OSS_FREE (pNotify);}/***************************************************************************** destroyPipe - de-allocates a USBD_PIPE and its resources** RETURNS: N/A*/LOCAL VOID destroyPipe (pUSBD_PIPE pPipe){ pUSB_IRP pIrp; pUSBD_BUS pBus; if (pPipe != NULL) { pPipe->pipeDeletePending = TRUE; /* Cancel all IRPs outstanding on this pipe. * * NOTE: Since the IRP completion callbacks are on a different thread, * we need to wait until all callbacks have been completed. This * functionality is built into doTransferAbort(). */ while ((pIrp = usbListFirst (&pPipe->irps)) != NULL) doTransferAbort (pPipe, pIrp); /* Release bandwidth and notify HCD that the pipe is going away. */ pBus = pPipe->pNode->pBus; pBus->nanoseconds -= pPipe->nanoseconds; usbHcdPipeDestroy (&pBus->pHcd->nexus, pPipe->hcdHandle); /* Unlink pipe from owning client's list of pipes */ if (pPipe->pClient != NULL) usbListUnlink (&pPipe->clientPipeLink); /* Unlink pipe from owning node's list of pipes */ if (pPipe->pNode != NULL) usbListUnlink (&pPipe->nodePipeLink); /* Release pipe handle */ if (pPipe->handle != NULL) usbHandleDestroy (pPipe->handle); OSS_FREE (pPipe); }}/***************************************************************************** destroyClient - tears down a USBD_CLIENT structure** RETURNS: N/A*/LOCAL VOID destroyClient (pUSBD_CLIENT pClient){ pUSBD_NOTIFY_REQ pNotify; pUSBD_PIPE pPipe; pUSBD_HCD pHcd; UINT16 busNo; /* unlink client from list of clients. * * NOTE: usbListUnlink is smart and only unlinks the structure if it is * actually linked. */ usbListUnlink (&pClient->clientLink); /* destroy all notification requests outstanding for the client */ while ((pNotify = usbListFirst (&pClient->notifyReqs)) != NULL) destroyNotify (pNotify); /* destroy all pipes owned by this client */ while ((pPipe = usbListFirst (&pClient->pipes)) != NULL) destroyPipe (pPipe); /* If this client is the current SOF master for any USBs, then release * the SOF master status. */ pHcd = usbListFirst (&hcdList); while (pHcd != NULL) { for (busNo = 0; busNo < pHcd->busCount; busNo++) if (pHcd->pBuses[busNo].pSofMasterClient == pClient) pHcd->pBuses[busNo].pSofMasterClient = NULL; pHcd = usbListNext (&pHcd->hcdLink); } /* Note: callbackQueue is always created after callbackExit and * before callbackThread */ if (pClient->callbackThread != NULL) { /* Terminate the client callback thread */ usbQueuePut (pClient->callbackQueue, CALLBACK_FNC_TERMINATE, 0, 0, CALLBACK_TIMEOUT); OSS_SEM_TAKE (pClient->callbackExit, CALLBACK_TIMEOUT); OSS_THREAD_DESTROY (pClient->callbackThread); } if (pClient->callbackQueue != NULL) usbQueueDestroy (pClient->callbackQueue); if (pClient->callbackExit != NULL) OSS_SEM_DESTROY (pClient->callbackExit); if (pClient->handle != NULL) usbHandleDestroy (pClient->handle); OSS_FREE (pClient);}/***************************************************************************** fncClientReg - Register a new USBD client** RETURNS: S_usbdLib_xxxx*/LOCAL int fncClientReg (pURB_CLIENT_REG pUrb){ pUSBD_CLIENT pClient; int s; /* validate URB */ if ((s = validateUrb (pUrb, sizeof (*pUrb), NULL)) != OK) return s; /* Create structures/resources/etc., required by new client */ if ((pClient = OSS_CALLOC (sizeof (*pClient))) == NULL) return S_usbdLib_OUT_OF_MEMORY; memcpy (pClient->clientName, pUrb->clientName, USBD_NAME_LEN); if (usbHandleCreate (USBD_CLIENT_SIG, pClient, &pClient->handle) != OK || OSS_SEM_CREATE (1, 0, &pClient->callbackExit) != OK || usbQueueCreate (CALLBACK_Q_DEPTH, &pClient->callbackQueue) != OK || OSS_THREAD_CREATE (clientThread, pClient, OSS_PRIORITY_INHERIT, "tUsbdClnt", &pClient->callbackThread) != OK) s = S_usbdLib_OUT_OF_RESOURCES; else { /* The client was initialized successfully. Add it to the list */ usbListLink (&clientList, pClient, &pClient->clientLink, LINK_TAIL); /* return the client's USBD_CLIENT_HANDLE */ pUrb->header.handle = pClient->handle; } if (s != OK) { destroyClient (pClient); } return s;}/***************************************************************************** fncClientUnreg - Unregister a USBD client** RETURNS: S_usbdLib_xxxx*/LOCAL int fncClientUnreg (pURB_CLIENT_UNREG pUrb){ pUSBD_CLIENT pClient; int s; /* validate Urb */ if ((s = validateUrb (pUrb, sizeof (*pUrb), &pClient)) != OK) return s; /* destroy client */ destroyClient (pClient); return s;}/***************************************************************************** fncMngmtCallbackSet - sets management callback for a client** RETURNS: S_usbdLib_xxxx*/LOCAL int fncMngmtCallbackSet (pURB_MNGMT_CALLBACK_SET pUrb){ pUSBD_CLIENT pClient; int s; /* validate URB */ if ((s = validateUrb (pUrb, sizeof (*pUrb), &pClient)) != OK) return s; /* Set the management callback */ pClient->mngmtCallback = pUrb->mngmtCallback; pClient->mngmtCallbackParam = pUrb->mngmtCallbackParam; return s;}/***************************************************************************** fncVersionGet - Return USBD version** RETURNS: S_usbdLib_xxxx*/LOCAL int fncVersionGet (pURB_VERSION_GET pUrb){ int s; /* validate urb */ if ((s = validateUrb (pUrb, sizeof (*pUrb), NULL)) != OK) return s; /* return version information */ pUrb->version = USBD_VERSION; strncpy ((char *) pUrb->mfg, USBD_MFG, USBD_NAME_LEN); return s;}/***************************************************************************** releaseAddress - release a USB device address** RETURNS: N/A*/LOCAL VOID releaseAddress (pUSBD_NODE pNode){ pUSBD_BUS pBus = pNode->pBus; pBus->adrsVec[pNode->busAddress / 8] &= ~(0x1 << (pNode->busAddress % 8));}/***************************************************************************** assignAddress - assigns a unique USB address to a node** RETURNS: TRUE if successful, else FALSE*/LOCAL BOOL assignAddress (pUSBD_NODE pNode){ pUSBD_BUS pBus = pNode->pBus; UINT16 i; /* Find an available address */ for (i = 1; i < USB_MAX_DEVICES; i++) { if ((pBus->adrsVec[i / 8] & (0x1 << (i % 8))) == 0) { /* i is the value of an unused address. Set the device adrs. */ if (usbdAddressSet (internalClient, pNode->nodeHandle, i) == OK) { pNode->busAddress = i; pBus->adrsVec[i / 8] |= 0x1 << (i % 8); return TRUE; } else { return FALSE; } } } return FALSE;}/***************************************************************************** notifyIfMatch - Invoke attach callback if appropriate.** Compares the device class/subclass/protocol for <pClassType> and <pNotify>.* If the two match, then invokes the callback in <pNotify> with an attach* code of <attachCode>.** RETURNS: N/A*/LOCAL VOID notifyIfMatch (pUSBD_NODE pNode, pUSBD_NODE_CLASS pClassType, pUSBD_CLIENT pClient, pUSBD_NOTIFY_REQ pNotify, UINT16 attachCode){ pNOTIFICATION pNotification; /* Do the pClassType and pNotify structures contain matching class * descriptions? */ if (pNotify->deviceClass == USBD_NOTIFY_ALL || pClassType->deviceClass == pNotify->deviceClass) { if (pNotify->deviceSubClass == USBD_NOTIFY_ALL || pClassType->deviceSubClass == pNotify->deviceSubClass) { if (pNotify->deviceProtocol == USBD_NOTIFY_ALL || pClassType->deviceProtocol == pNotify->deviceProtocol) { /* We have a match. Schedule the client attach callback.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -