📄 usbdcorelib.c
字号:
destroyClient (pClient); return s; }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; }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; }LOCAL VOID releaseAddress ( pUSBD_NODE pNode ) { pUSBD_BUS pBus = pNode->pBus; pBus->adrsVec [pNode->busAddress / 8] &= ~(0x1 << (pNode->busAddress % 8)); }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; }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) { 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); } } } } }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); } }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; }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 + -