📄 usbvideo.cpp
字号:
break;
}
RETAILMSG(1,(TEXT("Alt %d,mult %d,size %d\r\n"),alt,mult,size));
if (0!=RegisterWrite(pDrv, 0x30, mult))
{
return 0;
}
/*
if (usb_set_interface(ov->dev, ov->iface, alt) < 0) {
err("Set packet size: set interface error");
return -EBUSY;
}
*/
//设置接口,这里硬编码为使用第3套设置
SetStreamInterface(pDrv,3);
RETAILMSG(1,(TEXT("Reset!\r\n"),alt,mult,size));
if (!Ov51xReset(pDrv, 0x3F))
{
return 0;
}
pDrv->nPacketSize = size;
RETAILMSG(1,(TEXT("Restart!\r\n"),alt,mult,size));
if (!Ov51xRestart(pDrv))
{
return 0;
}
return 1;
}
//-----------------------------------------------------------------------
// IssueIsochTransfer - implements a synch isoch transfer to the device.
// This code was based on IssueVendorTransfer from USBClient.cpp
//
DWORD IssueIsochTransfer (LPCUSB_FUNCS pUsbFuncs, HANDLE hUsbDevice,
LPTRANSFER_NOTIFY_ROUTINE NotifyRoutine, // Transfer completion routine.
PVOID NotifyContext, // Single argument passed to the completion routine
DWORD Flags, // USB_XXX flags describing the transfer
DWORD dwStartingFrame, // Starting frame to read
DWORD dwNumFrames, // Number of frames to read
PDWORD pdwFrameLengths, // Array that receives the length of each frame
LPVOID pBuffer, // Pointer to transfer buffer
ULONG PhysAddr, // Specifies the physical address, which may be NULL, of the data buffer
LPDWORD pBytesTransferred, // Number of bytes transferred by USB
DWORD dwTimeout, // Timeout in msec
PUSB_ERROR pUsbRc) // Returns USB_ERROR or USB_TRANSFER
{
USB_TRANSFER hTransfer;
DWORD dwErr = ERROR_SUCCESS;
BOOL bRc = TRUE;
DWORD z, dwWaitReturn;
if (pUsbFuncs && hUsbDevice && pdwFrameLengths && pBytesTransferred && pUsbRc)
{
*pUsbRc = USB_NO_ERROR;
*pBytesTransferred = 0;
if (NotifyContext && NotifyRoutine && dwTimeout)
ResetEvent(NotifyContext); // NotifyContext *must* be an EVENT
hTransfer = pUsbFuncs->lpIssueIsochTransfer( hUsbDevice, NotifyRoutine,
NotifyContext, Flags, dwStartingFrame, dwNumFrames,
pdwFrameLengths, pBuffer,PhysAddr);
if (hTransfer)
{
//
// Asynch call completed.
// Get transfer status & number of bytes transferred
//
// 异步调用完成,则等待传输完成的回调事件,然后判断传输状态以及处理传输的数据
if (NotifyContext && NotifyRoutine)
{
RETAILMSG(1,(TEXT("Asynch!\r\n")));
if (!dwTimeout)
{
*pUsbRc = (USB_ERROR)hTransfer;
return dwErr;
}
//
// sync the transfer completion / timer
//
dwWaitReturn = WaitForSingleObject( NotifyContext,
dwTimeout );
switch (dwWaitReturn)
{
case WAIT_OBJECT_0:
//
// The completion event was signalled by the callback.
// Get transfer status & number of bytes transferred
//
bRc = pUsbFuncs->lpGetIsochResults (hTransfer, dwNumFrames, pdwFrameLengths, pUsbRc);
// sum total data transferred.
for (z = 0; z < dwNumFrames; z++)
{
*pBytesTransferred += pdwFrameLengths[z];
if (pUsbRc[z])
{
if ((pUsbRc[z] != USB_DATA_TOGGLE_MISMATCH_ERROR) &&
(pUsbRc[z] != USB_DATA_UNDERRUN_ERROR)) //Ignore underrun error
{
RETAILMSG(1,(TEXT("ERROR %d in frame %d\r\n"), pUsbRc[z], z));
dwErr = pUsbRc[z];
if (dwErr) break;
}
}
}
break;
case WAIT_TIMEOUT:
//
// The transfer reqest timed out.
// Get transfer status & number of bytes transferred
//
RETAILMSG(1,(TEXT("%s:WAIT_TIMEOUT on hT:0x%x\n"), (Flags & USB_IN_TRANSFER) ? TEXT("IN") : TEXT("OUT"), hTransfer ));
GetTransferStatus(pUsbFuncs, hTransfer, pBytesTransferred, pUsbRc);
//
// let caller know it timed out
//
dwErr = ERROR_TIMEOUT;
break;
default:
dwErr = ERROR_GEN_FAILURE;
RETAILMSG(1,(TEXT("*** Unhandled WaitReason:%d ***\n"), dwWaitReturn ));
// ASSERT(0);
break;
}
}
else
{
//
// Synch call completed.
// Get transfer status & number of bytes transferred
//
// 同步调用完成,则不用WaitForSingleObject传输完成事件
RETAILMSG(1,(TEXT("Synch!\r\n")));
bRc = pUsbFuncs->lpGetIsochResults (hTransfer, dwNumFrames, pdwFrameLengths, pUsbRc);
// sum total data transferred.
for (z = 0; z < dwNumFrames; z++)
{
*pBytesTransferred += pdwFrameLengths[z];
if (pUsbRc[z])
{
if (pUsbRc[z] != USB_DATA_UNDERRUN_ERROR) //Ignore underrun error
dwErr = pUsbRc[z];
}
}
}
CloseTransferHandle(pUsbFuncs, hTransfer);
} else
{
dwErr = ERROR_GEN_FAILURE;
RETAILMSG(1,(TEXT("*** IssueIsochTransfer ERROR(3, 0x%x) ***\n"), dwErr ));
}
} else
dwErr = ERROR_INVALID_PARAMETER;
if (ERROR_SUCCESS != dwErr)
{
SetLastError(dwErr);
RETAILMSG(1,(TEXT("IssueIsochTransfer ERROR(5, BytesTransferred:%d, Win32Err:%d )\n"),
pBytesTransferred?*pBytesTransferred:-1, dwErr));
}
return dwErr;
}
//初始化实时传输
int Ov51xReadOneFrame(PDRVCONTEXT pDrv,unsigned char *pBuff,DWORD startaddress)
{
PBYTE pDataBuff,pEnd;
int nNumPackets;
DWORD dw;
DWORD dwFrameLen[MAXPACKETS];
DWORD dwUsbRc[MAXPACKETS];
DWORD dwBytes;
int packetindex;
PDEVICECONTEXT pPDD=(PDEVICECONTEXT)pDrv->dwDeviceContext;
//以下为进行实时传输部分
/*for (n = 0; n < OV511_NUMSBUF; n++)
{
urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
if (!urb) {
err("init isoc: usb_alloc_urb ret. NULL");
return -ENOMEM;
}
ov->sbuf[n].urb = urb;
urb->dev = ov->dev;
urb->context = &ov->sbuf[n];
urb->pipe = usb_rcvisocpipe(ov->dev, OV511_ENDPOINT_ADDRESS);
urb->transfer_flags = URB_ISO_ASAP;
urb->transfer_buffer = ov->sbuf[n].data;
urb->complete = ov51x_isoc_irq;
urb->number_of_packets = FRAMES_PER_DESC;
urb->transfer_buffer_length = ov->packet_size * FRAMES_PER_DESC;
urb->interval = 1;
for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
urb->iso_frame_desc[fx].offset = ov->packet_size * fx;
urb->iso_frame_desc[fx].length = ov->packet_size;
}
}*/
pDataBuff=(PBYTE)LocalAlloc(LPTR,961*MAXPACKETS);
if(!pDataBuff)
{
RETAILMSG(1,(TEXT("Allocate Frame Buffer Failed!\r\n")));
return 0;
}
pEnd = pDataBuff + 961*MAXPACKETS;
//这里采用了硬编码,有待完善,每次调用读取传输961*10个字节
nNumPackets = MAXPACKETS;//(pPDD->pipeVideo.wPacketSize / 1024) + 2;
int nPacketSize = pPDD->pipeVideo.wPacketSize;
for (packetindex = 0; (packetindex < MAXPACKETS); packetindex++)
{
dwFrameLen[packetindex] = 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
RETAILMSG(1, (TEXT("Read %5d bytes at %x dw: %d\r\n"), dwBytes, pDataBuff, dw));
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
RETAILMSG(1,(TEXT ("Exception calling IssueIsochTransfer %d %d\r\n"), dw, GetLastError()));
return 0;
}
if (dw)
{
RETAILMSG(1,(TEXT ("Error calling IssueIsochTransfer %d %d\r\n"), dw, GetLastError()));
}
if (dwBytes == 0)
{
RETAILMSG(1,(TEXT("packet size read if %d bytes! :(\r\n"), dwBytes));
}
if(dwBytes>0)
{
PBYTE dest=pBuff+startaddress;
memcpy(dest,pDataBuff,dwBytes);
}
LocalFree(pDataBuff);
return dwBytes;
}
//设置默认参数
int Ov51xSetDefaultParams(PDRVCONTEXT pDrv)
{
int i;
struct ov511_frame frame[OV511_NUMFRAMES];
/* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used
* (using read() instead). */
for (i = 0; i < OV511_NUMFRAMES; i++) {
frame[i].width = 640;
frame[i].height = 480;
frame[i].bytes_read = 0;
//frame[i].format = VIDEO_PALETTE_YUV420;
frame[i].depth = 12;
}
WriteRegvals(pDrv);
/* Initialize to max width/height, YUV420 or RGB24 (if supported) */
if (!Ov511ModeInitRegs(pDrv, 320, 240, 0))
{
return 0;
}
//这里硬编码为使用第7套设置,包大小为961
int size;
size = 961;
if(!Ov511SetPacketSize(pDrv,size))
{
RETAILMSG(1,(TEXT("Set Packet Size Failed!\r\n")));
return 0;
}
return 1;
}
//初始化寄存器
int Ov511ModeInitRegs(PDRVCONTEXT pDrv,int width, int height, int sub_flag)
{
int hsegs, vsegs;
if (!Ov51xStop(pDrv))
{
return 0;
}
RegisterWrite(pDrv, R511_CAM_UV_EN, 0x01);
RegisterWrite(pDrv, R511_SNAP_UV_EN, 0x01);
RegisterWrite(pDrv, R511_SNAP_OPTS, 0x03);
/* Here I'm assuming that snapshot size == image size.
* I hope that's always true. --claudio
*/
hsegs = (width >> 3) - 1;
vsegs = (height >> 3) - 1;
RegisterWrite(pDrv, R511_CAM_PXCNT, hsegs);
RegisterWrite(pDrv, R511_CAM_LNCNT, vsegs);
RegisterWrite(pDrv, R511_CAM_PXDIV, 0x00);
RegisterWrite(pDrv, R511_CAM_LNDIV, 0x00);
/* YUV420, low pass filter on */
RegisterWrite(pDrv, R511_CAM_OPTS, 0x03);
/* Snapshot additions */
RegisterWrite(pDrv, R511_SNAP_PXCNT, hsegs);
RegisterWrite(pDrv, R511_SNAP_LNCNT, vsegs);
RegisterWrite(pDrv, R511_SNAP_PXDIV, 0x00);
RegisterWrite(pDrv, R511_SNAP_LNDIV, 0x00);
/*
if (ov->compress) {
/* Enable Y and UV quantization and compression */
/*RegisterWrite(pDrv, R511_COMP_EN, 0x07);
RegisterWrite(pDrv, R511_COMP_LUT_EN, 0x03);
ov51x_reset(ov, OV511_RESET_OMNICE);
}*/
if (!Ov51xRestart(pDrv))
{
return 0;
}
return 1;
}
//给OV511寄存器赋初始值(在OV511初始化时调用)
int WriteRegvals(PDRVCONTEXT pDrv)
{
RegisterWrite(pDrv,R51x_SYS_RESET,0x7f);
RegisterWrite(pDrv,R51x_SYS_INIT,0x01);
RegisterWrite(pDrv,R51x_SYS_RESET,0x7f);
RegisterWrite(pDrv,R51x_SYS_INIT,0x01);
RegisterWrite(pDrv,R51x_SYS_RESET,0x3f);
RegisterWrite(pDrv,R51x_SYS_INIT,0x01);
RegisterWrite(pDrv,R51x_SYS_RESET,0x3d);
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -