📄 usbdcorelib.c
字号:
} else { /* Failed to attach...release allocated structs, etc. */ destroyHcd (pHcd); } return s; }/***************************************************************************** fncHcdDetach - Detach an HCD from the USBD** RETURNS: S_usbdLib_xxxx*/LOCAL int fncHcdDetach ( pURB_HCD_DETACH pUrb ) { pUSBD_HCD pHcd; int s; /* Validate URB */ if ((s = validateUrb (pUrb, sizeof (*pUrb), NULL)) != OK) return s; /* Validate attachToken */ if (usbHandleValidate (pUrb->attachToken, USBD_HCD_SIG, (pVOID *) &pHcd) != OK) return S_usbdLib_BAD_HANDLE; /* Detach the HCD and release HCD structures, etc. */ destroyHcd (pHcd); return s; }/***************************************************************************** fncStatisticsGet - Return USBD operating statistics** RETURNS: S_usbdLib_xxxx*/LOCAL int fncStatisticsGet ( pURB_STATISTICS_GET pUrb ) { pUSBD_NODE pNode; /* Validate root */ if (!validateNode (pUrb->nodeId, &pNode)) return S_usbdLib_BAD_HANDLE; /* Validate other parameters */ if (pUrb->pStatistics == NULL) return S_usbdLib_BAD_PARAM; /* Copy statistics to callers buffer */ memcpy (pUrb->pStatistics, &pNode->pBus->stats, min (pUrb->statLen, sizeof (pNode->pBus->stats))); return OK; }/***************************************************************************** fncBusCountGet - Returns number of USB buses in system** RETURNS: S_usbdLib_xxxx*/LOCAL int fncBusCountGet ( pURB_BUS_COUNT_GET pUrb ) { pUSBD_HCD pHcd; UINT16 busCount; busCount = 0; pHcd = usbListFirst (&hcdList); while (pHcd != NULL) { busCount += pHcd->busCount; pHcd = usbListNext (&pHcd->hcdLink); } pUrb->busCount = busCount; return OK; }/***************************************************************************** fncRootIdGet - Returns root node id for a USB** RETURNS: S_usbdLib_xxxx*/LOCAL int fncRootIdGet ( pURB_ROOT_ID_GET pUrb ) { pUSBD_HCD pHcd; UINT16 i; int s = OK; /* Find the HCD/bus corresponding to the index pUrb->busCount */ i = pUrb->busIndex; pHcd = usbListFirst (&hcdList); while (pHcd != NULL) { if (i < pHcd->busCount) { if (pHcd->pBuses [i].pRoot != NULL) pUrb->rootId = pHcd->pBuses [i].pRoot->nodeHandle; else s = S_usbdLib_INTERNAL_FAULT; break; } else { i -= pHcd->busCount; pHcd = usbListNext (&pHcd->hcdLink); } } if (pHcd == NULL) s = S_usbdLib_BAD_PARAM; return s; }/***************************************************************************** fncHubPortCountGet - Returns number of hubs on a port** RETURNS: S_usbdLib_xxxx*/LOCAL int fncHubPortCountGet ( pURB_HUB_PORT_COUNT_GET pUrb ) { pUSBD_NODE pNode; /* validate node handle */ if (!validateNode (pUrb->hubId, &pNode)) return S_usbdLib_BAD_HANDLE; if (pNode->nodeInfo.nodeType != USB_NODETYPE_HUB) return S_usbdLib_NOT_HUB; /* return number of ports on this hub */ pUrb->portCount = pNode->numPorts; return OK; }/***************************************************************************** fncNodeIdGet - Returns id of node attached to a hub port** RETURNS: S_usbdLib_xxxx*/LOCAL int fncNodeIdGet ( pURB_NODE_ID_GET pUrb ) { pUSBD_NODE pNode; /* validate node handle */ if (!validateNode (pUrb->hubId, &pNode)) return S_usbdLib_BAD_HANDLE; if (pNode->nodeInfo.nodeType != USB_NODETYPE_HUB) return S_usbdLib_NOT_HUB; /* If the port index is valid, return the node id, if any, attached * to this port. */ if (pUrb->portIndex >= pNode->numPorts) return S_usbdLib_BAD_PARAM; pUrb->nodeType = USB_NODETYPE_NONE; if (pNode->pPorts != NULL && pNode->pPorts [pUrb->portIndex].pNode != NULL) { pUrb->nodeType = pNode->pPorts [pUrb->portIndex].pNode->nodeInfo.nodeType; pUrb->nodeId = pNode->pPorts [pUrb->portIndex].pNode->nodeHandle; } return OK; }/***************************************************************************** scanClassTypes - Scans nodes for matching class types** Scan <pNode> and all child nodes to see if they have exposed one or more* class types matching that described in <pNotify>. If we find match(es),* then invoke the corresponding notification callbacks.** RETURNS: N/A*/LOCAL VOID scanClassTypes ( pUSBD_NODE pNode, pUSBD_CLIENT pClient, pUSBD_NOTIFY_REQ pNotify ) { pUSBD_NODE_CLASS pClassType; UINT16 portNo; if (pNode != NULL) { /* Scan all class types exposed for this node. */ pClassType = usbListFirst (&pNode->classTypes); while (pClassType != NULL) { notifyIfMatch (pNode, pClassType, pClient, pNotify, USBD_DYNA_ATTACH); pClassType = usbListNext (&pClassType->classLink); } /* If this node is a hub, then recursively scan child nodes. */ if (pNode->nodeInfo.nodeType == USB_NODETYPE_HUB && pNode->pPorts != NULL) { for (portNo = 0; portNo < pNode->numPorts; portNo++) scanClassTypes (pNode->pPorts [portNo].pNode, pClient, pNotify); } } }/***************************************************************************** fncDynaAttachReg - Register a client for dynamic attach notification** RETURNS: S_usbdLib_xxxx*/LOCAL int fncDynaAttachReg ( pURB_DYNA_ATTACH_REG_UNREG pUrb ) { pUSBD_CLIENT pClient; pUSBD_NOTIFY_REQ pNotify; pUSBD_HCD pHcd; UINT16 busNo; int s; /* Validate parameters. */ if ((s = validateUrb (pUrb, sizeof (*pUrb), &pClient)) != OK) return s; if (pUrb->attachCallback == NULL) return S_usbdLib_BAD_PARAM; /* Create a new dynamic notification request structure */ if ((pNotify = OSS_CALLOC (sizeof (*pNotify))) == NULL) return S_usbdLib_OUT_OF_MEMORY; pNotify->deviceClass = pUrb->deviceClass; pNotify->deviceSubClass = pUrb->deviceSubClass; pNotify->deviceProtocol = pUrb->deviceProtocol; pNotify->callback = pUrb->attachCallback; /* Link this to the list of notification requests for the client */ usbListLink (&pClient->notifyReqs, pNotify, &pNotify->reqLink, LINK_TAIL); /* At the time of the initial notification registration (now), it is * necessary to scan the list of devices already attached to the USB(s) * in order to see if any match the request. Devices attached/removed * later will be handled by the busThread. */ pHcd = usbListFirst (&hcdList); while (pHcd != NULL) { for (busNo = 0; busNo < pHcd->busCount; busNo++) scanClassTypes (pHcd->pBuses [busNo].pRoot, pClient, pNotify); pHcd = usbListNext (&pHcd->hcdLink); } return OK; }/***************************************************************************** fncDynaAttachUnreg - Unregister a client for dynamic attach notification** RETURNS: S_usbdLib_xxxx*/LOCAL int fncDynaAttachUnreg ( pURB_DYNA_ATTACH_REG_UNREG pUrb ) { pUSBD_CLIENT pClient; pUSBD_NOTIFY_REQ pNotify; int s; /* Validate parameters. */ if ((s = validateUrb (pUrb, sizeof (*pUrb), &pClient)) != OK) return s; /* Search the client's list of notification requests for one which * matches exactly the parameters in the URB. */ pNotify = usbListFirst (&pClient->notifyReqs); while (pNotify != NULL) { if (pNotify->deviceClass == pUrb->deviceClass && pNotify->deviceSubClass == pUrb->deviceSubClass && pNotify->deviceProtocol == pUrb->deviceProtocol && pNotify->callback == pUrb->attachCallback) { /* We found a matching notification request. Destroy it. */ destroyNotify (pNotify); return OK; } pNotify = usbListNext (&pNotify->reqLink); } /* If we get this far, no matching request was found. Declare an error */ return S_usbdLib_GENERAL_FAULT; }/***************************************************************************** controlIrpCallback - called when control pipe Irp completes** By convention, the USB_IRP.userPtr field is a pointer to the USBD_NODE* for this transfer.** RETURNS: N/A*/LOCAL VOID controlIrpCallback ( pVOID p /* completed IRP */ ) { pUSB_IRP pIrp = (pUSB_IRP) p; pUSBD_NODE pNode = pIrp->userPtr; pURB_HEADER pUrb = pNode->pUrb; /* Store the actual length transferred */ if (pNode->pActLen != NULL) *pNode->pActLen = pIrp->bfrList [1].actLen; /* Store the completion result in the URB */ setUrbResult (pUrb, (pIrp->result == OK) ? OK : S_usbdLib_IO_FAULT); /* We're done with the control pipe structures for this node. */ OSS_SEM_GIVE (pNode->controlSem); }/***************************************************************************** controlRequest - Formats and submits a control transfer request** This is an internal utility function which formats a USB Setup packet* and sends it to the control pipe of a node.** RETURNS: S_usbdLib_xxxx*/LOCAL int controlRequest ( pURB_HEADER pUrb, /* URB header */ USBD_NODE_ID nodeId, /* node id */ UINT8 requestType, /* bmRequestType */ UINT8 request, /* bRequest */ UINT16 value, /* wValue */ UINT16 index, /* wIndex */ UINT16 length, /* wLength */ pVOID pBfr, /* data */ pUINT16 pActLen /* actual len for IN data */ ) { pUSBD_CLIENT pClient; pUSBD_NODE pNode; pUSB_SETUP pSetup; pUSB_IRP pIrp; /* validate the client handle for this request */ if (!validateClient (pUrb->handle, &pClient)) return S_usbdLib_BAD_HANDLE; /* validate the node to which this request is directed */ if (!validateNode (nodeId, &pNode)) return S_usbdLib_BAD_HANDLE; /* Only one control request can be outstanding at a time. */ if (OSS_SEM_TAKE (pNode->controlSem, EXCLUSION_TIMEOUT) != OK) return S_usbdLib_TIMEOUT; /* we now own the control mutex for this node. format and issue the * control request to this node. */ pSetup = &pNode->setup; pIrp = &pNode->irp; /* format the setup packet */ pSetup->requestType = requestType; pSetup->request = request; pSetup->value = TO_LITTLEW (value); pSetup->index = TO_LITTLEW (index); pSetup->length = TO_LITTLEW (length); /* format an IRP to execute this control transfer */ memset (pIrp, 0, sizeof (USB_IRP) + sizeof (USB_BFR_LIST)); pIrp->userPtr = pNode; pIrp->irpLen = sizeof (USB_IRP) + sizeof (USB_BFR_LIST); pIrp->userCallback = controlIrpCallback; pIrp->flags = USB_FLAG_SHORT_OK; pIrp->timeout = USB_TIMEOUT_DEFAULT; pIrp->transferLen = sizeof (USB_SETUP) + length; /* format bfrList [] entry for Setup packet */ pIrp->bfrCount = 0; pIrp->bfrList [pIrp->bfrCount].pid = USB_PID_SETUP; pIrp->bfrList [pIrp->bfrCount].pBfr = (pUINT8) pSetup; pIrp->bfrList [pIrp->bfrCount].bfrLen = sizeof (USB_SETUP); pIrp->bfrCount++; /* format bfrList [] entry for data stage, if any. */ if (length > 0) { pIrp->bfrList [pIrp->bfrCount].pid = ((requestType & USB_RT_DEV_TO_HOST) != 0) ? USB_PID_IN : USB_PID_OUT; pIrp->bfrList [pIrp->bfrCount].pBfr = pBfr; pIrp->bfrList [pIrp->bfrCount].bfrLen = length; pIrp->bfrCount++; } /* All control transfers are followed by a "status" packet for which * the direction is the opposite of that for the data stage and the * length of the transfer is 0. */ pIrp->bfrList [pIrp->bfrCount].pid = ((requestType & USB_RT_DEV_TO_HOST) != 0) ? USB_PID_OUT : USB_PID_IN; pIrp->bfrList [pIrp->bfrCount].pBfr = NULL; pIrp->bfrL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -