⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbcam.c

📁 Windows CE下USB驱动(OV511)
💻 C
📖 第 1 页 / 共 5 页
字号:
    DWORD nStreamID = -1;  
    PDEVICECONTEXT pPDD = NULL;

    DEBUGMSG(1, (TEXT("Looking for Stream Interfaces %d %d\r\n"), bIFStrm, bIFSubStrm));

    __try {
        
        if (lpUsbDev->lpConfigs->dwCount != sizeof (USB_CONFIGURATION))
        {
            RETAILMSG(1, (TEXT("Unexpected CUSB_CONFIGURATION dwCount: %d  ***********\r\n"), lpUsbDev->lpConfigs->dwCount));
            return FALSE;
        }

        
        // Walk interface table to find the number of Video stream interface alternates and if there are 
        // other video streams that aren't alts.
        DEBUGMSG(1,(TEXT("There are %d interfaces.\r\n"),lpUsbDev->lpConfigs->dwNumInterfaces));
        for (i = 0; i < lpUsbDev->lpConfigs->dwNumInterfaces; i++)
        {
            lpIF = &lpUsbDev->lpConfigs->lpInterfaces[i];
            
            if ((lpIF->Descriptor.bInterfaceClass == bIFStrm) && (lpIF->Descriptor.bInterfaceSubClass == bIFSubStrm))
            {
                // Is first stream?
                if (nStreamID == -1)
                {
                    nStreamID = lpIF->Descriptor.bInterfaceNumber;
                }
                else if (nStreamID == lpIF->Descriptor.bInterfaceNumber)
                {
                    nStreamAlts++;
                }
                else
                {
                    nOtherStreams++;
                }
            }
        }
        if (nStreamID == -1)
        {
            DEBUGMSG(1, (TEXT("No stream interfaces\r\n")));
            return FALSE;
        }
        
        //设备可以使用,创建设备上下文		
        pPDD = (PDEVICECONTEXT)VirtualAlloc (NULL, sizeof (PDEVICECONTEXT), MEM_COMMIT, PAGE_EXECUTE_READWRITE); 
        if (pPDD == 0)
        {
            RETAILMSG(1, (TEXT("Not enough memory!\r\n")));
            SetLastError (ERROR_NOT_ENOUGH_MEMORY);
            return FALSE;
        }
        
        pPDD->nInterfaces = nStreamAlts + 1;
        pPDD->hVendorEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
        
        DEBUGMSG(1, (TEXT("Found %d stream interfaces. ID %d\r\n"), pPDD->nInterfaces, nStreamID));
        if (nOtherStreams)
        {
            DEBUGMSG(1, (TEXT("Multiple stream interfaces found on device.  Using first one.\r\n")));
        }
        
        // Allocate the array for the stream interface descriptors
        //保存视频传输接口
        
        if (pPDD->nInterfaces > 0)
        {
            DEBUGMSG(1,(TEXT("%d interfaces will be saved!\r\n"),pPDD->nInterfaces));
            pPDD->usbVideoIF = (PUSBIF)VirtualAlloc (NULL, sizeof(USBIF), MEM_COMMIT, PAGE_EXECUTE_READWRITE);;/*pPDD->nInterfaces **/ 
        }
        
        //保存接口
        //OV511有8套接口设置,对应不同的传输Packet Size
        //PUSBIF temp;
        for (i = 0; i < lpUsbDev->lpConfigs->dwNumInterfaces; i++)
        {
            lpIF = &lpUsbDev->lpConfigs->lpInterfaces[i];
            
            //保存接口			
            //作为测试,只保存第7个接口设置以及使用
            if(i==7)
            {
                pPDD->usbVideoIF->ifDesc=lpIF->Descriptor;
                if (lpIF->lpEndpoints)
                {
                    pPDD->usbVideoIF->epDesc = lpIF->lpEndpoints->Descriptor;
                    pPDD->usbVideoIF->fEndpoint = TRUE;
                }
                else
                {
                    pPDD->usbVideoIF->fEndpoint = FALSE;
                }
                DEBUGMSG(1,(TEXT("Saving interface %d...\r\n"),lpIF->Descriptor.bAlternateSetting));
            }			
            
        }
        
        DEBUGMSG(1, (TEXT("Device interfaces saved!\r\n")));
        
        *pdwContext = (DWORD)pPDD;
        
        return TRUE;
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        DEBUGMSG(1, (TEXT("Exception walking device interfaces\r\n")));
        return FALSE;
    }
}

//停止OV511视频采集
BOOL OV51xStop(PDRVCONTEXT pDrv)
{
    DEBUGMSG(1,(TEXT("Stopping streaming...\r\n")));
    pDrv->bStopped = TRUE;
    if(RegisterWrite(pDrv, 0x50, 0x3d) == TRUE)
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

//重新开始OV511采集
BOOL OV51xRestart(PDRVCONTEXT pDrv)
{
    if(pDrv->bStopped)
    {
        pDrv->bStopped=FALSE;
        if(RegisterWrite(pDrv, 0x50, 0x00) == TRUE)
        {
            return TRUE;
        }
    }
    return FALSE;
}

//重置OV511
BOOL OV51xReset(PDRVCONTEXT pDrv,BYTE reset_type)
{
    BOOL bRc;
    bRc = RegisterWrite(pDrv, 0x50, reset_type);
    bRc = RegisterWrite(pDrv, 0x50, 0);
    
    return bRc;
}

//设置视频接口
DWORD SetStreamInterface(PDRVCONTEXT pDrv,BYTE nInterFace)
{
    USB_TRANSFER hTransfer;
    PUSBIF lpIF;
    DWORD rc;
    
    PDEVICECONTEXT pPDD= (PDEVICECONTEXT)pDrv->dwDeviceContext;
    
    //如果管道已经打开,就先关闭
    if (pPDD->pipeVideo.hEvent != 0)
    {
        pDrv->lpUsbFuncs->lpClosePipe (pPDD->pipeVideo.hPipe);
        CloseHandle (pPDD->pipeVideo.hEvent);
        pPDD->pipeVideo.hEvent = 0;
    }
    
    lpIF=pPDD->usbVideoIF;
    
    //打开第7个接口
    DEBUGMSG(1, (TEXT("Set Interface %d\r\n"),lpIF->ifDesc.bAlternateSetting));
    hTransfer = pDrv->lpUsbFuncs->lpSetInterface (pDrv->hDevice, NULL, NULL, 0, lpIF->ifDesc.bInterfaceNumber, 
        lpIF->ifDesc.bAlternateSetting);
    if (hTransfer == 0)
    {
        DEBUGMSG(1, (TEXT("Error calling SetInterface rc=%d\r\n"), GetLastError()));
        return GetLastError();
    }
    if (!CloseTransferHandle (pDrv->lpUsbFuncs, hTransfer))
    {
        rc = GetLastError();
    }
    
    rc = 0;
    // Open a pipe to the end point
    // 依据这个接口的Endpoint Descriptor,打开传输管道
    if (lpIF->fEndpoint)
    {
        
        DEBUGMSG(1, (TEXT("End Point 0x%x!\r\n"), lpIF->fEndpoint));
        DEBUGMSG(1, (TEXT("Open pipe!\r\n")));
        // Open the pipe
        pPDD->pipeVideo.hPipe = pDrv->lpUsbFuncs->lpOpenPipe (pDrv->hDevice, &lpIF->epDesc);
        // Check for sucessful open
        DEBUGMSG(1, (TEXT("Pipe: 0x%x!\r\n"), pPDD->pipeVideo.hPipe));
        if (pPDD->pipeVideo.hPipe != NULL)
        {
            // Copy some pipe attributes
            pPDD->pipeVideo.ucAddr = lpIF->epDesc.bEndpointAddress;
            pPDD->pipeVideo.wPacketSize = lpIF->epDesc.wMaxPacketSize;
            
            DEBUGMSG(1,(TEXT("Actual Packet Size %d\r\n"),pPDD->pipeVideo.wPacketSize));
            // First, create an event for handshaking
            // 创建传输完成的回调事件
            pPDD->pipeVideo.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
        } 
        else
        {
            rc = GetLastError();
            if (rc == 0) 
            {
                rc = ERROR_NOT_ENOUGH_MEMORY; // Sometimes, there isn't an extended error here
            }
            DEBUGMSG(1, (TEXT("Error opening pipe  rc: %d\r\n"), rc));
        }
    }
    if (rc)
    {
        DEBUGMSG(1, (TEXT("Error in SetStreamInterface  rc: %d  ExtErr: %d\r\n"), rc, GetLastError()));
    }
    DEBUGMSG(1, (TEXT("SetStreamInterface--  rc %d\r\n"), rc));
    
    if(rc==0)
    {
        return 1;
    }
    else
    {
        return 0;
    }
    
}

//设置OV511传输包大小
BOOL OV511SetPacketSize(PDRVCONTEXT pDrv, DWORD size)
{
    DWORD alt,mult;
    
    mult = size >> 5;
    
    if (!OV51xStop(pDrv))
    {
        return 0;
    }
    
    switch(size)
    {
    case 0:
        alt=0;
        break;
    case 33:
        alt=1;
        break;
    case 129:
        alt=2;
        break;
    case 257:
        alt=3;
        break;
    case 385:
        alt=4;
        break;
    case 513:
        alt=5;
        break;
    case 769:
        alt=6;
        break;
    case 961:
        alt=7;
        break;
    default:
        return 0;
        break;
    }
    
    DEBUGMSG(1,(TEXT("Alt %d,mult %d,size %d\r\n"),alt,mult,size));
    
    if (RegisterWrite(pDrv, 0x30, (BYTE)mult)  == FALSE)
    {
        return FALSE;
    }
    
    /*
    if (usb_set_interface(pDrv->dev, pDrv->iface, alt) < 0) {
    err("Set packet size: set interface error");
    return -EBUSY;
    }
    */
    //设置接口,这里硬编码为使用第3套设置
    SetStreamInterface(pDrv,3);	
    
    DEBUGMSG(1,(TEXT("Reset!\r\n"),alt,mult,size));
    
    if (OV51xReset(pDrv, 0x3F) == FALSE)
    {
        return FALSE;
    }
    
    pDrv->nPacketSize = size;
    
    DEBUGMSG(1,(TEXT("Restart!\r\n"),alt,mult,size));
    if (OV51xRestart(pDrv) == FALSE)
    {
        return FALSE;
    }
    
    return TRUE;
}

DWORD OV51xReadOneFrame(PDRVCONTEXT pDrv, BYTE *pBuff, DWORD startaddress)
{
    PBYTE pDataBuff, pBuf, ptr;
    DWORD nNumPackets;
    DWORD dw;
    DWORD dwFrameLen[MAXPACKETS];
    DWORD dwUsbRc[MAXPACKETS];
    DWORD dwBytes;
    DWORD dwPacketIndex;
    DWORD nPacketSize;
    DWORD address = 0;
    DWORD i, j, k, k1 ,k2;
    DWORD pack = 0;
    BOOL Frame = FALSE;

    PDEVICECONTEXT pPDD=(PDEVICECONTEXT)pDrv->dwDeviceContext;
    
    memset(RawFrameData, 0x00, 115223);
    memset(RealFrameData, 0x00, 115712);
    
    ptr = RawFrameData;

    for(i = 0; i < 25; i++)
    {
        pDataBuff = DataBuf;
        if(pDataBuff == NULL)
        {
            return 0;
        }
        memset(pDataBuff, 0x00, 961 * 10);
        nNumPackets = MAXPACKETS;      
        nPacketSize = pPDD->pipeVideo.wPacketSize;        
        for (dwPacketIndex = 0; dwPacketIndex < MAXPACKETS; dwPacketIndex++)
        {
            dwFrameLen[dwPacketIndex] = 961;
        }        
        __try {            
            dw = IssueIsochTransfer (   pDrv->lpUsbFuncs, 
                pPDD->pipeVideo.hPipe, 
                DefaultTransferComplete, 
                pPDD->pipeVideo.hEvent,
                USB_IN_TRANSFER | USB_SHORT_TRANSFER_OK | USB_START_ISOCH_ASAP | USB_COMPRESS_ISOCH,
                0,               // Using USB_START_ISOCH_ASAP precludes the need for a start frame
                nNumPackets,      // Number of frames to read
                dwFrameLen,      // Array that receives the length of each frame
                pDataBuff,       // Pointer to transfer buffer
                0,               // Specifies the physical address, which may be NULL, of the data buffer
                &dwBytes,	      // Number of bytes transferred by USB
                1500,            // Timeout in msec
                dwUsbRc);	      // Returns USB_ERROR or USB_TRANSFER          
        }
        __except (EXCEPTION_EXECUTE_HANDLER)
        {
            DEBUGMSG(1, (TEXT ("Exception calling IssueIsochTransfer %d %d\r\n"), dw, GetLastError()));
            return 0;
        }
        if (dw)
        {
            DEBUGMSG(1,(TEXT ("Error calling IssueIsochTransfer %d %d\r\n"), dw, GetLastError()));
            
        }
        if (dwBytes == 0)
        {
            DEBUGMSG(1,(TEXT("packet size read if %d bytes! :(\r\n"), dwBytes));
        }
        else
        {
            address += dwBytes;
            pBuf = DataBuf;
            for(j = 0; j < dwBytes / 961; j++)
            {
                //查找帧开始标志
                k = (pBuf[0] | pBuf[1] | pBuf[2] | pBuf[3] | pBuf[4] | pBuf[5] | pBuf[6] | pBuf[7]);
                k1 = (pBuf[8] & 0xff);
                k2 = (pBuf[8] & 0xff);                    
                if (k == 0 && (k1 == 24 || k2 ==25))
                {
                    Frame = TRUE;
                    break;                
                }
                else
                {
                    pBuf += 961;
                }
            }   
        }
        j++;
        pack = 1;
        if(Frame == TRUE)
        {
            pBuf += 9;
            memmove(ptr, pBuf, 951);        //复制第一包
            ptr += 951;
            pBuf += 952;
            for(; j < 10; j++)
            {               
                memmove(ptr, pBuf, 960);
                ptr += 960;
                pBuf += 961;
                pack += 1;
            }
            for(i = 0; i < 11; i++)
            {
                memset(DataBuf, 0x00, 961 * 10);
                pDataBuff = DataBuf;
                if(pDataBuff == NULL)
                {
                    return 0;
                }
                __try {                
                    dw = IssueIsochTransfer (   pDrv->lpUsbFuncs, 
                        pPDD->pipeVideo.hPipe, 
                        DefaultTransferComplete, 
                        pPDD->pipeVideo.hEvent,
                        USB_IN_TRANSFER | USB_SHORT_TRANSFER_OK | USB_START_ISOCH_ASAP | USB_COMPRESS_ISOCH,
                        0,               // Using USB_START_ISOCH_ASAP precludes the need for a start frame
                        nNumPackets,      // Number of frames to read
                        dwFrameLen,      // Array that receives the length of each frame
                        pDataBuff,       // Pointer to transfer

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -