📄 bulkdev.cpp
字号:
// bulkdev.cpp - device class implementation for USB Bulk sample driver
//
//=============================================================================
//
// Compuware Corporation
// NuMega Lab
// 9 Townsend West
// Nashua, NH 03060 USA
//
// Copyright (c) 1998 Compuware Corporation. All Rights Reserved.
// Unpublished - rights reserved under the Copyright laws of the
// United States.
//
//=============================================================================
#include <vdw.h>
#include <kusb.h>
#include "bulkdev.h"
#include "bulkioct.h"
extern KTrace Tracer; // Global driver trace object
////////////////////////////////////////////////////////////////////////////////
// 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
//
// The object being constructed contains a data member (m_Usb) of type
// KPnpLowerDevice. By initializing it, the driver binds the FDO to the
// PDO and creates an interface to the upper edge of the system USB
// class driver.
UsbBulkDevice::UsbBulkDevice(PDEVICE_OBJECT Pdo, ULONG Unit) :
KPnpDevice(
Pdo,
KUnitizedName(L"UsbBulk", Unit),
FILE_DEVICE_UNKNOWN,
KUnitizedName(L"UsbBulk", Unit)
)
{
Tracer << "UsbBulkDevice::UsbBulkDevice() Entry\n";
m_Usb.Initialize(this, Pdo); // initialize the USB interface
// initialize description of data in pipe (In Bulk)
m_Endpoints[0].Initialize(1, 0, 0, 0x81, &m_Interface, &m_Pipe0);
// initialize description of data out pipe (Out Bulk)
m_Endpoints[1].Initialize(1, 0, 0, 0x2, &m_Interface, &m_Pipe1);
SetLowerDevice(&m_Usb); // inform PnP code of our Top-of-stack device
SetPnpPolicy(); // use the default Pnp policy
}
////////////////////////////////////////////////////////////////////////////////
// Destructor
//
// This is the destructor for the Functional Device Object, or FDO.
UsbBulkDevice::~UsbBulkDevice()
{
Tracer << "UsbBulkDevice::~UsbBulkDevice() Entry\n";
}
////////////////////////////////////////////////////////////////////////////////
// Default handler for IRP_MJ_PNP
//
// This routine just passes the IRP through to USBD. 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.
//
// For diagnostic purposes, this routine is set up to emit the function
// name to the debugger.
//
NTSTATUS UsbBulkDevice::DefaultPnp(KIrp I)
{
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",
"IRP_MN_undefined",
"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"
};
ULONG Minor = I.MinorFunction();
CHAR* IrpName;
if ( Minor < IRP_MN_SURPRISE_REMOVAL )
IrpName = minors[Minor];
else
IrpName = "<unknown>";
DbgPrint("Pnp IRP minor function=%s\n", IrpName);
I.ForceReuseOfCurrentStackLocationInCalldown();
return m_Usb.PnpCall(this, I);
}
////////////////////////////////////////////////////////////////////////////////
// Default handler for IRP_MJ_POWER
//
// This routine just passes the IRP through to USBD. It is
// the default handler for IRP_MJ_POWER.
//
NTSTATUS UsbBulkDevice::DefaultPower(KIrp I)
{
I.IndicatePowerIrpProcessed();
I.CopyParametersDown();
return m_Usb.PnpPowerCall(this, I);
}
////////////////////////////////////////////////////////////////////////////////
// OnStartDevice - handler for IRP_MJ_PNP/IRP_MN_START_DEVICE
//
// This is the routine where the driver initializes the physical device and
// sets up its USB related data members.
//
// This device has one interface and one pipe. Other USB devices
// are more complex, but it simply a matter of adding more data
// members to the device class in order to support more interfaces
// or pipes.
NTSTATUS UsbBulkDevice::OnStartDevice(KIrp I)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
AC_STATUS acStatus;
PUSB_ENDPOINT pTrouble;
Tracer << "UsbBulkDevice::OnStartDevice() Entry\n";
// The default Pnp policy has already cleared the IRP with the lower device
// Now we initialize the device object
acStatus = m_Usb.ActivateConfiguration(
1, // configuration 1
2, // number of endpoints to configure
m_Endpoints, // address of our endpoint table
&pTrouble // gets pointer to problem endpoint, if any
);
switch (acStatus)
{
case AC_SUCCESS:
Tracer << "Configuration OK\n";
status = STATUS_SUCCESS;
break;
case AC_COULD_NOT_LOCATE_INTERFACE:
Tracer << "Could not locate interface, endpoint address "
<< ULONG(pTrouble->m_EndpointAddress) << "\n";
break;
case AC_COULD_NOT_PRECONFIGURE_INTERFACE:
Tracer << "Could not get configuration descriptor\n";
break;
case AC_CONFIGURATION_REQUEST_FAILED:
Tracer << "Board did not accept configuration URB\n";
break;
case AC_FAILED_TO_INITIALIZE_INTERFACE_OBJECT:
Tracer << "Failed to initialize interface for pipe["
<< ULONG(pTrouble-m_Endpoints) << "]\n";
break;
case AC_FAILED_TO_LOCATE_ENDPOINT_ADDRESS:
Tracer << "Failed to locate endpoint address for pipe["
<< ULONG(pTrouble-m_Endpoints) << "]\n";
break;
}
return status; // base class completes the IRP
}
/////////////////////////////////////////////////////////////////////////
// OnStopDevice
//
// The system calls this when the device is stopped
NTSTATUS UsbBulkDevice::OnStopDevice(KIrp I)
{
Tracer << "UsbBulkDevice::OnStopDevice() Entry\n";
return m_Usb.Unconfigure();
// base class passes to lower device
}
/////////////////////////////////////////////////////////////////////////
// OnRemoveDevice
//
// The system calls this when the device is removed.
NTSTATUS UsbBulkDevice::OnRemoveDevice(KIrp I)
{
Tracer << "UsbBulkDevice::OnRemoveDevice() Entry\n";
// Our PnP policy will take care of
// (1) giving the IRP to USBD
// (2) detaching the PDO
// (3) deleting the device object
return STATUS_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////
// Dispatchers
//
// Nothing to do on Create and Close. A real driver would add additional
// dispatchers for data operations such as Read and Write. The compiler
// will combine identically coded functions.
NTSTATUS UsbBulkDevice::Create(KIrp I)
{
Tracer << "UsbBulkDevice::Create() Entry\n";
I.ForceReuseOfCurrentStackLocationInCalldown();
NTSTATUS status = m_Usb.PnpCall(this, I);
Tracer << "UsbBulkDevice:Create Status " << (ULONG)status << "\n";
return status;
}
NTSTATUS UsbBulkDevice::Close(KIrp I)
{
Tracer << "UsbBulkDevice::Close() Entry\n";
I.ForceReuseOfCurrentStackLocationInCalldown();
NTSTATUS status = m_Usb.PnpCall(this, I);
Tracer << "UsbBulkDevice:Close Status " << (ULONG)status << "\n";
return status;
}
NTSTATUS UsbBulkDevice::InternalDeviceControl(KIrp I)
{
Tracer << "UsbBulkDevice::InternalDeviceControl() Entry\n";
I.ForceReuseOfCurrentStackLocationInCalldown();
NTSTATUS status = m_Usb.PnpCall(this, I);
Tracer << "UsbBulkDevice::InternalDeviceControl Status "
<< (ULONG)status << "\n";
return status;
}
/////////////////////////////////////////////////////////////////////////
// DeviceControl
//
// The system calls this when an application issues DeviceIoControl
//
NTSTATUS UsbBulkDevice::DeviceControl(KIrp I)
{
Tracer << "UsbBulkDevice::DeviceControl() Entry\n";
#pragma warning(disable:4065) // switch with no cases
switch (I.IoctlCode())
{
default:
Tracer << "UNKNOWN [ID=" << I.IoctlCode() << "] );\n",
I.Information() = 0;
return I.PnpComplete(this, STATUS_INVALID_PARAMETER);
}
}
////////////////////////////////////////////////////////////////////////////////
// Default handler for IRP_MJ_READ
//
// This routine is the default handler for IRP_MJ_READ.
// Incoming IRPs are passed on to the USB device, synchronously.
//
// The KPnpDevice class handles restricting IRP flow
// if the device is stopping or being removed.
//
NTSTATUS UsbBulkDevice::Read(KIrp I)
{
NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES;
Tracer << "UsbBulkDevice::Read() Entry\n";
PUCHAR pBuffer = (PUCHAR)I.BufferedReadDest();
ULONG dwTotalSize = I.ReadSize(CURRENT);
ULONG dwBytesRead = 0;
// Create an URB to do actual Bulk read from Pipe0
PURB pUrb = m_Pipe0.BuildBulkTransfer(pBuffer, // Where is data coming from?
dwTotalSize, // How much data to read?
TRUE, // direction (TRUE = IN)
NULL); // Link to next URB
if ( pUrb != NULL)
{
// Submit the URB to our USB device, synchronously - say less is OK
pUrb->UrbBulkOrInterruptTransfer.TransferFlags =
(USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK);
status = m_Pipe0.SubmitUrb(pUrb, NULL, NULL);
if ( NT_SUCCESS(status) )
{
dwBytesRead = pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength;
if (dwBytesRead > 0)
Tracer << "Read() got " << dwTotalSize << " bytes from USB\n";
}
delete pUrb;
}
I.Information() = dwBytesRead;
return I.PnpComplete(this, status, IO_NO_INCREMENT);
}
////////////////////////////////////////////////////////////////////////////////
// Default handler for IRP_MJ_WRITE
//
// This routine is the default handler for IRP_MJ_WRITE.
// Incoming IRPs just send data down to the USB device, synchronously.
//
// The KPnpDevice class handles restricting IRP flow
// if the device is stopping or being removed.
//
NTSTATUS UsbBulkDevice::Write(KIrp I)
{
NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES;
Tracer << "UsbBulkDevice::Write() Entry\n";
PVOID pBuffer = I.BufferedWriteSource();
ULONG dwTotalSize = I.WriteSize(CURRENT);
ULONG dwBytesSent = 0;
// Create an URB to do actual Bulk read from Pipe0
KMemory Mdl(pBuffer, dwTotalSize);
Mdl.SetPageArray();
PURB pUrb = m_Pipe1.BuildBulkTransfer(Mdl, // Where is data coming from?
dwTotalSize, // How much data to read?
FALSE, // direction (FALSE = OUT)
NULL); // Link to next URB
// Submit the URB to our USB device, synchronously
if (pUrb != NULL)
{
status = m_Pipe1.SubmitUrb(pUrb, NULL, NULL);
if ( NT_SUCCESS(status) )
{
dwBytesSent = pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength;
Tracer << "Write() posted " << dwTotalSize << " bytes to USB\n";
}
delete pUrb;
}
I.Information() = dwBytesSent;
return I.PnpComplete(this, status, IO_NO_INCREMENT);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -