📄 trans.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.
//
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Module Name:
// Trans.cpp
//
// Abstract: Provides interface to UHCI host controller
//
// Notes:
//
//------------------------------------------------------------------------------
//
// Copyright (C) 2005-2006, Freescale Semiconductor, Inc. All Rights Reserved.
// THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
// AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT
//
//------------------------------------------------------------------------------
#include <windows.h>
#include <Cphysmem.hpp>
#include "trans.h"
#include "cpipe.h"
#include "chw.h"
#include "cehcd.h"
#ifndef _PREFAST_
#pragma warning(disable: 4068) // Disable pragma warnings
#endif
//***********************************************************************************
static void
memdump(unsigned char * data, unsigned short num_bytes, unsigned short offset )
//
// Purpose: Dump the memory content to the console
//
// Parameters: data - pointer to the data to be dumped
// num_bytes - size of data buffer
// offset - the index where it starts with
//
// Returns: Nothing
//
// Notes:
//
// ******************************************************************
{
unsigned short i,j,l;
unsigned char tmp_str[100];
unsigned char tmp_str1[10];
for (i = 0; i < num_bytes; i += 16) {
unsigned short n ;
tmp_str[0]='\0';
n = i+offset ;
for (j=0; j<4; j++) {
l=n%16;
if (l>=10)
tmp_str[3-j]=(unsigned char)('A'+l-10);
else
tmp_str[3-j]=(unsigned char)(l+'0');
n >>= 4 ;
}
tmp_str[4]='\0';
strcat ( (char *)tmp_str, ": ");
/* Output the hex bytes */
for (j = i; j < (i+16); j++) {
int m ;
if (j < num_bytes) {
m=((unsigned int)((unsigned char)*(data+j)))/16 ;
if (m>=10)
tmp_str1[0]='A'+(unsigned char)m-10;
else
tmp_str1[0]=(unsigned char)m+'0';
m=((unsigned int)((unsigned char)*(data+j)))%16 ;
if (m>=10)
tmp_str1[1]='A'+(unsigned char)m-10;
else
tmp_str1[1]=(unsigned char)m+'0';
tmp_str1[2]='\0';
strcat ((char *)tmp_str, (char *)tmp_str1);
strcat ((char *)tmp_str, " ");
}
else {
strcat((char *)tmp_str," ");
}
}
strcat((char *)tmp_str, " ");
l=(unsigned short)strlen((char *)tmp_str);
/* * Output the ASCII bytes */
for (j = i; j < (i+16); j++){
if (j < num_bytes){
char c = *(data+j);
if (c < ' ' || c > 'z')
c = '.';
tmp_str[l++]=c;
}
else
tmp_str[l++]=' ';
}
tmp_str[l++]='\r'; tmp_str[l++]='\n'; tmp_str[l++]='\0';
RETAILMSG(1, (L"%S", tmp_str));
}
RETAILMSG(1, (TEXT("\r\n")));
}
//********************************************************************************************
DWORD CTransfer::m_dwGlobalTransferID=0;
CTransfer::CTransfer(IN CPipe * const pCPipe, IN CPhysMem * const pCPhysMem,STransfer sTransfer)
: m_sTransfer( sTransfer)
, m_pCPipe(pCPipe)
, m_pCPhysMem(pCPhysMem)
//
// Purpose: Constructor of CTransfer class
//
// Parameters: pCPipe - Pointer to CPipe object to be associated with
// pCPhysMem - Pointer to CPhysMem to be used
// sTransfer - STransfer containing all the information for USB transfer
//
// Returns: Nothing
//
// Notes:
// ******************************************************************
{
m_pNextTransfer=NULL;
m_paControlHeader=0;
m_pAllocatedForControl=NULL;
m_pAllocatedForClient=NULL;
memcpy(&m_sTransfer, &sTransfer,sizeof(STransfer));
m_DataTransferred =0 ;
m_dwTransferID = m_dwGlobalTransferID++;
m_fDoneTransferCalled = FALSE;
}
//********************************************************************
CTransfer::~CTransfer()
//
// Purpose: Destructor of CTransfer class
//
// Parameters: None
//
// Returns: Nothing
//
// Notes:
// ******************************************************************
{
if (m_pAllocatedForControl!=NULL)
m_pCPhysMem->FreeMemory( PUCHAR(m_pAllocatedForControl),m_paControlHeader, CPHYSMEM_FLAG_NOBLOCK );
if (m_pAllocatedForClient!=NULL)
m_pCPhysMem->FreeMemory( PUCHAR(m_pAllocatedForClient), m_sTransfer.paBuffer, CPHYSMEM_FLAG_NOBLOCK );
DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE , (TEXT("CTransfer::~CTransfer() (this=0x%x,m_pAllocatedForControl=0x%x,m_pAllocatedForClient=0x%x)\r\n"),
this,m_pAllocatedForControl,m_pAllocatedForClient));
}
//*******************************************************************
BOOL CTransfer::Init(void)
//
// Purpose: Initialize routine for the CTransfer class
// This includes allocation of memory and setup the CTransfer class
// necessary to do the transfer. Finally, it calls AddTransfer() to do
// the transfer
//
// Parameters: None
//
// Returns: TRUE - success, FALSE - failure
//
// Notes:
// ******************************************************************
{
DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("CTransfer::Init (this=0x%x,id=0x%x)\r\n"),this,m_dwTransferID));
// We must allocate the control header memory here so that cleanup works later.
if (m_sTransfer.lpvControlHeader != NULL && m_pAllocatedForControl == NULL ) {
// This must be a control transfer. It is asserted elsewhere,
// but the worst case is we needlessly allocate some physmem.
if ( !m_pCPhysMem->AllocateMemory(
DEBUG_PARAM( TEXT("IssueTransfer SETUP Buffer") )
sizeof(USB_DEVICE_REQUEST),
&m_pAllocatedForControl,
CPHYSMEM_FLAG_NOBLOCK ) ) {
DEBUGMSG( ZONE_WARNING, (TEXT("CPipe(%s)::IssueTransfer - no memory for SETUP buffer\n"), m_pCPipe->GetPipeType() ) );
m_pAllocatedForControl=NULL;
return FALSE;
}
m_paControlHeader = m_pCPhysMem->VaToPa( m_pAllocatedForControl );
DEBUGCHK( m_pAllocatedForControl != NULL && m_paControlHeader != 0 );
__try {
memcpy(m_pAllocatedForControl,m_sTransfer.lpvControlHeader,sizeof(USB_DEVICE_REQUEST));
} __except( EXCEPTION_EXECUTE_HANDLER ) {
// bad lpvControlHeader
return FALSE;
}
}
#ifdef DEBUG
if ( m_sTransfer.dwFlags & USB_IN_TRANSFER ) {
// I am leaving this in for two reasons:
// 1. The memset ought to work even on zero bytes to NULL.
// 2. Why would anyone really want to do a zero length IN?
DEBUGCHK( m_sTransfer.dwBufferSize > 0 &&
m_sTransfer.lpvBuffer != NULL );
__try { // IN buffer, trash it
memset( PUCHAR( m_sTransfer.lpvBuffer ), GARBAGE, m_sTransfer.dwBufferSize );
} __except( EXCEPTION_EXECUTE_HANDLER ) {
}
}
#endif // DEBUG
if ( m_sTransfer.dwBufferSize > 0 && m_sTransfer.paBuffer == 0 ) {
// ok, there's data on this transfer and the client
// did not specify a physical address for the
// buffer. So, we need to allocate our own.
if ( !m_pCPhysMem->AllocateMemory(
DEBUG_PARAM( TEXT("IssueTransfer Buffer") )
m_sTransfer.dwBufferSize,
&m_pAllocatedForClient,
CPHYSMEM_FLAG_NOBLOCK ) ) {
DEBUGMSG( ZONE_WARNING, (TEXT("CPipe(%s)::IssueTransfer - no memory for TD buffer\n"), m_pCPipe->GetPipeType() ) );
m_pAllocatedForClient = NULL;
return FALSE;
}
m_sTransfer.paBuffer = m_pCPhysMem->VaToPa( m_pAllocatedForClient );
PREFAST_DEBUGCHK( m_pAllocatedForClient != NULL);
PREFAST_DEBUGCHK( m_sTransfer.lpvBuffer!=NULL);
DEBUGCHK(m_sTransfer.paBuffer != 0 );
if ( !(m_sTransfer.dwFlags & USB_IN_TRANSFER) ) {
__try { // copying client buffer for OUT transfer
memcpy( m_pAllocatedForClient, m_sTransfer.lpvBuffer, m_sTransfer.dwBufferSize );
//if ((m_sTransfer.dwBufferSize == 512) || (m_sTransfer.dwBufferSize == 31))
//DEBUGMSG(1, (TEXT("Out Transaction size %d\r\n"), m_sTransfer.dwBufferSize));
//memdump(m_pAllocatedForClient, (USHORT)m_sTransfer.dwBufferSize, 0);
} __except( EXCEPTION_EXECUTE_HANDLER ) {
// bad lpvClientBuffer
RETAILMSG(1, (TEXT("CQTransfer:Init: Exception handler\r\n")));
return FALSE;
}
}
}
DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE , (TEXT("CQTransfer::Init (this=0x%x,id=0x%x),m_pAllocatedForControl=0x%x,m_pAllocatedForClient=0x%x\r\n"),
this,m_dwTransferID,m_pAllocatedForControl,m_pAllocatedForClient));
return AddTransfer();
}
//********************************************************************************
CQTransfer::~CQTransfer()
//
// Purpose: Destructor of CQTransfer
//
// Parameters: None
//
// Returns: Nothing
//
// Notes:
// ******************************************************************
{
CQTD * pCurTD = m_pCQTDList;
while (pCurTD!=NULL) {
CQTD * pNextTD = pCurTD->GetNextTD();
pCurTD->~CQTD();
m_pCPhysMem->FreeMemory((PBYTE)pCurTD,m_pCPhysMem->VaToPa((PBYTE)pCurTD), CPHYSMEM_FLAG_HIGHPRIORITY |CPHYSMEM_FLAG_NOBLOCK );
pCurTD = pNextTD;
}
}
//********************************************************************
BOOL CQTransfer::AddTransfer()
//
// Purpose: Setup all the queue transfer descriptor and do the actual transfer
// of the data through IssueTransfer
//
// Parameters: None
//
// Returns: TRUE - success, FALSE - failure
//
// Notes:
// ******************************************************************
{
DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("CQTransfer::AddTransfer (this=0x%x,id=0x%x)\r\n"),this,m_dwTransferID));
if (m_pCQTDList) { // Has been created. Somthing wrong.
ASSERT(FALSE);
return FALSE;
}
BOOL bDataToggle1= FALSE;
CQTD * pStatusTD = NULL;
if (m_paControlHeader!=NULL && m_sTransfer.lpvControlHeader!=NULL) {
// This is setup packet.
if (m_pCQTDList = new(m_pCPhysMem) CQTD(this, ((CQueuedPipe * const)m_pCPipe)->GetQHead())) {
PhysBufferArray bufferArray;
bufferArray.dwNumOfBlock=1;
bufferArray.dwStartOffset=m_paControlHeader & EHCI_PAGE_OFFSET_MASK;
bufferArray.dwBlockSize=min(bufferArray.dwStartOffset + sizeof(USB_DEVICE_REQUEST),EHCI_PAGE_SIZE );
bufferArray.dwArrayBlockAddr[0]=(m_paControlHeader & EHCI_PAGE_ADDR_MASK);
bufferArray.dwArrayBlockAddr[1]=((m_paControlHeader+sizeof(USB_DEVICE_REQUEST)) & EHCI_PAGE_ADDR_MASK ); // Terminate
m_pCQTDList->IssueTransfer( TD_SETUP_PID, bDataToggle1, sizeof(USB_DEVICE_REQUEST),&bufferArray,TRUE);
bDataToggle1 = !bDataToggle1;
}
else
return FALSE;
// Status Packet
pStatusTD = new(m_pCPhysMem) CQTD(this, ((CQueuedPipe * const)m_pCPipe)->GetQHead());
if (pStatusTD) {
PhysBufferArray bufferArray;
bufferArray.dwNumOfBlock=0;
bufferArray.dwBlockSize=0;
bufferArray.dwStartOffset=0;
bufferArray.dwArrayBlockAddr[0]=0;
bufferArray.dwArrayBlockAddr[1]=0;// Terminate
pStatusTD->IssueTransfer( (m_sTransfer.dwFlags & USB_IN_TRANSFER)!=0?TD_OUT_PID:TD_IN_PID,
TRUE, 0 ,&bufferArray,TRUE);
}
else
return FALSE;
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -