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

📄 usbdcorelib.c

📁 VxWorks下USB驱动的源代码!
💻 C
📖 第 1 页 / 共 5 页
字号:
                 *                 * 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);            }            pNotify = usbListNext (&pNotify->reqLink);        }        pClient = usbListNext (&pClient->clientLink);    }}/***************************************************************************** createNodeClass - Creates a USBD_NODE_CLASS structure** Creates a USBD_NODE_CLASS structure, initializes it with the passed* parameters, and attaches it to the <pNode>.** RETURNS: TRUE if successful, else FALSE if out of memory.*/LOCAL BOOL createNodeClass    (pUSBD_NODE pNode,     UINT16 configuration,     UINT16 interface, UINT16 deviceClass, UINT16 deviceSubClass, UINT16 deviceProtocol){    pUSBD_NODE_CLASS pClassType;    if ((pClassType = OSS_CALLOC (sizeof (*pClassType))) == NULL)        return FALSE;    pClassType->configuration = configuration;    pClassType->interface = interface;    pClassType->deviceClass = deviceClass;    pClassType->deviceSubClass = deviceSubClass;    pClassType->deviceProtocol = deviceProtocol;    usbListLink (&pNode->classTypes, pClassType, &pClassType->classLink, LINK_TAIL);    return TRUE;}/***************************************************************************** interrogateDeviceClass - Retrieve's device class information** Interrogate the device class and construct one or more USBD_NODE_CLASS * structures and attach them to <pNode>.  <deviceClass>, <deviceSubClass>,* and <deviceProtocol> are the device-level fields for this device.  If* <deviceClass> is 0, then this routine will automatically interrogate* the interface-level class information. If the information is provided* at the device level then the interfaces are not probed. ** RETURNS: TRUE if successful, else FALSE if error.*/LOCAL BOOL interrogateDeviceClass    (pUSBD_NODE pNode, UINT16 deviceClass, UINT16 deviceSubClass, UINT16 deviceProtocol){    pUSB_CONFIG_DESCR pCfgDescr;    pUSB_INTERFACE_DESCR pIfDescr;    pUINT8 pCfgBfr;    pUINT8 pRemBfr;    UINT16 cfgLen;    UINT16 remLen;    UINT16 numConfig;    UINT8 configIndex;    BOOL retcode = TRUE;    UINT8 configValue = 1;    /* If class information has been specified at the device level, then     * record it and return.     */    if ((deviceClass != 0) && (deviceSubClass != 0) && (deviceProtocol != 0))        return createNodeClass (pNode, 0, 0, deviceClass, deviceSubClass, deviceProtocol);    /* Read the device descriptor to determine the number of configurations. */    if (usbConfigCountGet (internalClient, pNode->nodeHandle, &numConfig) != OK)        return FALSE;    /* Read and process each configuration. */    for (configIndex = 0; configIndex < numConfig && retcode; configIndex++) {        /* Read the next configuration descriptor. */        if (usbConfigDescrGet (internalClient, pNode->nodeHandle, configIndex,                               &cfgLen, &pCfgBfr) != OK) {            retcode = FALSE;        } else {            if ((pCfgDescr = usbDescrParse (pCfgBfr, cfgLen, USB_DESCR_CONFIGURATION)) != NULL) {                /* Scan each interface descriptor.                  *                 * NOTE: If we can't find an interface descriptor, we just keep                 * going.                  */                pRemBfr = pCfgBfr;                remLen = cfgLen;                configValue = pCfgDescr->configurationValue;                while ((pIfDescr = usbDescrParseSkip (&pRemBfr, &remLen,                                                      USB_DESCR_INTERFACE)) != NULL && retcode) {                    if (!createNodeClass (pNode, configValue,                                          pIfDescr->interfaceNumber, pIfDescr->interfaceClass,                                          pIfDescr->interfaceSubClass, pIfDescr->interfaceProtocol))                    {                        retcode = FALSE;                    }                }            }            /* Release bfr allocated by usbConfigDescrGet(). */            OSS_FREE (pCfgBfr);        }    }    return retcode;}/***************************************************************************** destroyNode - deletes node structure** RETURNS: N/A*/LOCAL VOID destroyNode (pUSBD_NODE pNode){    pUSBD_NODE_CLASS pClassType;    pUSBD_PIPE pPipe;    /* Mark node as "going down" */    pNode->nodeDeletePending = TRUE;    /* Cancel any other pipes associated with this node...This has the     * effect of cancelling any IRPs outstanding on this node. */    while ((pPipe = usbListFirst (&pNode->pipes)) != NULL)        destroyPipe (pPipe);    /* Notify an interested clients that this node is going away. */    notifyClients (pNode, USBD_DYNA_REMOVE);    /* Delete any class type structures associated with this node. */    while ((pClassType = usbListFirst (&pNode->classTypes)) != NULL) {        usbListUnlink (&pClassType->classLink);        OSS_FREE (pClassType);    }    /* release bus address associated with node */    releaseAddress (pNode);    /* Release node resources/memory. */    if (pNode->controlSem != NULL)        OSS_SEM_DESTROY (pNode->controlSem);    if (pNode->nodeHandle != NULL)        usbHandleDestroy (pNode->nodeHandle);    OSS_FREE (pNode->pHubStatus);    OSS_FREE (pNode);}/***************************************************************************** destroyAllNodes - destroys all nodes in a tree of nodes** Recursively destroys all nodes from <pNode> and down.  If <pNode> is* NULL, returns immediately.** RETURNS: N/A*/LOCAL VOID destroyAllNodes (pUSBD_NODE pNode){    int i;    if (pNode != NULL) {        if (pNode->nodeInfo.nodeType == USB_NODETYPE_HUB && pNode->pPorts != NULL) {            /* destroy all children of this node */            for (i = 0; i < pNode->numPorts; i++)                destroyAllNodes (pNode->pPorts[i].pNode);        }        destroyNode (pNode);    }}/***************************************************************************** updateHubPort - Determine if a device has been attached/removed** Note: The <port> parameter to this function is 0-based (0 = first port,* 1 = second port, etc.)  However, on the USB interface itself, the index* passed in a Setup packet to identify a port is 1-based.** RETURNS: N/A*/LOCAL VOID updateHubPort (pUSBD_NODE pNode, UINT16 port){    USB_HUB_STATUS *pStatus;    UINT16 actLen;    UINT16 nodeSpeed;    pStatus = OSS_MALLOC (sizeof (USB_HUB_STATUS));    /* retrieve status for the indicated hub port. */    if (usbdStatusGet (internalClient,                       pNode->nodeHandle,                       USB_RT_CLASS | USB_RT_OTHER,                       port + 1,                       sizeof (USB_HUB_STATUS),                       (UINT8 *) pStatus, &actLen) != OK || actLen < sizeof (USB_HUB_STATUS)) {        OSS_FREE (pStatus);        return;    }    /* correct the status byte order */    pStatus->status = FROM_LITTLEW (pStatus->status);    pStatus->change = FROM_LITTLEW (pStatus->change);    /* Process the change indicated by status.change */    /* NOTE: To see if a port's connection status has changed we also see     * whether our internal understanding of the port's connection status     * matches the hubs's current connection status.  If the two do not     * agree, then we also assume a connection change, whether the hub is     * indicating one or not. This covers the case at power on where the     * hub does not report a connection change (i.e., the device is already     * plugged in), but we need to initialize the port for the first time.     */    if ((pStatus->change & USB_HUB_C_PORT_CONNECTION) != 0 ||        ((pNode->pPorts[port].pNode == NULL) !=         ((pStatus->status & USB_HUB_STS_PORT_CONNECTION) == 0))) {        /* Given that there has been a change on this port, it stands to         * reason that all nodes connected to this port must be invalidated -         * even if a node currently appears to be connected to the port.         */        destroyAllNodes (pNode->pPorts[port].pNode);        pNode->pPorts[port].pNode = NULL;        /* If a node appears to be connected to the port, reset the port. */        if ((pStatus->status & USB_HUB_STS_PORT_CONNECTION) != 0) {            /* Wait 100 msec after detecting a connection to allow power to             * stabilize.  Then enable the port and issue a reset.             */            OSS_THREAD_SLEEP (USB_TIME_POWER_ON);            usbdFeatureSet (internalClient, pNode->nodeHandle,                            USB_RT_CLASS | USB_RT_OTHER, USB_HUB_FSEL_PORT_RESET, port + 1);            /*              * Acoording to the USB spec (refer to section 7.1.7.3) we should             * wait 50 msec for reset signaling + an additional 10 msec reset              * recovery time.  We double this time for safety's sake since              * we have seen a few devices that do not respond to the suggested              * time of 60 msec.             */            OSS_THREAD_SLEEP (2 * USB_TIME_RESET + USB_TIME_RESET_RECOVERY);        }        /* Clear the port connection change indicator - whether or not it         * appears that a device is currently connected. */        usbdFeatureClear (internalClient, pNode->nodeHandle,                          USB_RT_CLASS | USB_RT_OTHER, USB_HUB_FSEL_C_PORT_CONNECTION, port + 1);        /* If a node appears to be connected, create a new node structure for          * it and attach it to this hub. */        if ((pStatus->status & USB_HUB_STS_PORT_CONNECTION) != 0) {            /* If the following call to createNode() fails, it returns NULL.             * That's fine, as the corresponding USBD_PORT structure will be             * initialized correctly either way.             */            nodeSpeed = ((pStatus->status & USB_HUB_STS_PORT_LOW_SPEED) != 0) ?                USB_SPEED_LOW : USB_SPEED_FULL;            if ((pNode->pPorts[port].pNode = createNode (pNode->pBus,                                                         pNode->pBus->pRoot->nodeHandle,                                                         pNode->nodeHandle, port, nodeSpeed,                                                         pNode->topologyDepth + 1)) == NULL) {                /* Attempt to initialize the port failed.  Disable the port */                usbdFeatureClear (internalClient, pNode->nodeHandle,                                  USB_RT_CLASS | USB_RT_OTHER, USB_HUB_FSEL_PORT_ENABLE, port + 1);            }        }    }    if ((pStatus->change & USB_HUB_C_PORT_ENABLE) != 0) {        /* Clear the port enable change indicator */        usbdFeatureClear (internalClient, pNode->nodeHandle,                          USB_RT_CLASS | USB_RT_OTHER, USB_HUB_FSEL_C_PORT_ENABLE, port + 1);    }    if ((pStatus->change & USB_HUB_C_PORT_SUSPEND) != 0) {        /* Clear the suspend change indicator */        usbdFeatureClear (internalClient, pNode->nodeHandle,                          USB_RT_CLASS | USB_RT_OTHER, USB_HUB_FSEL_C_PORT_SUSPEND, port + 1);    }    if ((pStatus->change & USB_HUB_C_PORT_OVER_CURRENT) != 0) {        /* Clear the over current change indicator */        usbdFeatureClear (internalClient, pNode->nodeHandle,                          USB_RT_CLASS | USB_RT_OTHER, USB_HUB_FSEL_C_PORT_OVER_CURRENT, port + 1);    }    if ((pStatus->change & USB_HUB_C_PORT_RESET) != 0) {        /* Clear the reset change indicator */        usbdFeatureClear (internalClient, pNode->nodeHandle,                          USB_RT_CLASS | USB_RT_OTHER, USB_HUB_FSEL_C_PORT_RESET, port + 1);    }}/***************************************************************************** hubIrpCallback - called when hub status IRP completes** By convention, the USB_IRP.userPtr field is a pointer to the USBD_NODE* for this transfer.** RETURNS: N/A*/LOCAL VOID hubIrpCallback (pVOID p  /* completed IRP */    ){    pUSB_IRP pIrp = (pUSB_IRP) p;    pUSBD_NODE pNode = (pUSBD_NODE) pIrp->userPtr;    /* If the IRP was canceled, it means that the hub node is being torn     * down, so don't queue a request for the bus thread.     */    if (pIrp->result != S_usbHcdLib_IRP_CANCELED) {        /* Let the bus thread update the port and re-queue the hub IRP. */        usbQueuePut (pNode->pBus->busQueue, BUS_FNC_UPDATE_HUB,                     0, (UINT32) pNode->nodeHandle, OSS_BLOCK);    }}

⌨️ 快捷键说明

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