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

📄 usbvideo.cpp

📁 Windows+CE下USB摄像头驱动开发,使用EVC开发。摄像头为 网眼 Webeye 2000 VID 0x05A9 PID 0xA511 输出格式:RAW-YUV
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		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 + -