📄 ezusbdevice.cpp
字号:
// 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 + -