⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbdcorelib.c

📁 基于VXWORK环境的ARM9 S2410的USB驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
		 */		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. 		 *		 * NOTE: The pNotification structure is created here and		 * released when consumed in the client callback thread.		 *		 * NOTE: In a very large USB topology (at least several		 * dozen nodes) there is a chance that we could overrun		 * a client's callback queue depending on the type of 		 * notification requests the client has made.  If this happens,		 * the following call to usbQueuePut() may block.  If *that*		 * happens, there is a chance of a deadlock if the client's		 * callback code - invoked from the clientThread() reenters		 * the USBD.  A simple solution, if that situation is observed,		 * is to increase the depth of the callback queue.		 */		if ((pNotification = OSS_CALLOC (sizeof (*pNotification))) 		    != NULL)		    {		    pNotification->callback = pNotify->callback;		    pNotification->nodeId = pNode->nodeHandle;		    pNotification->attachCode = attachCode;		    pNotification->configuration = pClassType->configuration;		    pNotification->interface = pClassType->interface;		    pNotification->deviceClass = pClassType->deviceClass;		    pNotification->deviceSubClass = pClassType->deviceSubClass;		    pNotification->deviceProtocol = pClassType->deviceProtocol;		    usbQueuePut (pClient->callbackQueue, 			CALLBACK_FNC_NOTIFY_ATTACH, 0, (UINT32) pNotification, 			OSS_BLOCK);		    }		}	    }	}    }/***************************************************************************** notifyClients - notify clients of a dynamic attach/removal** Scans the clientList looking for clients who have requested dynamic* attach/removal notification for a class matching <pNode>.  If any* are found, their dynamic attach callback routines will be invoked* with an attach code of <attachCode>.** RETURNS: N/A*/LOCAL VOID notifyClients    (    pUSBD_NODE pNode,    UINT16 attachCode    )    {    pUSBD_CLIENT pClient;    pUSBD_NOTIFY_REQ pNotify;    pUSBD_NODE_CLASS pClassType;    /* Scan for clients which have requested dynamic attach notification. */    pClient = usbListFirst (&clientList);    while (pClient != NULL)	{	/* Walk through the list of notification requests for this client */	pNotify = usbListFirst (&pClient->notifyReqs);	while (pNotify != NULL)	    {	    /* Walk through the class types for this node, looking for one	     * which matches the current client notification request.	     */	    pClassType = usbListFirst (&pNode->classTypes);	    while (pClassType != NULL)		{		notifyIfMatch (pNode, pClassType, pClient, pNotify, attachCode);		pClassType = usbListNext (&pClassType->classLink);		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -