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

📄 pddvclas.cpp

📁 基于webCan方面的源程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	rc = DoVendorTransfer (pDrv, USBVID_SET_CUR, USB_VIDEO_VS_CS_PROBE_CTL,
		                   bInterface, bUnit, (PBYTE)&pSPC, wProbeLen);
	if (rc)
		DEBUGMSG (ZONE_ERROR, (DTAG TEXT("Error setting probe values. rc %d\r\n"), rc));

	// Get back probe values
	if (rc == 0)
	{
		rc = DoVendorTransfer (pDrv, USBVID_GET_CUR, USB_VIDEO_VS_CS_PROBE_CTL,
		                       bInterface, bUnit, (PBYTE)&pSPC, wProbeLen);
		if (rc)
			DEBUGMSG (ZONE_ERROR, (DTAG TEXT("Error getting final probe values. rc %d\r\n"), rc));
	}

	// Set the commit values
	if (rc == 0)
	{
		rc = DoVendorTransfer (pDrv, USBVID_SET_CUR, USB_VIDEO_VS_CS_COMMIT_CTL,
		                       bInterface, bUnit, (PBYTE)&pSPC, wProbeLen);
		if (rc)
			DEBUGMSG (ZONE_ERROR, (DTAG TEXT("Error setting probe values. rc %d\r\n"), rc));
	}
	if (rc == 0)
	{
		//(db) USB2
		// Save the max payload value, we need this for choosing the proper interface
		*pdwMaxBandwidth = (pSPC.dwMaxVideoFrameSize * 10000) / pSPC.dwFrameInterval;

	DEBUGMSG (ZONE_FUNC | ZONE_PROBE, (DTAG TEXT("Alt BW %d\r\n"), *pdwMaxBandwidth));
		
		*pdwMaxBandwidth = pSPC.dwMaxPayloadTransferSize;
	}
	DEBUGMSG (ZONE_FUNC | ZONE_PROBE, 
	          (DTAG TEXT("ProbeCommitVidStream-- Fmt: %d  Frm: %d  Compression %d Interval %d  Transfer size: %d Frame size %d BW %d\r\n"), 
	          pSPC.bFormatIndex, pSPC.bFrameIndex, pSPC.wCompQuality, pSPC.dwFrameInterval, pSPC.dwMaxPayloadTransferSize, pSPC.dwMaxVideoFrameSize, *pdwMaxBandwidth));
	
	return rc;
}

//-----------------------------------------------------------------------
// AllocateInternalStreamBuffers - If a still is requested and no
// stream is currently running, this routine allocates streaming buffers
// internally.
// 
int AllocateInternalStreamBuffers (PPDDCONTEXT pPDD, DWORD dwMaxBuff) 
{
	int i, rc = 0;

	//
	// See if the new format is too small for the current default
	//
	if (pPDD->strStreamDefault.dwBuffSize < dwMaxBuff)
	{
		// We/re changing buffers, stop the current read thread 
		StopReadThread (pPDD);

		// Free old buffers
		for (i = 0; i < NUMDEFBUFFS; i++)
		{
			if (pPDD->strStreamDefault.pFrame[i].pBuff) LocalFree (pPDD->strStreamDefault.pFrame[i].pBuff);
			pPDD->strStreamDefault.pFrame[i].pBuff = 0;
		}

		// Allocate new buffers
		for (i = 0; i < NUMDEFBUFFS; i++)
		{
			pPDD->strStreamDefault.pFrame[i].pBuff = (PBYTE)LocalAlloc (LPTR, dwMaxBuff);

			// Check to see if the alloc is successful
			if (pPDD->strStreamDefault.pFrame[i].pBuff == 0)
			{
				// If we've already allocated some buffs, we need to free the ones we did
				if (i) 
				{
					// Yes, I'm reusing 'i', but I'm bailing out of this loop
					for (i = 0; i < NUMDEFBUFFS; i++)
					{
						if (pPDD->strStreamDefault.pFrame[i].pBuff) LocalFree (pPDD->strStreamDefault.pFrame[i].pBuff);
						pPDD->strStreamDefault.pFrame[i].pBuff = 0;
					}
				}
				DEBUGMSG (ZONE_ERROR, (DTAG TEXT("Failure allocating stream buffers\r\n")));
				return ERROR_NOT_ENOUGH_MEMORY;
			}
		}

		// We've set up the default buffs, set the buff ptr.
		pPDD->strStreamDefault.dwBuffSize = dwMaxBuff;

		// Use the reserved field to store the event handle local to the driver
		if (pPDD->strStreamDefault.dwReserved == 0)
			pPDD->strStreamDefault.dwReserved = (DWORD)CreateEvent (NULL, FALSE, FALSE, NULL);
	} 
	return rc;
}
//-----------------------------------------------------------------------
// NegotiateQuality - Given a fixed set of format/frame/interval, see if a
// quality setting can be found that allows us to fit into the available
// bus bandwidth.
// 
int NegotiateQuality (PDRVCONTEXT pDrv, BYTE bFormatIndex, BYTE bFrameIndex, DWORD dwValidInterval)
{
	int rc;
	DWORD dwBandwidth;
	WORD wQuality, wQualityMin, wQualityMax, wQualityInc;

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

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

	// Get the range of valid compression values for this format/frame/rate
	rc = GetMinMaxQuality (pDrv, bFormatIndex, bFrameIndex, dwValidInterval,
							&wQualityMin, &wQualityMax, &wQualityInc);
	if (rc == 0)
	{
		DEBUGMSG (ZONE_PROBE, (DTAG TEXT("Probe/Commit trying interval rate %d  Comp: min %d max %d int %d\r\n"), 
				  dwValidInterval, wQualityMin, wQualityMax, wQualityInc));
		
		// Loop through each compression quality setting finding one that works.
		for (wQuality = wQualityMax; wQuality >= wQualityMin; wQuality -= wQualityInc)
		{
			// Send the the paramters to the camera, it'll tell us the bandwidth it needs
			rc = ProbeCommitVidStream (pDrv, bFormatIndex, bFrameIndex, &dwValidInterval, wQuality,
									   &dwBandwidth);
			if (rc == 0) 
			{
				// Save the format and stream rate
				pPDD->wCurrFormatIndex = bFormatIndex;
				pPDD->wCurrFrameIndex = bFrameIndex;
				pPDD->dwCurrValidInterval = dwValidInterval;

				// Try to find an interface that will support the bandwidth
				rc = SetStreamInterface (pDrv, 1, dwBandwidth);
				if (rc == 0)
				{
					//Probe commit worked and we have an interface.  Yea! we're done.
					DEBUGMSG (ZONE_PROBE, (DTAG TEXT("Probe/Commit complete. Fmt: %d  Frm: %d  rate %d Compression %d Bandwidth %d\r\n"), 
							  bFormatIndex, bFrameIndex, dwValidInterval, wQuality, dwBandwidth));
					break;
				}
			}
		}
	}
	DEBUGMSG (ZONE_FUNC, (DTAG TEXT("NegotiateQuality--  rc %d\r\n"), rc));
	return rc;
}
	
