?? usbfndrv.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.
//
// 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: usbfndrv.cpp
Abstract:
Serial PDD Common Code.
Notes:
--*/
#include <windows.h>
#include <types.h>
#include <memory.h>
#include <notify.h>
#include <devload.h>
#include <windev.h>
#include <serdbg.h>
#include <serhw.h>
#include "s2440.h"
#include <nkintr.h>
#include <ceddk.h>
#include <drv_glob.h>
#include <2440usb.h>
#include <usbfndrv.h>
CUsbFuncTransfer::CUsbFuncTransfer(CUsbFuncPipe *hPipe, DWORD dwFlags,DWORD cbBuffer, PVOID pvBuffer, DWORD dwBufferPhysicalAddress)
: m_pPipe(hPipe)
, m_dwFlags(dwFlags)
, m_dwBufferSize (cbBuffer)
, m_pvBuffer (pvBuffer)
, m_dwPhysAddr (dwBufferPhysicalAddress)
{
ASSERT(hPipe!=NULL);
ASSERT(cbBuffer!=NULL);
ASSERT(pvBuffer!=NULL);
m_hCompleteEvent=CreateEvent(NULL, TRUE, FALSE, NULL); // Manual Reset and Initial FALSE
m_ufnTransfer = NULL;
}
CUsbFuncTransfer::~CUsbFuncTransfer()
{
if (m_pPipe) {
if ( m_ufnTransfer) {
if (!IsTransferComplete()) { // We need Cancel it.
AbortTransfer();
}
CloseTransfer();
}
}
if (m_hCompleteEvent) {
CloseHandle(m_hCompleteEvent);
}
}
BOOL CUsbFuncTransfer::Init()
{
return (m_pPipe && m_pPipe->GetFunctionPtr() && m_hCompleteEvent);
}
BOOL CUsbFuncTransfer::IssueTransfer(DWORD dwLength)
{
PREFAST_ASSERT(m_pPipe);
PREFAST_ASSERT(m_pPipe->GetFunctionPtr());
if (dwLength>GetBufferSize())
dwLength = GetBufferSize();
if (IsTransferClosed()) {
ResetEvent(m_hCompleteEvent);
DWORD dwRet =m_pPipe->GetFunctionPtr()->lpIssueTransfer(
m_pPipe->GetDeviceHandle(),m_pPipe->GetPipeHandle(),CompleteNotificationStub,this,m_dwFlags,
dwLength,m_pvBuffer,m_dwPhysAddr, NULL, &m_ufnTransfer);
DEBUGMSG (ZONE_EVENTS,(TEXT("CUsbFuncTransfer::IssueTransfer(Handle=0x%x,flags =0x%x size=0x%x)\r\n"),
m_ufnTransfer,m_dwFlags, dwLength));
// ASSERT(dwRet == ERROR_SUCCESS);
return(dwRet == ERROR_SUCCESS);
}
else
return FALSE;
}
BOOL CUsbFuncTransfer::WaitForTransferComplete(DWORD dwTicks)
{
PREFAST_ASSERT(m_hCompleteEvent!=NULL);
if (!IsTransferClosed()) {
return ( WaitForSingleObject(m_hCompleteEvent , dwTicks) == WAIT_OBJECT_0);
}
else
return TRUE;
}
BOOL CUsbFuncTransfer::GetTransferStatus(PDWORD pdwBytesTranfered, PDWORD pdwError)
{
PREFAST_ASSERT(m_pPipe);
PREFAST_ASSERT(m_pPipe->GetFunctionPtr());
if (!IsTransferClosed()) {
DWORD dwRet = m_pPipe->GetFunctionPtr()->lpGetTransferStatus(m_pPipe->GetDeviceHandle(),m_ufnTransfer,pdwBytesTranfered,pdwError);
ASSERT(dwRet == ERROR_SUCCESS);
return(dwRet == ERROR_SUCCESS);
}
else {
if (pdwError)
*pdwError = UFN_NOT_COMPLETE_ERROR;
if (pdwBytesTranfered)
*pdwBytesTranfered = 0;
return FALSE;
}
}
BOOL CUsbFuncTransfer::CloseTransfer()
{
PREFAST_ASSERT(m_pPipe);
PREFAST_ASSERT(m_pPipe->GetFunctionPtr());
if (!IsTransferClosed()) {
DWORD dwRet = m_pPipe->GetFunctionPtr()->lpCloseTransfer(m_pPipe->GetDeviceHandle(),m_ufnTransfer);
ASSERT(dwRet == ERROR_SUCCESS);
m_ufnTransfer = NULL;
return(dwRet == ERROR_SUCCESS);
}
else
return TRUE;
}
BOOL CUsbFuncTransfer::AbortTransfer()
{
PREFAST_ASSERT(m_pPipe);
PREFAST_ASSERT(m_pPipe->GetFunctionPtr());
if (!IsTransferComplete()) {
DWORD dwRet = m_pPipe->GetFunctionPtr()->lpAbortTransfer(m_pPipe->GetDeviceHandle(),m_ufnTransfer);
DEBUGMSG (ZONE_EVENTS,(TEXT("CUsbFuncTransfer::AbortTransfer(Handle=0x%x,flags =0x%x )\r\n"),
m_ufnTransfer,m_dwFlags));
ASSERT(dwRet == ERROR_SUCCESS);
return(dwRet == ERROR_SUCCESS);
}
else
return TRUE;
}
DWORD WINAPI CUsbFuncTransfer::CompleteNotificationStub(PVOID pvNotifyParameter)
{
DEBUGMSG (ZONE_EVENTS,(TEXT("CUsbFuncTransfer::CompleteNotificationStub(pv=0x%x)\r\n"),pvNotifyParameter));
ASSERT(pvNotifyParameter);
if (pvNotifyParameter) {
return ((CUsbFuncTransfer *)pvNotifyParameter) -> CompleteNotification();
}
else {
ASSERT(FALSE);
return ERROR_INVALID_DATA;
}
}
DWORD WINAPI CUsbFuncTransfer::CompleteNotification()
{
PREFAST_ASSERT(m_hCompleteEvent!=NULL);
PREFAST_ASSERT(m_pPipe);
if (!IsTransferClosed()) {
SetEvent(m_hCompleteEvent);
m_pPipe->TransferComplete(this);
return ERROR_SUCCESS;
}
else {
ASSERT(FALSE);
return ERROR_INVALID_DATA;
}
}
//------------------------------------------------Pipe ----------------------------------------------
CUsbFuncPipe::CUsbFuncPipe(USBSerialFn * pSerialFn, UFN_HANDLE hDevice,PCUFN_FUNCTIONS pUfnFuncs,UCHAR bEndpointAddr,BOOL fRead,DWORD dwMaxPacketSize, DWORD dwMaxTransferSize, DWORD dwMaxNumOfTransfer)
: CMiniThread (0, TRUE)
, m_pSerialFn (pSerialFn)
, m_hDevice ( hDevice)
, m_pUfnFuncs(pUfnFuncs)
, m_bEndpointAddr(bEndpointAddr)
, m_fRead ( fRead )
, m_dwMaxPacketSize ( dwMaxPacketSize )
, m_dwTranferSize(dwMaxTransferSize)
, m_dwNumOfTransfer(min(MAX_TRANSFER,dwMaxNumOfTransfer))
{
// Calculate buffer needed.
m_dwBufferSize = m_dwNumOfTransfer*m_dwTranferSize;
m_pbBuffer = new BYTE[m_dwBufferSize ];
m_dwBufferPhysAddr = 0;
for (DWORD dwIndex = 0; dwIndex< MAX_TRANSFER; dwIndex ++)
m_pTransferArray[dwIndex] = NULL;
m_dwWriteIndex = m_dwCompleteIndex = 0;
m_dwCurPosition = 0;
m_fZeroLengthNeeded = FALSE;
m_TerminateEvent = CreateEvent(NULL, FALSE, FALSE, NULL); // Manual Reset and Initial FALSE
m_hPipe = NULL;
}
BOOL CUsbFuncPipe::Init()
{
if (m_TerminateEvent && m_pbBuffer ) {
Lock();
ThreadStart();
Unlock();
return TRUE;
}
return FALSE;
}
CUsbFuncPipe::~CUsbFuncPipe()
{
Lock();
m_bTerminated = TRUE;
ThreadStart();
if (m_TerminateEvent) {
SetEvent(m_TerminateEvent);
}
Unlock();
BOOL fRet=WaitThreadComplete(1000);
// ASSERT(fRet == TRUE);
Lock();
ClosePipe();
if (m_pbBuffer!=NULL) {
delete m_pbBuffer;
}
if ( m_TerminateEvent)
CloseHandle(m_TerminateEvent);
Unlock();
}
BOOL CUsbFuncPipe::OpenPipe()
{
Lock();
if (m_hPipe==NULL) {
DWORD dwRet = m_pUfnFuncs->lpOpenPipe(m_hDevice, m_bEndpointAddr, &m_hPipe);
if (dwRet != ERROR_SUCCESS) {
m_hPipe = NULL;
ASSERT(FALSE);
}
if (m_hPipe != NULL) {
m_dwWriteIndex = m_dwCompleteIndex = 0;
BOOL fReturn = TRUE;
for (DWORD dwIndex = 0; dwIndex<m_dwNumOfTransfer; dwIndex ++) {
m_pTransferArray[dwIndex] = new CUsbFuncTransfer(this,
m_fRead? USB_OUT_TRANSFER: USB_IN_TRANSFER ,
m_dwTranferSize,
m_pbBuffer + (dwIndex*m_dwTranferSize),
m_dwBufferPhysAddr!=0?(m_dwBufferPhysAddr+(dwIndex*m_dwTranferSize)): 0 ) ;
if (m_pTransferArray[dwIndex]!= NULL && m_pTransferArray[dwIndex]->Init()== TRUE ) { // Successful
if (m_fRead) { // Lauch Issue Transfer first.
if (!m_pTransferArray[dwIndex]->IssueTransfer()) {
ASSERT(FALSE);
fReturn = FALSE;
break;
}
}
}
else {
ASSERT(FALSE);
fReturn = FALSE;
break;
}
}
if (!fReturn) { // Fail on Open Pipe or on Transfer.
ClosePipe();
}
}
}
if (m_hPipe)
SetEvent(m_TerminateEvent);
Unlock();
return (m_hPipe!=NULL);
}
void CUsbFuncPipe::ClosePipe()
{
Lock();
if (m_hPipe!=NULL) {
// Delete Transfer In order is required.
DWORD dwIndex = m_dwCompleteIndex;
do {
if (m_pTransferArray[dwIndex]!=NULL) {
delete m_pTransferArray[dwIndex];
m_pTransferArray[dwIndex] = NULL;
}
dwIndex= (dwIndex!=0?dwIndex-1:m_dwNumOfTransfer-1);
}
while (dwIndex !=m_dwCompleteIndex ) ;
m_pUfnFuncs->lpClosePipe(m_hDevice, m_hPipe);
}
m_hPipe = NULL;
Unlock();
}
DWORD CUsbFuncPipe::ReadData(PUCHAR pRxBuffer,ULONG *pBufflen)
{
DWORD dwBytesDropped = 0;
Lock();
if (m_hPipe != NULL && m_fRead && pRxBuffer && pBufflen && *pBufflen) {
DEBUGMSG (ZONE_READ,(TEXT("+CUsbFuncPipe::ReadData (0x%x,0x%x)\r\n"),pRxBuffer, pBufflen?*pBufflen:0));
DWORD dwRoomLeft = *pBufflen;
DWORD dwBytesStored = 0;
PREFAST_ASSERT(m_pTransferArray[m_dwCompleteIndex] != NULL);
DWORD dwBytes=0;
DWORD dwError=UFN_NO_ERROR;
if ( !m_pTransferArray[m_dwCompleteIndex]->IsTransferClosed() &&
m_pTransferArray[m_dwCompleteIndex]->IsTransferComplete() &&
m_pTransferArray[m_dwCompleteIndex]->GetTransferStatus(&dwBytes, &dwError) &&
dwError == UFN_NO_ERROR ) {
PBYTE pBuffer = (PBYTE)m_pTransferArray[m_dwCompleteIndex]->GetBufferPtr();
while (dwRoomLeft && m_dwCurPosition < dwBytes ) { // Then we have some work to do.
BYTE bData = pBuffer[m_dwCurPosition++];
if (m_pSerialFn == NULL || (m_pSerialFn->DataReplaced(&bData,FALSE))) {
*pRxBuffer++ = bData;
dwRoomLeft --;
dwBytesStored ++;
}
}
if (m_dwCurPosition >= dwBytes) { // This transfer has been completely unloaded.
m_pTransferArray[m_dwCompleteIndex]->CloseTransfer();
m_pTransferArray[m_dwCompleteIndex]->IssueTransfer();
// Advance to next one.
m_dwCompleteIndex = IncIndex(m_dwCompleteIndex);
m_dwCurPosition = 0;
}
}
else {
// ASSERT(FALSE);
if (!m_pTransferArray[m_dwCompleteIndex]->IsTransferClosed()) {
m_pTransferArray[m_dwCompleteIndex]->AbortTransfer();
m_pTransferArray[m_dwCompleteIndex]->CloseTransfer();
m_pTransferArray[m_dwCompleteIndex]->IssueTransfer();
}
dwBytesDropped = m_pTransferArray[m_dwCompleteIndex]->GetBufferSize();
m_dwCompleteIndex = IncIndex(m_dwCompleteIndex);
m_dwCurPosition = 0;
}
*pBufflen = dwBytesStored;
DEBUGMSG (ZONE_READ,(TEXT("-CUsbFuncPipe::ReadData (0x%x,0x%x) return drop=%x\r\n"),pRxBuffer, pBufflen?*pBufflen:0,dwBytesDropped));
}
else
ASSERT(FALSE);
Unlock();
return dwBytesDropped ;
}
//
//WriteDataOnce:
// It generates one Transfer if transfer that indexed by m_dwWriteIndex is not used.
//
void CUsbFuncPipe::WriteDataOnce(PUCHAR pTxBuffer, ULONG *pBuffLen)
{
Lock();
DEBUGMSG (ZONE_WRITE,(TEXT("+CUsbFuncPipe::WriteDataOnce (0x%x,0x%x) , m_fZeroLengthNeeded =%d \r\n"),
pTxBuffer,pBuffLen?*pBuffLen:0,m_fZeroLengthNeeded));
PREFAST_ASSERT(pBuffLen!=NULL);
if (m_pTransferArray[m_dwCompleteIndex]->IsTransferComplete()) {
m_pTransferArray[m_dwCompleteIndex]->CloseTransfer();
m_dwCompleteIndex = IncIndex(m_dwCompleteIndex);
}
// Next Xmit Transfer
if (m_pTransferArray[m_dwWriteIndex]->IsTransferClosed()) {
if (pTxBuffer && pBuffLen && *pBuffLen) {
DWORD dwInputLength = min(*pBuffLen,m_pTransferArray[m_dwWriteIndex]->GetBufferSize());
memcpy(m_pTransferArray[m_dwWriteIndex]->GetBufferPtr(),pTxBuffer, dwInputLength);
m_pTransferArray[m_dwWriteIndex]->IssueTransfer(dwInputLength);
m_fZeroLengthNeeded = ((dwInputLength & (m_dwMaxPacketSize-1)) == 0 );
DEBUGMSG (ZONE_WRITE,(TEXT("CUsbFuncPipe::WriteDataOnce: MaxPacketSize=%d,dwInputLength=%d , m_fZeroLengthNeeded =%d \r\n"),
m_dwMaxPacketSize,dwInputLength, m_fZeroLengthNeeded));
m_dwWriteIndex = IncIndex(m_dwWriteIndex);
SetEvent(m_TerminateEvent);
*pBuffLen = dwInputLength;
}
else {
if (m_fZeroLengthNeeded) { // Send 0 Length Packet.
m_pTransferArray[m_dwWriteIndex]->IssueTransfer(0);
m_dwWriteIndex = IncIndex(m_dwWriteIndex);
SetEvent(m_TerminateEvent);
}
m_fZeroLengthNeeded = FALSE;
*pBuffLen = 0;
}
}
else
*pBuffLen = 0;
DEBUGMSG (ZONE_WRITE,(TEXT("-CUsbFuncPipe::WriteDataOnce (0x%x,0x%x) , m_fZeroLengthNeeded =%d \r\n"),
pTxBuffer,pBuffLen?*pBuffLen:0,m_fZeroLengthNeeded));
Unlock();
}
//
// WriteData:
// It generate multiple Transfer when free transfer and data available.
//
void CUsbFuncPipe::WriteData(PUCHAR pTxBuffer, ULONG *pBuffLen)
{
Lock();
DEBUGMSG (ZONE_WRITE,(TEXT("+CUsbFuncPipe::WriteData (0x%x,0x%x)\r\n"), pTxBuffer,pBuffLen?*pBuffLen:0));
DWORD dwLeft =(pBuffLen?*pBuffLen:0);
if (!m_fRead) {
DWORD dwBytes ;
do {
dwBytes = dwLeft;
WriteDataOnce(pTxBuffer,&dwBytes);
pTxBuffer += dwBytes;
if (dwLeft >= dwBytes)
dwLeft -= dwBytes;
else
dwLeft = 0;
} while (dwBytes!=0);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -