📄 pddvclas.cpp
字号:
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 + -