📄 usbvideo.cpp
字号:
#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 + -