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

📄 usbvideo.cpp

📁 Windows+CE下USB摄像头驱动开发,使用EVC开发。摄像头为 网眼 Webeye 2000 VID 0x05A9 PID 0xA511 输出格式:RAW-YUV
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include <windows.h>                 // For all that Windows stuff
#include <USBdi.h>					// USB includes
#include <usb100.h>					// USB includes
#include "usbclient.h"				// USB client driver helper code

#include "Ov511Cam.h" 				// Local driver includes
#include "USBVideo.h"
//视频相关处理函数

//分析控制和视频接口
BOOL ParseStreamInterfaces(LPCUSB_DEVICE lpUsbDev, BYTE bIFStrm, BYTE bIFSubStrm, DWORD *pdwContext)
{
	RETAILMSG(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;
		}
		
		DWORD i;
		LPCUSB_INTERFACE lpIF;
		int nStreamAlts = 0;
		int nOtherStreams = 0;
		int nStreamID = -1;
		
		// Walk interface table to find the number of Video stream interface alternates and if there are 
		// other video streams that aren't alts.
		RETAILMSG(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)
		{
			RETAILMSG(1, (TEXT("No stream interfaces\r\n")));
			return FALSE;
		}
		
		//设备可以使用,创建设备上下文		
		PDEVICECONTEXT pPDD = (PDEVICECONTEXT)LocalAlloc (LPTR, sizeof (PDEVICECONTEXT)); 
		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);
		
		RETAILMSG(1, (TEXT("Found %d stream interfaces. ID %d\r\n"), pPDD->nInterfaces, nStreamID));
		if (nOtherStreams)
		{
			RETAILMSG(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)
		{
			RETAILMSG(1,(TEXT("%d interfaces will be saved!\r\n"),pPDD->nInterfaces));
			pPDD->usbVideoIF = (PUSBIF)LocalAlloc (LPTR, sizeof (PUSBIF));/*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;
				}
				RETAILMSG(1,(TEXT("Saving interface %d...\r\n"),lpIF->Descriptor.bAlternateSetting));
			}			
			
		}

		RETAILMSG(1, (TEXT("Device interfaces saved!\r\n")));

		*pdwContext = (DWORD)pPDD;

		return TRUE;
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		RETAILMSG(1, (TEXT("Exception walking device interfaces\r\n")));
		return FALSE;
	}
}

//写OV511寄存器
int RegisterWrite(PDRVCONTEXT pDrv, unsigned char reg, unsigned char value)
{
	USB_DEVICE_REQUEST req;
	DWORD dwBytes;
	DWORD dw, dwErr;

	RETAILMSG(1, (TEXT("RegisterWrite++\r\n")));

	// Get our pdd specific context
	PDEVICECONTEXT pPDD = (PDEVICECONTEXT)pDrv->dwDeviceContext; 
	
	req.bmRequestType = USB_TYPE_VENDOR | USB_RECIP_DEVICE;
	
	req.bRequest = 2;
	req.wValue   = 0;
	req.wIndex   = (USHORT)reg;
	req.wLength  = 1;

	unsigned char buf=value;

	dwBytes = 0;
	dwErr = USB_NO_ERROR;
	dw = IssueVendorTransfer (pDrv->lpUsbFuncs, pDrv->hDevice, 
							DefaultTransferComplete, pPDD->hVendorEvent,
							USB_OUT_TRANSFER | USB_SHORT_TRANSFER_OK,
							&req, &buf, 
							NULL, &dwBytes, 2000, &dwErr);
	if (dw)
	{
		RETAILMSG(1, (TEXT("Error calling IssueVendorTransfer rc: %d  ExtErr: %d\r\n"), 
				  dw, GetLastError()));
	}

	// If no data transferred, stuff in an error
	if (!dw && (dwBytes != 1))
	{
		RETAILMSG(1, (TEXT("No Data Transfered!\r\n")));
		dw = ERROR_BAD_LENGTH;
	}

	RETAILMSG(1, (TEXT("RegisterWrite-- rc %d,%d bytes transfered!\r\n"), dw,dwBytes));
	return dw;
}

//读OV511寄存器
int RegisterRead(PDRVCONTEXT pDrv, unsigned char reg, unsigned char *value)
{
	USB_DEVICE_REQUEST req;
	DWORD dwBytes;
	DWORD dw, dwErr;

	RETAILMSG(1, (TEXT("RegisterRead++\r\n")));

	// Get our pdd specific context
	PDEVICECONTEXT pPDD = (PDEVICECONTEXT)pDrv->dwDeviceContext; 
	
	req.bmRequestType = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
	
	req.bRequest = 3;
	req.wValue   = 0;
	req.wIndex   = (USHORT)reg;
	req.wLength  = 1;

	unsigned char buf=0;

	dwBytes = 0;
	dwErr = USB_NO_ERROR;
	dw = IssueVendorTransfer (pDrv->lpUsbFuncs, pDrv->hDevice, 
							DefaultTransferComplete, pPDD->hVendorEvent,
							USB_IN_TRANSFER | USB_SHORT_TRANSFER_OK,
							&req, &buf, 
							NULL, &dwBytes, 2000, &dwErr);
	if (dw)
	{
		RETAILMSG(1, (TEXT("Error calling IssueVendorTransfer rc: %d  ExtErr: %d\r\n"), 
				  dw, GetLastError()));
	}

	// If no data transferred, stuff in an error
	if (!dw && (dwBytes != 1))
	{
		RETAILMSG(1, (TEXT("No Data Transfered!\r\n")));
		dw = ERROR_BAD_LENGTH;
	}

	*value=buf;

	RETAILMSG(1, (TEXT("RegisterRead-- rc %d,%d bytes transfered!\r\n"), dw,dwBytes));
	return dw;
}

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

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

//重置OV511
int Ov51xReset(PDRVCONTEXT pDrv,unsigned char reset_type)
{
	int rc;
	rc = RegisterWrite(pDrv, 0x50, reset_type);
	rc = RegisterWrite(pDrv, 0x50, 0);

	if(0==rc)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

//设置视频接口
int SetStreamInterface(PDRVCONTEXT pDrv,BYTE nInterFace)
{
	USB_TRANSFER hTransfer;
	PUSBIF lpIF;
	int 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个接口
	RETAILMSG(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)
	{
		RETAILMSG(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)
	{

		RETAILMSG(1, (TEXT("Open pipe!\r\n")));
		// Open the pipe
		pPDD->pipeVideo.hPipe = pDrv->lpUsbFuncs->lpOpenPipe (pDrv->hDevice, &lpIF->epDesc);
		// Check for sucessful open
		if (pPDD->pipeVideo.hPipe)
		{
			// Copy some pipe attributes
			pPDD->pipeVideo.ucAddr = lpIF->epDesc.bEndpointAddress;
			pPDD->pipeVideo.wPacketSize = lpIF->epDesc.wMaxPacketSize;

			RETAILMSG(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
			}
			RETAILMSG(1, (TEXT("Error opening pipe  rc: %d\r\n"), rc));
		}
	}
	if (rc)
	{
		RETAILMSG(1, (TEXT("Error in SetStreamInterface  rc: %d  ExtErr: %d\r\n"), rc, GetLastError()));
	}
	RETAILMSG(1, (TEXT("SetStreamInterface--  rc %d\r\n"), rc));
	
	if(rc==0)
	{
		return 1;
	}
	else
	{
		return 0;
	}

}

//设置OV511传输包大小
int Ov511SetPacketSize(PDRVCONTEXT pDrv,int size)
{
	int 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;

⌨️ 快捷键说明

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