📄 usbloopbacklib.c
字号:
pUSB_INTERFACE_DESCR pIfDescr = NULL; pUSB_ENDPOINT_DESCR pBulkOutEp = NULL; pUSB_ENDPOINT_DESCR pBulkInEp = NULL; pUSB_ENDPOINT_DESCR pIntOutEp = NULL; pUSB_ENDPOINT_DESCR pIntInEp = NULL; pUSB_ENDPOINT_DESCR pIsochOutEp = NULL; pUSB_ENDPOINT_DESCR pIsochInEp = NULL; UINT8 * pBfr; UINT8 * pScratchBfr; UINT16 actLen; UINT16 ifNo; UINT16 maxPacketSize; if ((pBfr = OSS_MALLOC (USB_MAX_DESCR_LEN)) == NULL) return ERROR; /* Read the configuration descriptor to get the configuration selection * value and to determine the device's power requirements. */ if (usbdDescriptorGet (usbdHandle, pLoopbackDev->nodeId, USB_RT_STANDARD | USB_RT_DEVICE, USB_DESCR_CONFIGURATION, 0, 0, USB_MAX_DESCR_LEN, pBfr, &actLen) != OK) { OSS_FREE (pBfr); return ERROR; } if ((pCfgDescr = usbDescrParse (pBfr, actLen, USB_DESCR_CONFIGURATION)) == NULL) { OSS_FREE (pBfr); return ERROR; } /* Look for the interface indicated in the pLoopbackDev structure. */ ifNo = 0; /* * usbDescrParseSkip() modifies the value of the pointer it recieves * so we pass it a copy of our buffer pointer */ pScratchBfr = pBfr; while ((pIfDescr = usbDescrParseSkip (&pScratchBfr, &actLen, USB_DESCR_INTERFACE)) != NULL) { if (ifNo == pLoopbackDev->interface) break; ifNo++; } if (pIfDescr == NULL) { OSS_FREE (pBfr); return ERROR; } /* Retrieve the endpoint descriptor(s) following the identified interface * descriptor. */ if (USB_IS_BULK_LOOPBACK_SUPPORTED(pLoopbackDev ->protocol)) { if ((pBulkOutEp = findEndpoint (pScratchBfr, actLen, USB_ENDPOINT_OUT,USB_ATTR_BULK)) == NULL) { OSS_FREE (pBfr); return ERROR; } if ((pBulkInEp = findEndpoint (pScratchBfr, actLen, USB_ENDPOINT_IN,USB_ATTR_BULK)) == NULL) { OSS_FREE (pBfr); return ERROR; } } if (USB_IS_INT_LOOPBACK_SUPPORTED(pLoopbackDev ->protocol)) { if ((pIntOutEp = findEndpoint (pScratchBfr, actLen, USB_ENDPOINT_OUT,USB_ATTR_INTERRUPT)) == NULL) { OSS_FREE (pBfr); return ERROR; } if ((pIntInEp = findEndpoint (pScratchBfr, actLen, USB_ENDPOINT_IN, USB_ATTR_INTERRUPT)) == NULL) { OSS_FREE (pBfr); return ERROR; } } if (USB_IS_ISOCH_LOOPBACK_SUPPORTED(pLoopbackDev ->protocol)) { if ((pIsochOutEp = findEndpoint (pScratchBfr, actLen, USB_ENDPOINT_OUT,USB_ATTR_ISOCH)) == NULL) { OSS_FREE (pBfr); return ERROR; } if ((pIsochInEp = findEndpoint (pScratchBfr, actLen, USB_ENDPOINT_IN, USB_ATTR_ISOCH)) == NULL) { OSS_FREE (pBfr); return ERROR; } } /* Select the configuration. */ if (usbdConfigurationSet (usbdHandle, pLoopbackDev->nodeId, pCfgDescr->configurationValue, pCfgDescr->maxPower * USB_POWER_MA_PER_UNIT) != OK) { OSS_FREE (pBfr); return ERROR; } /* Update the current configuration in the pLoopbackDev */ pLoopbackDev->configuration = pCfgDescr->configurationValue; /* Select interface * * NOTE: Some devices may reject this command, and this does not represent * a fatal error. Therefore, we ignore the return status. */ usbdInterfaceSet (usbdHandle, pLoopbackDev->nodeId, pLoopbackDev->interface, pIfDescr->alternateSetting); pLoopbackDev->alternateSetting = pIfDescr->alternateSetting; if (USB_IS_BULK_LOOPBACK_SUPPORTED(pLoopbackDev->protocol)) { /* Create semaphore used for bulk loopback synchronization */ if (OSS_SEM_CREATE (1, 0 , &(pLoopbackDev->bulkLoopbackSem)) != OK) { return (S_usbLoopbackLib_OUT_OF_RESOURCES); } /* Create a pipe for bulk output to the Loopback. */ maxPacketSize = *((pUINT8) &pBulkOutEp->maxPacketSize) | (*(((pUINT8) &pBulkOutEp->maxPacketSize) + 1) << 8); /* update the bulk out ep address in pLoopback device */ pLoopbackDev->bulkOutEpAddress = pBulkOutEp->endpointAddress; if (usbdPipeCreate (usbdHandle, pLoopbackDev->nodeId, pBulkOutEp->endpointAddress, pCfgDescr->configurationValue, pLoopbackDev->interface, USB_XFRTYPE_BULK, USB_DIR_OUT, maxPacketSize, 0, 0, &pLoopbackDev->bulkOutPipeHandle) != OK) { printf("bulk out pipe creation failed \n"); OSS_FREE (pBfr); return ERROR; } /* Create a pipe for bulk In from the Loopback. */ maxPacketSize = *((pUINT8) &pBulkInEp->maxPacketSize) | (*(((pUINT8) &pBulkInEp->maxPacketSize) + 1) << 8); /* update the bulk IN ep address in pLoopback device */ pLoopbackDev->bulkInEpAddress = pBulkInEp->endpointAddress; if (usbdPipeCreate (usbdHandle, pLoopbackDev->nodeId, pBulkInEp->endpointAddress, pCfgDescr->configurationValue, pLoopbackDev->interface, USB_XFRTYPE_BULK, USB_DIR_IN, maxPacketSize, 0, 0, &pLoopbackDev->bulkInPipeHandle) != OK) { printf("bulk in pipe creation failed \n"); OSS_FREE (pBfr); return ERROR; } } if (USB_IS_INT_LOOPBACK_SUPPORTED(pLoopbackDev ->protocol)) { /* Create semaphore used for bulk loopback synchronization */ if (OSS_SEM_CREATE (1, 0 , &(pLoopbackDev->intLoopbackSem)) != OK) { return (S_usbLoopbackLib_OUT_OF_RESOURCES); } /* Create a pipe for Interrupt output to the Loopback. */ maxPacketSize = *((pUINT8) &pIntOutEp->maxPacketSize) | (*(((pUINT8) &pIntOutEp->maxPacketSize) + 1) << 8); /* update the Int out ep address in pLoopback device */ pLoopbackDev->intOutEpAddress = pIntOutEp->endpointAddress; if (usbdPipeCreate (usbdHandle, pLoopbackDev->nodeId, pIntOutEp->endpointAddress, pCfgDescr->configurationValue, pLoopbackDev->interface, USB_XFRTYPE_INTERRUPT, USB_DIR_OUT, maxPacketSize, USB_LOOPBACK_DEFAULT_BANDWIDTH_INT_OUT,/* bandwidth For interrupt pipes, * this parameter should express the number * of bytes per frame to be transferred. */ pIntOutEp->interval, &pLoopbackDev->intOutPipeHandle) != OK) { printf("Interrupt out pipe creation failed \n"); OSS_FREE (pBfr); return ERROR; } /* Create a pipe for Interrupt In from the Loopback. */ maxPacketSize = *((pUINT8) &pIntInEp->maxPacketSize) | (*(((pUINT8) &pIntInEp->maxPacketSize) + 1) << 8); /* update the Int in ep address in pLoopback device */ pLoopbackDev->intInEpAddress = pIntInEp->endpointAddress; if (usbdPipeCreate (usbdHandle, pLoopbackDev->nodeId, pIntInEp->endpointAddress, pCfgDescr->configurationValue, pLoopbackDev->interface, USB_XFRTYPE_INTERRUPT, USB_DIR_IN, maxPacketSize, USB_LOOPBACK_DEFAULT_BANDWIDTH_INT_IN, /* bandwidth For interrupt pipes, * this parameter should express the number * of bytes per frame to be transferred. */ pIntInEp->interval, &pLoopbackDev->intInPipeHandle) != OK) { printf("Interrupt in pipe creation failed \n"); OSS_FREE (pBfr); return ERROR; } } if (USB_IS_ISOCH_LOOPBACK_SUPPORTED(pLoopbackDev ->protocol)) { /* Create semaphore used for bulk loopback synchronization */ if (OSS_SEM_CREATE (1, 0 , &(pLoopbackDev->isochLoopbackSem)) != OK) { return (S_usbLoopbackLib_OUT_OF_RESOURCES); } /* Create a pipe for Interrupt output to the Loopback. */ maxPacketSize = *((pUINT8) &pIsochOutEp->maxPacketSize) | (*(((pUINT8) &pIsochOutEp->maxPacketSize) + 1) << 8); /* update the Isoch out ep address in pLoopback device */ pLoopbackDev->isochOutEpAddress = pIsochOutEp->endpointAddress; if (usbdPipeCreate (usbdHandle, pLoopbackDev->nodeId, pIsochOutEp->endpointAddress, pCfgDescr->configurationValue, pLoopbackDev->interface, USB_XFRTYPE_ISOCH, USB_DIR_OUT, maxPacketSize, USB_LOOPBACK_DEFAULT_BANDWIDTH_ISOCH_OUT, /* bandwidth For interrupt pipes, * this parameter should express the number * of bytes per second to be transferred. */ 1, &pLoopbackDev->isochOutPipeHandle) != OK) { printf("Isoch out pipe creation failed \n"); OSS_FREE (pBfr); return ERROR; } /* Create a pipe for Interrupt In from the Loopback. */ maxPacketSize = *((pUINT8) &pIsochInEp->maxPacketSize) | (*(((pUINT8) &pIsochInEp->maxPacketSize) + 1) << 8); /* update the Isoch in ep address in pLoopback device */ pLoopbackDev->isochInEpAddress = pIsochInEp->endpointAddress; if (usbdPipeCreate (usbdHandle, pLoopbackDev->nodeId, pIsochInEp->endpointAddress, pCfgDescr->configurationValue, pLoopbackDev->interface, USB_XFRTYPE_ISOCH, USB_DIR_IN, maxPacketSize, USB_LOOPBACK_DEFAULT_BANDWIDTH_ISOCH_IN, /* bandwidth For interrupt pipes, * this parameter should express the number * of bytes per second to be transferred. */ 1, &pLoopbackDev->isochInPipeHandle) != OK) { printf("Isoch in pipe creation failed \n"); OSS_FREE (pBfr); return ERROR; } } OSS_FREE (pBfr); return OK; }/***************************************************************************** destroyAttachRequest - disposes of an ATTACH_REQUEST structure** RETURNS: N/A*/LOCAL VOID destroyAttachRequest ( pATTACH_REQUEST pRequest ) { /* Unlink request */ usbListUnlink (&pRequest->reqLink); /* Dispose of structure */ OSS_FREE (pRequest); }/***************************************************************************** destroyLoopbackDevice - disposes of a USB_LOOPBACK_DEVICE structure** Unlinks the indicated USB_LOOPBACK_DEVICE structure and de-allocates* resources associated with the channel.** RETURNS: N/A*/LOCAL VOID destroyLoopbackDevice ( pUSB_LOOPBACK_DEVICE pLoopbackDev ) { if (pLoopbackDev != NULL) { /* Unlink the structure. */ usbListUnlink (&pLoopbackDev->loopbackLink); while (pLoopbackDev->ctrlLoopbackInProgress || pLoopbackDev->bulkLoopbackInProgress || pLoopbackDev->intLoopbackInProgress || pLoopbackDev->isochLoopbackInProgress ) { OSS_THREAD_SLEEP (1); } /* relaese semaphores */ if (pLoopbackDev->bulkLoopbackSem != NULL) { OSS_SEM_DESTROY (pLoopbackDev->bulkLoopbackSem); pLoopbackDev->bulkLoopbackSem = NULL; } if (pLoopbackDev->intLoopbackSem != NULL) { OSS_SEM_DESTROY (pLoopbackDev->intLoopbackSem); pLoopbackDev->intLoopbackSem = NULL; } if (pLoopbackDev->isochLoopbackSem != NULL) { OSS_SEM_DESTROY (pLoopbackDev->isochLoopbackSem); pLoopbackDev->isochLoopbackSem = NULL; } /* Release pipes and wait for IRPs to be cancelled if necessary. */ if (pLoopbackDev->bulkOutPipeHandle != NULL) usbdPipeDestroy (usbdHandle, pLoopbackDev->bulkOutPipeHandle); if (pLoopbackDev->bulkInPipeHandle != NULL) usbdPipeDestroy (usbdHandle, pLoopbackDev->bulkInPipeHandle); if (pLoopbackDev->intOutPipeHandle != NULL) usbdPipeDestroy (usbdHandle, pLoopbackDev->intOutPipeHandle); if (pLoopbackDev->intInPipeHandle != NULL) usbdPipeDestroy (usbdHandle, pLoopbackDev->intInPipeHandle); if (pLoopbackDev->isochOutPipeHandle != NULL) usbdPipeDestroy (usbdHandle, pLoopbackDev->isochOutPipeHandle); if (pLoopbackDev->isochInPipeHandle != NULL) usbdPipeDestroy (usbdHandle, pLoopbackDev->isochInPipeHandle); /* release buffers */ /* Release structure. */ OSS_FREE (pLoopbackDev); } }/***************************************************************************** createLoopbackDevice - creates a new USB_LOOPBACK_DEVICE structure** Creates a new USB_LOOPBACK_DEVICE structure for the indicated <nodeId>.* If successful, the new structure is linked into the loopbackList upon * return.** <configuration> and <interface> identify the configuration/interface* that first reported itself as a Loopback for this device.** RETURNS: pointer to newly created structure, or NULL if failure*/LOCAL pUSB_LOOPBACK_DEVICE createLoopbackDevice ( USBD_NODE_ID nodeId, UINT16 configuration, UINT16 interface, UINT16 deviceProtocol ) { pUSB_LOOPBACK_DEVICE pLoopbackDev; /* Try to allocate space for a new Loopback struct */ if ((pLoopbackDev = OSS_CALLOC (sizeof (*pLoopbackDev))) == NULL) { destroyLoopbackDevice (pLoopbackDev); return NULL; } pLoopbackDev->loopbackChan.pDrvFuncs = &usbLoopbackDrvFuncs; pLoopbackDev->nodeId = nodeId; pLoopbackDev->connected = TRUE; pLoopbackDev->configuration = configuration; pLoopbackDev->interface = interface; pLoopbackDev->protocol = deviceProtocol; /* Try to configure the Loopback. */ if (configureLoopbackDevice (pLoopbackDev) != OK) { destroyLoopbackDevice (pLoopbackDev); return NULL; } /* Link the newly created structure. */ usbListLink (&loopbackList, pLoopbackDev, &pLoopbackDev->loopbackLink, LINK_TAIL); return pLoopbackDev; }/***************************************************************************** findLoopbackDevice - Searches for a USB_LOOPBACK_DEVICE for indicated node ID** RETURNS: pointer to matching USB_LOOPBACK_DEVICE or NULL if not found*/LOCAL pUSB_LOOPBACK_DEVICE findLoopbackDevice ( USBD_NODE_ID nodeId ) { pUSB_LOOPBACK_DEVICE pLoopbackDev = usbListFirst (&loopbackList); while (pLoopbackDev != NULL) { if (pLoopbackDev->nodeId == nodeId) break; pLoopbackDev = usbListNext (&pLoopbackDev->loopbackLink); } return pLoopbackDev; }/****************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -