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

📄 pddvclas.cpp

📁 wince 下
💻 CPP
📖 第 1 页 / 共 5 页
字号:

	// Find an interface that has the packet size we need
	lpIF = FindStreamInterface (pPDD, nInterface, TRUE, wPacketSize);

	// See if interface not found
	if (lpIF == 0)
		return -1;

	hTransfer = pDrv->lpUsbFuncs->lpSetInterface (pDrv->hDevice, NULL, NULL, 0, nInterface, 
	                                              lpIF->ifDesc.bAlternateSetting);
	if (hTransfer == 0)
	{
		DEBUGMSG (ZONE_ERROR, (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
	if (lpIF->fEndpoint)
	{
		// Open the pipe
		pPDD->pipeStream.hPipe = pDrv->lpUsbFuncs->lpOpenPipe (pDrv->hDevice, &lpIF->epDesc);
		// Check for sucessful open
		if (pPDD->pipeStream.hPipe)
		{
			// Copy some pipe attributes
			pPDD->pipeStream.ucAddr = lpIF->epDesc.bEndpointAddress;
			pPDD->pipeStream.wPacketSize = lpIF->epDesc.wMaxPacketSize;

			// First, create an event for handshaking
			pPDD->pipeStream.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
			DEBUGMSG (ZONE_ERROR, (DTAG TEXT("Error opening pipe  rc: %d\r\n"), rc));
		}
	}
	if (rc)
		DEBUGMSG (ZONE_ERROR, (DTAG TEXT("Error in SetStreamInterface  rc: %d  ExtErr: %d\r\n"), rc, GetLastError()));
	DEBUGMSG (ZONE_FUNC, (DTAG TEXT("SetStreamInterface--  rc %d\r\n"), rc));
	return rc;
}
//-----------------------------------------------------------------------
// ParseStreamInterfaces - Walks the camera's USB interface descriptors
// to determine the supported freaturs of the camera.
//
BOOL ParseStreamInterfaces (PPDDCONTEXT pPDD, LPCUSB_DEVICE lpUsbDev, BYTE bIFCtl,
							BYTE bIFSubCtl, BYTE bIFStrm, BYTE bIFSubStrm)
{
    DEBUGMSG (ZONE_USBLOAD, (DTAG TEXT("ParseStreamInterfaces++\r\n")));

    DEBUGMSG (ZONE_USBLOAD, (DTAG TEXT("Looking for Ctl IF %d %d and Stream IF %d %d\r\n"), bIFCtl, bIFSubCtl, bIFStrm, bIFSubStrm));
	__try {
	
		if (lpUsbDev->lpConfigs->dwCount != sizeof (USB_CONFIGURATION))
		{
			DEBUGMSG (ZONE_ERROR, (DTAG 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.
		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)
		{
			DEBUGMSG (ZONE_ERROR, (DTAG TEXT("No stream interfaces\r\n")));
			return FALSE;
		}
		pPDD->nStreamInterfaces = nStreamAlts + 1;
	    DEBUGMSG (ZONE_USBLOAD, (DTAG TEXT("Found %d stream interfaces. ID %d\r\n"), pPDD->nStreamInterfaces, nStreamID));
		if (nOtherStreams)
		{
			DEBUGMSG (ZONE_WARNING, (DTAG TEXT("Multiple stream interfaces found on device.  Using first one.\r\n")));
		}

		// Allocate the array for the stream interface descriptors
		if (pPDD->nStreamInterfaces)
		{
			pPDD->usbstrmIF = (PUSBSTRMIF)LocalAlloc (LPTR, pPDD->nStreamInterfaces * sizeof (USBSTRMIF));
		}

		nStreamAlts = 0;  // We'll use this to keep track of which stream and alt we've found.
		// Walk interface table again to get the info we need
		for (i = 0; i < lpUsbDev->lpConfigs->dwNumInterfaces; i++)
		{
			lpIF = &lpUsbDev->lpConfigs->lpInterfaces[i];

			//	
			// See if this is the video control interface
			//
			if ((lpIF->Descriptor.bInterfaceClass == bIFCtl) && (lpIF->Descriptor.bInterfaceSubClass == bIFSubCtl))
			{
				// Copy descriptor info
				pPDD->usbctlIF.ifDesc = lpIF->Descriptor;
				if (lpIF->lpvExtended)
				{
					// Cast the extended ptr as a video control extended header ptr
					PUSBVIDCTLIFDESCRIPTOR lpExDesc = (PUSBVIDCTLIFDESCRIPTOR)lpIF->lpvExtended;


					// Verify the header length
					if (lpExDesc->bLen > 0x0a)
					{
						// Allocate the space for the descriptor
						pPDD->usbctlIF.lpepExtDesc = LocalAlloc (LPTR, lpExDesc->wTotalLen);
						if (pPDD->usbctlIF.lpepExtDesc)
						{
							// Copy over the extended descriptor
							memcpy (pPDD->usbctlIF.lpepExtDesc, lpExDesc, lpExDesc->wTotalLen); 
						} 
						else
						{
							DEBUGMSG (ZONE_ERROR, (DTAG TEXT("Out of memory allocating extended if descriptor\r\n")));
							return FALSE;
						}
					}
					else
					{
						DEBUGMSG (ZONE_ERROR | ZONE_USBLOAD, 
						          (DTAG TEXT("Unexpected extended Ctl header format")));
						return FALSE;
					}
				} 
				else
					pPDD->usbctlIF.lpifExtDesc = 0;

				// Grab the interrupt end point if specified
				if (lpIF->lpEndpoints)
				{
					pPDD->usbctlIF.epDesc = lpIF->lpEndpoints->Descriptor;
					pPDD->usbctlIF.fEndpoint = TRUE;
				}
				else
					pPDD->usbctlIF.fEndpoint = FALSE;
			}
			//
			// See if this is the video stream interface
			//
			if ((lpIF->Descriptor.bInterfaceClass == bIFStrm) && 
				(lpIF->Descriptor.bInterfaceSubClass == bIFSubStrm) &&
				(lpIF->Descriptor.bInterfaceNumber == nStreamID))   // Also check for matching interface number found above
			{
				// Copy descriptor info
				pPDD->usbstrmIF[nStreamAlts].ifDesc = lpIF->Descriptor;
				if (lpIF->lpvExtended)
				{
					// Cast the extended ptr as a video control extended header ptr
					PUSBVIDSTREAMIFDESCRIPTOR lpExDesc = (PUSBVIDSTREAMIFDESCRIPTOR)lpIF->lpvExtended;

					// Verify the header length
					if (lpExDesc->bLen > 0x0a)
					{
						// Allocate the space for the descriptor
						pPDD->usbstrmIF[nStreamAlts].lpepExtDesc = LocalAlloc (LPTR, lpExDesc->wTotalLen);
						if (pPDD->usbstrmIF[nStreamAlts].lpepExtDesc)
						{
							// Copy over the extended descriptor
							memcpy (pPDD->usbstrmIF[nStreamAlts].lpepExtDesc, lpExDesc, lpExDesc->wTotalLen); 
						} 
						else
						{
							DEBUGMSG (ZONE_ERROR, (DTAG TEXT("Out of memory allocating extended if descriptor\r\n")));
							return FALSE;
						}
					} 
					else
					{
						DEBUGMSG (ZONE_ERROR | ZONE_USBLOAD, 
						          (DTAG TEXT("Unexpected extended Stream header format")));
						return FALSE;
					}

				} 
				else
					pPDD->usbstrmIF[nStreamAlts].lpifExtDesc = 0;

				// Grab the interrupt end point if specified
				if (lpIF->lpEndpoints)
				{
					pPDD->usbstrmIF[nStreamAlts].epDesc = lpIF->lpEndpoints->Descriptor;
					pPDD->usbstrmIF[nStreamAlts].fEndpoint = TRUE;
				}
				else
					pPDD->usbstrmIF[nStreamAlts].fEndpoint = FALSE;
				
				nStreamAlts++;  // Inc index into stream interface array
			}
		}
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		DEBUGMSG (ZONE_ERROR, (DTAG TEXT("Exception walking device interfaces\r\n")));
		return FALSE;
	}
    DEBUGMSG (ZONE_USBLOAD, (DTAG TEXT("ParseStreamInterfaces--\r\n")));
	return TRUE;
}

//-----------------------------------------------------------------------
// GetCameraError - Queries the error code from the device
// 
int GetCameraError (PDRVCONTEXT pDrv, BYTE *pErr)
{
	int rc = 0;
	BYTE bInterface = VID_IF_STREAM;
	BYTE bUnit = 0;

	DEBUGMSG (ZONE_FUNC, (DTAG TEXT("GetCameraError++\r\n")));

	// Get our pdd specific context
	PPDDCONTEXT pPDD = (PPDDCONTEXT)pDrv->dwPddContext; 

	*pErr = 0;
	rc = DoVendorTransfer (pDrv, USBVID_SET_CUR, USB_VIDEO_VS_CS_PROBE_CTL,
	                       bInterface, bUnit, pErr, 1);

	if (rc)
		DEBUGMSG (ZONE_ERROR, (DTAG TEXT("Error reading error code from camera rc %d\r\n"), rc));

	DEBUGMSG (ZONE_FUNC, (DTAG TEXT("GetCameraError++ rc %d error code %d\r\n"), rc, *pErr));
	return rc;
}

//=========================================================================
// ReadIsocThread - Thread that calls the Iscoh transfer function to 
// read the image data from the camera.
//
#define MAXFRAMES 1
DWORD WINAPI ReadIsocThread (PVOID pArg) {

	PDRVCONTEXT pDrv = (PDRVCONTEXT)pArg;
	PPDDCONTEXT pPDD = (PPDDCONTEXT)pDrv->dwPddContext; 
	PBYTE pDataBuff, pEnd;
	int nNumFrames;
	DWORD dw;
	DWORD dwFrameLen[MAXFRAMES];
	DWORD dwUsbRc[MAXFRAMES];
	DWORD dwBytes;
#ifdef DEBUG
	DWORD dwTicksAtFrameEnd = 0;
#endif
	BYTE bSaveBytes[16];
	DWORD dwFrameBytes;
	BYTE bError;

    DEBUGMSG (ZONE_FUNC | ZONE_THREAD, 
	          (DTAG TEXT("ReaReadIsocThreaddThread++ ID:%08x\r\n"), GetCurrentThread()));

	// Tweak the thread priority since we need priority over apps 
	// to read the pipe on time.
	SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
	
	// Initialize the ptrs
	pPDD->pstrStream->dwCurrBuff = 0;  
	pPDD->pstrStream->dwValidFrames = 0;  // No valid frames yet...
	pDataBuff = pPDD->pstrStream->pFrame[pPDD->pstrStream->dwCurrBuff].pBuff;
	pEnd = pDataBuff + pPDD->pstrStream->dwBuffSize;

	memset (dwFrameLen, 0, sizeof (dwFrameLen));
	memset (dwUsbRc, 0, sizeof (dwUsbRc));

	// Compare the buffer size with the packet size to make sure we at least can
	// read something.
	if (pPDD->pstrStream->dwBuffSize < pPDD->pipeStream.wPacketSize)
	{
	    DEBUGMSG (ZONE_ERROR, (DTAG TEXT("ReadThread failure, read buff size smaller than packet size\r\n")));
		return -1;
	}
#if MAXFRAMES > 1
	// See if we need multiple packets because stream packet size is > 1024
	{
		nNumFrames = (pPDD->pipeStream.wPacketSize / 1024) + 1;
		if (nNumFrames > MAXFRAMES)
		{
			DEBUGMSG (ZONE_ERROR, (DTAG TEXT("Packetsize %d > larger than supported\r\n"), pPDD->pipeStream.wPacketSize));
			return -2;
		}
	}
#endif	
	//
	//  Isoc pipe read loop
	//
	while (pPDD->wReadThreadState != STREAMTHD_STOPPED)	
	{
		// If we're looking for the first frame, reset ptr to start of first buffer
		if (pPDD->wReadThreadState == STREAMTHD_FRAMESYNC)
		{
			pDataBuff = pPDD->pstrStream->pFrame[pPDD->pstrStream->dwCurrBuff].pBuff;
			pEnd = pDataBuff + pPDD->pstrStream->dwBuffSize;
		}

		// Init size of frame buffers
#if MAXFRAMES > 1
		int nPacket = pPDD->pipeStream.wPacketSize;
		
		for (nNumFrames = 0; (nPacket > 0) && (nNumFrames < MAXFRAMES); nNumFrames++)
		{
			// Max transfer in USB is 1K
			dwFrameLen[nNumFrames] = min (nPacket, 1024);
			nPacket -= dwFrameLen[nNumFrames];
		}
#else	
		dwFrameLen[0] = min (pPDD->pipeStream.wPacketSize, 1024);
		nNumFrames = 1;
#endif

		// Limit check on buffer
		if (pDataBuff + dwFrameLen[0] >= pEnd)
		{
			DEBUGMSG (ZONE_ERROR | ZONE_THREAD, (DTAG TEXT("Buffer too small for next isoc data packet!\r\n")));
			break;
		}

		__try {


			dw = IssueIsochTransfer (pDrv->lpUsbFuncs, pPDD->pipeStream.hPipe, 
									 DefaultTransferComplete, pPDD->pipeStream.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
									 nNumFrames,      // 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

			DEBUGMSG (ZONE_READDATA && (dwBytes > 12), (DTAG TEXT("Read %5d bytes at %x  dw: %d\r\n"), dwBytes, pDataBuff, dw));
		}
		__except (EXCEPTION_EXECUTE_HANDLER)
		{
			DEBUGMSG (ZONE_ERROR | ZONE_THREAD, (DTAG TEXT ("Exception calling IssueIsochTransfer %d %d\r\n"), dw, GetLastError()));
			break;
		}
		if (dw)
		{
			DEBUGMSG (ZONE_ERROR | ZONE_THREAD, (DTAG TEXT ("Error calling IssueIsochTransfer %d %d\r\n"), dw, GetLastError()));
			if ((dw == 8) || (dw == 9)) // USB overrun and underrun errors.
				continue;
//			else
//				break;

			int rc = GetCameraError (pDrv, &bError);
			if (rc)
				DEBUGMSG (ZONE_ERROR, (DTAG TEXT("Can't read camera error code rc %d\r\n"), rc));
			else
				DEBUGMSG (ZONE_ERROR, (DTAG TEXT("Camera error code %d\r\n"), bError));
		
		
		}
		// See if we read at least the header
		if (dwBytes == 0)
		{
			DEBUGMSG (ZONE_READDATA, (DTAG TEXT("packet size read if %d bytes smaller than standard header\r\n"), dwBytes));
			continue;
		}

		// Look at payload header
		PUSBVIDPAYLOADHDR pPktHdr = (PUSBVIDPAYLOADHDR)pDataBuff;
		BYTE bPktFlags;
		if (pPktHdr->bLen != sizeof (USBVIDPAYLOADHDR))
		{
			DEBUGMSG (ZONE_PACKETS, (DTAG TEXT("===============

⌨️ 快捷键说明

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