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

📄 bulkdev.cpp

📁 这是usb mass storage(海量存储)的源代码,欢迎下载
💻 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 + -