📄 pipe.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
#include "pipe.h"
#include "ufnmdd.h"
static
inline
VOID
FreeTransfer(
CFreeTransferList *pFreeTransferList,
PCUfnMddTransfer pTransfer
)
{
SETFNAME();
PREFAST_DEBUGCHK(pFreeTransferList);
DEBUGCHK(pTransfer);
DEBUGMSG(ZONE_TRANSFER, (_T("%s Freeing transfer 0x%08x\r\n"),
pszFname, pTransfer));
pFreeTransferList->FreeTransfer(pTransfer);
}
CPipe::CPipe(
DWORD dwPhysicalEndpoint,
PUFN_PDD_INTERFACE_INFO pPddInfo,
CFreeTransferList *pFreeTransferList
) : m_TransferQueue()
{
DEBUGCHK(pPddInfo);
DEBUGCHK(pFreeTransferList);
InitializeCriticalSection(&m_cs);
m_dwPhysicalEndpoint = dwPhysicalEndpoint;
m_pPddInfo = pPddInfo;
m_pFreeTransferList = pFreeTransferList;
m_fOpen = FALSE;
m_dwSig = UFN_PIPE_SIG;
m_dwCompletionCount = 0 ;
Reset();
#ifdef DEBUG
m_dwThreadId = 0;
m_dwLockCount = 0;
#endif
}
CPipe::~CPipe()
{
DEBUGCHK(!IsOpen());
DEBUGCHK(m_dwLockCount == 0);
DeleteCriticalSection(&m_cs);
}
VOID
CPipe::Reserve(
UFN_BUS_SPEED Speed,
BOOL fReserve,
DWORD dwInterfaceNumber,
DWORD dwEndpointIndex,
PUSB_ENDPOINT_DESCRIPTOR pEndpointDesc
)
{
Lock();
PUSB_ENDPOINT_DESCRIPTOR *ppOurEndpointDesc;
if (Speed == BS_FULL_SPEED) {
ppOurEndpointDesc = &m_pFullSpeedEndpointDesc;
}
else {
ppOurEndpointDesc = &m_pHighSpeedEndpointDesc;
}
if (fReserve) {
m_dwReservedSpeedMask |= Speed;
if (GetPhysicalEndpoint() != 0) {
*ppOurEndpointDesc = pEndpointDesc;
m_dwEndpointIndex = dwEndpointIndex;
m_dwInterfaceNumber = dwInterfaceNumber;
}
}
else {
m_dwReservedSpeedMask &= ~Speed;
*ppOurEndpointDesc = NULL;
m_dwEndpointIndex = -1;
m_dwInterfaceNumber = -1;
}
Unlock();
}
DWORD
CPipe::Open(UFN_BUS_SPEED Speed, PUSB_ENDPOINT_DESCRIPTOR pEndpointDesc)
{
SETFNAME();
DWORD dwRet;
Lock();
DEBUGCHK(m_TransferQueue.IsEmpty());
DEBUGCHK(m_DoneTransferQueue.IsEmpty());
DEBUGCHK(Speed & m_dwReservedSpeedMask);
if (IsOpen()) {
DEBUGMSG(ZONE_ERROR, (_T("%s Pipe (0x%08x) is already opened\r\n"), pszFname, this));
dwRet = ERROR_INVALID_PARAMETER;
}
else {
PUSB_ENDPOINT_DESCRIPTOR pOurEndpointDesc;
if (Speed == BS_FULL_SPEED) {
pOurEndpointDesc = m_pFullSpeedEndpointDesc;
}
else {
pOurEndpointDesc = m_pHighSpeedEndpointDesc;
}
if (pOurEndpointDesc == NULL) {
DEBUGCHK(GetPhysicalEndpoint() == 0);
DEBUGCHK(pEndpointDesc);
pOurEndpointDesc = pEndpointDesc;
}
else {
DEBUGCHK(GetPhysicalEndpoint() != 0);
DEBUGCHK(pEndpointDesc == NULL);
}
dwRet = m_pPddInfo->pfnInitEndpoint(m_pPddInfo->pvPddContext,
m_dwPhysicalEndpoint, Speed, pOurEndpointDesc, NULL, 0, 0, 0);
if (dwRet == ERROR_SUCCESS) {
DEBUGMSG(ZONE_INIT || ZONE_PIPE, (_T("%s Opened pipe (0x%08x): physical address %u, bus address 0x%02x\r\n"),
pszFname, this, m_dwPhysicalEndpoint, GetEndpointAddress()));
m_fOpen = TRUE;
}
else {
DEBUGMSG(ZONE_ERROR, (_T("%s Failed to open pipe (0x%08x): physical address %u, bus address 0x%02x\r\n"),
pszFname, this, m_dwPhysicalEndpoint, GetEndpointAddress()));
}
}
Unlock();
return dwRet;
}
DWORD
CPipe::Close() {
SETFNAME();
DWORD dwRet = ERROR_SUCCESS;
Lock();
if (IsOpen() == FALSE) {
DEBUGMSG(ZONE_PIPE, (_T("%s Pipe (0x%08x): physical address %u is not open\r\n"),
pszFname, this, GetPhysicalEndpoint()));
dwRet = ERROR_INVALID_HANDLE;
}
else {
// We will say we are closed even if there was a failure
m_fOpen = FALSE;
AbortAllTransfers();
dwRet = m_pPddInfo->pfnDeinitEndpoint(m_pPddInfo->pvPddContext, m_dwPhysicalEndpoint);
if (dwRet == ERROR_SUCCESS) {
DEBUGMSG(ZONE_INIT || ZONE_PIPE, (_T("%s Closed pipe (0x%08x): physical address %u, bus address 0x%02x\r\n"),
pszFname, this, m_dwPhysicalEndpoint, GetEndpointAddress()));
}
else {
DEBUGMSG(ZONE_ERROR, (_T("%s Failed to close pipe (0x%08x): physical address %u, bus address 0x%02x\r\n"),
pszFname, this, m_dwPhysicalEndpoint, GetEndpointAddress()));
}
}
Unlock();
return (dwRet == ERROR_SUCCESS);
}
VOID
CPipe::AbortAllTransfers(
)
{
SETFNAME();
Lock();
while (m_TransferQueue.IsEmpty() == FALSE) {
PCUfnMddTransfer pTransfer = m_TransferQueue.Back();
pTransfer->Validate();
DEBUGCHK(!pTransfer->IsComplete());
DWORD dwErr = AbortTransfer(pTransfer);
DEBUGCHK(dwErr == ERROR_SUCCESS);
}
Unlock();
}
DWORD
CPipe::IssueTransfer(
LPTRANSFER_NOTIFY_ROUTINE lpNotifyRoutine,
PVOID pvNotifyContext,
DWORD dwFlags,
DWORD cbBuffer,
PVOID pvBuffer,
DWORD dwBufferPhysicalAddress,
PCUfnMddTransfer *ppTransfer,
PVOID pvPddTransferInfo
)
{
SETFNAME();
Lock();
FUNCTION_ENTER_MSG();
DEBUGCHK( (lpNotifyRoutine && pvNotifyContext) ||
( (lpNotifyRoutine == NULL) && (pvNotifyContext == NULL) ) );
DEBUGCHK( (cbBuffer == 0) || (pvBuffer) );
DEBUGCHK(ppTransfer);
DWORD dwRet;
BOOL fTransferOnQueue = FALSE;
BOOL fStartTransfer = FALSE;
PCUfnMddTransfer pTransfer = NULL;
if (IsOpen() == FALSE) {
DEBUGMSG(ZONE_WARNING, (_T("%s Pipe (0x%08x): physical address %u is not open\r\n"),
pszFname, this, GetPhysicalEndpoint()));
dwRet = ERROR_INVALID_HANDLE;
goto EXIT;
}
pTransfer = m_pFreeTransferList->AllocTransfer();
if (pTransfer == NULL) {
dwRet = GetLastError();
DEBUGMSG(ZONE_ERROR, (_T("%s Failed to allocate new transfer. Error: %d\r\n"),
pszFname, dwRet));
goto EXIT;
}
pTransfer->Init(dwFlags, pvBuffer, dwBufferPhysicalAddress, cbBuffer,
pvPddTransferInfo, lpNotifyRoutine, pvNotifyContext, this);
pTransfer->AddRef();
if (m_TransferQueue.IsEmpty()) {
fStartTransfer = TRUE;
}
dwRet = m_TransferQueue.PushBack(pTransfer);
if (dwRet != ERROR_SUCCESS) {
goto EXIT;
}
pTransfer->AddRef();
fTransferOnQueue = TRUE;
__try {
*ppTransfer = pTransfer;
}
__except(EXCEPTION_EXECUTE_HANDLER) {
RETAILMSG(1, (_T("%s Exception!\r\n"), pszFname));
dwRet = ERROR_INVALID_PARAMETER;
}
if (dwRet != ERROR_SUCCESS) {
goto EXIT;
}
DEBUGMSG(ZONE_TRANSFER, (_T("%s Issuing %s transfer (0x%08x) on ep %u (0x%02x) for %u bytes\r\n"),
pszFname,
(pTransfer->GetDwFlags() & USB_REQUEST_DEVICE_TO_HOST) ? _T("IN") : _T("OUT"),
pTransfer, GetPhysicalEndpoint(), GetEndpointAddress(),
pTransfer->GetCbBuffer()));
if (fStartTransfer) {
DEBUGCHK(pTransfer == m_TransferQueue.Front());
pTransfer->EnteringPdd();
dwRet = m_pPddInfo->pfnIssueTransfer(m_pPddInfo->pvPddContext,
GetPhysicalEndpoint(), pTransfer->GetPddTransfer());
if (dwRet != ERROR_SUCCESS) {
RETAILMSG(1, (_T("%s Could not start transfer 0x%08x\r\n"),
pszFname, pTransfer));
pTransfer->LeavingPdd();
}
}
EXIT:
if (pTransfer) {
if (dwRet != ERROR_SUCCESS) {
__try {
*ppTransfer = NULL;
}
__except(EXCEPTION_EXECUTE_HANDLER) {
DEBUGMSG(ZONE_ERROR, (_T("%s Exception!\r\n"), pszFname));
}
if (fTransferOnQueue) {
// We must remove this transfer from the list.
// Note that we've been holding the endpoint lock
// this whole time so no one has taken the transfer off
// the queue yet.
DEBUGCHK(m_TransferQueue.Back() == pTransfer);
m_TransferQueue.PopBack();
pTransfer->Release();
}
}
if (dwRet != ERROR_SUCCESS) {
// Free the transfer
pTransfer->Release();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -