📄 usbdcorelib.c
字号:
/* 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->bfrList [pIrp->bfrCount].bfrLen = 0; pIrp->bfrCount++; /* Store info about pending control IRP in node struct */ pNode->pClient = pClient; pNode->pUrb = pUrb; pNode->pActLen = pActLen; /* submit the control transfer IRP. * * NOTE: If usbHcdIrpSubmit fails, it will still invoke the IRP callback * which will in turn release the controlSem taken above. The * callback will also set the URB completion status. */ if (usbdTransfer (internalClient, pNode->controlPipe, pIrp) != OK) return S_usbdLib_GENERAL_FAULT; return PENDING; }/***************************************************************************** resetDataToggle - reset data toggle on affected pipes** This function is called when a "configuration event" is detected* for a given node. This function searches all pipes associated with* the node for any that might be affected by the configuration event* and resets their data toggles to DATA0.** RETURNS: N/A*/LOCAL VOID resetDataToggle ( USBD_NODE_ID nodeId, UINT16 configuration, UINT16 interface, UINT16 endpoint ) { pUSBD_NODE pNode; pUSBD_PIPE pPipe; if (!validateNode (nodeId, &pNode)) return; pPipe = usbListFirst (&pNode->pipes); while (pPipe != NULL) { if (configuration == ANY_CONFIGURATION || configuration == pPipe->configuration) { if (interface == ANY_INTERFACE || interface == pPipe->interface) { if (endpoint == ANY_ENDPOINT || endpoint == pPipe->endpoint) { pPipe->dataToggle = USB_DATA0; } } } pPipe = usbListNext (&pPipe->nodePipeLink); } }/***************************************************************************** fncFeatureClear - Clear a USB feature** RETURNS: S_usbdLib_xxxx*/LOCAL int fncFeatureClear ( pURB_FEATURE_CLEAR_SET pUrb ) { /* Check if this constitutes a configuration event. So, reset the * data toggle for any affected pipes. */ if (pUrb->requestType == (USB_RT_STANDARD | USB_RT_ENDPOINT) && pUrb->feature == USB_FSEL_DEV_ENDPOINT_HALT) { resetDataToggle (pUrb->nodeId, ANY_CONFIGURATION, ANY_INTERFACE, pUrb->index); } return controlRequest (&pUrb->header, pUrb->nodeId, USB_RT_HOST_TO_DEV | pUrb->requestType, USB_REQ_CLEAR_FEATURE, pUrb->feature, pUrb->index, 0, NULL, NULL); }/***************************************************************************** fncFeatureSet - Set a USB feature** RETURNS: S_usbdLib_xxxx*/LOCAL int fncFeatureSet ( pURB_FEATURE_CLEAR_SET pUrb ) { return controlRequest (&pUrb->header, pUrb->nodeId, USB_RT_HOST_TO_DEV | pUrb->requestType, USB_REQ_SET_FEATURE, pUrb->feature, pUrb->index, 0, NULL, NULL); }/***************************************************************************** fncConfigGet - Get a device's configuration** RETURNS: S_usbdLib_xxxx*/LOCAL int fncConfigGet ( pURB_CONFIG_GET_SET pUrb ) { pUrb->configuration = 0; return controlRequest (&pUrb->header, pUrb->nodeId, USB_RT_DEV_TO_HOST | USB_RT_STANDARD | USB_RT_DEVICE, USB_REQ_GET_CONFIGURATION, 0, 0, 1, &pUrb->configuration, NULL); }/***************************************************************************** fncConfigSet - Set a device's configuration** RETURNS: S_usbdLib_xxxx*/LOCAL int fncConfigSet ( pURB_CONFIG_GET_SET pUrb ) { pUSBD_NODE pNode; pUSBD_NODE pParentNode; /* Validate parameters */ if (!validateNode (pUrb->nodeId, &pNode)) return S_usbdLib_BAD_HANDLE; /* Verify that the port to which this device is connected is capable of * providing the current needed by this device. */ if (pNode != pNode->pBus->pRoot && pNode->pBus->pRoot != NULL) { /* Retrieve the pointer to the parent hub for this node */ validateNode (pNode->nodeInfo.parentHubId, &pParentNode); /* Check the power required against the parent's capability */ if (pUrb->maxPower > pParentNode->maxPowerPerPort) return S_usbdLib_POWER_FAULT; } /* This constitutes a configuration event. So, reset the data toggle * for any affected pipes. */ resetDataToggle (pUrb->nodeId, pUrb->configuration, ANY_INTERFACE, ANY_ENDPOINT); /* Set the device's configuration */ return controlRequest (&pUrb->header, pUrb->nodeId, USB_RT_HOST_TO_DEV | USB_RT_STANDARD | USB_RT_DEVICE, USB_REQ_SET_CONFIGURATION, pUrb->configuration, 0, 0, NULL, NULL); }/***************************************************************************** fncDescriptorGet - Retrieve a USB descriptor** RETURNS: S_usbdLib_xxxx*/LOCAL int fncDescriptorGet ( pURB_DESCRIPTOR_GET_SET pUrb ) { return controlRequest (&pUrb->header, pUrb->nodeId, USB_RT_DEV_TO_HOST | pUrb->requestType, USB_REQ_GET_DESCRIPTOR, pUrb->descriptorType << 8 | pUrb->descriptorIndex, pUrb->languageId, pUrb->bfrLen, pUrb->pBfr, &pUrb->actLen); }/***************************************************************************** fncDescriptorSet - Sets a USB descriptor** RETURNS: S_usbdLib_xxxx*/LOCAL int fncDescriptorSet ( pURB_DESCRIPTOR_GET_SET pUrb ) { return controlRequest (&pUrb->header, pUrb->nodeId, USB_RT_HOST_TO_DEV | pUrb->requestType, USB_REQ_SET_DESCRIPTOR, pUrb->descriptorType << 8 | pUrb->descriptorIndex, pUrb->languageId, pUrb->bfrLen, pUrb->pBfr, NULL); }/***************************************************************************** fncInterfaceGet - Returns a device's interface setting** RETURNS: S_usbdLib_xxxx*/LOCAL int fncInterfaceGet ( pURB_INTERFACE_GET_SET pUrb ) { pUrb->alternateSetting = 0; return controlRequest (&pUrb->header, pUrb->nodeId, USB_RT_DEV_TO_HOST | USB_RT_STANDARD | USB_RT_INTERFACE, USB_REQ_GET_INTERFACE, 0, pUrb->interfaceIndex, 1, &pUrb->alternateSetting, NULL); }/***************************************************************************** fncInterfaceSet - Sets a device's interface setting** RETURNS: S_usbdLib_xxxx*/LOCAL int fncInterfaceSet ( pURB_INTERFACE_GET_SET pUrb ) { /* This constitutes a configuration event. So, reset the data toggle * for any affected pipes. */ resetDataToggle (pUrb->nodeId, ANY_CONFIGURATION, pUrb->interfaceIndex, ANY_ENDPOINT); return controlRequest (&pUrb->header, pUrb->nodeId, USB_RT_HOST_TO_DEV | USB_RT_STANDARD | USB_RT_INTERFACE, USB_REQ_SET_INTERFACE, pUrb->alternateSetting, pUrb->interfaceIndex, 0, NULL, NULL); }/***************************************************************************** fncStatusGet - Returns a device/interface/endpoint status word** RETURNS: S_usbdLib_xxxx*/LOCAL int fncStatusGet ( pURB_STATUS_GET pUrb ) { return controlRequest (&pUrb->header, pUrb->nodeId, USB_RT_DEV_TO_HOST | pUrb->requestType, USB_REQ_GET_STATUS, 0, pUrb->index, pUrb->bfrLen, pUrb->pBfr, &pUrb->actLen); }/***************************************************************************** fncAddressGet - Returns a node's USB address** RETURNS: S_usbdLib_xxxx*/LOCAL int fncAddressGet ( pURB_ADDRESS_GET_SET pUrb ) { pUSBD_NODE pNode; /* validate node handle */ if (!validateNode (pUrb->nodeId, &pNode)) return S_usbdLib_BAD_HANDLE; /* return current USB address for node */ pUrb->deviceAddress = pNode->busAddress; return OK; }/***************************************************************************** fncAddressSet - Sets a node's USB address** RETURNS: S_usbdLib_xxxx*/LOCAL int fncAddressSet ( pURB_ADDRESS_GET_SET pUrb ) { int s; s = controlRequest (&pUrb->header, pUrb->nodeId, USB_RT_HOST_TO_DEV | USB_RT_STANDARD | USB_RT_DEVICE, USB_REQ_SET_ADDRESS, pUrb->deviceAddress, 0, 0, NULL, NULL); OSS_THREAD_SLEEP (USB_TIME_SET_ADDRESS); return s; }/***************************************************************************** fncNodeInfoGet - Returns information about a node** RETURNS: S_usbdLib_xxxx*/LOCAL int fncNodeInfoGet ( pURB_NODE_INFO_GET pUrb ) { pUSBD_NODE pNode; /* Validate root */ if (!validateNode (pUrb->nodeId, &pNode)) return S_usbdLib_BAD_HANDLE; /* Validate other parameters */ if (pUrb->pNodeInfo == NULL) return S_usbdLib_BAD_PARAM; /* Copy node info to caller's buffer */ memcpy (pUrb->pNodeInfo, &pNode->nodeInfo, min (pUrb->infoLen, sizeof (pNode->nodeInfo))); return OK; }/***************************************************************************** fncVendorSpecific - Executes a vendor-specific USB request** RETURNS: S_usbdLib_xxxx*/LOCAL int fncVendorSpecific ( pURB_VENDOR_SPECIFIC pUrb ) { return controlRequest (&pUrb->header, pUrb->nodeId, pUrb->requestType, pUrb->request, pUrb->value, pUrb->index, pUrb->length, pUrb->pBfr, &pUrb->actLen); }/***************************************************************************** fncPipeCreate - Create a new transfer pipe** RETURNS: S_usbdLib_xxxx*/LOCAL int fncPipeCreate ( pURB_PIPE_CREATE pUrb ) { pUSBD_CLIENT pClient; pUSBD_NODE pNode; pUSBD_PIPE pPipe; pUSBD_BUS pBus; UINT32 nanoseconds = 0; HCD_PIPE_HANDLE hcdPipeHandle; /* validate the client handle for this request */ if (!validateClient (pUrb->header.handle, &pClient)) return S_usbdLib_BAD_HANDLE; /* validate the node to which this request is directed */ if (!validateNode (pUrb->nodeId, &pNode)) return S_usbdLib_BAD_HANDLE; /* Validate other parameters */ if ((pUrb->transferType == USB_XFRTYPE_ISOCH || pUrb->transferType == USB_XFRTYPE_INTERRUPT) && pUrb->bandwidth == 0) return S_usbdLib_BAD_PARAM; if (pUrb->transferType == USB_XFRTYPE_INTERRUPT && pUrb->serviceInterval == 0) return S_usbdLib_BAD_PARAM; /* Make sure a default packet size is specified */ if (pUrb->maxPayload == 0) pUrb->maxPayload = USB_MIN_CTRL_PACKET_SIZE; /* Notify HCD of new pipe and make sure enough bandwidth is available to * create the pipe. */ pBus = pNode->pBus; if (usbHcdPipeCreate (&pBus->pHcd->ne
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -