⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ezusbdevice.cpp

📁 EZ_USB cy7c68013的驱动程序
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// EzUsbDevice.cpp - Implementation of EzUsbDevice device class
//=============================================================================
//
// Compuware Corporation
// NuMega Lab
// 9 Townsend West
// Nashua, NH 03060  USA
//
// Copyright (c) 1999 Compuware Corporation. All Rights Reserved.
// Unpublished - rights reserved under the Copyright laws of the
// United States.
//
//=============================================================================

#pragma warning(disable:4200)		  
#include <vdw.h>
#pragma warning (default:4710)

#include <kusb.h>
#include <KUsbBusIntf.h>

#include "EzUsbFirmware.h"
#include "EzUsbDeviceIoctl.h"
#include "EzUsbIsoTransfer.h"
#include "EzUsbIntTransfer.h"
#include "EzUsbDevice.h"

extern KDebugOnlyTrace t;				// Global driver trace object	

extern INTEL_HEX_RECORD loader[];		// Firmware for the EZUSB device
extern INTEL_HEX_RECORD EzUsbMonitor[]; // Firmware for the EZUSB device
extern INTEL_HEX_RECORD EzUsbMonitorFx2[]; // Firmware for the EZUSB-FX2 device

//=============================================================================
// EzUsbDevice Constructor
//
//		This is the constructor for the Functional Device Object, or FDO.
//		It is derived from KPnpDevice, which builds in automatic
//	    dispatching of subfunctions of IRP_MJ_POWER and IRP_MJ_PNP to
//		virtual member functions.
//
// Input
//		Pdo		Physical Device Object - this is a pointer to a system
//				device object that represents the physical device.
//
//		Unit	Unit number - this is a number to append to the device's
//				base device name to form the Logical Device Object's name
//
EzUsbDevice::EzUsbDevice(PDEVICE_OBJECT Pdo, ULONG Unit)
	:KPnpDevice(
		Pdo,
		KUnitizedName(L"Ezusb-", Unit), 
		FILE_DEVICE_UNKNOWN,
		KUnitizedName(L"Ezusb-", Unit),
		0,
		DO_DIRECT_IO | DO_POWER_PAGABLE
		),
	 m_pIsoDM(NULL),
	 m_LastFailedUrbStatus(0)
{
	t << "Entering EzUsbDevice (ctor)\n";

	// Check constructor status
    if( ! NT_SUCCESS(m_ConstructorStatus) )
	{
	    return;
	}

	// Remember our unit number
	m_Unit = Unit;

	// Initialize the lower device
	m_Lower.Initialize(this, Pdo);

	// Initialize the interface object
	m_UsbInterface.Initialize(m_Lower, 0, 1, 0); 

	// Initialize the pipe objects
	for( UCHAR i = 0; i < EZUSB_MAX_ENDPOINTS/2; i++ )
	{
		m_Endpoints[i].Initialize(m_Lower, static_cast<UCHAR>(i + 1));
		m_Endpoints[i + EZUSB_MAX_ENDPOINTS/2].Initialize(m_Lower,  static_cast<UCHAR>(i + 1 + 0x80));
	}

	//Most drivers would have KUsbPipe data members for each endpoint
	//and call the Initialize method for each member
	//m_Endpoint1_OUT.Initialize(m_Lower, 0x01); 
	//m_Endpoint2_IN .Initialize(m_Lower, 0x82); 
	//m_Endpoint2_OUT.Initialize(m_Lower, 0x02); 

	// Initialize the interrupt transfer object
	NTSTATUS Status = m_IntXfer.Initialize(
		&m_Lower,
		&m_Endpoints[EZUSB_MAX_ENDPOINTS/2 + 1]
		);

	ASSERT( STATUS_SUCCESS == Status );

	IntBuffLen = 4;
	pIntBuff = new (NonPagedPool) UCHAR[IntBuffLen];
	ASSERT( pIntBuff );

    // Inform the base class of the lower edge device object
	SetLowerDevice(&m_Lower);

	// Initialize the PnP Policy settings to the "standard" policy
	SetPnpPolicy();

	// Initialize the Power Policy settings to the "standard" policy
	SetPowerPolicy();

	// Adjust the power policy.  By default, the base class will power the
	// device down when the last file handle is closed.  For this 
	// development kit, this is not the desired behavior.  
    m_PowerPolicies.m_GeneralPolicy.m_PowerDnOnClose = FALSE; 

#if (_WDM_ && (WDM_MAJORVERSION > 1 ||((WDM_MAJORVERSION == 1) && (WDM_MINORVERSION >= 0x20))))
	Status = m_BusIntf.Initialize(m_Lower.TopOfStack());
	if (STATUS_SUCCESS == Status)
		m_fBusIntfAvailable = TRUE;
	else
		m_fBusIntfAvailable = FALSE;
#endif
}

//=============================================================================
// EzUsbDevice Destructor
//
//		This is the destructor for the Functional Device Object, or FDO.
//
EzUsbDevice::~EzUsbDevice()
{
	t << "Entering ~EzUsbDevice() (dtor)\n";

	delete pIntBuff;
}

//=============================================================================
// PNPMinorFunctionName
//
//		Return a string describing the Plug and Play minor function	
//
char *PNPMinorFunctionName(ULONG mn)
{
#ifdef 	DBG
	static char* minors[] = {
		"IRP_MN_START_DEVICE",
		"IRP_MN_QUERY_REMOVE_DEVICE",
		"IRP_MN_REMOVE_DEVICE",
		"IRP_MN_CANCEL_REMOVE_DEVICE",
		"IRP_MN_STOP_DEVICE",
		"IRP_MN_QUERY_STOP_DEVICE",
		"IRP_MN_CANCEL_STOP_DEVICE",
		"IRP_MN_QUERY_DEVICE_RELATIONS",
		"IRP_MN_QUERY_INTERFACE",
		"IRP_MN_QUERY_CAPABILITIES",
		"IRP_MN_QUERY_RESOURCES",
		"IRP_MN_QUERY_RESOURCE_REQUIREMENTS",
		"IRP_MN_QUERY_DEVICE_TEXT",
		"IRP_MN_FILTER_RESOURCE_REQUIREMENTS",
		"<unknown minor function>",
		"IRP_MN_READ_CONFIG",
		"IRP_MN_WRITE_CONFIG",
		"IRP_MN_EJECT",
		"IRP_MN_SET_LOCK",
		"IRP_MN_QUERY_ID",
		"IRP_MN_QUERY_PNP_DEVICE_STATE",
		"IRP_MN_QUERY_BUS_INFORMATION",
		"IRP_MN_DEVICE_USAGE_NOTIFICATION",
		"IRP_MN_SURPRISE_REMOVAL"
	};

	if (mn > IRP_MN_SURPRISE_REMOVAL) 
		return "<unknown minor function>";
	else
		return minors[mn];
#else
	return NULL;

	UNREFERENCED_PARAMETER(mn);
#endif
}

//=============================================================================
// EzUsbDevice::DefaultPnp - Default handler for IRP_MJ_PNP
//
//		This routine just passes the IRP through to the lower device. It is 
//		the default handler for IRP_MJ_PNP. IRPs that correspond to
//		any virtual members of KpnpDevice that handle minor functions of
//		IRP_MJ_PNP and that are not overridden get passed to this routine.
//
NTSTATUS EzUsbDevice::DefaultPnp(KIrp I) 
{
	t << "Entering DefaultPnp with IRP minor function="
	  << PNPMinorFunctionName(I.MinorFunction()) << "\n";

	I.ForceReuseOfCurrentStackLocationInCalldown();
	return m_Lower.PnpCall(this, I);
}

//=============================================================================
// EzUsbDevice::DefaultPower - Default handler for IRP_MJ_POWER 
//
//		This routine just passes the IRP through to the lower device. It is 
//		the default handler for IRP_MJ_POWER.
//
NTSTATUS EzUsbDevice::DefaultPower(KIrp I) 
{
	t << "Entering DefaultPower\n";

	I.IndicatePowerIrpProcessed();
	I.CopyParametersDown();
	return m_Lower.PnpPowerCall(this, I);
}

//=============================================================================
// EzUsbDevice::SystemControl - Handler for IRP_MJ_SYSTEM_CONTROL
//
//		This routine just passes the IRP through to the next device since 
//		this driver is not a WMI provider.
//
NTSTATUS EzUsbDevice::SystemControl(KIrp I) 
{
	I.ForceReuseOfCurrentStackLocationInCalldown();
	return m_Lower.PnpCall(this, I);
}

//=============================================================================
// EzUsbDevice::OnStartDevice - Handler for IRP_MJ_PNP / IRP_MN_START_DEVICE
//
//		This is the routine where the driver configures the USB device and
//		sets up its USB related data members.
//
//		The EZUSB device has one interface and numerous endpoints. Other USB 
//		devices likely have less endpoints, but it simply a matter of adding 
//		or removing data members to the device class in order to support more 
//		interfaces and model the USB device endpoints.
//
NTSTATUS EzUsbDevice::OnStartDevice(KIrp I)
{
	t << "Entering OnStartDevice\n";

	NTSTATUS status = STATUS_UNSUCCESSFUL;
	BOOLEAN bDownloadMonitor = FALSE;
	AC_STATUS acStatus = AC_SUCCESS;

	I.Information() = 0;

	// Since this driver supports all of the EZUSB family of chips, determine
	// the device and vendor ID of this device.  If its the default device,
	// change the alternate setting of the interface to 1 and download the 
	// 8051 debug monitor.
	USB_DEVICE_DESCRIPTOR desc;
	status = m_Lower.GetDeviceDescriptor( &desc );
	if ( !NT_SUCCESS(status) )
	{ 
		return status;
	}

	if(desc.idVendor == 0x0547 && desc.idProduct == 0x0080)
	{
		// default Anchor device, change the initial alternate setting to 1.
		m_UsbInterface.m_CurrentAlternateSetting = 1;
		bDownloadMonitor = TRUE;
	}

	if(desc.idVendor == 0x04B4 && desc.idProduct == 0x0081)
	{
		// default Anchor device, change the initial alternate setting to 1.
		m_UsbInterface.m_CurrentAlternateSetting = 1;
		bDownloadMonitor = TRUE;
	}

	// Activate Configuration value 1, the first configuration (index 0) of the device
	// described by the first configuration descriptor
	acStatus = m_Lower.ActivateConfiguration(1);

	switch (acStatus)
	{
		case AC_SUCCESS:
			t << "USB Configuration OK\n";

			if(TRUE	== bDownloadMonitor)
			{
				status = DownloadFirmware();
			}
			else
			{
				status = STATUS_SUCCESS;
			}

			//This is the Product ID for Walter Oney's sample device
			//for testing interrupt transfers
			if(desc.idVendor == 0x0547 && desc.idProduct == 0x102D)
			{
				//Start an interrupt transfer
				m_IntXfer.StartPolling(
					pIntBuff,
					IntBuffLen,
					OnInterrupt
					);
			}

			TestBusInterface();
			break;

		case AC_COULD_NOT_LOCATE_INTERFACE:
			t << "Could not locate interface\n";
			break;

		case AC_COULD_NOT_PRECONFIGURE_INTERFACE:
			t << "Could not get configuration descriptor\n";
			break;

		case AC_CONFIGURATION_REQUEST_FAILED:
			t << "Board did not accept configuration URB\n";
			break;

		case AC_FAILED_TO_INITIALIZE_INTERFACE_OBJECT:
			t << "Failed to initialize interface object\n";
			break;

		case AC_FAILED_TO_GET_DESCRIPTOR:
			t << "Failed to get device descriptor\n";
			break;

		case AC_FAILED_TO_OPEN_PIPE_OBJECT:
			//NOTE: this may or may not be fatal.  It could mean that
			//the device has an endpoint for which a KUsbPipe object has
			//not been instanced.  If the intention is to not use this pipe,
			//then it's ok.  Otherwise, there could be a failure.  Clients can
			//iterate through the pipe array to check which are open/closed
			//vs. what interface info says to figure out what is going on.
			status = STATUS_SUCCESS;
			t << "Failed to open pipe object \n";
			break;

		default:
			t << "Unexpected error activating USB configuration\n";
			break;
	}

   return status;  // base class completes the IRP
}


//=============================================================================
// EzUsbDevice::TestBusInterface
//
void EzUsbDevice::TestBusInterface()
{
#if (_WDM_ && (WDM_MAJORVERSION > 1 ||((WDM_MAJORVERSION == 1) && (WDM_MINORVERSION >= 0x20))))

	if (m_fBusIntfAvailable) {
		t << "USB Bus Interface Size: " << m_BusIntf.Size() << "\n";
		t << "USB Bus Interface Version: " << m_BusIntf.Version() << "\n";
		t << "High Speed Device: " << (m_BusIntf.IsDeviceHighSpeed()?"TRUE":"FALSE") << "\n";

		USBD_VERSION_INFORMATION UsbVerInfo;
		RtlZeroMemory(&UsbVerInfo, sizeof(USBD_VERSION_INFORMATION));
		ULONG HcdCapabilities = 0;

		m_BusIntf.GetUSBDIVersion(&UsbVerInfo, &HcdCapabilities);

		t << "USBDI_Version: " << UsbVerInfo.USBDI_Version << "\n";
		t << "Supported_USB_Version: " << UsbVerInfo.Supported_USB_Version << "\n";


		ULONG TotalBW, ConsumedBW;
		NTSTATUS Status = m_BusIntf.GetBandwidth(&TotalBW,&ConsumedBW);

		if (STATUS_SUCCESS == Status) {
			t << "Total Bandwidth: " << TotalBW << "\n";
			t << "Consumed Bandwidth: " << ConsumedBW << "\n";
		}

		PWSTR HcName = NULL;
		Status = m_BusIntf.GetControllerName(HcName);

		if (STATUS_SUCCESS == Status && HcName) {

			t << "HC Name: " << HcName << "\n";
			delete HcName;
		}

		ULONG CurrentFrame;
		m_BusIntf.QueryBusTime(&CurrentFrame);

		t << "Current Frame: " << CurrentFrame << "\n";
	}
#endif
}


//=============================================================================
// EzUsbDevice::OnQueryCapabilities
//
//		This function is implemented to allow surprise removal of EzUsb so
//		that the annoying dialog is not presented to the user.
//
NTSTATUS EzUsbDevice::OnQueryCapabilities(KIrp I)
{
	t << "Entering OnQueryCapabilitiesn";

	I.CopyParametersDown();
	I.SetCompletionRoutine(LinkTo(OnQueryCapabilitiesComplete), this, TRUE, TRUE, TRUE);

	return m_Lower.PnpCall(this, I);
}


NTSTATUS EzUsbDevice::OnQueryCapabilitiesComplete(KIrp I)
{
	if (I->PendingReturned)
		I.MarkPending();

	I.DeviceCapabilities()->SurpriseRemovalOK = TRUE;

	return STATUS_SUCCESS;
}

//=============================================================================
// EzUsbDevice::DownloadFirmware
//
//		This routine will download firmware to the default USB device -
//		VendorID = 0x0547 and DeviceID = 0x0080.  It is called from
//		EzUsbDevice::OnStartDevice
//
NTSTATUS EzUsbDevice::DownloadFirmware(void)
{
	t << "Entering DownloadFirmware\n";

	NTSTATUS status = STATUS_SUCCESS;

	Reset8051(1);

	status = DownloadIntelHex(loader);
	if( !NT_SUCCESS(status) )
		return status;

	Reset8051(0);

	if (IsFx2()) {
		status = DownloadIntelHex(EzUsbMonitor);
	} 
	else {
		status = DownloadIntelHex(EzUsbMonitorFx2);
	}

	if( !NT_SUCCESS(status) )
		return status;

	Reset8051(1);
	Reset8051(0);
	
	return status;
}

//=============================================================================
// EzUsbDevice::Reset8051

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -