📄 usbcam.c
字号:
/****************************************Copyright (c)**************************************************
** Guangzhou ZHIYUAN electronics Co.,LTD.
**
** http://www.zyinside.com
**
**--------------File Info-------------------------------------------------------------------------------
** File Name: USBCAMERA.c
** Last modified Date: 2007-01-9
** Last Version: V1.0
** Description: This driver Control the Usb Camera With Ov511 chip for PXA270
**
**------------------------------------------------------------------------------------------------------
** Created By: Wangyi Li 李望一
** Created date: 2007-01-9
** Version: V1.0
** Descriptions: The original version
**
**------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Description:
**
********************************************************************************************************/
#include "cam.h"
#include "String.h"
OV511STATUS ov;
DBGPARAM dpCurSettings;
static BYTE yQuanTable511[] = OV511_YQUANTABLE;
static BYTE uvQuanTable511[] = OV511_UVQUANTABLE;
static BYTE yQuanTable518[] = OV518_YQUANTABLE;
static BYTE uvQuanTable518[] = OV518_UVQUANTABLE;
static BYTE RawFrameData[115223];
static BYTE RealFrameData[115712];
static BYTE DataBuf[961 * 10];
HINSTANCE hInst; // DLL instance handle
USBCAMSTRUCT csCameras[] =
{
{ TEXT("OminiVision Ov511"), VID_OMINIVISION, PID_OV511},
{ TEXT("OminiVision WebEye 2000"), VID_OMINIVISION, 0xA511},
};
static int autobright = 1;
static int autogain = 1;
static int autoexp = 1;
static int debug;
static int snapshot;
static int cams = 1;
static int compress;
static int testpat;
static int dumppix;
static int led = 1;
static int dump_bridge;
static int dump_sensor;
static int printph;
static int phy = 0x1f;
static int phuv = 0x05;
static int pvy = 0x06;
static int pvuv = 0x06;
static int qhy = 0x14;
static int qhuv = 0x03;
static int qvy = 0x04;
static int qvuv = 0x04;
static int lightfreq;
static int bandingfilter;
static int clockdiv = -1;
static int packetsize = -1;
static int framedrop = -1;
static int fastset;
static int force_palette;
static int backlight;
static int remove_zeros;
static int mirror;
static int ov518_color;
//-----------------------------------------------------------------------
// IssueIsochTransfer - implements a synch isoch transfer to the device.
// This code was based on IssueVendorTransfer from USBClient.cpp
//
DWORD __inline 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)
{
DEBUGMSG(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传输完成事件
DEBUGMSG(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);
//DEBUGMSG(1,(TEXT("IssueIsochTransfer ERROR(5, BytesTransferred:%d, Win32Err:%d )\n"),
// pBytesTransferred?*pBytesTransferred:-1, dwErr));
}
return dwErr;
}
//写OV511寄存器
BOOL
RegisterWrite(PDRVCONTEXT pDrv,
BYTE reg,
BYTE value)
{
USB_DEVICE_REQUEST req;
DWORD dwBytes;
DWORD dw, dwErr;
BOOL bRc = FALSE;
BYTE buf = value;
// Get our pdd specific context
PDEVICECONTEXT pPDD = (PDEVICECONTEXT)pDrv->dwDeviceContext;
DEBUGMSG(1, (TEXT("RegisterWrite++\r\n")));
req.bmRequestType = USB_TYPE_VENDOR | USB_RECIP_DEVICE;
req.bRequest = 2;
req.wValue = 0;
req.wIndex = (USHORT)reg;
req.wLength = 1;
dwBytes = 0;
dwErr = USB_NO_ERROR;
dw = IssueVendorTransfer ( pDrv->lpUsbFuncs,
pDrv->hDevice,
DefaultTransferComplete,
pPDD->hVendorEvent,
USB_OUT_TRANSFER | USB_SHORT_TRANSFER_OK,
&req,
&buf,
(DWORD)NULL,
&dwBytes,
2000,
&dwErr);
if (dw)
{
DEBUGMSG(1, (TEXT("Error calling IssueVendorTransfer rc: %d ExtErr: %d\r\n"),
dw, GetLastError()));
bRc = FALSE;
}
else
{
// If no data transferred, stuff in an error
if (!dw && (dwBytes != 1))
{
DEBUGMSG(1, (TEXT("No Data Transfered!\r\n")));
dwErr = ERROR_BAD_LENGTH;
}
else
{
bRc = TRUE;
}
}
DEBUGMSG(1, (TEXT("RegisterWrite-- rc %d,%d bytes transfered!\r\n"), dw,dwBytes));
return bRc;
}
//读OV511寄存器
BOOL
RegisterRead( PDRVCONTEXT pDrv,
BYTE reg,
BYTE *value)
{
USB_DEVICE_REQUEST req;
DWORD dwBytes;
DWORD dw, dwErr;
BOOL bRc = FALSE;
BYTE buf = 0;
PDEVICECONTEXT pPDD = (PDEVICECONTEXT)pDrv->dwDeviceContext;
DEBUGMSG(1, (TEXT("RegisterRead++\r\n")));
// Get our pdd specific context
req.bmRequestType = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
req.bRequest = 3;
req.wValue = 0;
req.wIndex = (USHORT)reg;
req.wLength = 1;
dwBytes = 0;
dwErr = USB_NO_ERROR;
dw = IssueVendorTransfer( pDrv->lpUsbFuncs,
pDrv->hDevice,
DefaultTransferComplete,
pPDD->hVendorEvent,
USB_IN_TRANSFER | USB_SHORT_TRANSFER_OK,
&req,
&buf,
(DWORD)NULL,
&dwBytes,
2000,
&dwErr);
if (dw)
{
RETAILMSG(1, (TEXT("Error calling IssueVendorTransfer rc: %d ExtErr: %d\r\n"),
dw, GetLastError()));
}
else
{ // If no data transferred, stuff in an error
if (!dw && (dwBytes != 1))
{
RETAILMSG(1, (TEXT("No Data Transfered!\r\n")));
dw = ERROR_BAD_LENGTH;
}
else
{
bRc = TRUE;
*value = buf;
}
}
DEBUGMSG(1, (TEXT("RegisterRead-- rc %d,%d bytes transfered!\r\n"), dw,dwBytes));
return bRc;
}
/*
* Writes bits at positions specified by mask to an OV51x reg. Bits that are in
* the same position as 1's in "mask" are cleared and set to "value". Bits
* that are in the same position as 0's in "mask" are preserved, regardless
* of their respective state in "value".
*/
BOOL
RegWriteMask( PDRVCONTEXT pDrv,
BYTE reg,
BYTE value,
BYTE mask)
{
DWORD bRc;
BYTE tmp;
BYTE oldval, newval;
bRc = RegisterRead(pDrv, reg, &tmp);
if (bRc == FALSE)
return bRc;
oldval = (BYTE)tmp;
oldval &= (~mask); //Clear the masked bits
value &= mask; //Enforce mask on value
newval = oldval | value; //Set the desired bits
bRc = RegisterWrite(pDrv, reg, newval);
return bRc;
}
BOOL
OV511IICWrite(PDRVCONTEXT pDrv,
BYTE reg,
BYTE value)
{
int retries;
BYTE tmp;
BOOL bRc = FALSE;
DEBUGMSG(1, (TEXT("OV511 Write IIC 0x%2X:0x%2X\r\n"), reg, value));
/* Three byte write cycle */
retries = OV511IICREADETRIES;
while (1) {
/* Select camera register */
bRc = RegisterWrite(pDrv, R51x_I2C_SADDR_3, reg);
if (bRc == FALSE)
break;
/* Write "value" to I2C data port of OV511 */
bRc = RegisterWrite(pDrv, R51x_I2C_DATA, value);
if (bRc == FALSE)
break;
/* Initiate 3-byte write cycle */
bRc = RegisterWrite(pDrv, R511_I2C_CTL, 0x01);
if (bRc == FALSE)
break;
/* Retry until idle */
do
{
bRc = RegisterRead(pDrv, R511_I2C_CTL, &tmp);
}
while ((bRc == TRUE) && (tmp & 1) == 0);
if (bRc == FALSE)
break;
/* Ack? */
if ((tmp & 2) == 0) {
bRc = TRUE;
break;
}
if (--retries < 0) {
DEBUGMSG(1, (TEXT("i2c write retries exhausted\r\n")));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -