从SDK sample中的uvc例子修改而来, 在 描述符中增加2个interface(1 control 1VS stream ), 一个EP0的address是和例子一样的0rex81,而我自己新增加EP1的address为0x83。
但是我实现知识,GraphEdit 是可以打开我的FX3 capture 设备,而且也是有2个pin。 linux下面也是可以enum出2个video设备,但是运行的时候,第一个EP可以渲染的,但是第二个是不能渲染!
我的方案是这样:
我只开了一个DMA Channel, 2个EP都只用这个channel, 但是用了2个标志变量来分别判断EP0和EP1是否打开的。在有一个EP打开的时候,DMA 就Create了这个channel,但是只有当EP0和EP1都关闭的时候,才将这个DMA channel destroy掉。 也就是说只要有EP一个工作 ,这个dmachannel就一直工作,就一直有数据向这个DMA Channel 输送数据! 但是如果有一个EP关闭的话,那么我还是将这个EP flush一下的。 但是这样却不知道为什么会不对呢?? EP1 根本就不能渲染????? 不知道是什么缘故?? 求问!
下面是部分的代码片段:
static void
CyFxUVCApplnUSBEventCB (
CyU3PUsbEventType_t evtype, /* Event type */
uint16_t evdata /* Event data */
)
{
uint8_t interface = 0, altSetting = 0;
if (evtype == CY_U3P_USB_EVENT_SETINTF )
CyU3PDebugPrint(4,"CyFxUVCApplnUSBEventCB evtype = %d \n ",evtype);
switch (evtype)
{
case CY_U3P_USB_EVENT_SETINTF:
/* Start the video streamer application if the
* interface requested was 1. If not, stop the
* streamer. */
interface = CY_U3P_GET_MSB(evdata);
altSetting = CY_U3P_GET_LSB(evdata);
if ((altSetting == CY_FX_UVC_STREAM_INTERFACE) &&
((interface == 1)||(interface == 3)))
{
/* Stop the application before re-starting. */
if (glIsApplnActive||glIsApplnActive2)
{
CyFxUVCApplnStop (interface);
} //else //added 0913
CyFxUVCApplnStart (interface);
break;
}
/* Fall-through. */
case CY_U3P_USB_EVENT_SETCONF:
case CY_U3P_USB_EVENT_RESET:
case CY_U3P_USB_EVENT_DISCONNECT:
/* Stop the video streamer application. */
if (glIsApplnActive||glIsApplnActive2)
{
CyFxUVCApplnStop (interface);
}
break;
default:
break;
}
// CyU3PDebugPrint(4,"CyFxUVCApplnUSBEventCB is ok \n");
}
CyU3PReturnStatus_t
CyFxUVCApplnStart (uint8_t interface)
{
CyU3PEpConfig_t epCfg;
CyU3PDmaChannelConfig_t dmaCfg;
CyU3PReturnStatus_t apiRetStatus = CY_U3P_SUCCESS;
CyU3PDebugPrint(4, "+++++CyFxUVCApplnStart++++\n");
/*changed by jijun.yu 0913*/
uint8_t epAddr = -1;
if (!glIsApplnActive && (interface == 1))
epAddr = CY_FX_EP_ISO_VIDEO;
else if (!glIsApplnActive2 && (interface == 3))
epAddr = CY_FX_EP_ISO_VIDEO_2;
else
return CY_U3P_SUCCESS;
CyU3PDebugPrint(4, "+++++CyFxUVCApplnStart epAddr = %d++++\n",epAddr);
/* Video streaming endpoint configuration */
epCfg.enable = CyTrue;
epCfg.epType = CY_U3P_USB_EP_ISO;
epCfg.pcktSize = CY_FX_EP_ISO_VIDEO_PKT_SIZE;
epCfg.isoPkts = 1;
epCfg.burstLen = 1;
epCfg.streams = 0;
//changed by jijun.yu 0913
apiRetStatus = CyU3PSetEpConfig(epAddr, &epCfg); //CY_FX_EP_ISO_VIDEO
if (apiRetStatus != CY_U3P_SUCCESS)
{
CyU3PDebugPrint (4, "CyU3PSetEpConfig failed, Error Code = %d\n", apiRetStatus);
return apiRetStatus;
}
/* Create a DMA Manual OUT channel for streaming data */
/* Video streaming Channel is not active till a stream request is received */
dmaCfg.size = CY_FX_UVC_STREAM_BUF_SIZE;
dmaCfg.count = CY_FX_UVC_STREAM_BUF_COUNT;
dmaCfg.prodSckId = CY_U3P_CPU_SOCKET_PROD;
dmaCfg.consSckId = CY_FX_EP_VIDEO_CONS_SOCKET;
dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE;
dmaCfg.cb = NULL;
dmaCfg.prodHeader = 0;
dmaCfg.prodFooter = 0;
dmaCfg.consHeader = 0;
dmaCfg.prodAvailCount = 0;
/*changed jijun 0913*/
if ((!glIsApplnActive) && (!glIsApplnActive2)) {
apiRetStatus = CyU3PDmaChannelCreate (&glChHandleUVCStream, CY_U3P_DMA_TYPE_MANUAL_OUT, &dmaCfg);
if (apiRetStatus != CY_U3P_SUCCESS)
{
CyU3PDebugPrint (4, "CyU3PDmaChannelCreate failed, error code = %d\n",apiRetStatus);
return apiRetStatus;
}
}
#ifdef stream2
apiRetStatus = CyU3PDmaChannelCreate (&glChHandleUVCStream2, CY_U3P_DMA_TYPE_MANUAL_OUT, &dmaCfg);
if (apiRetStatus != CY_U3P_SUCCESS)
{
CyU3PDebugPrint (4, "CyU3PDmaChannelCreate failed, error code = %d\n",apiRetStatus);
return apiRetStatus;
}
#endif
/* Flush the endpoint memory */
CyU3PUsbFlushEp(epAddr);
/////////////??????
if (!glIsApplnActive && !glIsApplnActive2) {
apiRetStatus = CyU3PDmaChannelSetXfer (&glChHandleUVCStream, 0);
if (apiRetStatus != CY_U3P_SUCCESS)
{
CyU3PDebugPrint (4, "CyU3PDmaChannelSetXfer failed, error code = %d\n", apiRetStatus);
return apiRetStatus;
}
}
#ifdef stream2
apiRetStatus = CyU3PDmaChannelSetXfer (&glChHandleUVCStream2, 0);
if (apiRetStatus != CY_U3P_SUCCESS)
{
CyU3PDebugPrint (4, "CyU3PDmaChannelSetXfer failed, error code = %d\n", apiRetStatus);
return apiRetStatus;
}
#endif
/* Update the flag so that the application thread is notified of this. */
if (interface == 1)
glIsApplnActive = CyTrue;
if (interface == 3)
glIsApplnActive2 = CyTrue;
return CY_U3P_SUCCESS;
}
/* This function stops the video streaming. It is called from the USB event
* handler, when there is a reset / disconnect or SET_INTERFACE for alternate
* interface 0. */
void
CyFxUVCApplnStop (uint8_t interface)
{
CyU3PEpConfig_t epCfg;
uint8_t epAddr = -1;
CyU3PDebugPrint(4, "CyFxUVCApplnStop interface = %d \n",interface);
/* Update the flag so that the application thread is notified of this. */
if (interface ==1) {
epAddr = CY_FX_EP_ISO_VIDEO;
glIsApplnActive = CyFalse;
}
if (interface == 3) {
epAddr = CY_FX_EP_ISO_VIDEO_2;
glIsApplnActive2 = CyFalse;
}
/* Abort and destroy the video streaming channel */
if ((!glIsApplnActive) && (!glIsApplnActive2)) {
CyU3PDebugPrint(4,"Destroy the dma channel \n");
CyU3PDmaChannelDestroy (&glChHandleUVCStream);
#ifdef stream2
CyU3PDmaChannelDestroy (&glChHandleUVCStream2);
#endif
}
/* Flush the endpoint memory */
CyU3PUsbFlushEp(epAddr);
/* Disable the video streaming endpoint. */
CyU3PMemSet ((uint8_t *)&epCfg, 0, sizeof (epCfg));
epCfg.enable = CyFalse;
CyU3PSetEpConfig(epAddr, &epCfg);
}
|
|