📄 usbtarglib.c
字号:
/* This request isn't supported unless the target application has * provided a statusGet handler. */ if (pTcd->pCallbacks->statusGet == NULL) return ERROR; if ((*pTcd->pCallbacks->statusGet) (pTcd->callbackParam, pTcd->targChannel, pSetup->requestType, index, min (length, sizeof (pTcd->dataBfr)), pTcd->dataBfr, &actLen) != OK) { return ERROR; } /* Transmit the descriptor back to the host */ return initDataErpForResponse (pTcd, actLen); }/***************************************************************************** requestSetAddress - processes a SET_ADDRESS setup packet** RETURNS: OK if setup packet valid, else ERROR if invalid*/LOCAL STATUS requestSetAddress ( pTARG_TCD pTcd, pUSB_SETUP pSetup ) { UINT16 deviceAddress = FROM_LITTLEW (pSetup->value); /* If the target application has provided a SetAddress callback, * then invoke it now. */ if (pTcd->pCallbacks->addressSet != NULL) (*pTcd->pCallbacks->addressSet) (pTcd->callbackParam, pTcd->targChannel, deviceAddress); /* The new address goes into effect after the Status phase, if any. */ pTcd->deviceAddress = deviceAddress; usbTcdAddressSet (&pTcd->tcdNexus, pTcd->deviceAddress); return initStatusErp (pTcd, USB_PID_IN); }/***************************************************************************** requestGetSynchFrame - processes a GET_SYNCH_FRAME setup packet** RETURNS: OK if setup packet valid, else ERROR if invalid*/LOCAL STATUS requestGetSynchFrame ( pTARG_TCD pTcd, pUSB_SETUP pSetup ) { UINT16 endpoint = FROM_LITTLEW (pSetup->index); /* This request isn't supported unless the target application has * provided a synchFrameGet handler. */ if (pTcd->pCallbacks->synchFrameGet == NULL) return ERROR; /* Get the synch frame from the target application. */ if ((*pTcd->pCallbacks->synchFrameGet) (pTcd->callbackParam, pTcd->targChannel, endpoint, (pUINT16) pTcd->dataBfr) != OK) return ERROR; /* Transmit the synch frame back to the host */ return initDataErpForResponse (pTcd, sizeof (UINT16)); }/***************************************************************************** requestVendorSpecific - processes a "vendor specific" setup packet** RETURNS: OK if setup packet valid, else ERROR if invalid*/LOCAL STATUS requestVendorSpecific ( pTARG_TCD pTcd, pUSB_SETUP pSetup ) { /* This request isn't supported unless the target application has * provided a vendorSpecific handler. */ if (pTcd->pCallbacks->vendorSpecific == NULL) return ERROR; return (*pTcd->pCallbacks->vendorSpecific) (pTcd->callbackParam, pTcd->targChannel, pSetup->requestType, pSetup->request, FROM_LITTLEW (pSetup->value), FROM_LITTLEW (pSetup->index), FROM_LITTLEW (pSetup->length)); }/***************************************************************************** parseSetupPacket - parse/execute a control pipe request** The TARGET.setupBfr should contain a setup packet. Validate it. If* valid, parse and execute it.** RETURNS: OK if setup packet valid, else ERROR if invalid*/LOCAL STATUS parseSetupPacket ( pTARG_TCD pTcd ) { pUSB_SETUP pSetup; /* Validate the setup packet */ if (pTcd->setupErp.bfrList [0].actLen != sizeof (USB_SETUP)) return ERROR; pSetup = (pUSB_SETUP) pTcd->setupBfr; /* Execute based on the type of request. */ if ((pSetup->requestType & USB_RT_CATEGORY_MASK) == USB_RT_STANDARD) { switch (pSetup->request) { case USB_REQ_CLEAR_FEATURE: return requestClearFeature (pTcd, pSetup); case USB_REQ_SET_FEATURE: return requestSetFeature (pTcd, pSetup); case USB_REQ_GET_CONFIGURATION: return requestGetConfiguration (pTcd, pSetup); case USB_REQ_SET_CONFIGURATION: return requestSetConfiguration (pTcd, pSetup); case USB_REQ_GET_DESCRIPTOR: return requestGetDescriptor (pTcd, pSetup); case USB_REQ_SET_DESCRIPTOR: return requestSetDescriptor (pTcd, pSetup); case USB_REQ_GET_INTERFACE: return requestGetInterface (pTcd, pSetup); case USB_REQ_SET_INTERFACE: return requestSetInterface (pTcd, pSetup); case USB_REQ_GET_STATUS: return requestGetStatus (pTcd, pSetup); case USB_REQ_SET_ADDRESS: return requestSetAddress (pTcd, pSetup); case USB_REQ_GET_SYNCH_FRAME: return requestGetSynchFrame (pTcd, pSetup); default: break; } } return requestVendorSpecific (pTcd, pSetup); }/***************************************************************************** setupErpCallback - invoked when Setup ERP completes** This function receives control when a Setup ERP completes. Examines the* reason for completion, possibly invoking additional control request* handling.** RETURNS: N/A*/LOCAL VOID setupErpCallback ( pVOID p /* ptr to ERP */ ) { pUSB_ERP pErp = (pUSB_ERP) p; pTARG_TCD pTcd = (pTARG_TCD) pErp->userPtr; pTcd->setupErpPending = FALSE; /* Completion of a setup ERP, whether successful or not, implies that * any previous control pipe request must be terminated. */ if (pTcd->dataErpPending) cancelErp ((pTARG_PIPE) pTcd->dataErp.targPtr, &pTcd->dataErp); if (pTcd->statusErpPending) cancelErp ((pTARG_PIPE) pTcd->dataErp.targPtr, &pTcd->statusErp); /* Was the ERP successful? */ if (pErp->result == OK) { /* The ERP was successful. Parse the setup packet. */ if (parseSetupPacket (pTcd) == OK) { /* The packet can be parsed successfully. Other code will * take care of resubmitting the Setup ERP, so we do nothing. */ return; } else { /* We cannot process the indicated command. Stall the * control pipe. */ usbTargPipeStatusSet (pTcd->targChannel, pTcd->controlPipe, TCD_ENDPOINT_STALL); } } /* Re-submit the ERP unless it was canceled - which indicates that * the pipe is probably being torn down. */ if (pErp->result != S_usbTcdLib_ERP_CANCELED) initSetupErp (pTcd); }/***************************************************************************** responseErpCallback - invoked when control pipe response ERP completes** This function receives control after the data IN phase of a control pipe* request has completed.** RETURNS: N/A*/LOCAL VOID responseErpCallback ( pVOID p /* ptr to ERP */ ) { pUSB_ERP pErp = (pUSB_ERP) p; pTARG_TCD pTcd = (pTARG_TCD) pErp->userPtr; pTcd->dataErpPending = FALSE; /* If the ERP was successful, then we prepare the status phase. The * status phase is always in the oppposite direction to the data phase. * Since this callback handles only "responses" (from device to host), * then the status phase will always be an OUT (from host to device). * * If the data phase failed for some reason other than being canceled, * then we resubmit the Setup phase ERP to ensure that the target * continues to be responsive on the control pipe. */ if (pErp->result == OK) { initStatusErp (pTcd, USB_PID_OUT); return; } if (pErp->result != S_usbTcdLib_ERP_CANCELED) initSetupErp (pTcd); }/***************************************************************************** statusErpCallback - invoked when control pipe status packet completes** This function receives control after the status phase of a control pipe* request has completed.** RETURNS: N/A*/LOCAL VOID statusErpCallback ( pVOID p /* ptr to ERP */ ) { pUSB_ERP pErp = (pUSB_ERP) p; pTARG_TCD pTcd = (pTARG_TCD) pErp->userPtr; pTcd->statusErpPending = FALSE; /* Re-submit the Setup ERP. */ if (pErp->result != S_usbTcdLib_ERP_CANCELED) initSetupErp (pTcd); }/***************************************************************************** usbTargManagementCallback - invoked when TCD detects management event** This function is invoked by a TCD when the TCD detects a "management"* event on a target channel. Examples of management events include* bus resets, detection of a new or lost connection, etc.** RETURNS: N/A*/LOCAL VOID usbTargManagementCallback ( pVOID mngmtCallbackParam, /* caller-defined param */ TCD_HANDLE handle, /* channel */ UINT16 mngmtCode /* management code */ ) { pTARG_TCD pTcd = (pTARG_TCD) mngmtCallbackParam; switch (mngmtCode) { case TCD_MNGMT_VBUS_LOST: case TCD_MNGMT_BUS_RESET: /* Reset the device configuration to the power-on state. */ pTcd->deviceAddress = 0; /* code falls through into following case */ case TCD_MNGMT_VBUS_DETECT: case TCD_MNGMT_SUSPEND: case TCD_MNGMT_RESUME: /* reflect the management event to the target application */ mngmtFunc (pTcd, mngmtCode); break; } }/***************************************************************************** usbTargErpCallback - invoked when ERP completes** The TCD invokes this callback when an ERP completes. This gives us the* opportunity to monitor ERP execution. We reflect the callback to the* calling application after we finish our processing.** NOTE: By convention, the targPtr field of the ERP has been initialized* to point to the TARG_PIPE for this ERP.** RETURNS: N/A*/LOCAL VOID usbTargErpCallback ( pVOID p /* ptr to ERP */ ) { pUSB_ERP pErp = (pUSB_ERP) p; pTARG_PIPE pPipe = (pTARG_PIPE) pErp->targPtr; UINT16 packets; UINT16 i; OSS_MUTEX_TAKE (targMutex, OSS_BLOCK); /* Unlink the ERP */ usbListUnlink (&pErp->targLink); /* Check if this ERP is being deleted. If so, let the foreground * thread know the callback has been invoked. */ if (pErp == pPipe->erpBeingDeleted) pPipe->erpDeleted = TRUE; /* Update data toggle for pipe. Control and isochronous transfers * always begin with DATA0, which is set at pipe initialization - * so we don't change it here. Bulk and interrupt pipes alternate * between DATA0 and DATA1, and we need to keep a running track of * the state across ERPs. */ if (pErp->transferType == USB_XFRTYPE_INTERRUPT || pErp->transferType == USB_XFRTYPE_BULK) { /* Calculate the number of packets exchanged to determine the * next data toggle value. If the count of packets is odd, then * the data toggle needs to switch. * * NOTE: If the ERP is successful, then at least one packet MUST * have been transferred. However, it may have been a 0-length * packet. This case is handled after the following "for" loop. */ packets = 0; for (i = 0; i < pErp->bfrCount; i++) { packets += (pErp->bfrList [i].actLen + pPipe->pEndpoint->maxPacketSize - 1) / pPipe->pEndpoint->maxPacketSize; } if (pErp->result == OK) packets = max (packets, 1); if ((packets & 1) != 0) pPipe->dataToggle = (pPipe->dataToggle == USB_DATA0) ? USB_DATA1 : USB_DATA0; } /* Invoke the user's callback routine */ if (pErp->userCallback != NULL) (*pErp->userCallback) (pErp); OSS_MUTEX_RELEASE (targMutex); }/***************************************************************************** usbTargVersionGet - Retrieve usbTargLib version** This function returns the usbTargLib version. If <pVersion> is not NULL, the * usbTargLib returns its version in BCD in <pVersion>. For example, version * "1.02" would be coded as 01h in the high byte and 02h in the low byte.** If <pMfg> is not NULL it must point to a buffer of at least USBT_NAME_LEN * bytes in length in which the USBD will store the NULL terminated name of* the usbTargLib manufacturer (e.g., "Wind River Systems" + \0).** RETURNS: OK*/ STATUS usbTargVersionGet ( pUINT16 pVersion, /* usbTargLib version */ pCHAR pMfg /* usbTargLib manufacturer */ ) { /* return version info */ if (pVersion != NULL) *pVersion = TARG_VERSION; if (pMfg != NULL) strncpy (pMfg, TARG_MFG, USBT_NAME_LEN); return OK; }/***************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -