//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
//******************************************************************************
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//******************************************************************************
/*++

Module Name:  

BaseTst.cpp

Abstract:  
    USB Driver Default Function Test .

Functions:

Notes: 

--*/

#define __THIS_FILE__   TEXT("BaseTst.cpp")

#include <windows.h>
#include "usbtest.h"
#include "BaseTst.h"


DWORD WINAPI UsbFuncTest::TransferNotify(LPVOID lpvNotifyParameter) 
{
	DEBUGMSG(DBG_FUNC,(TEXT("UsbFunctTest::TransferNotify(0x%lx)\n"),lpvNotifyParameter));
	return ((UsbFuncTest *)lpvNotifyParameter)->FunctionComplete();
};

BOOL UsbFuncTest::CheckResult(BOOL bSuccess,USB_HANDLE usbTransfer)
{
	DEBUGMSG(DBG_FUNC,(TEXT("CheckResult\n")));
	if (!usbTransfer) {
		if (bSuccess) 
			g_pKato->Log(LOG_FAIL, TEXT("Fail at Transfer,return zero handle"));
		SetErrorCode(ERROR_USB_TRANSFER);
		DEBUGMSG(DBG_DETAIL,(TEXT("CheckResult NULL handle return FALSE")));
		return FALSE;
	};

	UsbTransfer aTransfer(usbTransfer,usbDriver.lpUsbFuncs);
	if (fAsync && WaitForComplete(USB_TIME_OUT)==FALSE) { // time out
		if (bSuccess)
			g_pKato->Log(LOG_FAIL, TEXT("Fail at Transfer,Time Out"));
		SetErrorCode(ERROR_USB_TRANSFER);
		DEBUGMSG(DBG_FUNC,(TEXT("CheckResult Time out return TRUE")));
		return FALSE;
	}
	else
	if (!aTransfer.IsTransferComplete ()) { // somthing wrong
		if (bSuccess) {
			DWORD dwError;
			DWORD dwByteTransfer;
			DWORD rtError;
			rtError=(DWORD)aTransfer.GetTransferStatus(&dwByteTransfer,&dwError);
			g_pKato->Log(LOG_FAIL, TEXT("Fail at Transfer,Error(%ld),TransferedByte(%ld),Return(%ld)"),dwError,dwByteTransfer,rtError);
		};
		SetErrorCode(ERROR_USB_TRANSFER);
		DEBUGMSG(DBG_FUNC,(TEXT("CheckResult transfer not complete return FALSE\n")));
		return FALSE;
	}
	else {
		DWORD dwError;
		DWORD dwByteTransfer;
		DWORD rtError;
		rtError=(DWORD)aTransfer.GetTransferStatus(&dwByteTransfer,&dwError);
		DEBUGMSG(DBG_DETAIL,(TEXT("GetTrasferStatus Return (%ld,%ld)\n"),dwByteTransfer,dwError));
		if (dwError!=USB_NO_ERROR) {
			if (bSuccess )
				g_pKato->Log(LOG_FAIL, TEXT("Fail at Transfer,Error(%ld),TransferedByte(%ld),Return(%ld)"),dwError,dwByteTransfer,rtError);
			SetErrorCode(ERROR_USB_TRANSFER);
			DEBUGMSG(DBG_FUNC,(TEXT("CheckResult transfer complete with error(%ld) return FALSE\n"),dwError));
			return FALSE;
		};
	};
	DEBUGMSG(DBG_FUNC,(TEXT("CheckResult return TRUE\n")));
	return TRUE;
};

class GetDespTest: public UsbFuncTest {
public:
	GetDespTest(UsbClientDrv *pDriverPtr,BOOL Async,UCHAR bType,UCHAR bIndex,WORD wLanguage,
			WORD wLength,LPVOID lpvBuffer,BOOL bSuccess);
};

GetDespTest::GetDespTest(UsbClientDrv *pDriverPtr,BOOL Async,UCHAR bType,UCHAR bIndex,WORD wLanguage,
			WORD wLength,LPVOID lpvBuffer,BOOL bSuccess) :
	UsbFuncTest(pDriverPtr,Async)
{
	DEBUGMSG(DBG_DETAIL,(TEXT("GetDespTest")));
       if(lpvBuffer == NULL || wLength > 0x9000)
            return;
        
       // Zero out buffer, just in case
       memset( lpvBuffer, 0, wLength );

	USB_STRING_DESCRIPTOR aDescriptor;

	hTransfer=usbDriver.GetDescriptor(TransferNotify,(PVOID)this,(fAsync?USB_NO_WAIT:0),
			bType,bIndex,wLanguage,2,&aDescriptor);
	if (!hTransfer) {
		g_pKato->Log(LOG_FAIL, TEXT("Fail GetDescriptor(Get Length) return NULL transfer handle"));
		SetErrorCode(ERROR_USB_TRANSFER);
	}
	else
	if (CheckResult(bSuccess,hTransfer)) {
		DEBUGMSG(DBG_DETAIL,(TEXT(" Descriptor Length (%ld),Type(%ld)"),
				(DWORD)aDescriptor.bLength,(DWORD)aDescriptor.bDescriptorType));
		if (aDescriptor.bDescriptorType!=bType) {
			g_pKato->Log(LOG_FAIL, TEXT("Fail GetDescriptor ,Wrong type request(%ld),Get(%ld)"),
					(DWORD)bType,(DWORD)aDescriptor.bDescriptorType);
			SetErrorCode(ERROR_USB_TRANSFER);
		}
		else
		if (!aDescriptor.bLength) {
			memcpy(lpvBuffer,&aDescriptor,2);
		}
		else {
			wLength=min(wLength,aDescriptor.bLength);
			hTransfer=usbDriver.GetDescriptor(TransferNotify,(PVOID)this,(fAsync?USB_NO_WAIT:0),
					bType,bIndex,wLanguage,wLength,lpvBuffer);
			if (!hTransfer) {
				g_pKato->Log(LOG_FAIL, TEXT("Fail GetDescriptor return NULL transfer handle"));
				SetErrorCode(ERROR_USB_TRANSFER);
			}
			else
				CheckResult(bSuccess,hTransfer);
		};
	};
	BOOL m_bHalted=FALSE;
	if (!usbDriver.IsDefaultPipeHalted(&m_bHalted)) {
		g_pKato->Log(LOG_FAIL,TEXT("IsDefaultPipeHalted return error"));
		SetErrorCode(ERROR_USB_TRANSFER);
	}
	else {
		if (m_bHalted) {
			if (!usbDriver.ResetDefaultPipe()) {
				g_pKato->Log(LOG_FAIL,TEXT("ResetDefaultPipe return Error!"));
				SetErrorCode(ERROR_USB_TRANSFER);
			};
		}
	};
};

BOOL GetCurrentDescriptor(UsbClientDrv *pDriverPtr,BOOL aSync,UCHAR bType,UCHAR bIndex,
						  WORD wLanguage,BOOL bSuccess)
{
	PUCHAR rBuffer = NULL; // 4 k;
	WORD bLength=0x1000;
	rBuffer = (PUCHAR)LocalAlloc(LPTR, 0x1000*sizeof(UCHAR));
	if(rBuffer == NULL){
		g_pKato->Log(LOG_FAIL, (TEXT("GetCurrentDescriptor: Out of Memory")));
		return FALSE;
	}

	DEBUGMSG(DBG_DETAIL,(TEXT("GetCurrentDescriptor (%s),bType(%lx),bIndex(%lx),wLanguage(%lx), should %s "),
		aSync?TEXT("Async"):TEXT("Sync"),
		(DWORD)bType,(DWORD)bIndex,(DWORD)wLanguage,
		bSuccess?TEXT("Success"):TEXT("Failure")));
	GetDespTest* pTest= new GetDespTest(pDriverPtr,aSync,bType,bIndex,
			wLanguage,bLength,rBuffer,bSuccess);
	if(pTest == NULL){
		g_pKato->Log(LOG_FAIL, (TEXT("GetCurrentDescriptor: Out of Memory")));
		LocalFree(rBuffer);
		return FALSE;
	}

	if ((pTest->GetErrorCode()==0) ^ bSuccess) { //Not match
		if (bSuccess)
			g_pKato->Log(LOG_FAIL, TEXT("Fail at GetDescriptor,DEVICE_DESCRIPTOR Error(%ld)"),pTest->GetErrorCode());
		else
			g_pKato->Log(LOG_FAIL, TEXT("Fail at GetDescriptor,Unexpected Success return"));
		delete pTest;
		LocalFree(rBuffer);
		return FALSE;
	} 
	else 
	if (pTest->GetErrorCode()==0) {
		PUSB_DEVICE_DESCRIPTOR pDeviceDesc=(PUSB_DEVICE_DESCRIPTOR)rBuffer;
		if (pDeviceDesc->bDescriptorType!=bType) {
			g_pKato->Log(LOG_FAIL, TEXT("Fail at GetDescriptor,DEVICE_DESCRIPTOR,Wrong Type" ));
			delete pTest;
			LocalFree(rBuffer);
			return FALSE;
		};
		if (bType==USB_STRING_DESCRIPTOR_TYPE) {
			TCHAR tString[0x100];
			if (pTest->usbDriver.TranslateStringDesc((LPCUSB_STRING_DESCRIPTOR)pDeviceDesc,tString,0x100))
				g_pKato->Log(LOG_COMMENT, TEXT("String Descr is \"%s\"" ),tString);
			else {
				g_pKato->Log(LOG_FAIL, TEXT("TranslateStringDescr" ));
				delete pTest;
				LocalFree(rBuffer);
				return FALSE;
			};
		}

	};
	g_pKato->Log(LOG_COMMENT, TEXT("GetCurrentDescriptor return success"));
	delete pTest;
	LocalFree(rBuffer);
	return TRUE;
}
BOOL GetDespscriptorTest(UsbClientDrv * pDriverPtr,BOOL aSync)
{
	LPCUSB_DEVICE pDevice=pDriverPtr->GetDeviceInfo();

	if (!GetCurrentDescriptor(pDriverPtr,aSync,USB_STRING_DESCRIPTOR_TYPE,0,0,TRUE))
		return FALSE;

	DEBUGMSG(DBG_DETAIL,(TEXT("Number of Configuration %d "),pDevice->Descriptor.bNumConfigurations));
	for (UCHAR uIndex=0;uIndex<pDevice->Descriptor.bNumConfigurations;uIndex++) {
		if (!GetCurrentDescriptor(pDriverPtr,aSync,USB_CONFIGURATION_DESCRIPTOR_TYPE,uIndex,0,TRUE))
			return FALSE;
	};
	if (!GetCurrentDescriptor(pDriverPtr,aSync,USB_DEVICE_DESCRIPTOR_TYPE,0,0,TRUE))
		return FALSE;

	if (!GetCurrentDescriptor(pDriverPtr,aSync,USB_DEVICE_DESCRIPTOR_TYPE,1,0,FALSE))
		return FALSE;
	if (!GetCurrentDescriptor(pDriverPtr,aSync,USB_CONFIGURATION_DESCRIPTOR_TYPE,1,0,FALSE))
		return FALSE;
	if (!GetCurrentDescriptor(pDriverPtr,aSync,USB_STRING_DESCRIPTOR_TYPE,1,0,FALSE))
		return FALSE;

	if (!GetCurrentDescriptor(pDriverPtr,aSync,USB_DEVICE_DESCRIPTOR_TYPE,1,1,FALSE))
		return FALSE;
	if (!GetCurrentDescriptor(pDriverPtr,aSync,USB_CONFIGURATION_DESCRIPTOR_TYPE,1,1,FALSE))
		return FALSE;
	if (!GetCurrentDescriptor(pDriverPtr,aSync,USB_STRING_DESCRIPTOR_TYPE,1,0x0409,TRUE))
		return FALSE;
	if (!GetCurrentDescriptor(pDriverPtr,aSync,USB_STRING_DESCRIPTOR_TYPE,2,0x0409, TRUE))
		return FALSE;
	if (!GetCurrentDescriptor(pDriverPtr,aSync,USB_STRING_DESCRIPTOR_TYPE,3,0x0409,TRUE))
		return FALSE;
	return TRUE;
};




class SetDespTest: public UsbFuncTest {
public:
	SetDespTest(UsbClientDrv *pDriverPtr,BOOL Async,UCHAR bType,UCHAR bIndex,WORD wLanguage,
			WORD wLength,LPVOID lpvBuffer,BOOL bSuccess);
};

SetDespTest::SetDespTest(UsbClientDrv *pDriverPtr,BOOL Async,UCHAR bType,UCHAR bIndex,WORD wLanguage,
			WORD wLength,LPVOID lpvBuffer,BOOL bSuccess) :
	UsbFuncTest(pDriverPtr,Async)
{
	DEBUGMSG(DBG_FUNC,(TEXT("SetDespTest with TransferNotify(0x%lx)\n"),this));
	hTransfer=
		usbDriver.SetDescriptor(TransferNotify,this,fAsync?USB_NO_WAIT:0,
			bType,bIndex,wLanguage,wLength,lpvBuffer);
	if (!hTransfer) {
		g_pKato->Log(LOG_FAIL, TEXT("Fail GetDescriptor return NULL transfer handle"));
		SetErrorCode(ERROR_USB_TRANSFER);
	}
	else
		CheckResult(bSuccess,hTransfer);
};

class GetInterfaceTest: public UsbFuncTest {
public:
	GetInterfaceTest(UsbClientDrv *pDriverPtr,BOOL Async,UCHAR bInterfaceNumber,PUCHAR lprAlternateSetting,BOOL bSuccess);
};

GetInterfaceTest::GetInterfaceTest(UsbClientDrv *pDriverPtr,BOOL Async,UCHAR bInterfaceNumber,PUCHAR lprAlternateSetting,BOOL bSuccess) :
	UsbFuncTest(pDriverPtr,Async)
{
	DEBUGMSG(DBG_FUNC,(TEXT("+GetInterfaceTest::GetInterfaceTest(%ld)\n"),Async));

	DEBUGMSG(DBG_DETAIL,(TEXT("GetInterfaceTest with TransferNotify(0x%lx)\n"),this));
	hTransfer=
		usbDriver.GetInterface(TransferNotify,this,fAsync?USB_NO_WAIT:0,
			bInterfaceNumber,lprAlternateSetting);
	if (!hTransfer) {
		g_pKato->Log(LOG_FAIL, TEXT("Fail GetDescriptor return NULL transfer handle"));
		SetErrorCode(ERROR_USB_TRANSFER);
	}
	else
		CheckResult(bSuccess,hTransfer);
	DEBUGMSG(DBG_FUNC,(TEXT("-GetInterfaceTest::GetInterfaceTest\n")));
};

class SetInterfaceTest: public UsbFuncTest {
public:
	SetInterfaceTest(UsbClientDrv *pDriverPtr,BOOL Async,UCHAR bInterfaceNumber,UCHAR bAlternateSetting,BOOL bSuccess);
};

SetInterfaceTest::SetInterfaceTest(UsbClientDrv *pDriverPtr,BOOL Async,UCHAR bInterfaceNumber,UCHAR bAlternateSetting,BOOL bSuccess) :
	UsbFuncTest(pDriverPtr,Async)
{
	hTransfer=
		usbDriver.SetInterface(TransferNotify,this,fAsync?USB_NO_WAIT:0,
			bInterfaceNumber,bAlternateSetting);
	if (!hTransfer) {
		g_pKato->Log(LOG_FAIL, TEXT("Fail SetDescriptor return NULL transfer handle"));
		SetErrorCode(ERROR_USB_TRANSFER);
	}
	else
		CheckResult(bSuccess,hTransfer);
};

class FeatureSetting: public UsbFuncTest {
public:
	FeatureSetting(UsbClientDrv *pDriverPtr,BOOL bSet,BOOL Async,
		DWORD dwFlag,WORD wFeature,UCHAR bIndex,BOOL bSuccess);
};

FeatureSetting::FeatureSetting(UsbClientDrv *pDriverPtr,BOOL bSet,BOOL Async,
							   DWORD dwFlag,WORD wFeature,UCHAR bIndex,BOOL bSuccess) :
	UsbFuncTest(pDriverPtr,Async)
{
	if (fAsync)
		dwFlag |=USB_NO_WAIT;
	else
		dwFlag &=~USB_NO_WAIT;

	hTransfer=
		(bSet?
		usbDriver.SetFeature(TransferNotify,this,dwFlag,wFeature,bIndex)
			:
		usbDriver.ClearFeature(TransferNotify,this,dwFlag,wFeature,bIndex)
			);

	if (!hTransfer) {
		g_pKato->Log(LOG_FAIL, TEXT("Fail SetDescriptor return NULL transfer handle"));
		SetErrorCode(ERROR_USB_TRANSFER);
	}
	else
		CheckResult(bSuccess,hTransfer);
};
class GetStatus: public UsbFuncTest {
public:
	GetStatus(UsbClientDrv *pDriverPtr,BOOL Async,UCHAR bIndex,DWORD dwFlag,
		LPWORD lpwStatus,BOOL bSuccess);
};

GetStatus::GetStatus(UsbClientDrv *pDriverPtr,BOOL Async,UCHAR bIndex,DWORD dwFlag,
					 LPWORD lpwStatus,BOOL bSuccess):
	UsbFuncTest(pDriverPtr,Async)
{
	if (fAsync)
		dwFlag |=USB_NO_WAIT;
	else
		dwFlag &=~USB_NO_WAIT;

	hTransfer=usbDriver.GetStatus(TransferNotify,this,dwFlag,bIndex,lpwStatus);
	if (!hTransfer) {
		g_pKato->Log(LOG_FAIL, TEXT("Fail SetDescriptor return NULL transfer handle"));
		SetErrorCode(ERROR_USB_TRANSFER);
	}
	else
		CheckResult(bSuccess,hTransfer);
};

BOOL GetInterfaceTest_A(UsbClientDrv *pDriverPtr,BOOL Async)
{
	UCHAR bInterfaceNumber=0;
	UCHAR uNextInterface=0;
	UINT count=0;
	DWORD errorCode=0;
	do {
		GetInterfaceTest * pGetInterfaceTest = new GetInterfaceTest(pDriverPtr,Async,bInterfaceNumber,&uNextInterface,TRUE);
		if(pGetInterfaceTest == NULL){
			g_pKato->Log(LOG_FAIL, TEXT("Out of memory"));
			return FALSE;
		}
		errorCode=pGetInterfaceTest->GetErrorCode();
		delete pGetInterfaceTest;
		if ((errorCode)!=0) {
			g_pKato->Log(LOG_FAIL, TEXT("Fail at GetInterface,errorCode(%ld)"),errorCode);
			return FALSE;
		};
		if (bInterfaceNumber==uNextInterface) // only interface it has
			break;
		bInterfaceNumber=uNextInterface;
		uNextInterface=0;
		count++;
	}while (count<10);

	bInterfaceNumber=0xfe;
	uNextInterface=0xfe;
	GetInterfaceTest * pGetInterfaceTest = new GetInterfaceTest(pDriverPtr,Async,bInterfaceNumber,&uNextInterface,FALSE);
	if(pGetInterfaceTest == NULL){
		g_pKato->Log(LOG_FAIL, TEXT("Out of memory"));
		return FALSE;
	}
	errorCode=pGetInterfaceTest->GetErrorCode();
	delete pGetInterfaceTest;
	if (errorCode==0 && bInterfaceNumber == uNextInterface) {
		g_pKato->Log(LOG_FAIL, TEXT("Fail at GetDescriptor,Unexpected Success return"));
		return FALSE;
	};
	return TRUE;
};

BOOL BaseCase1Command(UsbClientDrv *pDriverPtr,BOOL Async)
{

	DEBUGMSG(DBG_DETAIL,(TEXT("BaseCase1Command Test")));

	TransStatus transStatus;
	transStatus.lpUsbFuncs=pDriverPtr->lpUsbFuncs;
	transStatus.IsFinished=FALSE;

	LPCUSB_FUNCS lpUsbFuncs =pDriverPtr->lpUsbFuncs;
	USB_HANDLE usbHandle= pDriverPtr->GetUsbHandle();

	USB_DEVICE_DESCRIPTOR deviceDescriptor;

	memset(&deviceDescriptor,0,sizeof(USB_DEVICE_DESCRIPTOR));
	DEBUGMSG(DBG_DETAIL,(TEXT("Call GetDescriptor using correct argument")));
	transStatus.hTransfer=(*lpUsbFuncs->lpGetDescriptor)
			(usbHandle,
			Async?TransferNotify:NULL,
			&transStatus,
			(Async?USB_NO_WAIT:0),
			USB_DEVICE_DESCRIPTOR_TYPE,0,0,
			sizeof(USB_DEVICE_DESCRIPTOR),&deviceDescriptor);

	if (Async && transStatus.cEvent.Lock(USB_TIME_OUT)==FALSE) {
		g_pKato->Log(LOG_FAIL,TEXT("BaseCase1Command time out 1"));
		return FALSE;
	};
	if (transStatus.hTransfer) {
		if ((*lpUsbFuncs->lpIsTransferComplete)(transStatus.hTransfer))
			DEBUGMSG(DBG_DETAIL,(TEXT("Transfer Complete")));
		else
			DEBUGMSG(DBG_DETAIL,(TEXT("Transfer Complete")));
		(*lpUsbFuncs->lpCloseTransfer)(transStatus.hTransfer);
	};


	BOOL bReturn=TRUE;

	DEBUGMSG(DBG_DETAIL,(TEXT("Call GetDescriptor using Wrong argument")));
	memset(&deviceDescriptor,0,sizeof(USB_DEVICE_DESCRIPTOR));
	transStatus.hTransfer=(*lpUsbFuncs->lpGetDescriptor)
			(usbHandle,
			Async?TransferNotify:NULL,
			&transStatus,
			(Async?USB_NO_WAIT:0),
			USB_DEVICE_DESCRIPTOR_TYPE,1,0,
			sizeof(USB_DEVICE_DESCRIPTOR),&deviceDescriptor);

	if (Async && transStatus.cEvent.Lock(USB_TIME_OUT)==FALSE) {
		g_pKato->Log(LOG_FAIL,TEXT("BaseCase1Command time out 2"));
		bReturn=FALSE;
	}
	if (transStatus.hTransfer) {
		if ((*lpUsbFuncs->lpIsTransferComplete)(transStatus.hTransfer))
			DEBUGMSG(DBG_DETAIL,(TEXT("Transfer Complete")));
		else
			DEBUGMSG(DBG_DETAIL,(TEXT("Transfer Complete")));
		(*lpUsbFuncs->lpCloseTransfer)(transStatus.hTransfer);
	};

	DEBUGMSG(DBG_DETAIL,(TEXT("Call GetDescriptor using Wrong argument again")));
	memset(&deviceDescriptor,0,sizeof(USB_DEVICE_DESCRIPTOR));
	transStatus.hTransfer=(*lpUsbFuncs->lpGetDescriptor)
			(usbHandle,
			Async?TransferNotify:NULL,
			&transStatus,
			(Async?USB_NO_WAIT:0),
			USB_DEVICE_DESCRIPTOR_TYPE,1,0,
			sizeof(USB_DEVICE_DESCRIPTOR),&deviceDescriptor);

	if (Async && transStatus.cEvent.Lock(USB_TIME_OUT)==FALSE) {
		g_pKato->Log(LOG_FAIL,TEXT("BaseCase1Command time out 3"));
		bReturn=FALSE;
	};
	if (transStatus.hTransfer) {
		if ((*lpUsbFuncs->lpIsTransferComplete)(transStatus.hTransfer))
			DEBUGMSG(DBG_DETAIL,(TEXT("Transfer Complete")));
		else
			DEBUGMSG(DBG_DETAIL,(TEXT("Transfer Complete")));
		(*lpUsbFuncs->lpCloseTransfer)(transStatus.hTransfer);
	};

	return bReturn;
}
#define USB_GETSTATUS_DEVICE_STALL 1
BOOL TestEndpointFeature(UsbClientDrv * pDriverPtr,BOOL aSync,DWORD dwIndex,LPCUSB_ENDPOINT pEndpoint)
{
	g_pKato->Log(LOG_COMMENT,TEXT("End Point SetFeature USB_ENDPOINT_STALL "));
	{
		FeatureSetting *pSetFeature= new FeatureSetting(pDriverPtr,TRUE,aSync,
			USB_SEND_TO_ENDPOINT,USB_FEATURE_ENDPOINT_STALL,(UCHAR)pEndpoint->Descriptor.bEndpointAddress,TRUE);
		if(pSetFeature == NULL){
			g_pKato->Log(LOG_FAIL, TEXT("Out of memory"));
			return FALSE;
		}
		if (pSetFeature->GetErrorCode()) {
			g_pKato->Log(LOG_FAIL,TEXT("SetFeature USB_ENDPOINT_STALL Fail ErrorCode=%ld"),pSetFeature->GetErrorCode());
			delete pSetFeature;
			return FALSE;
		}
		else {
			delete pSetFeature;
			WORD wStatus=0;
			GetStatus * paGetStatus= new GetStatus(pDriverPtr,aSync,pEndpoint->Descriptor.bEndpointAddress,USB_SEND_TO_ENDPOINT,&wStatus,TRUE);
                    if(paGetStatus == NULL){
        			g_pKato->Log(LOG_FAIL, TEXT("Out of memory"));
        			return FALSE;
		        }
			if (paGetStatus->GetErrorCode()) {
				g_pKato->Log(LOG_FAIL,TEXT("GetStatus Fail ErrorCode=%ld"),paGetStatus->GetErrorCode());
				delete paGetStatus;
				return FALSE;
			}
			else {
				delete paGetStatus;
				if (!(wStatus & USB_GETSTATUS_DEVICE_STALL)) {
					g_pKato->Log(LOG_FAIL,TEXT("GetStatus return Can not SUPPORT STALL"));
				};
			}
		};
	};
	g_pKato->Log(LOG_COMMENT,TEXT("End Point ClearFeature USB_ENDPOINT_STALL "));
	{
		FeatureSetting *pClearFeature= new FeatureSetting(pDriverPtr,FALSE,aSync,
			USB_SEND_TO_ENDPOINT,USB_FEATURE_ENDPOINT_STALL,pEndpoint->Descriptor.bEndpointAddress,TRUE);
		if(pClearFeature == NULL){
			g_pKato->Log(LOG_FAIL, TEXT("Out of memory"));
			return FALSE;
		}
		if (pClearFeature->GetErrorCode()) {
			g_pKato->Log(LOG_FAIL,TEXT("ClearFeature REMODE_WAKEUP Fail ErrorCode=%ld"),pClearFeature->GetErrorCode());
			return FALSE;
		}
		else {
			WORD wStatus=0;
			GetStatus *paGetStatus= new GetStatus(pDriverPtr,aSync,pEndpoint->Descriptor.bEndpointAddress,USB_SEND_TO_ENDPOINT,&wStatus,TRUE);
			if(paGetStatus == NULL){
        			g_pKato->Log(LOG_FAIL, TEXT("Out of memory"));
        			return FALSE;
        		}
			if (paGetStatus->GetErrorCode()) {
				g_pKato->Log(LOG_FAIL,TEXT("GetStatus Fail ErrorCode=%ld"),paGetStatus->GetErrorCode());
			}
			else
				if (wStatus & USB_GETSTATUS_DEVICE_STALL) {
					g_pKato->Log(LOG_FAIL,TEXT("GetStatus return Can not clear STALL"));
				};
			delete paGetStatus;
		};
	};
	return TRUE;

}
BOOL TestInterface(UsbClientDrv *pDriverPtr,BOOL aSync,DWORD dwIndex,LPCUSB_INTERFACE pUsbInterface)
{
	UCHAR bAlternateSetting;
	GetInterfaceTest *pGInterface= new GetInterfaceTest(pDriverPtr,aSync,(UCHAR)dwIndex,&bAlternateSetting,TRUE);
	if(pGInterface == NULL){
		g_pKato->Log(LOG_FAIL, TEXT("Out of memory"));
		return FALSE;
	}
	if (pGInterface->GetErrorCode()) {
		g_pKato->Log(LOG_FAIL,TEXT("Get Interface  ErrorCode=%ld"),pGInterface->GetErrorCode());
		delete pGInterface;
		return FALSE;
	};
	delete pGInterface;

	g_pKato->Log(LOG_COMMENT,TEXT(" We Get Interface %d Interface, the AlternateSetting (%ld)"),
		(DWORD)dwIndex,(DWORD)bAlternateSetting);
	SetInterfaceTest * pSInterface= new SetInterfaceTest(pDriverPtr,aSync,(UCHAR)dwIndex,bAlternateSetting,TRUE);
	if(pSInterface == NULL){
		g_pKato->Log(LOG_FAIL, TEXT("Out of memory"));
		return FALSE;
	}

	if (pSInterface->GetErrorCode()) {
		g_pKato->Log(LOG_FAIL,TEXT("Get Interface  ErrorCode=%ld"),pSInterface->GetErrorCode());
		delete pSInterface;
		return FALSE;
	};
	delete pSInterface;
	g_pKato->Log(LOG_COMMENT,TEXT(" We Set Interface %d Interface, The interface have %ld endpoint"),
		(DWORD)dwIndex,(DWORD)pUsbInterface->Descriptor.bNumEndpoints);
	for (DWORD index=0;index<(DWORD)pUsbInterface->Descriptor.bNumEndpoints;index++) {
		if (((pUsbInterface->lpEndpoints+index)->Descriptor.bEndpointAddress & 
			(~USB_ENDPOINT_DIRECTION_MASK))!=0) {// do not test end point zero.
			if (!TestEndpointFeature(pDriverPtr,aSync,index,pUsbInterface->lpEndpoints+index)) {
				g_pKato->Log(LOG_FAIL,TEXT("TestEndpointFeature Fail for index %d: endpoint addr is %x"),
					index,(pUsbInterface->lpEndpoints+index)->Descriptor.bEndpointAddress);
				return FALSE;
			}
		};
	};
	return TRUE;

}
BOOL GetConfigureDescriptor(UsbClientDrv *pDriverPtr,BOOL aSync,DWORD dwIndex,
							LPCUSB_CONFIGURATION pUsbConfigure,
							PBYTE uDescripBuffer,WORD wLength)
{
	GetDespTest * pConfigDescriptor= new GetDespTest(pDriverPtr,aSync,USB_CONFIGURATION_DESCRIPTOR_TYPE,(UCHAR)dwIndex,0,
		wLength,uDescripBuffer,TRUE);
	if(pConfigDescriptor == NULL){
		g_pKato->Log(LOG_FAIL, TEXT("Out of memory"));
		return FALSE;
	}
	if (pConfigDescriptor->GetErrorCode()) {
		g_pKato->Log(LOG_FAIL,TEXT("Get ConfigDescriptor Fail ErrorCode=%ld"),pConfigDescriptor->GetErrorCode());
		delete pConfigDescriptor;
		return FALSE;
	};
	delete pConfigDescriptor;
	PUSB_CONFIGURATION_DESCRIPTOR pConfigDescr = (PUSB_CONFIGURATION_DESCRIPTOR)uDescripBuffer;
	if (pConfigDescr->bLength!=sizeof(USB_CONFIGURATION_DESCRIPTOR)) {
		g_pKato->Log(LOG_COMMENT,TEXT("GetConfigDescriptor Size is uncompatable user device(%ld), usbd expect(%ld)"),
			(DWORD)(pConfigDescr->bLength),sizeof(USB_CONFIGURATION_DESCRIPTOR));
	};
	g_pKato->Log(LOG_COMMENT,TEXT(" We found %d Interface Descriptor"),
		(DWORD)pConfigDescr->bNumInterfaces);

	if (pConfigDescr->bNumInterfaces!=pUsbConfigure->Descriptor.bNumInterfaces){
		g_pKato->Log(LOG_FAIL,TEXT("Interface Number (%ld) is not same as GetDeviceInfo(%ld) for configur %ld"),
			(DWORD)pConfigDescr->bNumInterfaces,(DWORD)pUsbConfigure->Descriptor.bNumInterfaces,dwIndex);
		return FALSE;
	}
	DWORD dwNumInterface=pConfigDescr->bNumInterfaces;
	for (DWORD index=0;index<dwNumInterface;index++) {
		if (!TestInterface(pDriverPtr,aSync,index,pUsbConfigure->lpInterfaces+index)) {
			g_pKato->Log(LOG_FAIL,TEXT("TestInterface Fail for index %d"),index);
			return FALSE;
		}
	}
	return TRUE;
}
BOOL DeviceRequest(UsbClientDrv *pDriverPtr,BOOL aSync)
{
	PUCHAR uDescripBuffer = NULL ; // 4 k;
	uDescripBuffer = (PUCHAR)LocalAlloc(LPTR, 0x1000*sizeof(UCHAR));
	if(uDescripBuffer == NULL){
		g_pKato->Log(LOG_FAIL,TEXT("Fail at DeviceRequest,out of memory"));
		return FALSE;
	}

	GetDespTest *pDeviceDescriptor= new GetDespTest(pDriverPtr,aSync,USB_DEVICE_DESCRIPTOR_TYPE,0,0,
		0x1000,uDescripBuffer,TRUE);
	if(pDeviceDescriptor == NULL){
		g_pKato->Log(LOG_FAIL, TEXT("Out of memory"));
		return FALSE;
	}

	if (pDeviceDescriptor->GetErrorCode()) {
		g_pKato->Log(LOG_FAIL,TEXT("Get DeviceDescriptor Fail ErrorCode=%ld"),pDeviceDescriptor->GetErrorCode());
		delete pDeviceDescriptor;
		LocalFree(uDescripBuffer);
		return FALSE;
	};
	delete pDeviceDescriptor;

	LPCUSB_DEVICE pUsbDevice=pDriverPtr->GetDeviceInfo();
       if(pUsbDevice == NULL){
		g_pKato->Log(LOG_FAIL,TEXT("Invalid USB device data structure!"));
		LocalFree(uDescripBuffer);
		return FALSE;
       }
	PUSB_DEVICE_DESCRIPTOR pDevice = (PUSB_DEVICE_DESCRIPTOR)uDescripBuffer;
       ASSERT(pDevice);
	if (pDevice->bLength!=sizeof(USB_DEVICE_DESCRIPTOR)) {
		g_pKato->Log(LOG_FAIL,TEXT("DeviceDescrip Size is uncompatable user device(%ld), usbd expect(%ld)"),
			(DWORD)(pDevice->bLength),sizeof(USB_DEVICE_DESCRIPTOR));
	};

	if (pDevice->bNumConfigurations!=pUsbDevice->Descriptor.bNumConfigurations) {
		g_pKato->Log(LOG_FAIL,TEXT("Configarun Number (%ld) is not same as GetDeviceInfo(%ld)"),
			(DWORD)pDevice->bNumConfigurations,(DWORD)pUsbDevice->Descriptor.bNumConfigurations);
		LocalFree(uDescripBuffer);
		return FALSE;
	}
	g_pKato->Log(LOG_COMMENT,TEXT(" We found %d Configuration Descriptor"),
		(DWORD)pDevice->bNumConfigurations);
	DWORD dwNumConfiguration=(DWORD)pDevice->bNumConfigurations;
	
	for (DWORD index=0;index<dwNumConfiguration;index++) {
		if (!GetConfigureDescriptor(pDriverPtr,aSync,index,
				pUsbDevice->lpConfigs+index,uDescripBuffer,0x1000)) {
			g_pKato->Log(LOG_FAIL,TEXT("GetConfigureDescriptor Fail for index %d"),index);
			pDriverPtr->ResetDefaultPipe();
			LocalFree(uDescripBuffer);
			return FALSE;
		};
	}
	LocalFree(uDescripBuffer);
	return TRUE;

}
