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

📄 usbdcorelib.c

📁 基于VXWORK环境的ARM9 S2410的USB驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
			!= OK ||	actLen < USB_HUB_DESCR_LEN)	{        OSS_FREE (pConfDescrBfr);        OSS_FREE (pHubDescrBuf);	return FALSE;	}    /* We now have all important descriptors for this hub.  Pick out     * important information and configure hub.     */    /* Record hub power capability */    pNode->pwrGoodDelay = pHubDescrBuf->pwrOn2PwrGood * 2; /* 2 msec per unit */    pNode->hubContrCurrent = pHubDescrBuf->hubContrCurrent;    if ((pCfgDescr->attributes & USB_ATTR_SELF_POWERED) != 0)	{	pNode->selfPowered = TRUE;	pNode->maxPowerPerPort = USB_POWER_SELF_POWERED;	}    else	{	pNode->selfPowered = FALSE;	pNode->maxPowerPerPort = USB_POWER_BUS_POWERED;	}    pNode->numPorts = pHubDescrBuf->nbrPorts;    /* If this hub is not already at the maximum USB topology depth, then     * create a pipe to monitor it's status and enable each of its ports.     */    if (pNode->topologyDepth < USB_MAX_TOPOLOGY_DEPTH)	{	/* Set the hub's configuration. */	if (usbdConfigurationSet (internalClient, 				  pNode->nodeHandle, 				  pCfgDescr->configurationValue, 				  pNode->hubContrCurrent) 			  != OK)	    {            OSS_FREE (pConfDescrBfr);            OSS_FREE (pHubDescrBuf);	    return FALSE;	    }	/* Create a pipe for interrupt transfers from this device. */	if (usbdPipeCreate (internalClient, 			    pNode->nodeHandle, 			    pEpDescr->endpointAddress, 			    pCfgDescr->configurationValue, 			    0, 			    USB_XFRTYPE_INTERRUPT, 			    USB_DIR_IN, 			    FROM_LITTLEW (pEpDescr->maxPacketSize), 			    HUB_STATUS_LEN (pNode), 			    pEpDescr->interval, 			    &pNode->hubStatusPipe) 			  != OK)	    {            OSS_FREE (pConfDescrBfr);            OSS_FREE (pHubDescrBuf);	    return FALSE;	    }	/* Allocate structures for downstream nodes. */	if ((pNode->pPorts = OSS_CALLOC (pNode->numPorts * sizeof (USBD_PORT))) 	    == NULL)	    {            OSS_FREE (pConfDescrBfr);            OSS_FREE (pHubDescrBuf);	    return FALSE;	    }	/* Initialize each hub port */	for (port = 0; port < pNode->numPorts; port++)	    {	    /* Enable power to the port */	    usbdFeatureSet (internalClient, pNode->nodeHandle, 		USB_RT_CLASS | USB_RT_OTHER, USB_HUB_FSEL_PORT_POWER, port + 1);	    }	OSS_THREAD_SLEEP (pNode->pwrGoodDelay); /* let power stabilize */	/* Initialize an IRP to listen for status changes on the hub */   	if (!initHubIrp (pNode))	    {            OSS_FREE (pConfDescrBfr);            OSS_FREE (pHubDescrBuf);	    return FALSE;	    }	}        OSS_FREE (pConfDescrBfr);    OSS_FREE (pHubDescrBuf);     return TRUE;    }/***************************************************************************** createNode - Creates and initializes new USBD_NODE** If the node is a hub, then automatically initializes hub.** RETURNS: pointer to newly created USBD_NODE, or*	   NULL if not successful*/LOCAL void reset_upll(void){	CLKCON &= ~0x00000040;	UPLLCON =  0x00078023;	CLKCON |=  0x00000040;	taskDelay(1);}LOCAL pUSBD_NODE createNode     (    pUSBD_BUS pBus,		    /* node's parent bus */    USBD_NODE_ID rootId,	    /* root id */    USBD_NODE_ID parentHubId,	    /* parent hub id */    UINT16 parentHubPort,	    /* parent hub port no */    UINT16 nodeSpeed,		    /* node speed */    UINT16 topologyDepth	    /* this node's depth in topology */    )    {    pUSBD_NODE pNode;    pUSBD_PIPE pPipe;    UINT16 actLen, i;    /* Allocate/initialize USBD_NODE */    if ((pNode = OSS_CALLOC (sizeof (*pNode))) == NULL)	return NULL;    /*      * The hub status buffer gets touched by hardware.  Ensure that      * it does not span a cache line     */    if ((pNode->pHubStatus = OSS_CALLOC (MAX_HUB_STATUS_LEN)) == NULL)	{	OSS_FREE (pNode);	return NULL;	}    if (usbHandleCreate (USBD_NODE_SIG, pNode, &pNode->nodeHandle) != OK ||	OSS_SEM_CREATE (1, 1, &pNode->controlSem) != OK)	{	destroyNode (pNode);	return NULL;	}    pNode->pBus = pBus;    pNode->nodeInfo.nodeSpeed = nodeSpeed;    pNode->nodeInfo.parentHubId = parentHubId;    pNode->nodeInfo.parentHubPort = parentHubPort;    pNode->nodeInfo.rootId = (rootId == 0) ? pNode->nodeHandle : rootId;    pNode->topologyDepth = topologyDepth;    /* Create a pipe for control transfers to this device. */    if (usbdPipeCreate (internalClient, pNode->nodeHandle, USB_ENDPOINT_CONTROL,	0, 0, USB_XFRTYPE_CONTROL, USB_DIR_INOUT, USB_MIN_CTRL_PACKET_SIZE, 0, 0, 	&pNode->controlPipe) != OK)	{	destroyNode (pNode);	return NULL;	}    /* Read the device descriptor to get the maximum payload size and to     * determine if this is a hub or not.     *     * NOTE: We read only the first 8 bytes of the device descriptor (which     * takes us through the maxPacketSize field) as suggested by the USB     * spec.     */	for(i=0; i<8; i++){	    if (usbdDescriptorGet (internalClient, pNode->nodeHandle,		USB_RT_STANDARD | USB_RT_DEVICE, USB_DESCR_DEVICE, 0, 0,		USB_MIN_CTRL_PACKET_SIZE, (pUINT8) &pNode->devDescr, &actLen) != OK ||		actLen < USB_MIN_CTRL_PACKET_SIZE){			/*printf("usbDescGet(%d) faile!\n", i);*/			reset_upll();		}else{			break;		}	}	if(i==8){		destroyNode (pNode);		return NULL;	}    /* Now that we've read the device descriptor, we know the actual     * packet size supported by the control pipe.  Update the pipe     * accordingly.     */    validatePipe (pNode->controlPipe, &pPipe);    pPipe->maxPacketSize = pNode->devDescr.maxPacketSize0;  /* field is byte wide */    /* Set a unique address for this device. */    if (!assignAddress (pNode))	{	destroyNode (pNode);	return NULL;	}    /* Notify the HCD of the change in device address and max packet size */    usbHcdPipeModify (&pBus->pHcd->nexus, pPipe->hcdHandle, 	pNode->busAddress, pPipe->maxPacketSize);    /* If this is a hub node, it requires additional initialization.  Otherwise,     * we're done unless and until a client performs additional I/O to this     * device.     */    if (pNode->devDescr.deviceClass == USB_CLASS_HUB)	{	pNode->nodeInfo.nodeType = USB_NODETYPE_HUB;	if (!initHubNode (pNode))	    {	    destroyNode (pNode);	    return NULL;	    }	}    else	{	pNode->nodeInfo.nodeType = USB_NODETYPE_DEVICE;	}    /* Read the device class type(s) from the device and notify interested     * clients of the device's insertion.     */    interrogateDeviceClass (pNode, pNode->devDescr.deviceClass,	pNode->devDescr.deviceSubClass, pNode->devDescr.deviceProtocol);    notifyClients (pNode, USBD_DYNA_ATTACH);    return pNode;    }/***************************************************************************** checkHubStatus - checks hub status and updates hub as necessary** Note: We take a Node ID as our parameter (instead of, say, a pointer* to a USBD_NODE structure) so that we can validate the node upon entry.* There are cases where this routine may be called when the underlying* node has already disappeared.** RETURNS: N/A*/LOCAL VOID checkHubStatus    (    USBD_NODE_ID nodeId    )    {    pUSBD_NODE pNode;    pUSB_IRP pIrp;    UINT16 port;    UINT8 portMask;    UINT8 statusIndex;    /* Is the node still valid? */    if (!validateNode (nodeId, &pNode))	return;    pIrp = &pNode->hubIrp;    /* Determine what status is available.     *     * The hubStatus vector contains one bit for the hub itself and      * then one bit for each port.     */    if (pIrp->result == OK)	{	port = 0;	statusIndex = 0;	portMask = USB_HUB_ENDPOINT_STS_PORT0;	while (port < pNode->numPorts && statusIndex < pIrp->bfrList [0].actLen)	    {	    if ((*(pNode->pHubStatus + statusIndex) & portMask) != 0)		{		/* This port appears to have status to report */		updateHubPort (pNode, port);		}	    port++;	    portMask <<= 1;	    if (portMask == 0)		{		portMask = 0x01;    /* next byte starts with bit 0 */		statusIndex++;		}	    }	}    /* resubmit the IRP */    if (pIrp->result != S_usbHcdLib_IRP_CANCELED)	initHubIrp (pNode);    }/***************************************************************************** busThread - bus monitor thread** A separate busThread() thread is spawned for each bus currently* attached to the USBD.  This thread is responsible for monitoring and* responding to bus events, like the attachment and removal of devices.* Using a separate thread for each bus helps to ensure that one bus's * behavior won't affect the throughput of other buses.** By convention, the <param> is a pointer to the USBD_BUS structure* for the associated bus.  This thread waits on the bus queue* in the bus structure.  At the time this thread is first created,* the USBD_BUS structure is only guaranteed to have an initialized* queue...other fields may not yet be initialized.** RETURNS: N/A*/LOCAL VOID busThread    (    pVOID param 		    /* thread parameter */    )    {    pUSBD_BUS pBus = (pUSBD_BUS) param;    USB_MESSAGE msg;    /* Execute messages from the busQueue until a BUS_FNC_TERMINATE    message is received. */    do	{	if (usbQueueGet (pBus->busQueue, &msg, OSS_BLOCK) != OK)	    break;	switch (msg.msg)	    {	    case BUS_FNC_UPDATE_HUB:		OSS_MUTEX_TAKE (structMutex, OSS_BLOCK);		checkHubStatus ((USBD_NODE_ID) msg.lParam);		OSS_MUTEX_RELEASE (structMutex);		break;	    }	}    while (msg.msg != BUS_FNC_TERMINATE);    /* Mark the callback routine as having terminated. */    OSS_SEM_GIVE (pBus->busExit);    }/***************************************************************************** hcdMngmtCallback - invoked when HCD detects managment event** RETURNS: N/A*/LOCAL VOID hcdMngmtCallback    (    pVOID mngmtCallbackParam,	    /* caller-defined param */    HCD_CLIENT_HANDLE handle,	    /* handle to host controller */    UINT16 busNo,		    /* bus number */    UINT16 mngmtCode		    /* management code */    )    {    pUSBD_HCD pHcd = (pUSBD_HCD) mngmtCallbackParam;    pUSBD_BUS pBus;    pUSBD_CLIENT pClient;    /* In an unusual case, this routine could be invoked by the HCD     * before we have completely initialized our structures.  In that     * case, just ignore the event.     */    if (pHcd->pBuses == NULL)	return;    pBus = &pHcd->pBuses [busNo];    if (pBus->busThread == NULL || pBus->busQueue == NULL ||	pBus->pRoot == NULL || pBus->pRoot->nodeHandle == NULL)	return;    /* Reflect the management event to interested clients */    OSS_MUTEX_TAKE (structMutex, OSS_BLOCK);    pClient = usbListFirst (&clientList);    while (pClient != NULL)	{	if (pClient->mngmtCallback != NULL)	    usbQueuePut (pClient->callbackQueue, CALLBACK_FNC_MNGMT_EVENT, 		mngmtCode, (UINT32) pBus->pRoot->nodeHandle, OSS_BLOCK);	pClient = usbListNext (&pClient->clientLink);	}    OSS_MUTEX_RELEASE (structMutex);    }/***************************************************************************** initHcdBus - Initialize USBD_BUS element of USBD_HCD structure** <pHcd> points to the USBD_HCD being initialized.  <busNo> is the index* of the HCD bus to be initialized.** RETURNS: S_usbdLib_xxxx*/LOCAL int initHcdBus    (    pUSBD_HCD pHcd,		    /* USBD_HCD being initialized */    UINT16 busNo		    /* Bus number to initialize */    )    {    pUSBD_BUS pBus = &pHcd->pBuses [busNo];    int s = OK;    /* Allocate resources for this bus. */    pBus->pHcd = pHcd;    pBus->busNo = busNo;    if (OSS_SEM_CREATE (1, 0, &pBus->busExit) != OK ||	usbQueueCreate (BUS_Q_DEPTH, &pBus->busQueue) != OK ||	OSS_THREAD_CREATE (busThread, pBus, OSS_PRIORITY_HIGH, "tUsbdBus", 	    &pBus->busThread) != OK ||	(pBus->pRoot = createNode (pBus, 0, 0, 0, USB_SPEED_FULL, 0)) == NULL)	{	/* NOTE: If we fail here, destroyHcd() will clean up partially	 * allocate structures/resources/etc.	 */	return S_usbdLib_OUT_OF_RESOURCES;	}    return s;    }/***************************************************************************** destroyHcd - tears down a USBD_HCD structure** Detaches the indicated HCD and tears down the HCD structures.** RETURNS: N/A*/LOCAL VOID destroyHcd    (    pUSBD_HCD pHcd    )    {    pUSBD_BUS pBus;    UINT16 busNo;    /* Unlink the HCD */    usbListUnlink (&pHcd->hcdLink);    /* Begin by de-allocating resources related to each bus */    for (busNo = 0; pHcd->pBuses != NULL && busNo < pHcd->busCount; busNo++)	{	pBus = &pHcd->pBuses [busNo];	/* Destroy all nodes associated with this bus */	destroyAllNodes (pBus->pRoot);	/* NOTE: The busQueue is always allocated before the busThread. */	if (pBus->busThread != NULL)	    {	    /* Issue a terminate request to the bus thread */	    usbQueuePut (pBus->busQueue, BUS_FNC_TERMINATE, 0, 0, BUS_TIMEOUT);	    OSS_SEM_TAKE (pBus->busExit, BUS_TIMEOUT);	    OSS_THREAD_DESTROY (pBus->busThread);	    }	if (pBus->busQueue != NULL)	    usbQueueDestroy (pBus->busQueue);	if (pBus->busExit != NULL)	    OSS_SEM_DESTROY (pBus->busQueue);	}

⌨️ 快捷键说明

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