//-----------------------------------------------------------------------
// FindStreamInterface - Find an interface given packet size needed.  
// If fMin is true, it finds the slowest interface that meets the
// packet size.  If fMin is false, if finds the fastest interface
// under the specified packet size.
//
PUSBSTRMIF FindStreamInterface (PPDDCONTEXT pPDD, BYTE nInterface, 
								WORD wPacketSize)
{
	int i;
	PUSBSTRMIF lpFound = 0;
	USHORT usSize, usFoundSize = 0;

	// Find the interface
	for (i = 0; i < pPDD->nStreamInterfaces; i++)
	{
		if (pPDD->usbstrmIF[i].ifDesc.bInterfaceNumber == nInterface) 
		{
			// Does the interface even have an endpoint?
			if (pPDD->usbstrmIF[i].fEndpoint)
			{
				//
				// Compute number of bytes transfered per frame for this endpoint. 
				// For USB 1, it's simply the value in the endpoint packet size.
				// For USB 2, the endpoint packet size value is not a discrete number.
				//  Instead, the lower 10 bits are multplied by a field that indicates
				//  how many transfers per frame are used.
				//

				WORD wPkt = pPDD->usbstrmIF[i].epDesc.wMaxPacketSize;
				// Copy basic value
				usSize = wPkt & USB_ENDPOINT_MAX_PACKET_SIZE_MASK;
				// Multiply by number of additional transfers per frame
				usSize *= (1 + ((wPkt & USB2_ENDPOINT_MAX_TRANSFER_MASK) >> USB2_ENDPOINT_MAX_TRANSFER_SHIFT));

				// Find the IF with min packet size that meets the needs
				if (usSize >= wPacketSize)
				{ 
					if (lpFound == 0) lpFound = &pPDD->usbstrmIF[i];
					if(usFoundSize < lpFound->epDesc.wMaxPacketSize)
					{
						lpFound = &pPDD->usbstrmIF[i];
						usFoundSize = usSize;
					}
				}
			}
			// See if we want a pipe with no bandwidth
			else if (wPacketSize == 0)
				return &pPDD->usbstrmIF[i];
		}
	}
	if (lpFound)
		return lpFound;
	return 0;
}

//-----------------------------------------------------------------------
// SetStreamInterface - Sets the requested stream interface.  The
// different stream interfaces have different data bandwidths.
// 
BOOL SetStreamInterface (PDRVCONTEXT pDrv, BYTE nInterface, DWORD dwBandwidth) 
{
	USB_TRANSFER hTransfer;
	PUSBSTRMIF lpIF;
	int rc;

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

	DEBUGMSG (ZONE_FUNC, (DTAG TEXT("SetStreamInterface++  Interface:%d  pktsize:%d\r\n"), 
	          nInterface, dwBandwidth));

	// Close the currently opened pipe if any
	if (pPDD->pipeStream.hEvent != 0)
	{
		pDrv->lpUsbFuncs->lpClosePipe (pPDD->pipeStream.hPipe);
		CloseHandle (pPDD->pipeStream.hEvent);
		pPDD->pipeStream.hEvent = 0;
	}

	// For USB 1.x, 1 mS frame rate 
	WORD wPacketSize = (WORD)dwBandwidth;

	// Find an interface that has the packet size we need
	lpIF = FindStreamInterface (pPDD, nInterface, 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;

			// USB 2 spec defines number of micro transfers per frame.
			pPDD->pipeStream.wPacketSize = ((lpIF->epDesc.wMaxPacketSize & USB_ENDPOINT_MAX_PACKET_SIZE_MASK) * 
			                                (1 + ((lpIF->epDesc.wMaxPacketSize & USB2_ENDPOINT_MAX_TRANSFER_MASK)
											       >> USB2_ENDPOINT_MAX_TRANSFER_SHIFT)
                                            )
										   );

			// 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 freatures of the camera.
//

#define USB_CONFIGURATION_SIZE_5  28
#define USB_CONFIGURATION_SIZE_6  32

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 {
		//
		// Descriptor structures changed from 5.0 to 6.  Need to check for both sizes
		//
		if ((lpUsbDev->lpConfigs->dwCount != USB_CONFIGURATION_SIZE_5) && 
		    (lpUsbDev->lpConfigs->dwCount != USB_CONFIGURATION_SIZE_6))
		{
			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.

		// (ce 6)
		// Need to auto adjust for different struct sizes
		//
		lpIF = lpUsbDev->lpConfigs->lpInterfaces;

		for (i = 0; i < lpUsbDev->lpConfigs->dwNumInterfaces; 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++;
			}
			// (ce 6) Inc by size of structure since it changed between 5 and 6
			lpIF = (LPCUSB_INTERFACE)((LPBYTE)lpIF + lpIF->dwCount);

		}
		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
		lpIF = lpUsbDev->lpConfigs->lpInterfaces; //(ce 6)
		for (i = 0; i < lpUsbDev->lpConfigs->dwNumInterfaces; 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

⌨️ 快捷键说明

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